Elektroda.pl
Elektroda.pl
X

Search our partners

Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[DELPHI] Eksport danych do Exela

blue_17 21 Jul 2010 12:07 4759 6
  • #1
    blue_17
    Level 32  
    Witam chciałbym eksportować dane z bazy MySQL-owej a konkretnie wyświetlanej tabeli w danym momencie w DBGridzie do Exela

    Ale nie mogę znaleźć kontrolek ExcelApplication i ExcelWorkBook, TExcelapplication ani nawet tych komponentów do zainstalowania bo piszę w delphi 2009

    Znalazłem coś takiego ale niestety 110$

    http://www.scip.be/index.php?Page=ComponentsExcelExport
  • Helpful post
    #2
    saper_2
    Level 18  
    Użyj OLEAutomation , załączam przykładową app którą dawno temu napisałem w ramach "testów" .
    do uses dodajesz ComObj ,a jak byś chciał więcej metod dla obiektów Excela to trzeba szukać to z helpem od VBA. Jak byś był zainteresowany formatowaniem komórek to nagrywasz sobie makro w Excelu potem dajesz wyświetl kod i patrzysz co i jak :) ,aha dołączam też unit ze stałymi do formatowania w Excelu.

    Niestety dużo ci nie pomogę gdyż przeniosłem się na VS C# :)
  • #3
    blue_17
    Level 32  
    Witam porady kolegi za bardzo mi nic nie dały ponieważ chciałem to w jak najprostszy sposób wykonać eksport tabeli wyświetlanej w DBGridzie do nowo otwartego arkusza Excela

    Pobrałem komponent

    http://www.scip.be/index.php?Page=ComponentsExcelExport

    I niestety nie wiem jak to ugryźć

    Połączenie z bazą MySQL-ową tworzę za pomocą elementów
    Code:

    SQLConnection1 -> SQLDataSet1 -> DataSetProvider1 -> ClientDataSet1 -> DataSource1 -> DBGrid1

    W moim programie wyświetlanie tabeli w DBGridzie realizuje w tensposób


    Code:
    procedure TForm1.sComboBox1Change(Sender: TObject);
    
    begin

      if SQLDataSet1.Active then SQLDataSet1.close;       // jesli SQLDataSet1 wlaczony to wylacz         // uaktualnianie DBGrida
      if ClientDataSet1.Active then ClientDataSet1.Close; // jesli ClientDataSet1 wlaczony to wylacz

    try

        SQLConnection1.DriverName := 'MySQL';                  //
        SQLConnection1.GetDriverFunc := 'getSQLDriverMYSQL';   //  Parametyry do DRUGIEGO
        SQLConnection1.LibraryName := 'dbxmys.dll';            //         połączenia
        SQLConnection1.VendorLib := 'libmysql.dll';            //


        SQLConnection1.Params.Values['Database']:= Form2.Edit1.text;  // pobierz nazwe bazy z Form2.Edit1
        SQLConnection1.Params.Values['User_Name']:= Form2.Edit2.text; // pobierz nazwe użytkownika z Form2.Edit2
        SQLConnection1.Params.Values['Password']:= Form2.Edit3.text;  // pobierz hasoł z Form2.Edit3
        SQLConnection1.Params.Values['HostName']:= Form2.Edit4.text;  // pobierz  nazwe hosta z form2.Edit4

        SQLDataSet1.CommandText := 'SELECT * FROM '+ sComboBox1.Items[sComboBox1.ItemIndex]; // wyswietl zawartosc tabeli wskazanej w comboboxsie


        SQLDataSet1.Active := true;       // wlacz SQLDataSet1
        ClientDataSet1.Active := true;   // wlacz ClientDataSet1
        sButton1.Enabled := True;       // uaktywnij przycisk      // uaktualninie DBGrid-a


        dopasuj_komurki; // dopasuj komórki

        except  // jeśl  nie można wyświetlić zawartości tabeli pokarzkomunikat

        raise Exception.Create('Nie można wyświetlić zawartości tabeli');

    end;
    end;



    Niestety próbując w taki sposób

    Code:

    SQLDataSet1.Open;
    scExcelExport1.Dataset:=Table1;
    scExcelExport1.ExportDataset;
    scExcelExport1.Disconnect;


    wyskakuje mi błąd

    Code:
    Dataset is not active


    Przykładowy kod programu demo znajduje się w załączniku a ja nie wiem jak to ugryźć
  • Helpful post
    #4
    saper_2
    Level 18  
    SQLDataset1 jest zamykany w momencie w którym otwierasz ClientDataSet (dzieje się to auto) , poza tym dobrym nawykiem jest sprawdzanie czy dataset (ogólnie rzecz biorąc komponent) jest w ogóle otwarty/aktywny.

    A ja nadal się bym upierał przy Ole, załączam przykładową app (src).
  • #5
    blue_17
    Level 32  
    No cóż respekt dla wiedzy

    Jeszcze chciałem się dowiedzieć jak zrobić aby nagłówki kolumn również znajdował się w arkuszu i jak dopasować szerokość komórek w exelu do długości danych

    Tak rozwiązałem to z dopasowaniem długości komórek do długości danych w DBGridzie, a w exelu nie wiem jak to wykonać.


    Code:
    procedure dopasuj_komurki;
    
    const
      dodatkowa_dlugosc = 10;

    var

      pomoc, n: Integer;
      max_dlugosc: array [0..30] of Integer;

    begin                            // DOPASOWANIE SZEROKOŚCI KOLUMN
        with Form1.SMDBGrid1 do
    begin
        Canvas.Font := Font; //zapamiętanie długości napisów w tytułach kolumn

        for n := 0 to Columns.Count - 1 do
          max_dlugosc[n] := Canvas.TextWidth(Fields[n].FieldName) +  dodatkowa_dlugosc; //jeśli pole jest dłuższe niż długość kolumny, to ustaw nowy max_dlugosc
        Form1.DataSource1.DataSet.First;

        while not Form1.DataSource1.DataSet.EOF do

    begin

        for n := 0 to Columns.Count - 1 do

    begin
        pomoc := Canvas.TextWidth(trim(Columns[n].Field.DisplayText)) +dodatkowa_dlugosc;
        if pomoc > max_dlugosc[n] then max_dlugosc[n] := pomoc;

    end;
        DataSource.DataSet.Next;
    end;

        DataSource.DataSet.First;
        for n := 0 to Columns.Count - 1 do
        if max_dlugosc[n] > 0 then             //ustaw nową szerokość kolumn
        Columns[n].Width := max_dlugosc[n];

    end;
    end;
  • #6
    saper_2
    Level 18  
    W ole to chyba tak byłoby:
    Code:

    sht.Columns['A:A'].EntireColumn.AutoFit; // autofit kolumny A

    A jak chcesz nagłówki to po prostu TField.FieldName albo .Name odzwierciedla nazwę kolumny w tabeli. Wstawiasz je jak dane w pierwszy wiersz ,a dane stawiasz o wiersz dalej :)

    O tak by to wyglądało (pisane z palca :D):
    Code:
    xl := CreateOLEObject('Excel.Application');
    
    wb := xl.WorkBooks.Add;
    sht := wb.Sheets.Add;
    xl.Visible := true;
    xl.DisplayAlerts := true;
    try
       cDataset.First; // sDataset - sqldataset
       // nazwy kolumn
       for i := 0 to cDataSet.FieldCount-1 do sht.Cells[1,i+1].Value := cDataset.Fields[i].Name; // albo FieldName
       // dane
       for i := 1 to cDataSet.RecordCount do begin
          for j := 1 to cDataset.FieldCount do begin
             //sht.Cells[row,col].Value := i; // kolumna A
          sht.Cells[i+1,j].Value := cDataset.Fields[j-1].AsString; // offset o +jeden wiersz
          end;
          cDataset.Next;
       end;
       // autofit kolumn od A do Z
       sht.Columns['A:Z'].EntireColumn.AutoFit;
       ...
       xl := Unassigned;
  • #7
    blue_17
    Level 32  
    Fajnie przepisuje ale nie mogę dojść jak zrobić z tymi nagłówkami tabeli

    Code:
    procedure TForm1.sButton1Click(Sender: TObject);
    
    var
       xl, sht, wb : Variant;
       row,i,j : integer;
       s : string;
    begin
       //Status('Starting M$ Excel...');

          if not SQLDataSet1.Active then begin
             MessageDlg('Dataset not opened.', mtWarning, [mbOK], 0);
             Exit;
          end;

         xl := CreateOLEObject('Excel.Application');
         wb := xl.WorkBooks.Add;
         sht := wb.Sheets.Add;
         xl.Visible := true;
         xl.DisplayAlerts := true;
       try
          //row := 1;
           // Kolumna A: Idx=1 ,B: Idx=2 itd...
           // Wiersz 1: Idx=1, 2: Idx=2 itd...
          SQLDataSet1.First; // sDataset - sqldataset

          for i := 0 to SQLDataSet1.FieldCount-1 do sht.Cells[1,i+1].Value := SQLDataset1.Fields[i].Name;


          for i := 1 to SQLDataSet1.RecordCount do begin
             for j := 1 to SQLDataSet1.FieldCount do begin
           sht.Cells[i,j].Value := SQLDataSet1.Fields[j-1].AsString;


            sht.Cells[i+1,j].Value := SQLDataset1.Fields[j-1].AsString; // offset o +jeden wiersz



             end;
             SQLDataSet1.Next;
          end;
       finally
          //Status('OK');
         end;
     
      sht.Columns['A:CV'].EntireColumn.AutoFit; // autofit 100 kolumn
       xl := Unassigned;
    end;