Nie jestem osobnikiem zbyt wścibskim i nigdy tak naprawdę nie byłem w stanie zrozumieć szaleństwa programów typu "Big Brother", w których podglądactwo z wstydliwej czynności zostało wzniesione na piedestał i okazało się Sztuką (przez wielkie "gie" co prawda, ale jednak sztuka to sztuka).
Niemniej jednak czasami zaglądam w statystyki tego bloga, a już najbardziej interesuje mnie jak ludzie do mnie trafiają (oprócz oczywistej nachalnej reklamy, którą czasem uskuteczniam wśród znajomych, a która całkiem nie działa). Ostatnio uczyniłem na ten temat nawet osobny wpis (tak, ten o karaluchach, sklepowej defekacji i usuwaniu ludzi), dziś natomiast wychodzę naprzeciw tym rzeszom przypadkowych szukaczy Wiedzy, którzy trafili do mnie za okruchami informacji o czytaniu z pliku w VBA.
Najpierw opis problemu, który próbujemy rozwiązać: chcemy napisać funkcję VBA, która, użyta w arkuszu, dla zadanego pliku tekstowego wyświetli podstawowe informacje statystyczne dotyczące tego pliku. W naszym przypadku, żeby zmieścić się w kategorii "pchełki", ograniczymy się do policzenia linii i znaków w pliku. Jak ktoś chce, niech sobie rozbuduje ten kod o liczenie słów, akapitów, imiesłowów bądź paraleli - sky is the limit, jak mówią lokalni.
Podam dwa rozwiązania, obydwa identyczne funkcjonalnie, pierwsze "nieeleganckie", używające wyłącznie standardowych, wbudowanych w VBA funkcji operacji na plikach, oraz drugie, "porządne", oparte o bibliotekę Microsoft Scripting Runtime (a więc bardziej "nowoczesne", chociaż tak naprawdę wcale nie lepsze).
Rozwiązanie 1:
Public Function GetFileStats(strFileName As String) As String
Dim f As Integer, strline As String, lines As Integer, chars As Integer
If Len(Dir$(strFileName)) = 0 Then
GetFileStats = "File '" & strFileName & "' could not be open."
Exit Function
End If
f = FreeFile
Open strFileName For Input As f
Do While Not EOF(f)
Line Input #f, strline
lines = lines + 1
chars = chars + Len(strline)
Loop
Close #f
GetFileStats = "File '" & strFileName & "': " & lines & " line(s), " & chars & " character(s)."
End Function
Rozwiązanie 2:
Public Function GetFileStats2(strFileName As String) As String
Dim fso As New FileSystemObject
Dim lines As Integer, chars As Long, strline As String
On Error GoTo no_file
Set ts = fso.OpenTextFile(strFileName)
On Error GoTo 0
Do While Not ts.AtEndOfStream
strline = ts.ReadLine
lines = lines + 1
chars = chars + Len(strline)
Loop
ts.Close
GetFileStats2 = "File '" & strFileName & "': " & lines & " line(s), " & chars & " character(s)."
endf:
Exit Function
no_file:
GetFileStats2 = "File '" & strFileName & "' could not be open."
Resume endf
End Function
Ponieważ dziś jestem solidnie zmęczony, wyjątkowo nie będę tłumaczył szczegółów obydwu rozwiązań - proszę sobie we własnym zakresie przeanalizować kod, jeżeli ktoś ma jakieś pytania, proszę o komentarz.
Aha, żeby włączyć bibliotekę Microsoft Scripting Runtime należy w edytorze VBA zajrzeć do menu Tools => References, znaleźć na liście pozycję "Microsoft Scripting Runtime" i, za przeproszeniem, postawić przy niej ptaszka. Dzięki temu będzie można tworzyć obiekty typów FileSystemObject czy TextStream, a także na nich operować.
Dobranoc.
a nie powinno być:
Loop
Close #f
–> f = FreeFile
?
FreeFile zwraca pierwszy dostępny identyfikator pliku (liczba, na ogół jedynka, chyba że otwieramy więcej plików na raz). Woła się to na ogół tu przed otwarciem pliku. Wołanie tego po zamknięciu pliku ma sens wyłącznie metafizyczny (o ile za chwilę nie otwieramy kolejnego pliku).
Żadne garbage collectory? destruktory? Nic?
FreeFile zwraca liczbę całkowitą. Open / Close otwiera i zamyka plik (otwarcie pliku "rezerwuje" tą liczbę, zamknięcie ją "zwalnia"). Co byś chciał jeszcze z tą liczbą zrobić, spalić ją komisyjnie w piecu hutniczym?