Access

  MS Access 2010+  |  Przetwarzanie plików  |   VBA 7.0



• Przetwarzanie plików.

„Przetwarzanie plików” - moje skromne uwagi.

Dla mnie szerokie zagadnienie „Przetwarzanie plików” jest zbyt szerokie by je opisać. Mnie praktycznie interesuje dostęp do plików w trybie odczytu i zapisu do plików binarnych. Dlatego też większość przykładów dotyczyć będzie odczytu i zapisu 24 bitowych bitmap *.bmp.
Pliki tekstowe stałej szerokości mnie nie interesują. Jeżeli chodzi o pliki tekstowe to spróbuję ułatwić sobie pisanie stron z przykładami - pliki *.html. Być może plik CSV jest godzien uwagi, ale MS Access dostarcza narzędzi do odczytu i zapisu tego typu plików. Nie mniej jednak sam zapis i odczyt pliku CSV jest prosty (czytaj nie jest mocno skomplikowany) więc być może stworzę jakiś przykładzik.

O pliku XML może będzie kiedyś. Temat ten zacząłem dość dawno temu, ale nie wiem kiedy temat uznam za skończony. Wstępnie opracowane dwa przykłady znajdują się na stronach:

  • Plik WMRODZ.xml zawiera wykaz rodzajów miejscowości i ich identyfikatorów
  • Plik TERC.xml zawiera wykaz identyfikatorów i nazw jednostek podziału terytorialnego

następne dwa przykłady są gdzieś na dysku

  • Plik SIMC.xml zawierający zbiór identyfikatorów i nazw miejscowości
  • Plik ULIC.xml zawierający zbiór identyfikatorów i nazw ulic.

ale dużo wody upłynie zanim przykłady te ujrzą światło dzienne .

Funkcja sprawdzająca argumenty otwarcia pliku.

Przed pobraniem zawartości pliku do zmiennej typu String bądź tablicy bajtów, lub zapisem danych do pliku powinniśmy wcześniej sprawdzić, czy operacja odczytu/zapisu jest możliwa. Wystąpić może kilka różnych przyczyn, które uniemożliwią nam odczytanie danych z pliku lub zapisanie danych do pliku.

Otwarcie pliku.

Plik możemy otworzyć za pomocą instrukcji Open opisanej na stronie Plik. Instrukcja Open.
W przypadku operacji odczytu danych z pliku, warunkiem koniecznym jest by plik istniał. Możemy to sprawdzić w bardzo łatwy sposób za pomocą wbudowanej funkcji Dir:

If Len(Dir(sFilePath)) > 0 Then => plik istnieje

  • W przypadku gdy plik sFilePath nie istnieje, a my chcemy wykonać operację
  • odczytu danych z nieistniejącego pliku, to za pomocą metody Raise obiektu Err powinniśmy wygenerować wtedy błąd wykonania o numerze 53 (File Not found), który będziemy musieli potem obsłużyć.
  • zapisu danych do pliku sFilePath, a plik nie istnieje, to plik zostanie utworzony jeśli tryb otwarcia pliku będzie typu Append, Binary, Output lub Random.

Aby sprawdzić, czy możemy odczytywać dane z pliku sFilePath spróbujmy go otworzyć w trybie dostępu binarnym (Binary) i do odczytu (Read).

Open sFilePath For Binary Access Read As #ff
    ' nie rób nic
Close #ff

Aby sprawdzić, czy możemy zapisywać dane do pliku sFilePath spróbujemy go otworzyć w trybie dostępu binarnymBinary do zapisu (Write).

Open sFilePath For Binary Access Write As #ff
    ' nie rób nic
Close #ff

  • Jeżeli otwierany w trybie do „Zapisu” plik ma ustawiony atrybut vbReadOnly generowany jest błąd wykonania o numerze 75 (Path/File access error). W takim przypadku nie będziemy mogli zapisać danych do takiego pliku.
  • Jeżeli otwierany do „Odczytu” lub „Zapisu” plik został wcześniej otwarty przez inny proces „Na wyłączność”, generowany jest błąd wykonania numerze 70 (Permission denied). W takim przypadku nie będziemy mogli odczytać, ani zapisać danych do takiego pliku.
  • Gdy otwierany plik został wcześniej otwarty przez inny proces, a podany tryb dostępu jest niedozwolony generowany jest błąd nr 55 (File already open). Dotyczy to trybu otwarcia pliku AppendOutput, dla których plik otwarty z innym numerem należy zamknąć.

Dodatkowe argumenty funkcji sprawdzającej

Aby uzyskać potrzebne dane z pliku, nie musimy odczytywać bezpośrednio całej zawartości pliku i ją przetwarzać w celu uzyskania potrzebnych danych. Dane z pliku możemy pobrać jednorazowo określając:

  • numer początkowego bajtu, znaku lub linii, od którego ma być dokonana operacja odczytu,
  • ilość bajtów, znaków, linii które mają być pobrane,
  • oraz w niektórych przypadkach powinniśmy określić znak końca linii. Dopuszczalny jest znak Chr$(13) lub vbNewLine (Chr$(13) & Chr$(10).

Pomocnicza funkcja sprawdzająca poprawność argumentów funkcji odczytujących i zapisujących dane do pliku.

⊗Public Function plikCheckArguments(ByVal sFilePath As String, _
                    ByVal fToWrite As Boolean, _
                    Optional ByVal lStart As Long = 1, _
                    Optional ByVal lCount As Long = -1, _
                    Optional ByVal sCharsEnd As String = vbNewLine, _
                    Optional ByVal sProcName As String = "") As Boolean
  • Pomocnicza funkcja plikCheckArguments (...) sprawdzająca poprawność argumentów funkcji odczytujących i zapisujących dane do pliku.
  • argumenty:
    • sFilePath
    • pełna ścieżka do pliku, na którym będzie wykonywana operacja zapis lub odczytu
      • dla operacji „Odczytu” plik sFilePath musi istnieć, w przeciwnym wypadku generowany jest błąd wykonania o numerze 53 (File Not found)
      • dla operacji „Zapisu” plik sFilePath nie może mieć atrybutu vbReadOnly. Gdy ma ustawiony atrybutu vbReadOnly, generowany jest wtedy błąd wykonania o numerze 75 (Path/File access error).
      • gdy plik sFilePath jest otwarty przez inny proces „Na wyłączność”, generowany jest błąd wykonania o numerze 70 (Permission denied)
      • gdy plik sFilePath został wcześniej otwarty przez inny proces, a podany tryb dostępu jest niedozwolony generowany jest błąd nr 55 (File already open). Dotyczy to trybu otwarcia pliku AppendOutput, dla których plik otwarty z innym numerem należy zamknąć.
    • fToWrite
    • argument określa tryb w jakim ma być otwarty plik sFilePath. Dla wartości True plik ma być otwarty w trybie „Do zapisu”. Dla wartości False plik ma być otwarty w trybie „Do odczytu”.
    • lStart
    • Domyślna wartość = 1. Numer początkowego bajtu (znaku, linii) od którego ma być dokonana operacja odczytu lub zapisu, Dla wartości argumentu lStart < 1 generowany jest błąd wykonania o numerze errInvalidStart = vbObjectError + err_plikError + 1, (err_plikError = 100)
    • lCount
    • Domyślna wartość = - 1. Ilość bajtów (znaków, linii) do operacji odczytu lub zapisu. Dla domyślnej wartości = -1 odczytane zostaną wszystkie bajty, (znaki, linie) od pozycji lStart. Wartość argumentu nie może być mniejsza od -1, ani równa Zero. Generowany jest wtedy błąd wykonania o numerze errInvalidCount = vbObjectError + err_plikError + 2, (err_plikError = 100)
    • sCharsEnd
    • argument nieobowiązkowy. Domyślna wartość = vbNewLine. Znak określający koniec linii. Dopuszczalny jest znak Chr$(13) lub vbNewLine (Chr$(13) & Chr$(10). Ewentualnie (przy zapisie) ciąg zerowej długości "". Dla innych wartości argumentu sCharsEnd generowany jest błąd wykonania o numerze errInvalidEnd = vbObjectError + err_plikError + 3, (err_plikError = 100)
    • sProcName
    • argument nieobowiązkowy. Domyślna wartość = "". nazwa funkcji wywołującej. W przypadku wywołania (wystąpienia) błędu przekazywana jest jako argument Source := sProcName metody Err.Raise. Jeżeli nazwa funkcji wywołującej nie zostanie przekazana, wartość argumentu sProcName ustawiana jest na nazwę bieżącej funkcji sProcName = conProcName, gdzie stała conProcName = "Funkcja plikCheckArguments(...)"
  • zwraca:
  • Przy powodzeniu zwraca True.
  • autor: Zbigniew Bratko
  • data: 11.01.2018
Option Compare Database
Option Explicit
 
'dolna granica zakresu numerów błędów dotyczących plików
Public Const err_plikError          As Long = 100
 
' plik nie istnieje
Public Const errFileNotFound     As Long = 53  ' File not found
' plik otwarty przez inny proces; podany tryb dostępu jest niedozwolony
Public Const errFileAlreadyOpen  As Long = 55  ' File already open
' Dostęp zabroniony. Plik został otwarty przez inny proces "Na wyłączność"
Public Const errPermissionDenied As Long = 70  ' Permission denied
' Plik ma ustawiony atrybut vbReadOnly. Nie jest możliwy zapis
Public Const errReadOnly         As Long = 75  ' Path/File access error
 
' Numer początkowy bajtu (znaku, linii), nie może być mniejszy niż 1
Public Const errInvalidStart     As Long = vbObjectError + err_plikError + 1
' Ilość bajtów (znaków, linii) do operacji odczytu lub zapisu
' nie może być mniejsza od -1, ani równa Zero
Public Const errInvalidCount     As Long = vbObjectError + err_plikError + 2
' Dopuszczalny jest znak Chr$(13) lub vbNewLine (Chr$(13) & Chr$(10).
' Ewentualnie (przy zapisie) ciąg zerowej długości ""
Public Const errInvalidEnd       As Long = vbObjectError + err_plikError + 3


Public Function plikCheckArguments(ByVal sFilePath As String, _
                    ByVal fToWrite As Boolean, _
                    Optional ByVal lStart As Long = 1, _
                    Optional ByVal lCount As Long = -1, _
                    Optional ByVal sCharsEnd As String = vbNewLine, _
                    Optional ByVal sProcName As String = "") As Boolean

On Error GoTo Err_Handler
Dim ff                    As Integer
Const conProcName         As String = "Funkcja plikCheckArguments(...)"
    
    
  ' nazwa funkcji wywołującej nie została przekazana,
  ' ustaw nazwę na bieżącą funkcję
  If Len(sProcName) = 0 Then sProcName = conProcName
  
  ' jeżeli odczytujemy dane z pliku, to plik musi istnieć
  If fToWrite = False And Len(Dir(sFilePath)) = 0 Then
    Err.Raise errFileNotFound
  End If

  ' sprawdź numer początkowy bajtu (znaku, linii) do odczytu
  If lStart < 1 Then Err.Raise errInvalidStart
  
  ' sprawdź poprawność ilości bajtów (znaków, linii) do odczytu
  If lCount = 0 Or lCount < -1 Then Err.Raise errInvalidCount
  
  ' sprawdź poprawność znaku końca linii
  If Len(sCharsEnd) > 0 Then
    If Not (sCharsEnd = Chr$(13) Or sCharsEnd = vbNewLine) Then
      Err.Raise errInvalidEnd
    End If
  Else
    ' przy odczycie, końcem linii nie może być ciąg zerowej długości
    If fToWrite = False Then Err.Raise errInvalidEnd
  End If

  ' plik istnieje - spróbuj go otworzyć do odczytu lub zapisu
  ' gdy wystąpi błąd, zostanie on obsłużony w kodzie obsługi błędów
  If Len(Dir(sFilePath)) > 0 Then
    ff = FreeFile
    If fToWrite = True Then
      Open sFilePath For Binary Access Write As #ff
     Else
      Open sFilePath For Binary Access Read As #ff
     End If
      Close #ff
  End If

  plikCheckArguments = True

Exit_Here:
  Exit Function

	Err_Handler:
  Select Case Err.Number
    Case 0 ' nie ma błędu
    Case errFileNotFound
      Err.Raise errFileNotFound, sProcName, _
                "Plik " & sFilePath & "nie istnieje !"
    Case errFileAlreadyOpen
      Err.Raise errFileAlreadyOpen, sProcName, _
                  "Plik " & sFilePath & vbNewLine & _
                  "jest otwarty przez inny proces !"
    Case errPermissionDenied
      Err.Raise errPermissionDenied, sProcName, _
                  "Brak dostępu do pliku " & sFilePath & vbNewLine & _
                  "Plik jest otwarty na wyłączność !"
    Case errReadOnly
      Err.Raise errReadOnly, sProcName, _
                  "Nie można zapisywać danych do pliku" & sFilePath & vbNewLine & _
                  "Plik jest tylko do odczytu !"
    Case errInvalidStart
      Err.Raise errInvalidStart, sProcName, _
                  "Niewłaściwa wartość argumentu lStart." & vbNewLine & _
                  "Prawidłowo: [lStart] > 0"
     Case errInvalidCount
      Err.Raise errInvalidCount, sProcName, _
                  "Niewłaściwa wartość argumentu lCount." & vbNewLine & _
                  "Prawidłowo: [lCount = -1] lub [lCount > 0]"
     Case errInvalidEnd
       Err.Raise errInvalidEnd, sProcName, _
                  "Niewłaściwa wartość argumentu sCharsEnd." & vbNewLine & _
                  "Znakiem końca linii może być:" & vbNewLine & _
                  " • vbCr = Chr(13)" & vbNewLine & _
                  " • vbCrLf = Chr(13) & Chr(10)" & vbNewLine & _
                  " • vbNewLine" & vbNewLine & _
                  " • "" "" - ciąg zerowej długości (tylko przy zapisie do pliku)."
    Case Else
      Err.Raise Err.Number, sProcName, _
                "Nieprzewidziany błąd!" & vbNewLine & _
                Err.Description
  End Select
Resume Exit_Here

End Function