Zmianie uległ w zasadzie connection string oraz zapytanie SQL. Potrzeby okazał się też plik Schema.ini. Plik ten mówi bibliotece ADO w jaki sposób ma interprewtować dane zawarte w pliku tekstowym. jak wiadomo niektóre pliki są rozdzielane znakiem średnika, inne przecinkiem a jeszcze inne za pomocą tabulatora. Dodatkowo w tym pliku możemy określić typ danych oraz nazwy importowanych kolumn.
UWAGA: Informacje z tego pliku są wykorzystywane między innymi w momencie importu danych do Excel-a za pomocą kreatora importu danych zewnętrznych.
Sub Raport(Target As Range, SQL As String, Optional Name) Dim sConn As String Dim sPath As String Dim sName As String Dim qt As QueryTable Dim wks As Excel.Worksheet If IsMissing(Name) Then ' sprawdź czy taki obiekt nie istnieje sName = "Lista" Else sName = CStr(Name) End If On Error Resume Next If ThisWorkbook.Names(sName).Name <> "" Then If Err.Number = 0 Then sName = sName & "_1" End If Err.Clear End If On Error GoTo ERR_Handler: ' ścieżka do pliku roboczego sPath = "E:\test\" ' Connection String sConn = "OLEDB;Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sPath & ";" & _ "Mode=Share Deny None;Extended Properties=""text;HDR=Yes;FMT=Delimited"";" '& _ ' skoroszyt roboczy Set wks = Target.Parent ' sprawdź czy obiekt istnieje If wks.QueryTables.Count > 0 Then ' generuje błąd jak QT nie ma, działanie celowe Set qt = wks.QueryTables(sName) Else ' generuj błąd braku obiektu Err.Raise 9 End If With qt ' tworzymy obiekt QueryTable we wskazanej lokalizacji .CommandType = xlCmdSql ' informacja o tym że korzystamy z polecenia SQL .CommandText = SQL ' Komenda SQL, gdzie [Sheet1$] skoroszytem, po wstawieniu np. [lista] pobieramy dane z zakresu nazwanego .Name = sName ' nazwa obiektu Querytable .Refresh BackgroundQuery:=False 'pobieramy dane End With END_Handler: Exit Sub ERR_Handler: Select Case Err.Number Case 9 ' tworzenie obiektu Set qt = wks.QueryTables.Add(Connection:=sConn, Destination:=Target) Resume Next Case Else MsgBox Err.Description Resume END_Handler: End Select End Sub ' przykład wykorzystania Sub test_2() ' wyswietl elementy ze skoroszytu Sheet1, znak $ konieczny do tego żeby JET wiedział że to cały skoroszyt Raport Sheet3.Range("A1"), "select * from plik#csv where jeszcze_coś_innego > #2009-07-05#", "Wynik_3" End Sub
Przykładowy plik Schema.ini. Zawiera on deklarację dla jednego pliku plik.csv.
[plik.csv] Format=Delimited(;) MaxScanRows=25 CharacterSet=ANSI Col1=Coś Char Col2=coś_innego Char Col3=jeszcze_coś_innego Date
UWAGA: Plik schema.ini musi być w tym samym katalogu co importowany plik tekstowy.
W przypadku gdyby w katalogu znajdowało się wiele plików tekstowych i każdy wymagał by określenia parametrów importu możemy dodać kolejne sekcje. Tak jak w kolejnym przykładzie:
[plik.csv] Format=Delimited(;) MaxScanRows=25 CharacterSet=ANSI Col1=Coś Char Col2=coś_innego Char Col3=jeszcze_coś_innego Date [plik_2.csv] Format=Delimited(;)Nie ma konieczności deklarowania wszystkich parametrów. W przypadku gdy tego nie zrobimy ADO wykorzysta wartości domyślne.
Przykładowy plik (plik.csv) który importowałem:
osoba;miasto;data ala;Łódź;2009-07-01 ola;Warszawa;2009-07-02 jola;Lublin;2009-07-03 ala;Warszawa;2009-07-04 ola;Lublin;2009-07-05 jola;Warszawa;2009-07-06 ala;Lublin;2009-07-07 ola;Warszawa;2009-07-08 jola;Lublin;2009-07-09 ela;Warszawa;2009-07-10
Modyfikacja Connection string-a oraz zapytania SQL polega na tym że nie deklarujemy jawnie nazwy pliku z którego pobieramy dane, deklarujemy tylko katalog. Pliki które znajdują się w tym katalogu traktujemy natomiast jak niezależne obiekty w "bazie danych" i na nich wykonujemy operacje.
UWAGA: zamiast kropki w nazwie pliku stosujemy znak #
Na koniec dodam że w zapytaniach możemy korzystać z pełnego zestawu funkcji dostępnych w dialekcie JET SQL.
Witam,
OdpowiedzUsuńWłaśnie tego szukałem. Pogratulować. Ale jednocześnie nadziałem się na błąd. Co w przypadku jeżeli dane mają wartość ujemną?
Przerobiłem sobie troszku to makro, m.in. po to żeby zaciągał z txt dane. I mam taką strukturę tego pliku:
powierzchnia|zlecenie|wartosc|
0,333|1|5987,52|
0,560-|1|11400-|
0,560|1|10820,5|
I idąc tym przykładem nie zaciąga do Excela wiersza 3 w którym są wartości ujemne. Jak to obejść? Próbuję już na wiele sposobów.
Wydaje mi się że minus powinien być na początku.
OdpowiedzUsuńRozwiązaniem tego problemy było by parsowanie pliku na wypadek wystąpienia minusa i przeniesienie na początek stringu tekstowego
A jak skonstruować zapytanie SQL, by pobierane były rekordy:
OdpowiedzUsuń1. od X do końca oraz
2. od X do Y?
1. sortujesz po kluczu który mówi o kolejności w kolejności odwrotnej i ograniczasz do n elementów za pomocą TOP X
OdpowiedzUsuń2. stosujesz konstrukcję
SELECT TOP 2 * FROM (
SELECT TOP 8 *
FROM Tabela1
ORDER BY Tabela1.Identyfikator
) AS S
ORDER BY S.Identyfikator DESC
gdzie 8 to początek + 2 elementy, trzeba pamiętać że trzeba pobrać elementy z nadmiarem co by móc później obciąć