Eksport z DBGrid do Access-a

0

Witam

Mam pytanie czy Delphi ma jakiś wbudowany element do eksportu danych z DBGrida do Accessa ?

Bo chciał bym dodać taką funkcję do mojego programu

A może dane można w inny sposób eksportować z użyciem SQL-a ?

Znalazłem sposób aby przenosić dane z Accessa do Excel-a ale to mi to nie dało.

0
blue_17 napisał(a)

Witam

Mam pytanie czy Delphi ma jakiś wbudowany element do eksportu danych z DBGrida do Accessa ?

Powtórzę to jeszcze raz za kolegami - DBGrid NIE PRZECHOWUJE DANYCH !!!

0

Dziękuję za odpowiedź

Mam następujące połączenia w mojej aplikacji

SQLConnection1 -> DataSetProvider -> ClientDataSet -> DataSource -> DBGird

Czy teraz mógł by mi kolega doradzić jak za to się zabrać i w takim razie który element przechowuje dane

0

Po prostu przekopiować dane z bazy MySQL do bazy Accessa.

  1. Połączenie z bazą MySQL już masz.
  2. Utworzyć drugie połączenie z bazą Accessa (o ile się nie mylę, chyba można za pomocą komponentów ADO).
  3. Pobierasz rekord z MySQL i dodajesz do Accessa (robisz to w pętli)
 MySQL.DataSource.First
 for i = 0 to MySQL.DataSource.RecordCount - 1 do
 begin
    Access.DataSource.Append;
    MySQL.DataSource.Next;
 end

Coś w tym stylu.
Ten kod oczywiście nie zadziała, to jest tylko zarys jak by to miało wyglądać.

0
  1. Dodaj do uses ComObj
  2. Posluz sie OleVariantem do otworzenia Accsessa.
  3. W petli, odnoszac sie do odpowiedniej tabeli w accessie przenies dane z bazy jako string.

W necie na pewno sa konkretne przyklady, ja akurat mam ale w C# jesli chodzi o Accessa.

0

Kolego maciejmt również dziękuje ci za odpowiedź ale jestem początkujący więc najlepiej przemawiają do mnie przykłady :)

Jeśli chodzi o rady kolegi to myślę że znalazłem rozwiązanie na formę wstawiam ADOQuery1 następnie ustawiam jego parametry połączenia a w kodzie zamieszczonym poniżej zmieniam tak aby tworzyć plik accesa, a nie exela.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons,ComObj, DB, ADODB, StdCtrls;

type
  TForm1 = class(TForm)
    ADOQuery1: TADOQuery;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var XApp:Variant;
sheet:Variant;
r,c:Integer;
row,col:Integer;
filName:Integer;
q:Integer;
begin
XApp:=CreateOleObject('Excel.Application');
XApp.Visible:=true;
XApp.WorkBooks.Add(-4167);
XApp.WorkBooks[1].WorkSheets[1].Name:='Sheet1';
sheet:=XApp.WorkBooks[1].WorkSheets['Sheet1'];
  for filName:=0 to AdoQuery1.FieldCount-1 do
   begin
    q:=filName+1;
    sheet.Cells[1,q]:=AdoQuery1.Fields[filName].FieldName;
   end;
for r:=0 to AdoQuery1.RecordCount-1 do
begin
  for c:=0 to AdoQuery1.FieldCount-1 do
  begin
   row:=r+2;
   col:=c+1;
   sheet.Cells[row,col]:=AdoQuery1.Fields[c].AsString;
  end;
  AdoQuery1.Next;
end;
XApp.WorkSheets['Sheet1'].Range['A1:AA1'].Font.Bold:=True;
XApp.WorkSheets['Sheet1'].Range['A1:K1'].Borders.LineStyle :=13;
XApp.WorkSheets['Sheet1'].Range['A2:K'+inttostr(AdoQuery1.RecordCount-1)].Borders.LineStyle :=1;
XApp.WorkSheets['Sheet1'].Columns[1].ColumnWidth:=16;
XApp.WorkSheets['Sheet1'].Columns[2].ColumnWidth:=7;
XApp.WorkSheets['Sheet1'].Columns[3].ColumnWidth:=19;
XApp.WorkSheets['Sheet1'].Columns[4].ColumnWidth:=9;
XApp.WorkSheets['Sheet1'].Columns[5].ColumnWidth:=9;
XApp.WorkSheets['Sheet1'].Columns[6].ColumnWidth:=9;
XApp.WorkSheets['Sheet1'].Columns[7].ColumnWidth:=46;
XApp.WorkSheets['Sheet1'].Columns[8].ColumnWidth:=9;
XApp.WorkSheets['Sheet1'].Columns[9].ColumnWidth:=7;
XApp.WorkSheets['Sheet1'].Columns[10].ColumnWidth:=6;
XApp.WorkSheets['Sheet1'].Columns[11].ColumnWidth:=13;

end;

procedure TForm1.FormActivate(Sender: TObject);
begin
    ADOQuery1.Open;
end;

end.

Największym problemem dla mnie jest edycja aby tworzył mi się plik accessa a nie exela bo z ustanowieniem połączania poradził bym sobie.

Ewentualni prosił bym jeszcze o wyjaśnienie co ustalają w pliku poniższe linie kodu, bo resztę rozumiem

XApp.WorkSheets['Sheet1'].Range['A1:AA1'].Font.Bold:=True;
XApp.WorkSheets['Sheet1'].Range['A1:K1'].Borders.LineStyle :=13;
XApp.WorkSheets['Sheet1'].Range['A2:K'+inttostr(AdoQuery1.RecordCount-1)].Borders.LineStyle :=1;

Dziękuję i pozdrawiam

0

Odpowiedź już dostałeś, ustanawiasz jedno połączenie z MySQL drugie z Access i kopiujesz dane w pętli, po co kombinujesz z Excelem? //Znając życie za jakiś czas zapyta jak eksportować dane do Excela [rotfl]

XApp.WorkSheets['Sheet1'].Range['A1:AA1'].Font.Bold:=True; //w zakresie komórek A1:AA1 pogrubia czcionkę
XApp.WorkSheets['Sheet1'].Range['A1:K1'].Borders.LineStyle :=13; //w zakresie komórek A1:K1 zmienia styl ramki
XApp.WorkSheets['Sheet1'].Range['A2:K'+inttostr(AdoQuery1.RecordCount-1)].Borders.LineStyle :=1; //to samo co wyżej tylko zakres jest od A2 do K[ilośćRekordówWAdoQuery]
0
blue_17 napisał(a)

Największym problemem dla mnie jest edycja aby tworzył mi się plik accessa a nie exela bo z ustanowieniem połączania poradził bym sobie.

  1. Tworzysz sobie pustą bazę w Accesie, odpowiadającą strukturze tej z MySQL i tylko kopiujesz dane.
  2. Jeśli nie chcesz kopiować wszystkich tabel, to tworzysz bazę Accessa bezpośrednio w kodzie i kopiujesz tylko to co jest potrzebne.
  3. A jak utworzyć bazę w kodzie, było szukaj.
  4. I po jakiego grzyba "kombinujesz z Excelem"
0

Witam poszperałem i znalazłem chyba to co chcę zrealizować :)

http://delphi.about.com/od/database/l/aa062601b.htm

Mam tylko pytanie czy zamiast

ADOConnection mogę użyć SQLConnection z mojej aplikacji do połączenia się z bazą ?

Ewentualnie proszę o opinie na temat tego rozwiązania

0
blue_17 napisał(a)

Mam tylko pytanie czy zamiast

ADOConnection mogę użyć SQLConnection z mojej aplikacji do połączenia się z bazą ?

To nawet nie chce się Tobie spróbować czy to zadziała :/

0
Młody napisał(a)

To nawet nie chce się Tobie spróbować czy to zadziała :/

Oczywiście że chce ale dla pewności wole najpierw zapytać bo właśnie w swojej aplikacji łącze się poprzez SQLConnection i jeśli było by to możliwe to by mi to uprościło :)

A wracając do tematu czy to do dobre rozwiązanie ?

0
blue_17 napisał(a)

Oczywiście że chce ale dla pewności wole najpierw zapytać bo właśnie w swojej aplikacji łącze się poprzez SQLConnection i jeśli było by to możliwe to by mi to uprościło :)

A wracając do tematu czy to do dobre rozwiązanie ?

Człowieku, tak to Ty się nic nie nauczysz.

Najpierw sam spróbuj, a jak nie działa to dopiero zadawaj pytanie.

0

A więc wykonałem według instrukcji ale...

W lini

  s:=s + ' ' + AccessType(Items[i]);

Wyrzuca mi błąd

undeclared identifier: 'AccessType'

Sądząc po właściwościach komponentu ADOConnection nie daje on się do połączeń z bazą MySQL-ową raczej przeznaczony jest do baz microsowt-owych

0

Ściągnij sobie kod źródłowy i wtedy zobacz.
W kodzie jest jeszcze jedna funkcja, która nie jest uwzględniona w tutorialu.

0

Popatrzyłem i faktycznie jest dodatkowa funkcja

Niestety bezpośredni po wstawieniu SQLConnection nie mogę połączyć tego elementu z ADOCommand próbowałem również połączyć przez DataSource ale z marnym skutkiem. :-/

0

Dlatego rozwiązanie podałem już wyżej, dwa połączenia, jedno z bazą MySQL, a drugie z bazą Access.

0

Wykonałem połączenie z drugą bazą na razie nie tworze jej w kodzie ale dla pewności wyświetlam jej zawartość w DBGridzie

procedure TForm1.btn1Click(Sender: TObject);
var
 connSTR : string;
begin
 ConnStr:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source="'+Edt1.Text+'";Persist Security Info=False'; // utworzenie opisu połączenia do pliku MDB
 if con1.Connected then con1.Close; //zamykamy poprzednio otwarte połączenie
 con1.ConnectionString:=ConnStr;
 con1.Open; //otwieramy połączenie
 cbb1.Items.Clear;
 con1.GetTableNames(cbb1.Items,false); //pobranie nazw tabeli do ComboBox-a
end;

procedure TForm1.cbb1Change(Sender: TObject);
begin
 tbl1.Close; //zamykamy poprzednio otwartą tabele
 tbl1.TableName:=cbb1.Items[cbb1.ItemIndex]; //podajemy nazwę wybraną w ComboBox-ie
 if tbl1.connection.Connected then tbl1.Open; //otwieramy tabele
end;

I teraz nie wiem co dalej [???]

0
blue_17 napisał(a)

I teraz nie wiem co dalej [???]

Parę postów wyżej napisałem Tobie praktycznie gotowe rozwiązanie, trochę przerobić, dorobić i śmiga.
Poskładaj to wszystko teraz do kupy i pomyśl.

0

Tak to zrobiłem ale nadal nie działa :(

procedure TForm1.Button5Click(Sender: TObject);

var

R : integer;

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


SQLConnection1.DriverName := 'dbxmysql';                  //
SQLConnection1.GetDriverFunc := 'getSQLDriverMYSQL50';    //
SQLConnection1.LibraryName := 'dbxopenmysql50.dll';       //  podmiana biblioteki
SQLConnection1.VendorLib := 'libmysql.dll';


SQLConnection1.Params.Values['Database']:= Form2.Edit4.text;  // pobierz nazwe bazy z Form2.Edit4.text
SQLConnection1.Params.Values['User_Name']:= Form2.Edit1.text; // pobierz nazwe użytkownika z Form2.Edit1.text
SQLConnection1.Params.Values['Password']:= Form2.Edit2.text;  // pobierz haslo z Form2.Edit2.text
SQLConnection1.Params.Values['HostName']:= Form2.Edit5.text;  // pobierz adres bazy z Form2.Edit5.text

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

SQLDataSet1.Active := true;       // wlacz SQLDataSet1
ClientDataSet1.Active := true;   // wlacz ClientDataSet1


for R := 0 to SQLDataSet1.RecordCount -1 do

begin

AdoTable1.Append;
SQLDataSet1.Next;



end;

SQLDataSet1.Close;

end;
0

I nie zadziała :)

blue_17 napisał(a)

for R := 0 to SQLDataSet1.RecordCount -1 do

begin

AdoTable1.Append;
SQLDataSet1.Next;

end;

SQLDataSet1.Close;

end;
</delphi>

dlaczego, wypadało by jeszcze wszystkie dane przepisać z jednej bazy do drugiej, a jak ?

for R := 0 to SQLDataSet1.RecordCount -1 do
begin
   AdoTable1.Append;  
   AdoTable1.FieldByName('nazwa_pola_1').AsString  := SQLDataSet1.FieldByName('nazwa_pola_1').AsString
   AdoTable1.FieldByName('nazwa_pola_2').AsInteger := SQLDataSet1.FieldByName('nazwa_pola_2').AsInteger
   AdoTable1.FieldByName('nazwa_pola_2').AsBool    := SQLDataSet1.FieldByName('nazwa_pola_3').AsBool

   AdoTable1.Post
   SQLDataSet1.Next;
end;

SQLDataSet1.Close;

end;
0
Młody napisał(a)

dlaczego, wypadało by jeszcze wszystkie dane przepisać z jednej bazy do drugiej, a jak ?

</quote>

A jednak błędzik...

for R := 0 to SQLDataSet1.RecordCount -1 do
begin
   AdoTable1.Append;
   AdoTable1.FieldByName('nazwa_pola_1').AsString  := SQLDataSet1.FieldByName('nazwa_pola_1').AsString
   AdoTable1.FieldByName('nazwa_pola_2').AsInteger := SQLDataSet1.FieldByName('nazwa_pola_2').AsInteger
   AdoTable1.FieldByName('nazwa_pola_2').AsBool    := SQLDataSet1.FieldByName('nazwa_pola_3').AsBool

   AdoTable1.Post
   SQLDataSet1.Next;
end;

SQLDataSet1.Close;

end;

błąd do teiści

Missing operator Or semicolon

w linii

AdoTable1.FieldByName('nazwa_pola_2').AsInteger := SQLDataSet1.FieldByName('nazwa_pola_2').AsInteger

Zrobiłem nieco inaczej bo poco mam wiedzieć jak nazywają się pola
ale też wyskakuje mi błąd ale w innej linii

for R := 0 to SQLDataSet1.RecordCount -1 do

   begin


   AdoTable1.Append;
   AdoTable1.FieldByName

   (ADOTable1.FieldDefList[R].Name).Value := ADOTable1.FieldList[R].Value;

   AdoTable1.Post
   SQLDataSet1.Close;

   end;

   SQLDataSet1.Next;

end;

błąd ten sam co u kolegi powyżej tylko że w linii

 SQLDataSet1.Close;

Wydaje mi się że coś nie tak z kolegi przeładowywaniem albo co bardziej prawdopodobne z moim zapisem ?

0

Wiesz co, może zacznij naukę od podstaw, ja nie podałem Tobie gotowego kodu, a jedynie przykład, a Ty wklejasz wszystko na pałę do edytora i chcesz, żeby od razu zadziałało, a komunikat o błędzie jest jednoznaczny :/

0

A na marginesie średnika NIE MA być tutaj ?

AdoTable1.Post

P.S Jestem bardzo początkujący [wstyd]

Zrobiłem to tak...

var

R : integer;

begin
   AdoTable1.Open;

   for R := 0 to SQLDataSet1.RecordCount -1 do

   begin


   AdoTable1.Append;
   AdoTable1.FieldByName

   (ADOTable1.FieldDefList[R].Name).Value := ADOTable1.FieldList[R].Value;

   AdoTable1.Post;
   SQLDataSet1.Next;

   end;

   SQLDataSet1.Close;
   AdoTable1.close;
end;

Niestety teraz otrzymałem komunikat

'Field 'identyfikator' cannot be modified'

Czyli nie mogę edytować nazwy kolumny w tabeli Accessa

0

Przypatrz się temu dokładnie co napisałeś i porównaj z tym co ja Tobie napisałem i znajdź różnicę. :-P

0

Chyba... są postępy

procedure TForm1.Button5Click(Sender: TObject);

var

R : integer;

begin

   ADOTable1.open;

   try

   for R := 0 to SQLDataSet1.RecordCount -1 do

   ADOTable1.Append;
   ADOTable1.FieldByName

   (ADOTable1.FieldDefList[R].Name).Value := ADOTable1.FieldList[R].Value;


   ADOTable1.Post;
   SQLDataSet1.Next;

finally

   SQLDataSet1.Close;

   end;

 end;

Cyba teraz kopiuje ale przy ostatnim rekordzie wyskakuje błąd

List index out of bounds
0

Nic nie kopiuje.
Powiedziałem 'znajdź różnice', a Ty dalej swoje :/

Jak może coś kopiować, jak Ty przepisujesz coś z ADOTable1 do ADOTable1 !!!

0

@blue_17 - zajmij się czymś innym bo programowanie w Twoim wydaniu jest bez sensu
dostałeś praktycznie gotowca, wystarczyło zmienić nazwy pól i uzupełnić średniki (co kompilator Ci grzecznie zasugerował)

for R := 0 to SQLDataSet1.RecordCount -1 do
begin
   AdoTable1.Append;
   AdoTable1.FieldByName('nazwa_pola_1').AsString  := SQLDataSet1.FieldByName('nazwa_pola_1').AsString;
   AdoTable1.FieldByName('nazwa_pola_2').AsInteger := SQLDataSet1.FieldByName('nazwa_pola_2').AsInteger;
   AdoTable1.FieldByName('nazwa_pola_2').AsBool    := SQLDataSet1.FieldByName('nazwa_pola_3').AsBool;
   AdoTable1.Post;
   SQLDataSet1.Next;
end;
   SQLDataSet1.Close;
end;

Teraz znowu kombinujesz jak koń pod górę ale znowu bez sensu

var
   R : integer;
begin
   ADOTable1.open;
try
   for R := 0 to SQLDataSet1.RecordCount -1 do
   ADOTable1.Append;
   ADOTable1.FieldByName
   (ADOTable1.FieldDefList[R].Name).Value := ADOTable1.FieldList[R].Value;
   ADOTable1.Post;
   SQLDataSet1.Next;
finally
   SQLDataSet1.Close;
   end;
 end;

Czym jest u Ciebie R? Licznikiem iterujacym po REKORDACH, dalej próbujesz nim iterować po KOLUMNACH, tylko w bardzo szczególnym przypadku uda się skopiować wszystkie pola, najczęściej jednak nie skopiujesz wszystkiego lub przekroczysz zakres - zależy ile rekordów masz do skopiowania.
Jeżeli już tak chcesz kombinować to potrzebna jest druga pętla.
No i jak kolega wcześniej zauważył kopiujesz do źródłowej tabeli.

0
pytek napisał(a)

najczęściej jednak nie skopiujesz wszystkiego lub przekroczysz zakres - zależy ile rekordów masz do skopiowania.

I to jest dla mnie złota informacja, a teraz garść wyjaśnień

Czy będę wiązał swoją przyszłość z delphi ? Strach o przyszłości mówić ale może faktycznie to nie dla mnie.

Wracając do tematu kompilator wyrzucał błąd odnośnie

AsBool więc zamieniłem na AsBoolean i teraz prawie działa :) alee...

procedure TForm1.Button5Click(Sender: TObject);

var

R : integer;

Begin

for R := 0 to SQLDataSet1.RecordCount -1 do

begin
 try
 SQLDataSet1.open;
 AdoTable1.Append;

 AdoTable1.FieldByName('Nazwisko').AsString := SQLDataSet1.FieldByName('nazwisko').AsString;
 AdoTable1.FieldByName('imie').AsString := SQLDataSet1.FieldByName('adres').AsString;
 AdoTable1.FieldByName('telefon').AsString := SQLDataSet1.FieldByName('password').AsString;

   AdoTable1.Post;
   SQLDataSet1.Next;



   SQLDataSet1.Close;

pętla nie działa bo napotyka no błąd

raised exception class EOleException with message 'Nieznany'

Przeładowywuje tylko pierwszy rekord

0
procedure TForm1.Button5Click(Sender: TObject);
begin
  SQLDataSet1.Open; //otwórz dataset
  SQLDataSet1.First; //przejdź do pierwszego rekordu
  while not SQLDataSet1.EOF do //wykonuj dopóki nie napotkasz końca zbioru
    begin
      AdoTable1.Append; //dodaj pusty rekord
      AdoTable1.FieldByName('Nazwisko').AsString := SQLDataSet1.FieldByName('nazwisko').AsString; //skopiuj dane
      AdoTable1.FieldByName('imie').AsString := SQLDataSet1.FieldByName('imie').AsString;
      AdoTable1.FieldByName('telefon').AsString := SQLDataSet1.FieldByName('telefon').AsString;
      AdoTable1.Post; //zapisz
      SQLDataSet1.Next; //przejdź do następnego rekordu
    end;
  SQLDataSet1.Close; //zamknij dataset - wiwaty, konfetti, brawa
end;
0
pytek napisał(a)
procedure TForm1.Button5Click(Sender: TObject);
begin
  SQLDataSet1.Open; //otwórz dataset
  SQLDataSet1.First; //przejdź do pierwszego rekordu
  while not SQLDataSet1.EOF do //wykonuj dopóki nie napotkasz końca zbioru
    begin
      AdoTable1.Append; //dodaj pusty rekord
      AdoTable1.FieldByName('Nazwisko').AsString := SQLDataSet1.FieldByName('nazwisko').AsString; //skopiuj dane
      AdoTable1.FieldByName('imie').AsString := SQLDataSet1.FieldByName('imie').AsString;
      AdoTable1.FieldByName('telefon').AsString := SQLDataSet1.FieldByName('telefon').AsString;
      AdoTable1.Post; //zapisz
      SQLDataSet1.Next; //przejdź do następnego rekordu
    end;
  SQLDataSet1.Close; //zamknij dataset - wiwaty, konfetti, brawa
end;

Widzę, że kolega już nie wytrzymał :-)

1 użytkowników online, w tym zalogowanych: 0, gości: 1