نقل البيانات من dbgrid إلى Excel
#1
كيف يمكنني نقل البانات من قاعدة بيانات إلى Excel ؟

قبل كل شيء كيف نتصل بالبرنامج EXcel

بكل بساطة عبر المكون TExcelApplication الموجود في الطرف Servers أو Serveurs (النسخة الفرنسية)

خلال عملنا سيكون لدينا
كود :
Table1: TTable;
DataSource1: TDataSource;
DBGird1: TDBGrid;
ExcelApplication1: TExcelApplication

السطرين الأتيين يضافان برمجيا
كود :
Tab: _workbook;
Fuil: _worksheet


وللعلم خانات Excel تدعى [ Range[ i, j حيث i و j عبارة عن مكان الخانة مثل A1، b3

تملء بواسطة دلفي :
كود :
Feuil.Range[A1,A1].Value[xlRangeValueDefault] :='Text to insert';
xlRangeValueDefault : (عبارة عن RangeValueDataType التي تعبر عن نوع المعطيات) ترجع Empty إذا كانت الخانة المعنية فارغة، وإذا Range أخذت أكثر من خانة فيرجع جدول من القيم.
راجع موقع ميكروسوفت
كود :
http://msdn2.microsoft.com/fr-fr/library/microsoft.office.tools.excel.namedrange.value(VS.80).aspx

أولا من DBGrid :

للعمل مع DBGrid يجب أن ننتبه إلى أمرين عنوان و المحتوى

نبدا بالعنوان :
لكي أستطيع استعمال حلقة (لأن كمية المعلومات غير معلومة) سأستعمل جدول يحتوي على الحروف من A حتى Z

كود :
var
  Form1: TForm1;
  
  a:array [1..26]of string[1]=('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','u','V','W','X','Y','Z');

لا ننسى أن نتصل بالبرنامج Excel

كود :
var Tab: _workbook;
    Feuil: _worksheet;
    i,j:Integer; //تسعمل لاحقا j
S:shortstring;//أيضا سنراها لاحقا

begin
ExcelApplication1.Connect;
ExcelApplication1.Visible[0]:=False;
Tab:=ExcelApplication1.Workbooks.Add(xlWBATWorksheet,0);
ExcelApplication1.Visible[0]:=true;
feuil:=Tab.Worksheets[1] as _worksheet;

بعدها نقوم بالآتي:
كود :
For i:=0 to DBGrid1.Columns.Count-1 do begin
  with Feuil.Range[A[i+1]+'1',A[i+1]+'1'] do begin
  Value[xlRangeValueDefault]:= DBGrid1.Columns.Items[i].Title.Caption;

//في مايلي عبارة عن تلوين الخانات وتغيير الخط ...
  Font.Name:='times new roman';
  Font.Size:=10;
  Font.Bold:=True;
   With Interior do begin
        ColorIndex := 15;
        Pattern := xlSolid;
        PatternColorIndex := xlAutomatic;
    End;
  With Borders do begin
        LineStyle := xlContinuous;
        Weight := xlThin;
        ColorIndex := xlAutomatic;
    End;
    end;
end;

الآن ننتقل إلى محتوى DBGrid :


كود :
j:=2;
// نوقف إظهار التغييرات و الانتقالات
TableTemp.DisableControls;
Table1.First;
While not Table1.Eof do begin
  For i:= 1 To  DBGrid1.Columns.Count Do
   begin
   s:=A[i]+inttostr(j);
   Feuil.Range[s,s].Value[xlRangeValueDefault] :=DBGrid1.Fields[i-1].AsString;
   end;
   Table1.Next;
   j:=j+1;
  end;

إذا لاحظت لقد أظهرنا ملف Excel قبل العملية ExcelApplication1.Visible[0]:=true

أي سترى الجدول يمتلء بالبيانات ، أما إذا أردت إخفاء عملية الملء عن المستعمل فقط لا تستدعي الإظهار قبل الانتهاء.

الآن لم يبقى أي شيء مهم، فقط إذا أردت تعديل الخطوط والمساحة

مثلا عند انتهاء العملية سنقوم بالتعديل على طول الخانات للتتناسب و المحتوى

كود :
ExcelApplication1.Cells.Select;
    ExcelApplication1.Columns.AutoFit;
    ExcelApplication1.Range['A1','A1'].Select;

ثم إغلاق الإتصال مع الملف
كود :
ExcelApplication1.Disconnect


ثانيا مباشرة من قاعدة البيانات:

هنا ليس لدينا عناوين وإنما أسماء الحقول

كود :
For i:=0 to Table1.FieldCount-1 do begin
  with Feuil.Range[A[i+1]+'1',A[i+1]+'1'] do begin
   Value[xlRangeValueDefault]:= Table1.Fields.Fields[i].FieldName;   // الخانة تأخذ اسم الحقل
  Font.Name:='times new roman';
  Font.Size:=10;
  Font.Bold:=True;
   With Interior do begin
        ColorIndex := 15;
        Pattern := xlSolid;
        PatternColorIndex := xlAutomatic;
    End;
  With Borders do begin
        LineStyle := xlContinuous;
        Weight := xlThin;
        ColorIndex := xlAutomatic;
    End;
    end;
end;

أما بالنسبة للمحتوى فنقوم بالأتي:

كود :
j:=2;
  Table1.First;
While not Table1.Eof do begin
  For i:= 1 To  Table1.FieldCount Do
   begin
   s:=A[i]+inttostr(j);
   Feuil.Range[s,s].Value[xlRangeValueDefault] :=Table1.Fields.Fields[i-1].AsString;
   end;
   Table1.Next;
   j:=j+1;
  end;

أما الباقي فلا يتغير

لإتمام الفهم أرفقت الملف

ملاحظة : لرؤية الفرق بين العمليتين جرب فقط قاعدة البيانات المرفقة

تحياتي Smile[/COLOR]


الملفات المرفقة
.zip   DB_To_Excel.zip (الحجم : 2.76 ك ب / التحميلات : 2,711)
الرد
#2
بارك الله فيك ، مثال جميل جداً .

استفسار بارك الله فيك .. لو اردت مثلا أن يتم التحديث على نفس النموذج sheet على الاكسل بدون أن يقوم البرنامج بفتح نموذج جديد في كل مرة ، ماهو الجزء الذي اقوم بتعديله في الكود ؟

وكذلك مثلا لو تم اغلاق الاكسل اثناء عملية التحديث أين يكون الكود الخاص exception في دلفي ؟
مع شكري الجزيل على مشاركتك وطرح الراقي.
الرد
#3
و فيك بركة

أولا أحب أن أوضح أن الشرح السابق ليس متكاملا و إنما هو إجابة حسب السؤال.

إقتباس :لدي استفسار بارك الله فيك .. لو اردت مثلا أن يتم التحديث على نفس النموذج sheet على الاكسل بدون أن يقوم البرنامج بفتح نموذج جديد في كل مرة ، ماهو الجزء الذي اقوم بتعديله في الكود ؟

بكل بساطة لا نستدعي ExcelApplication1.Disconnect إلا عندما نريد (مثلا نضعها في OnClose للفورم أو لجدول قاعدة البيانات حسب المبرمج)

(في رأيي) من الأحسن أن لا نصدر البيانات إلا بعد الإنتهاء. لأنه قد يربك المستعمل.

بالنسبة للتحديث لم أفهم ، هل فقط الشكل أم المحتوى ؟؟

الشكل لا يحتاج إلى شرح مثل مل ذكر شابقا

كود :
[COLOR=Black]//في مايلي عبارة عن تلوين الخانات وتغيير الخط ...
  Font.Name:='times new roman';
  Font.Size:=10;
  Font.Bold:=True;
   With Interior do begin
        ColorIndex := 15;
        Pattern := xlSolid;
        PatternColorIndex := xlAutomatic;
    End;
  With Borders do begin
        LineStyle := xlContinuous;
        Weight := xlThin;
        ColorIndex := xlAutomatic;
    End;
    end;[/COLOR]

أما المحتوى:

علمنا من الشرح أنه

Feuil.Range[ 'A'i , 'A'i ].Value[xlRangeValueDefault] = Table1.Fields.Fields[ i+1 ].AsString


هذا إذا علمنا أي الخانات في قاعدة البيانات غيرنا

أو يمكن إعادة العملية من جديد، و التعديل هو لا نتصل ببرنامج Excel بعد الضغط على زر Export وإنما نجعله - مثلا - بعد فتح قاعدة البيانات

كود :
[COLOR=Black]procedure TForm1.Table1AfterOpen(DataSet: TDataSet);
begin
    ExcelApplication1.Connect;
    ExcelApplication1.Visible[0]:=False;
    Tab:=ExcelApplication1.Workbooks.Add(xlWBATWorksheet,0);
    feuil:=Tab.Worksheets[1] as _worksheet;
end;[/COLOR]

هكذا نحتفظ باتصال واحد حتى نهاية التطبيق.

إقتباس :وكذلك مثلا لو تم اغلاق الاكسل اثناء عملية التحديث أين يكون الكود الخاص exception في دلفي ؟

كما قلت أولا : من الأحسن أن لا نصدر إلا البيانات الجاهزة للتصدير.

لكن إذا صادفنا مثل هذا المشكل (مثل تطبيق لتحرير جداول في الوقت الحقيقي - أي المستعمل يرى النتيجة آنيا) يمكن استعمال Try ..Exception في طرفي أي عملية مباشرة الاتصال.

في المثال:

كود :
[COLOR=Black]procedure TForm1.Table1AfterOpen(DataSet: TDataSet);
begin
  [color=Blue]Try[/color]
    ExcelApplication1.Connect;
    ExcelApplication1.Visible[0]:=False;
    Tab:=ExcelApplication1.Workbooks.Add(xlWBATWorksheet,0);
    feuil:=Tab.Worksheets[1] as _worksheet;
  [color=Blue]except[/color]
    on E: Exception do MessageDlg(E.Message,mtError,[mbOK], E.HelpContext);
[color=Blue]  end;[/color]

end;[/COLOR]

عند التصدير (من DBGrid)

كود :
[color=Blue]Try[/color]
[COLOR=Black] Try
  ExcelApplication1.Visible[0]:=true;
  For i:=0 to DBGrid1.Columns.Count-1 do
  begin
    with Feuil.Range[A[i+1]+'1',A[i+1]+'1'] do
    begin
      Value[xlRangeValueDefault]:= DBGrid1.Columns.Items[i].Title.Caption;
      Font.Name:='times new roman';
      Font.Size:=10;
      Font.Bold:=True;
      With Interior do
      begin
        ColorIndex := 15;
        Pattern := xlSolid;
        PatternColorIndex := xlAutomatic;
      End;
      With Borders do
      begin
        LineStyle := xlContinuous;
        Weight := xlThin;
        ColorIndex := xlAutomatic;
      End;
    End;
  End;
  
  j:=2;
  Table1.DisableControls;
  Table1.First;
  While not Table1.Eof do
  begin
    For i:= 1 To  DBGrid1.Columns.Count Do
    begin
      s:=A[i]+inttostr(j);
      Feuil.Range[s,s].Value[xlRangeValueDefault] :=DBGrid1.Fields[i-1].AsString;
    end;
    Table1.Next;
    j:=j+1;
  end;
Finally
  ExcelApplication1.Cells.Select;
  ExcelApplication1.Columns.AutoFit;
  ExcelApplication1.Range['A1','A1'].Select;
End;
[color=Blue]Except[/color]
on E: Exception do MessageDlg(E.Message,mtError,[mbOK], E.HelpContext);[/COLOR]
[color=Blue]End;[/color]

آمل أنني أجبت ، وإذا أي استفتارات أخرى فمرحبا اجيب انا أو غيري لا فرق

كما أن هذه الحلول لا تصلح لنقلها مباشرة للبرنامج. وإنما توضح الوسيلة فقط.، ربما في المستقبل سيكون لنا لقاء ببرنامج من هذه النوعية.

في الأخير ليس إلا حل أراه ، وكل من لديه حل أحسن فليقدمه وسـأكون من الشاكرين

ما الفائدة إذا لم نتبادل الخبرات

تحياتي Smile
الرد
#4
شكرا أخي على المجهود الكبير
هل يمكن عكس العملية
الرد
#5
إقتباس :هل يمكن عكس العملية
طبعا، بنفس الطريقة باستعمال OLE: قراءة/حلقات/إضافة...
يمكن الاتصال بـ Excel من خلال ADO ونسخ البيانات بطريقة أسهل
بعض المحركات تدعم ذلك مباشرة:
كود :
http://support.microsoft.com/kb/321686
الرد
#6
kachwahed كتب :[COLOR=Black]
يمكن الاتصال بـ excel من خلال ado ونسخ البيانات بطريقة أسهل

المسألة تبدو غامضة هل يمكن توضيح الفكرة
الرد
#7
إقتباس :يمكن توضيح الفكرة
مثال بـ ADO
http://www.delphi4arab.net/forum/showthread.php?p=24949
الرد
#8
لقد فهمة الفكرة و أصبحت الفكرة و اضحت تماما
الرد
#9
سلام عليكم
أليكم مثال بسيط عن TscExcelExport
ويمكن تحكم فيexcel عبر خصائص هذه مركب


الملفات المرفقة
.rar   Paradox.Excel.rar (الحجم : 1.94 ك ب / التحميلات : 640)
الرد
#10
سلام عليكم
أليكم table paradox للمثال


الملفات المرفقة
.rar   Paradox.rar (الحجم : 544 بايت / التحميلات : 489)
الرد


التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم