Tworzenie z Delphi 7 arkusza Excela i łączenie do MSSQLa

0

Chciałbym z poziomu Delphi 7 utworzyć nowy arkusz Excela.
A potem sterując z Delphi Excelem połączyć się do serwera MSSQL i bazy.
Oraz wykonać dość skomplikowane zapytanie SELECT
Nie wiem jak z poziomu Delphi utworzyć to połączenie w Excelu i wpisać zawartość kwerendy SQLa do Excela.

1

Jeśli masz excela zainstalowanego na kompie gdzie będzie twoja aplikacja to:
Ole object
lub
ADO

Następnie z poziomu delphi używając ADO, FIREDAC, UNIDAC lub ZEOSLIB (dowolny framwerok) łączysz się do bazy.

0

Nie wiem czy dobrze opisałem co chcę osiągnąć.
Ja chcę z poziomu Delphi uruchomić arkusz Excela i żeby potem Excel podłączył się bezpośrednio do bazy MSSQL.
Użytkownik zobaczyłby w Excelu kilkadziesiąt tysięcy rekordów wyniku zapytania SQL
Znalazłem w sieci kod włąsciwości połączenia Excela dla VB ""Provider=SQLOLEDB;Data Source=serverName;"Initial Catalog=databaseName;"
Przypuszczam, że musiałbym w Delphi użyć czegoś podobnego dla utworzonego arkusza Excela aby się on podpiął do bazy.
Tylko nie wiem jak to użyć tych parametrów połączenia w Delphi do sterowania Excelem.

1

A po co do tego Delphi, skoro Excel może pobrać dane bezpośrednio z bazy danych?
Odświeżać to i nawet automatycznie łączyć z innymi danymi w skoroszycie.
Nie rozumiem idei...

0

Idea jest taka. W Delphi generuję różne zapytania SQL, czasem bardzo nietypowe z dynamicznie zmienianą zawartością zapytania.
Ale do pokazania większej ilości danych przydaje się Excel.
Próbowałem otwierać bazę MSSQL w Delphi i kopiować 50 tys. wierzy za pomocą schowka do Excela ale to dosć długo trwa.
Gdybym potrafił takie wygenerowane zapytanie SQL wrzucić z poziomu Delphi do Query w Excelu to otwierałoby się to super szybko.
Już od dawna o tym myślałem, ale za słabo znam temat operowania Excelem z poziomu Delphi :(

2

@TomaszNN: przecież można podłączyć arkusz kalkulacyjny do bazy danych.

2

nie wnikałem jak to można zrobić ale jakby ci się nie udało to mam dwie sugestie:

  • zamiast Excela użyć grida w Delphi i pokazać te dane od razu na formatce, chyba że jednak chciałbyś później użyć możliwości Excela po stronie oglądającego wyniki i je formatować itp. to to rozwiązanie odpada,
  • w Excelu użyć prostego połączenia do bazy i w select zamiast tworzyć duże zapytanie użyć widoku, np. "select * from widok" a zawartość tego widoku edytować w delphi (lub od razu w SSMS co pozwoli na łatwe sprawdzenie poprawności przed opublikowaniem). Widoków może być oczywiście dużo różnych a w Excelu można napisać makro do ich przełączania
0

Napiszę jeszcze dokładniej czemu chcę tak nietypowo to rozwiązać.
Mam w Delphi napisaną aplikację. Ona ma dostęp do setek różnorakich zapytań SQL
Gdy użytkownik wybierze w aplikacji interesująco go kwerendę oraz poustawia parametry tej kwerendy.
To chciałbym użyć tego zapytania/ kwerendy w nowo utworzonym w arkuszu Excela.
Taka aplikacja naprawdę ułatwia mi zarządzanie raportami.
Do każdego użytkownika mam w niej przypisane zapytania SQLa.
Użytkownicy nawet ich bezpośrednio nie widzą. Tzn. nie mają podglądu kodu SQLa

@robertz68: "zamiast Excela użyć grida w Delphi i pokazać te dane od razu na formatce,"
Mam dokładnie tak zrobione. Potem eksportuję te dane do Excela przez schowek.
Działa to fajnie dla niewielkiej ilości danych.
Gdy jest więcej to czas kopiowania do Excela wydłuża się.
Dlatego chciałem ten tekst zapytania SQL wrzucić do właściwości połączenia w Excelu.
Tylko nie wiem jak ;)

1

Nie jestem programistą delphi, ale musisz szukać pod nazwą "delphi automate excel" to naprowadzi Cię np. na coś takiego:

https://www.physiologyweb.com/delphi_code_examples/delphi_code_open_modify_save_and_close_an_existing_excel_file.html

Później zostaje tylko korzystanie z obiektów Excela, najprościej nagrywać makra z jakąś operacją i przerobić kod VBA na delphi, przykład stworzenia query i załadowania do arkusza:

Sub Makro1()
'
' Makro1 Makro
'

'
    ActiveWorkbook.Queries.Add Name:="NazwaTabeli", Formula:= _
        "let" & Chr(13) & "" & Chr(10) & "    Źródło = Sql.Database(""NazwaSerwera"", ""NazwaBazy"")," & Chr(13) & "" & Chr(10) & "    dbo_NazwaTabeli = Źródło{[Schema=""dbo"",Item=""NazwaTabeli""]}[Data]" & Chr(13) & "" & Chr(10) & "in" & Chr(13) & "" & Chr(10) & "    dbo_NazwaTabeli"
    ActiveWorkbook.Worksheets.Add
    With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _
        "OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=NazwaTabeli;Extended Properties=""""" _
        , Destination:=Range("$A$1")).QueryTable
        .CommandType = xlCmdSql
        .CommandText = Array("SELECT * FROM [NazwaTabeli]")
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = True
        .ListObject.DisplayName = "NazwaTabeli"
        .Refresh BackgroundQuery:=False
    End With
End Sub

No i trochę dokumentacji Excel:

https://docs.microsoft.com/en-us/office/vba/api/excel.queries.add
https://docs.microsoft.com/en-us/office/vba/api/excel.listobjects.add

To powinno Cie naprowadzić na rozwiązanie problemu

0
var
  Excel: OLEVariant;
  IWorkbook: OLEVariant;
  ISheet: OLEVariant;
  connstring:OleVariant;
begin
  Excel := CreateOleObject('Excel.Application');
  try
    //trzeba wczesniej utworzyc DSN
    connstring:='ODBC;DSN=Tom;UID=Marko;Trusted_Connection=Yes;APP=Microsoft Office;WSID=KOMP667;DATABASE=BAZA_RAP;';
    Excel.DisplayAlerts := False;
    Excel.ScreenUpdating := true;
    Excel.SheetsInNewWorkbook := 1;
    IWorkbook := Excel.Workbooks.Add;
    ISheet := IWorkbook.Sheets[1];
    ISheet.QueryTables.Add(connstring, ISheet.Cells[1,1],Sql:='SELECT * FROM RAPORTY');
    Excel.Visible := True;
    Excel:=null;
  except
    Excel.quit;
    raise;
  end;

Powyższy kod otwiera mi Excela i tworzy połączenie.
Tylko trzeba mieć zdefiniowane wcześniej to DSN.
No i nie wyświetlają mi się jeszcze te dane :(

0

Czytaj dokumentacje, musisz wywłoać refresh https://docs.microsoft.com/en-us/office/vba/api/excel.querytable.refresh

0

Ogólnie działa z prostą kwerendą.
Gdy wrzuciłem taką co liczy kilkaset linii to już niestety nic się nie dzieje.
Problem jest gdy używam ODBC
Gdy dodaję kwerendę z ręki do Excela przez OLEDB to chodzi
Nie mam pojęcia czemu.

0
TomaszNN napisał(a):

Ale do pokazania większej ilości danych przydaje się Excel.

To twoje Delphi ma wycięty silnik do raportów?

0

W excelu nagraj sobie makro jak pobierasz dane i odtwórz w delphi

0
    With ActiveWorkbook.Connections("ANA2 master").OLEDBConnection
        .BackgroundQuery = True
        .CommandText = Array( _
        "SELECT " & Chr(13) & "" & Chr(10) & "     TOP 100 *" & Chr(13) & "" & Chr(10) & "  FROM [Customer]")
        .CommandType = xlCmdSql
        .Connection = Array( _
        "OLEDB;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=master;Data Source=ANA2;Use Proce" _
        , _
        "dure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=KK-188;Use Encryption for Data=False;Tag with column colla" _
        , "tion when possible=False")
        .RefreshOnFileOpen = False
        .SavePassword = False
        .SourceConnectionFile = ""
        .SourceDataFile = ""
        .ServerCredentialsMethod = xlCredentialsMethodIntegrated
        .AlwaysUseConnectionFile = False
    End With
    With ActiveWorkbook.Connections("ANA2 master")
        .Name = "ANA2 master"
        .Description = ""
    End With
    Application.CutCopyMode = False
    With ActiveSheet.ListObjects.Add(SourceType:=4, Source:=ActiveWorkbook. _
        Connections("ANA2 master"), Destination:=Range("$A$1")).TableObject
        .RowNumbers = False
        .PreserveFormatting = True
        .RefreshStyle = 1
        .AdjustColumnWidth = True
        .ListObject.DisplayName = "Table_master_Query"
        .Refresh
    End With

Jest szansa by to odtworzyć w Delphi 7 ??

0

@TomaszNN: ADO --> ADOConnection --> buduje połączenie poszukaj u nas 4programmers tej tematyki

3

@TomaszNN: przecież w pierwszym komentarzu podałem Ci gotowe rozwiązanie obu problemów ... Ole.Object tworzy Ci fizycznie arkusz kalkulacyjny, którym zarządzasz z poziomu delphi. ADO (lub inny framework do bazy) tworzy ci połączenie z MSSQL. Nie musisz połączenia do bazy robić po stronie arkusza skoro i tak zarządzasz excelem z poziomu delphi.

Mało tego z tego co rozumiem chcesz na podstawie zapytania z aplikacji, przekazanego do bazy pobrać rekordy i zapisać je do excela. Jeśli dysponujesz Delphi + FastReport to możesz całkowicie olać excela i przygotować sobie szablon, który łyknie dane z bazy i wyeksportuje je do excela. (choć FastReport chyba jest płatny - choć pewności nie mam)

3

export do XLSX możesz też wykonać za pomocą ZEXMLSS

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