اتصال وثيق بين دلفي وإكسل [Wang Anpeng ([email protected]) 2002/4/14] باعتبارها RAD ممتازة، تعد وظيفة قاعدة بيانات Delphi القوية واحدة من أهم ميزاتها، ولكن التحكم السريع في QuickReport الذي يصعب تشغيله لا يمكنه في كثير من الأحيان تلبية احتياجات إعداد تقارير قاعدة البيانات. إذا كان تقريرك معقدًا للغاية، أو يتطلب مرونة في تغييرات التنسيق، فإن استخدام Excel كخادم التقارير يعد اختيارًا جيدًا. يعمل مكون Excel الذي توفره دلفي بدءًا من الإصدار 5 على تبسيط تطبيق تقنية أتمتة OLE بشكل كبير. على أية حال، ملفات المساعدة المفقودة كانت دائمًا الجانب الأكثر انتقادًا في دلفي، وهذه المكونات الجديدة ليست استثناءً. نموذج كائن Excel عبارة عن بنية هرمية تشبه الشجرة. الجذر هو التطبيق نفسه، وهو كائن السمة للكائن الجذر التفاصيل، يرجى الرجوع إلى ملف تعليمات MSOffice VBA. للتحكم في Excel في دلفي، يجب عليك أولاً إنشاء اتصال مع برنامج الخادم، وفتح المصنف، ثم تبادل البيانات مع ورقة العمل المستهدفة، وأخيراً قطع الاتصال. افتح مصنف Excel يبدأ مثالنا بنموذج رئيسي يحتوي على TStringGrid (بالطبع يجب ملء بعض البيانات) وزرين. اسحب عنصر تحكم TExcelapplication من علامة تبويب الخوادم في لوحة التحكم وضعه في النموذج. أولاً، قم بتعيين ConnectKind على ckRunningOrNew، مما يعني أنه إذا كان من الممكن اكتشاف مثيل Excel قيد التشغيل، فقم بإنشاء اتصال به، وإلا قم بتشغيل Excel. بالإضافة إلى ذلك، إذا كنت تريد أن يقوم البرنامج بإنشاء اتصال مع برنامج الخادم بمجرد تشغيله، فيمكنك تعيين خاصية الاتصال التلقائي إلى True. كل ما يتطلبه الأمر لإنشاء اتصال مع Excel هو عبارة واحدة: Excel Connect ربما لاحظت وجود العديد من عناصر تحكم Excel الأخرى في علامة التبويب "الخوادم" التي يمكن ربطها ببرنامج Excel السابق من خلال طريقة ConnectTo: ExcelWorkbook1.ConnectTo(. Excel .ActiveWorkbook); ExcelWorksheet1.ConnectTo(Excel . ActiveSheet as _Worksheet); ExcelWorksheet2.ConnectTo(Excel . Worksheets.Item['Sheet2'] as _Worksheet)؛ تجدر الإشارة إلى أنه يجب فتح المصنف أو ورقة العمل المقابلة قبل استخدام طريقة ConnectTo، بالإضافة إلى ذلك، لن توفر عناصر التحكم هذه راحة إضافية في معظم الحالات، لذا من الأفضل استخدام تطبيق TExcelApplication واحد فقط. بمجرد إنشاء اتصال بخادم Excel، يمكن إنشاء مصنف جديد: var wkBook : _LCID : Integer ... LCID := GetUserDefaultLCID(); الدالة يتم استخدام المعلمة الأولى لتحديد القالب المستخدم للمصنف الجديد، ويمكنك استخدام xlWBATChart وxlWBATExcel4IntlMacroSheet. xlWBATExcel4MacroSheet أو ثابت xlWBATWorksheet، أو يمكن أن يكون اسم ملف xls موجود. EmptyParam هنا هي وحدة المتغيرات والمتغير المحدد، مما يعني استخدام القالب العالمي الافتراضي لإنشاء مصنف جديد. إذا قمت بفتح مستند xls موجود، فيجب عليك تمرير اسم الملف الذي سيتم فتحه كمعلمة أولى إلى الدالة Open: wkBook:=Excel.WorkBooks.Open(edtDesFile.text,EmptyParam,EmptyParam, EmptyParam,EmptyParam,EmptyParam,EmptyParam ، EmptyParam،EmptyParam،EmptyParam،EmptyParam، EmptyParam,EmptyParam,LCID); يجب أن تعلم أن جميع عمليات البيانات مخصصة بشكل أساسي لورقة العمل النشطة. يستخدم البيان التالي متغير _WorkSheet لتمثيل الخلية النشطة الحالية. إذا كنت تعرف اسم ورقة العمل، فيمكن استبدال رقم الفهرس باسم ورقة العمل: wkSheet:=wkBook.Sheets[1] as _WorkSheet؛ بعد الانتهاء من تبادل البيانات، تحتاج إلى حفظ المصنف: Excel.ActiveWorkBook.SaveAs ('MyOutput'، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، LCID)؛ أو: Excel.ActiveWorkBook.Save(LCID)؛ وأخيرًا، أغلق المصنف وافصله عن Excel: wkBook.Close(True, SaveAsName, EmptyParam, LCID); ; تحتوي طريقة الإغلاق هنا على وظيفة الحفظ. تشير المعلمة الأولى إلى ما إذا كان سيتم حفظ التعديلات قبل إغلاق المصنف أم لا. وتعطي المعلمة الثانية اسم الملف المراد حفظه. يتم استخدام المعلمة الثالثة لمؤلفين متعددين لمعالجة الموقف. يطلب السطر الثاني إنهاء Excel. تبادل البيانات مع ورقة العمل يتم تنفيذ بيانات الإدخال على خلية معينة أو نطاق معين من ورقة العمل النشطة، والخلايا كلاهما من خصائص كائن ورقة العمل. الخلايا عبارة عن مجموعة من الخلايا، إذا لم يتم تحديد موقع محدد، فيمكن أن تمثل جميع الخلايا في ورقة العمل بأكملها، ومع ذلك، يتم استخدامها بشكل عام للإشارة إلى خلية معينة، على سبيل المثال، WS.Cells.Item[1,1]. تمثل الخلية A1 الأحدث في الزاوية اليسرى العليا. لاحظ أن العنصر هو الخاصية الافتراضية للخلايا في VBA ويمكن حذفه، ولكن لا توجد مثل هذه الراحة في دلفي. لتعيين قيمة لخلية، يجب عليك الرجوع إلى خاصية القيمة الخاصة بها وغني عن القول أن هذه الخاصية هي متغير متغير، على سبيل المثال: wkSheet.Cells.Item[1, 1].Value := 'Address Book'; بالطبع، يمكنك أيضًا تعيين قيمة للخلية. حدد الصيغة: var AFormula:String …… AFormula:='=Rand()'; wkSheet.Range['F3','G6'].Value:=AFormula; الطريقة المذكورة أعلاه مباشرة وبسيطة للغاية، ولكنها بطيئة جدًا وغير مناسبة للتقارير الكبيرة. فهل يمكن نقل جميع البيانات إلى Excel بالتسلسل؟ يمكننا استخدام النطاق. يمثل هذا الكائن منطقة في ورقة العمل عندما نسحبها للخارج، وعادة ما تكون منطقة مستطيلة "،"J42"]. هناك مشكلة صغيرة هنا، لأنه إذا تجاوزت البيانات 26 عمودًا (على سبيل المثال، هناك 100 عمود) أو إذا كان نطاق المنطقة المستهدفة بحاجة إلى تحديد سريع، فسيكون استخدام أسماء الأحرف لتمييز الخلايا أكثر صعوبة. تذكر أنه نظرًا لأن "C3" هو عنوان الخلية، فيمكننا بالطبع استخدام الخلايا أيضًا، مثل Range[Cells.Item[1,1], Cells.Item[100,100]]. من الممكن أن تكون قيمة Range عبارة عن مصفوفة، لكن يجب ألا تستخدم Array في دلفي لتعيين قيمة لها! تذكر أنه في دلفي، تكون قيمة كائن Excel دائمًا من النوع Variant. var Datas: Variant; Ir, ic: Integer …… Datas:= varArrayCreate([1,ir,1,ic],varVariant); عناصر المصفوفة هنا باستخدام wkSheet تفعل Range[cells.Item[3,1],cells.Item[ir+2,ic]].Value:=Datas; تجدر الإشارة إلى أن كلاً من ورقة العمل والنطاق لهما خاصية الخلايا للتوضيح، يتم استخدام العبارة with هنا. بالإضافة إلى ذلك، النطاق اتجاهي. لا يمكن تعيين صفيف أحادي البعد تم إنشاؤه باستخدام VarArrayCreate إلا لنطاق صف واحد. إذا كنت تريد تحديد قيمة لنطاق ذو عمود واحد، فيجب عليك استخدام صفيف ثنائي الأبعاد مثال: Datas:=VarArrayCreate([1,100,1 ,1], varVariant); // إنشاء مصفوفة ديناميكية 100*1. بالمناسبة، Cells.Item[] يُرجع فعليًا كائن Range. استرداد البيانات من ورقة العمل هو في الأساس عملية عكسية لكتابة البيانات، ما يجب الانتباه إليه هو كيفية تحديد نطاق بيانات ورقة العمل: var ir, ic : Integer …… wkSheet.Cells.SpecialCells(xlCellTypeLastCell,EmptyParam; .Activate ; ir := Excel.ActiveCell.Row ic := Excel.ActiveCell.Column; يتم استخدام وظيفة الخلية الخاصة SpecialCells بذكاء هنا للحصول على الخلية الأخيرة التي تحتوي على البيانات. تحرير البيانات فيما يلي مثالان لتحرير البيانات. var DestRange: OleVariant; begin DestRange := Excel.Range['C1', 'D4']; Excel.Range['A1', 'B4'].Copy(DestRange); إذا قمت بتمرير معلمة فارغة إلى وظيفة النسخ، فسيتم نسخ البيانات الموجودة في هذه المنطقة إلى الحافظة، ويمكن لصقها في مواقع أخرى باستخدام طريقة اللصق لاحقًا. var WS: _Worksheet; …… Excel.Range['A1', 'B4').Copy(EmptyParam); // انسخ البيانات في ورقة العمل إلى الحافظة WS := Excel.Activesheet as _Worksheet; // تغيير ورقة عمل النشاط WS .Range['C1', 'D4').Select; WS.Paste(EmptyParam, EmptyParam, lcid); // الصق محتويات الحافظة في ورقة عمل جديدة. إعدادات التنسيق اختر Excel كخادم التقارير بشكل أساسي بسبب إمكانات التنسيق القوية. نقوم أولاً بدمج الخلايا التي تحمل عنوان "دفتر العناوين" ونعرضها في المنتصف، ثم نغير الخط إلى "نص رسمي" مكون من 18 نقطة بالخط العريض: مع wkSheet.Range['A1','D1'],Font ابدأ Merge(True); // دمج الخلايا HorizontalAlignment:= xlCenter الحجم:=18; إذا كان محتوى الخلية طويلاً، فلن يتم عرض جزء من المحتوى. الطريقة المعتادة هي النقر نقرًا مزدوجًا فوق الحافة اليمنى للمنطقة المحددة بحيث يتكيف عرض كل عمود تلقائيًا مع طول المحتوى. في دلفي، يمكن أيضًا تحقيق عرض العمود التكيفي وارتفاع الصف من خلال طريقة الاحتواء التلقائي. تجدر الإشارة إلى أنه لا يمكن استخدام هذه الطريقة إلا للصف بأكمله والعمود بأكمله، وإلا فستتم المطالبة بخطأ رفض تنفيذ طريقة OLE: wkSheet.Columns.EntireColumn.AutoFit؛ تتطلب التقارير ذات النمط الصيني عادةً خطوط جدول علوية وسفلية، ويمكنك استخدام خاصية مجموعة الحدود. تجدر الإشارة إلى أن كائنات المجموعة في VBA عادة ما يكون لها خاصية العنصر الافتراضية، والتي لا يمكن حذفها في دلفي. يتم استخدام خاصية الوزن لتحديد سمك خطوط الجدول: مع Aname.RefersToRange، تبدأ الحدود HorizontalAlignment:= xlRight; Item[xlEdgeBottom].Weight:=xlMedium; Item[xlEdgeTop].Weight:=xlMedium; .الوزن: =xlرفيع؛ item[xlInsideVertical].Weight:=xlThin; يتم تعيين إعداد الصفحة وإعداد صفحة الطباعة من خلال خاصية كائن PageSetUp في ورقة العمل. يوجد أكثر من 40 ثوابت ورقية تم إعدادها مسبقًا في Excel VBA. وتجدر الإشارة إلى أن بعض الطابعات تدعم بعض أنواع الورق فقط. يتم استخدام اتجاه السمة للتحكم في اتجاه الطباعة، ويشير المشهد الثابت = 2 إلى الطباعة الأفقية. يتم استخدام الخصائص المنطقية CenterHorizontally وCentreVertically لتحديد ما إذا كان المحتوى المطبوع يتم توسيطه أفقيًا وعموديًا. باستخدام wkSheet.PageSetUp، ابدأ PaperSize:=xlPaperA4; // نوع الورق A4 PRintTitleRows := 'A1:D1'; // كرر هذا الصف/الصفحة LeftMargin:=18; 0.25" سيختلف بين الطابعات TopMargin:=36; //0.5" BottomMargin:=36; //0.5" CenterHorizontally:=True; Orientation:=1; // الطباعة الأفقية (أفقي) = 2، عمودي = 1 نهاية؛ لطباعة تقرير، يمكنك استدعاء أسلوب PrintOut لورقة العمل. هذه الطريقة التي يحددها VBA لها إجمالي 8 معلمات اختيارية، يتم استخدام الأولين لتحديد صفحات البداية والنهاية، وعدد النسخ التي سيتم طباعتها بالتنسيق الثالث، ومع ذلك، في دلفي، تتم إضافة معلمة LCID في النهاية، وEmptyParam لا يمكن استخدامها لهذه المعلمة. وبالمثل، طريقة معاينة الطباعة PrintPreview لا تحتوي على معلمات في VBA، ولكنها تتطلب معلمتين عند استدعائها في دلفي. // wkBook.PrintPreview(True,LCID); // للمعاينة wkSheet.PrintOut(EmptyParam,EmptyParam,1, EmptyParam,EmptyParam,EmptyParam, EmptyParam,EmptyParam,LCID); أكثر تعقيدًا، الطريقة الأفضل هي تسمية نطاقات جداول محددة ثم الرجوع إليها بالاسم. الأسماء هي خاصية كائن مجموعة في WorkBook، والتي تحتوي على أسلوب Add يمكنه القيام بهذه المهمة. var Aname : Excel2000.Name …… Aname := wkBook.Names.Add('Address Book','=Sheet1!$A$3:$D$7', EmptyParam, EmptyParam, EmptyParam,EmptyParam,EmptyParam,EmptyParam, EmptyParam, EmptyParam,EmptyParam); المعلمة الأولى لوظيفة الإضافة هي الاسم المحدد، والمعلمة الثانية هي نطاق الخلايا الذي يمثله الاسم. تجدر الإشارة إلى أن نوع اسم النطاق يجب أن يستخدم مؤهلًا. إذا تم استخدام مكتبة النوع (D4)، فإن المؤهل هو Excel_TLB. بالإضافة إلى ذلك، يجب أن يستخدم النطاق المسمى مرجعًا مطلقًا، أي إضافة الرمز "$". بمجرد تسمية نطاق، يمكنك الرجوع إليه بهذا الاسم السطر التالي من التعليمات البرمجية يجعل محتويات دفتر العناوين تظهر بالخط العريض: AName.RefersToRange.Font.Bold:=True ولكن ربما يكون الشيء الأكثر إثارة للدهشة هو أنه يمكنك ذلك ديناميكيًا تعديل برامج الماكرو Excel في دلفي! تقوم التعليمة البرمجية التالية بإنشاء ماكرو للمصنف الذي يسجل آخر وقت وصول عند إغلاق المصنف: var LineNo: integer CM: CodeModule:String begin CM := WkBook.VBProject.VBComponents.Item( 'ThisWorkbook'). Codemodule LineNo := CM.CreateEventProc('BeforeClose', 'Workbook'); SDate:='تاريخ الوصول الأخير:'+DateToStr(Date()); CM.InsertLines(LineNo + 1, ' Range("B2").Value = "'+sDate+''"'); الماكرو أضف وحدة إلى قسم الاستخدامات السابقة: VBIDE2000 إذا تم استخدام مكتبة النوع، فإن الوحدة المقابلة هي VBIDE_TLB. مفتاح هذا الرمز هو كائن CodeModule، ولسوء الحظ، لا يوجد أي أثر لهذا الكائن في مستند تعليمات Excel VBA، لذلك يمكننا فقط البحث في MSDN. Delphi4 والإصدارات السابقة لا توفر Delphi4 كائن TExcelApplication، ويجب تقديم مكتبة نوع لاستخدام تقنية أتمتة OLE. مكتبة الأنواع الخاصة بـ Excel97 هي Excel8.olb. الفرق الرئيسي بين هاتين الطريقتين هو طريقة إنشاء اتصال مع برنامج الخادم. فيما يلي إطار عمل البرنامج للتحكم في Excel من خلال مكتبة النوع: يستخدم Windows وComObj وActiveX وExcel_TLB؛ var Excel: _Application؛ غير معروف: IUnknown؛ غير معروف // حاول التقاط مثيل البرنامج قيد التشغيل if (Result = MK_E_UNAVAILABLE) ثم Excel := CoApplication.Create // ابدأ مثيل برنامج جديد else begin {Check for Errors while the GetActiveObject way call} OleCheck(Result); (Unknown.QueryInterface(_Application, Excel)); end …… // تنفيذ معالجة البيانات Excel.Visible[LCID] := True; // Excel.DisplayAlerts[LCID] := False; // عرض مربع حوار المطالبة Excel.Quit؛ المحاولة المعتادة... باستثناء البنية غير مستخدمة هنا لأن آلية معالجة الاستثناء تتطلب عمليات فحص OLE معقدة، مما يقلل التكلفة سرعة تنفيذ الجزء الاستثناء. تجدر الإشارة إلى أن الوظيفة المصاحبة CoApplication وبعض الأسماء الثابتة التي تم إنشاؤها بواسطة إصدارات دلفي المختلفة قد تكون مختلفة، لذا يجب عليك التحقق من مكتبة الأنواع المقابلة. قبل استدعاء الأسلوب Quit، تأكد من تحرير كافة المصنفات ومتغيرات أوراق العمل التي تم إنشاؤها في البرنامج، وإلا فقد يكون Excel موجودًا في الذاكرة ويتم تشغيله (يمكنك الضغط على Ctrl+Alt+Del للعرض). توجد مشكلة صغيرة في استدعاء GetActiveObject لالتقاط مثيل البرنامج. إذا كان Excel في حالة تشغيل مصغرة، فقد يتم عرض الإطار الرئيسي للبرنامج فقط ولن تكون منطقة المستخدم مرئية. بالإضافة إلى ذلك، إذا كنت لا ترغب في تقديم مكتبة نوع، فيمكنك أيضًا استخدام الارتباط المتأخر، ولكنه أبطأ بكثير. يوضح المثال التالي متغيرًا يمثل تطبيق Excel: var Excel: Variant...try Excel := GetActiveOleObject('Excel.Application'); .مرئي := صحيح؛ عند استخدام الارتباط المتأخر، لا يتحقق المترجم من طريقة كائن Excel التي يتم استدعاؤها، ولكنه يترك هذه المهام لبرنامج الخادم لإكمالها أثناء التنفيذ، وبهذه الطريقة، يتم تعيين عدد كبير من المعلمات الافتراضية بواسطة VBA (غالبًا أكثر من اثنتي عشرة). تُستخدم كما ينبغي، لذا فإن هذه الطريقة لها فائدة غير متوقعة - الكود موجز: var WBk, WS, SheetName: OleVariant ..... WBk := Excel.WorkBooks.Open('C:/Test.xls ') ؛WS := WBk.Worksheets.Item['SheetName']; WS.Activate …… WBk.Close(SaveChanges := True); Excel.Quit; بالإضافة إلى التشغيل البطيء، إذا كنت تريد استخدام الثوابت المحددة في مكتبة النوع ، فقط يمكنك القيام بذلك بنفسك: const xlWBATWorksheet = -4167 …… XLApp.Workbooks.Add(xlWBatWorkSheet); وأخيرًا، لا تنس تحرير المتغيرات بعد إغلاق Excel: Excel := Unsigned; ما يلي هو الكود المصدري المستخدم في مثال هذه المقالة، والذي تم تمريره ضمن Delphi6+MSOffice2000. تستخدم واجهة الوحدة Unit1 Windows، والرسائل، وSysUtils، والمتغيرات، والفئات، والرسومات، وعناصر التحكم، والنماذج، ومربعات الحوار، وOleServer، وExcel2000، وGrids، وStdCtrls؛ إجراء FormActivate(Sender: TObject); Button1Click(Sender: TObject); الإجراء الخاص {الإعلانات الخاصة} الإجراء OpenExl; الإجراء AddFormula; تنسيق الإجراء; الإجراء AddMacro; الإجراء العام {الإعلانات العامة} النهاية; التنفيذ {$R *.dfm} يستخدم VBIDE2000؛ wkSheet:_WorkSheet; Rows[1].CommaText:='Zhang San، ذكر، 25,010-33775566'; Rows[2].CommaText:='لي سي، ذكر، 47,012-6574906';CommaText:='الجمعة، أنثى ,18,061-7557381'; Rows[4].CommaText:='Sun Tao، أنثى، 31,3324559'؛ end؛ الإجراء TForm1.OpenExl؛ يبدأ بـ Excel Connect؛ ، LCID)؛ wkSheet:=wkBook.Sheets[1] as _WorkSheet end; TForm1.Write2Xls; var Datas:Variant; i,j:Integer; begin ir:=StringGrid1.RowCount; :=1 إلى ir do لـ j:=1 إلى ic do Datas[i,j]:=StringGrid1.Cells[j-1,i-1]; مع wkSheet، ابدأ Activate(LCID); Cells.Item[1,1].Value:='Address Book[cells .Item[3,1],cells.Item[ir+2,ic]].Value:=Datas; // Excel.Visible[LCID]:=True; Datas:=Unsigned; end; الإجراء TForm1.Retrieve; var Datas:Variant; i,j:Integer; =Excel.ActiveCell.Column; Datas:=Range[Cells.Item[1,1],Cells.Item[ir,ic]].Value; مع StringGrid1 تبدأ ColCount:=ic; إلى ir-1 do for j:=0 to ic-1 do Cells[j,i]:=Datas[i+1,j+1]; Datas:=UnAssigned; end; الإجراء TForm1.CloseExl; const SaveAsName='test.xls'; ورقة الاسم تبدأ AName:=wkBook.Names.Add('Address Book','=Sheet1!$A$3:$D$7',EmptyParam,EmptyParam, EmptyParam,EmptyParam,EmptyParam,EmptyParam, EmptyParam,EmptyParam,EmptyParam نهاية الإجراء TForm1); .AddFormula; var AFormula:String; AFormula:='=Rand()'; wkSheet.Range['F3','G6'].Value:=AFormula end; الإجراء TForm1.Formats; يبدأ الخط Merge(True); // دمج الخلايا HorizontalAlignment:= xlCenter الحجم:=18; FontStyle:=Bold; end; wkSheet.Columns.EntireColumn.AutoFit; مع Aname.RefersToRange,تبدأ الحدود HorizontalAlignment:= xlRight; Item[xlInsideHorizontal].Weight:=xlThin; item[xlInsideVertical].Weight:=xlThin; end; الإجراء TFORm1.AddMacro; var LineNo: integer; VBComponents.Item('ThisWorkbook').Codemodule; := CM.CreateEventProc('BeforeClose', 'Workbook'); SDate:='تاريخ آخر وصول:'+DateToStr(Date()); CM.InsertLines(LineNo + 1, ' Range("B2").Value = "'+sDate+'"'); end; الإجراء TForm1.Printit; يبدأ بـ wkSheet.PageSetUp PaperSize:=xlPaperA4; // نوع الورق A4 PrintTitleRows := 'A1:D1'; // كرر هذا الصف/الصفحة LeftMargin:=18; //0.25" الهامش الأيسر RightMargin:=18; //0.25" سيختلف بين الطابعات الهامش العلوي: = 36؛ //0.5" الهامش السفلي: = 36؛ //0.5" المركز أفقيًا: = صحيح؛ Orientation:=1; ابدأ بتجربة OpenExl؛ NameSheet; PrintIt; AddMacro; أخيرًا CloseExl end; واحدة من أهم ميزاته، لكن عنصر التحكم QuickReport الذي يصعب تشغيله لا يمكنه في كثير من الأحيان تلبية احتياجات تقارير قاعدة البيانات. إذا كان تقريرك معقدًا جدًا، أو يتطلب مرونة في تغييرات التنسيق، فإن استخدام Excel كخادم التقارير يعد اختيارًا جيدًا. يعمل مكون Excel الذي توفره دلفي بدءًا من الإصدار 5 على تبسيط تطبيق تقنية أتمتة OLE بشكل كبير. على أية حال، ملفات المساعدة المفقودة كانت دائمًا الجانب الأكثر انتقادًا في دلفي، وهذه المكونات الجديدة ليست استثناءً. نموذج كائن Excel عبارة عن بنية هرمية تشبه الشجرة. الجذر هو التطبيق نفسه، وهو كائن السمة للكائن الجذر التفاصيل، يرجى الرجوع إلى ملف تعليمات MSOffice VBA. للتحكم في Excel في دلفي، يجب عليك أولاً إنشاء اتصال مع برنامج الخادم، وفتح المصنف، ثم تبادل البيانات مع ورقة العمل المستهدفة، وأخيراً قطع الاتصال. افتح مصنف Excel يبدأ مثالنا بنموذج رئيسي يحتوي على TStringGrid (بالطبع يجب ملء بعض البيانات) وزرين. اسحب عنصر تحكم TExcelApplication من علامة تبويب الخوادم في لوحة التحكم وضعه في النموذج. أولاً، قم بتعيين ConnectKind على ckRunningOrNew، مما يعني أنه إذا كان من الممكن اكتشاف مثيل Excel قيد التشغيل، فقم بإنشاء اتصال به، وإلا قم بتشغيل Excel. بالإضافة إلى ذلك، إذا كنت تريد أن يقوم البرنامج بإنشاء اتصال مع برنامج الخادم بمجرد تشغيله، فيمكنك تعيين خاصية الاتصال التلقائي إلى True. كل ما يتطلبه الأمر لإنشاء اتصال مع Excel هو عبارة واحدة: Excel Connect ربما لاحظت وجود العديد من عناصر تحكم Excel الأخرى في علامة التبويب "الخوادم" التي يمكن ربطها ببرنامج Excel السابق من خلال طريقة ConnectTo: ExcelWorkbook1.ConnectTo(. Excel . ActiveWorkbook); ExcelWorksheet1.ConnectTo(Excel . ActiveSheet as _Worksheet); ExcelWorksheet2.ConnectTo(Excel . Worksheets.Item['Sheet2'] as _Worksheet)؛ تجدر الإشارة إلى أنه يجب فتح المصنف أو ورقة العمل المقابلة قبل استخدام طريقة ConnectTo، بالإضافة إلى ذلك، لن توفر عناصر التحكم هذه راحة إضافية في معظم الحالات، لذا من الأفضل استخدام تطبيق TExcelApplication واحد فقط. بمجرد إنشاء اتصال بخادم Excel، يمكن إنشاء مصنف جديد: var wkBook : _LCID : Integer ... LCID := GetUserDefaultLCID(); الدالة يتم استخدام المعلمة الأولى لتحديد القالب المستخدم للمصنف الجديد، ويمكنك استخدام xlWBATChart وxlWBATExcel4IntlMacroSheet. xlWBATExcel4MacroSheet أو ثابت xlWBATWorksheet، أو يمكن أن يكون اسم ملف xls موجود. EmptyParam هنا هي وحدة المتغيرات والمتغير المحدد، مما يعني استخدام القالب العالمي الافتراضي لإنشاء مصنف جديد. إذا قمت بفتح مستند xls موجود، فيجب عليك تمرير اسم الملف الذي سيتم فتحه كمعلمة أولى إلى الدالة Open: wkBook:=Excel.WorkBooks.Open(edtDesFile.text,EmptyParam,EmptyParam, EmptyParam,EmptyParam,EmptyParam,EmptyParam ، EmptyParam،EmptyParam،EmptyParam،EmptyParam، EmptyParam,EmptyParam,LCID); يجب أن تعلم أن جميع عمليات البيانات مخصصة بشكل أساسي لورقة العمل النشطة. يستخدم البيان التالي متغير _WorkSheet لتمثيل الخلية النشطة الحالية. إذا كنت تعرف اسم ورقة العمل، فيمكن استبدال رقم الفهرس باسم ورقة العمل: wkSheet:=wkBook.Sheets[1] as _WorkSheet؛ بعد الانتهاء من تبادل البيانات، تحتاج إلى حفظ المصنف: Excel.ActiveWorkBook.SaveAs ('MyOutput'، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، EmptyParam، LCID)؛ أو: Excel.ActiveWorkBook.Save(LCID)؛ وأخيرًا، أغلق المصنف وافصله عن Excel: wkBook.Close(True, SaveAsName, EmptyParam, LCID); ; تحتوي طريقة الإغلاق هنا على وظيفة الحفظ. تشير المعلمة الأولى إلى ما إذا كان سيتم حفظ التعديلات قبل إغلاق المصنف أم لا. وتعطي المعلمة الثانية اسم الملف المراد حفظه. يتم استخدام المعلمة الثالثة لمؤلفين متعددين لمعالجة الموقف. يطلب السطر الثاني إنهاء Excel. تبادل البيانات مع ورقة العمل يتم تنفيذ بيانات الإدخال على خلية أو نطاق معين من ورقة العمل النشطة، ويعتبر النطاق والخلايا من خصائص كائن ورقة العمل. الخلايا عبارة عن مجموعة من الخلايا، إذا لم يتم تحديد موقع محدد، فيمكن أن تمثل جميع الخلايا في ورقة العمل بأكملها، ومع ذلك، يتم استخدامها بشكل عام للإشارة إلى خلية معينة، على سبيل المثال، WS.Cells.Item[1,1]. تمثل الخلية A1 الأحدث في الزاوية اليسرى العليا. لاحظ أن العنصر هو الخاصية الافتراضية للخلايا في VBA ويمكن حذفه، ولكن لا توجد مثل هذه الراحة في دلفي. لتعيين قيمة لخلية، يجب عليك الرجوع إلى خاصية القيمة الخاصة بها وغني عن القول أن هذه الخاصية هي متغير متغير، على سبيل المثال: wkSheet.Cells.Item[1, 1].Value := 'Address Book'; بالطبع، يمكنك أيضًا تعيين قيمة للخلية. حدد الصيغة: var AFormula:String …… AFormula:='=Rand()'; wkSheet.Range['F3','G6'].Value:=AFormula; الطريقة المذكورة أعلاه مباشرة وبسيطة للغاية، ولكنها بطيئة جدًا وغير مناسبة للتقارير الكبيرة. فهل يمكن نقل جميع البيانات إلى Excel بالتسلسل؟ يمكننا استخدام النطاق. يمثل هذا الكائن منطقة في ورقة العمل عندما نسحبها للخارج، وعادة ما تكون منطقة مستطيلة "،"J42"]. هناك مشكلة صغيرة هنا، لأنه إذا تجاوزت البيانات 26 عمودًا (على سبيل المثال، هناك 100 عمود) أو إذا كان نطاق المنطقة المستهدفة بحاجة إلى تحديد سريع، فسيكون استخدام أسماء الأحرف لتمييز الخلايا أكثر صعوبة. تذكر أنه نظرًا لأن "C3" هو عنوان الخلية، فيمكننا بالطبع استخدام الخلايا أيضًا، مثل Range[Cells.Item[1,1], Cells.Item[100,100]]. من الممكن أن تكون قيمة Range عبارة عن مصفوفة، لكن يجب ألا تستخدم Array في دلفي لتعيين قيمة لها! تذكر أنه في دلفي، تكون قيمة كائن Excel دائمًا من النوع Variant. var Datas: Variant; Ir, ic: Integer …… Datas:= varArrayCreate([1,ir,1,ic],varVariant); عناصر المصفوفة هنا باستخدام wkSheet تفعل Range[cells.Item[3,1],cells.Item[ir+2,ic]].Value:=Datas; تجدر الإشارة إلى أن كلاً من ورقة العمل والنطاق لهما خاصية الخلايا للتوضيح، يتم استخدام العبارة with هنا. بالإضافة إلى ذلك، النطاق اتجاهي. لا يمكن تعيين صفيف أحادي البعد تم إنشاؤه باستخدام VarArrayCreate إلا لنطاق صف واحد. إذا كنت تريد تحديد قيمة لنطاق ذو عمود واحد، فيجب عليك استخدام صفيف ثنائي الأبعاد مثال: Datas:=VarArrayCreate([1,100,1 ,1], varVariant); // إنشاء مصفوفة ديناميكية 100*1. بالمناسبة، Cells.Item[] يُرجع فعليًا كائن Range. استرداد البيانات من ورقة العمل هو في الأساس عملية عكسية لكتابة البيانات، ما يجب الانتباه إليه هو كيفية تحديد نطاق البيانات في ورقة العمل: var ir, ic : Integer …… wkSheet.Cells.SpecialCells(xlCellTypeLastCell,EmptyParam; .Activate ; ir := Excel.ActiveCell.Row ic := Excel.ActiveCell.Column; يتم استخدام وظيفة الخلية الخاصة SpecialCells بذكاء هنا للحصول على الخلية الأخيرة التي تحتوي على البيانات. تحرير البيانات فيما يلي مثالان لتحرير البيانات. var DestRange: OleVariant; begin DestRange := Excel.Range['C1', 'D4']; Excel.Range['A1', 'B4'].Copy(DestRange); إذا قمت بتمرير معلمة فارغة إلى وظيفة النسخ، فسيتم نسخ البيانات الموجودة في هذه المنطقة إلى الحافظة، ويمكن لصقها في مواقع أخرى باستخدام طريقة اللصق لاحقًا. var WS: _Worksheet; …… Excel.Range['A1', 'B4').Copy(EmptyParam); // انسخ البيانات في ورقة العمل إلى الحافظة WS := Excel.Activesheet as _Worksheet; // تغيير ورقة عمل النشاط WS .Range['C1', 'D4').Select; WS.Paste(EmptyParam, EmptyParam, lcid); // الصق محتويات الحافظة في ورقة عمل جديدة إعدادات التنسيق اختر Excel كخادم التقارير بشكل أساسي بسبب إمكانات التنسيق القوية. نقوم أولاً بدمج الخلايا التي تحمل عنوان "دفتر العناوين" ونعرضها في المنتصف، ثم نغير الخط إلى "نص رسمي" مكون من 18 نقطة بالخط العريض: مع wkSheet.Range['A1','D1'],Font ابدأ Merge(True); // دمج الخلايا HorizontalAlignment:= xlCenter الحجم:=18; إذا كان محتوى الخلية طويلاً، فلن يتم عرض جزء من المحتوى. الطريقة المعتادة هي النقر نقرًا مزدوجًا فوق الحافة اليمنى للمنطقة المحددة بحيث يتكيف عرض كل عمود تلقائيًا مع طول المحتوى. في دلفي، يمكن أيضًا تحقيق عرض العمود التكيفي وارتفاع الصف من خلال طريقة الاحتواء التلقائي. تجدر الإشارة إلى أنه لا يمكن استخدام هذه الطريقة إلا للصف بأكمله والعمود بأكمله، وإلا فستتم المطالبة بخطأ رفض تنفيذ طريقة OLE: wkSheet.Columns.EntireColumn.AutoFit؛ تتطلب التقارير ذات النمط الصيني عادةً خطوط جدول علوية وسفلية، ويمكنك استخدام خاصية مجموعة الحدود. تجدر الإشارة إلى أن كائنات المجموعة في VBA عادة ما يكون لها خاصية العنصر الافتراضية، والتي لا يمكن حذفها في دلفي. يتم استخدام خاصية الوزن لتحديد سمك خطوط الجدول: مع Aname.RefersToRange، تبدأ الحدود HorizontalAlignment:= xlRight; Item[xlEdgeBottom].Weight:=xlMedium; Item[xlEdgeTop].Weight:=xlMedium; .الوزن: =xlرفيع؛ item[xlInsideVertical].Weight:=xlThin; يتم تعيين إعداد الصفحة وإعداد صفحة الطباعة من خلال خاصية كائن PageSetUp في ورقة العمل. يوجد أكثر من 40 ثوابت ورقية محددة مسبقًا في Excel VBA. وتجدر الإشارة إلى أن بعض الطابعات تدعم بعض أنواع الورق فقط. يتم استخدام اتجاه السمة للتحكم في اتجاه الطباعة، ويشير المشهد الثابت = 2 إلى الطباعة الأفقية. يتم استخدام الخصائص المنطقية CenterHorizontally وCentreVertically لتحديد ما إذا كان المحتوى المطبوع يتم توسيطه أفقيًا وعموديًا. باستخدام wkSheet.PageSetUp، ابدأ PaperSize:=xlPaperA4; // نوع الورق A4 PrintTitleRows := 'A1:D1'; // كرر هذا الصف/الصفحة LeftMargin:=18; 0.25" سيختلف بين الطابعات TopMargin:=36; //0.5" BottomMargin:=36;//0.5" CenterHorizontally:=True; Orientation:=1; المعلمات الاختيارية، يتم استخدام الأولين لتحديد صفحات البداية والنهاية، وعدد النسخ المطبوعة بالتنسيق الثالث، ومع ذلك، في دلفي، تتم إضافة معلمة LCID في النهاية، ولا يمكن استخدام EmptyParam لهذه المعلمة. . وبالمثل، طريقة معاينة الطباعة PrintPreview لا تحتوي على معلمات في VBA، ولكنها تتطلب معلمتين عند استدعائها في دلفي. // wkbook.printpreview (True ، LCID) ؛ أكثر تعقيدًا ، هو النهج الأفضل هو تسمية نطاقات جدول محددة ثم الرجوع إليها بالاسم. الأسماء هي خاصية كائن جمع من المصنف ، والتي لديها طريقة إضافة يمكنها القيام بهذه المهمة. var aname: excel2000.name ؛ فارغة ، فارغة ParkedParam) ؛ المعلمة الأولى لدالة ADD هي الاسم المحدد ، والمعلمة الثانية هي نطاق الخلية الذي يمثله الاسم. تجدر الإشارة إلى أن نوع المدى يجب أن يستخدم مؤهلًا. بالإضافة إلى ذلك ، يجب أن يستخدم النطاق المسمى المرجع المطلق ، أي إضافة رمز "$". بمجرد تسمية نطاق ، يمكنك الإشارة إليه بهذا الاسم. تعديل برامج الماكرو Excel في Delphi! الرمز التالي ينشئ ماكرو لمصنفنا الذي يسجل آخر وقت عند إغلاق المصنف: Var Lineno: integer ؛ codemodule ؛ SDATE: "تاريخ الوصول الأخير:"+DateToStr () ؛ يضيف الماكرو وحدة إلى قسم الاستخدامات السابقة: VBIDE2000. مفتاح هذا الرمز هو كائن codemodule. لا توفر Delphi4 والإصدارات السابقة Delphi4 كائن Texcelapplication ، ويجب تقديم مكتبة النوع لاستخدام تقنية OLE Automation. الفرق الرئيسي بين هذين الطريقتين هو إنشاء اتصال مع برنامج الخادم ؛ غير معروف) (غير معروف. True ؛ تكلفة سرعة تنفيذ الجزء باستثناء. تجدر الإشارة إلى أن COAPTLICATION المرفق وبعض الأسماء الثابتة التي تم إنشاؤها بواسطة إصدارات DELPHI مختلفة قد تكون مختلفة ، لذلك يجب عليك التحقق من مكتبة النوع المقابل. قبل استدعاء طريقة الإقلاع ، تأكد من إصدار جميع متغيرات المصنف وأوراق العمل التي تم إنشاؤها في البرنامج ، وإلا فقد يقيم Excel في الذاكرة وتشغيله (يمكنك الضغط على Ctrl+Alt+Del للعرض). هناك مشكلة صغيرة في استدعاء GetCiveObject لالتقاط مثيل البرنامج. بالإضافة إلى ذلك ، إذا كنت لا ترغب في تقديم مكتبة من النوع ، فيمكنك أيضًا استخدام الربط المتأخر ، ولكنه أبطأ بكثير. يعلق المثال التالي متغيرًا متغيرًا لتمثيل Excel: متغير ؛ . عند استخدام الربط المتأخر ، لا يتحقق المترجم المستخدمة كما ينبغي. ') ؛ ws : = WBK.Workseets.Item ['sheetname'] ؛ ، يمكنك فقط القيام بذلك بنفسك: const xlwbatworkseet = -4167 ؛ أخيرًا ، لا تنسى إطلاق المتغيرات بعد إغلاق Excel: excel: = غير معروف ؛ الوحدة 1 ؛ تكوين الإجراء (المرسل: الإجراء) ؛ Button1Click (Sender) ؛ wksheet: _Worksheet ؛ صفوف [1] ، 18،061-7557381 '؛ الصفوف [4] ، lcid) ؛ tform1.write2xls ؛ : = 1 إلى الأشعة تحت الحمراء تفعل ل j: = 1 إلى IC تفعل البيانات [i ، j]: stringgrid1.cells [J-1] ؛ .item [3،1] ، cells.item [IR+2 ، IC]]. بيانات: = excel.activecell.column ؛ Datas: = cells.item [1،1] إلى IR-1 do for j: = 0 to IC-1 do cells [j ، i]: = datas [i+1 ، j+1] ؛ DataS: end end ؛ Nameshet aname: = wkbook.names.add ("كتاب العناوين" ، = sheet1! $ 3: $ d $ "، فارغة ، فارغة addformula Apormula: = 'Rand ()' ؛ Font Do Merge (True) ؛ fontstyle: end Bold ؛ العنصر [xlinside ". vbcomponents.item ('ThisWorkbook'). codemodule ؛ : = cm.CreateEventProc ('beforeClose' ، 'Workbook') ؛ "+sdate+" أوراق: = xlpapera4 ؛ Topmargin: = 36 ؛ التوجيه: 1 ؛ ؛ Nameshet.