INI Abschnitt lesen

Einen Abschnitt aus einer INI-Datei lesen

Das Lesen und Schreiben einzelner Werte in einer INI-Datei ist im Vergleich zum Lesen und Schreiben ganzer Abschnitte relativ simpel. Nachfolgend werden wir folgenden beispielhaften Abschnitt aus unserer INI-Datei auslesen:

Abschnitte

Die hierzu notwendige Funktion GetPrivateProfileSection besitzt folgende 4 Argumente:

GetPrivateProfileSection
Argument Bedeutung Beispielwerte
lpAppName Name der Sektion bzw. des Abschnitts Section 01
lpReturnedString Dimensionierte Rückgabestring dimensionierter String
nSize Länge von lpReturnedString Länge des dimensionierter Strings
lpFileName Gültiger Pfad zur INI-Datei C:\WINNT\Dummy.ini

Auch hier dimensionieren wir den Rückgabestring am besten wieder in der Länge der Datei, um unliebsame Überraschungen zu erwarten.

Der Rückgabewert der Funktion GetPrivateProfileSection entspricht der Länge des Rückgabestrings. War dieser String nicht genügend lang dimensioniert, entspricht der Rückgabewert der Längenangabe nSize – 2.

Etwas problematisch stellen sich die Darstellung der unterschiedlichen Schlüssel und deren Werte in einem einzelnen String dar. Diese Werte werden jeweils durch ein Chr(0)-Zeichen voneinander getrennt. Da wir uns auch hier eine Wrapper-Funktion erstellen, sorgen wir auch gleichzeitig für eine komfortable Rückgabe der einzelnen Schlüssel in Form eines Arrays. Da jeder Eintrag aus „Schlüssel=Wert“ besteht, gehen wir einen Schritt weiter und teilen auch diese Information jeweils auf. Dazu benötigen wir eine Struktur bzw. für die Übergabe an die Wrapper-Funktion ein Struktur-Array:

'Struktur-Array
Private Type INI_SECTION_DATA
             sKeyName   As String
             sKeyValue  As String
End Type

Diese Struktur nimmt für jeden Eintrag in der betroffenen Sektion jeweils den Schlüsselnamen und den Schlüsselwert auf. Um alle Schlüssel der Sektion zu berücksichtigen, nutzen wir ein Struktur-Array vom Typ INI_SECTION_DATA.

Mithilfe von VBA 6 (ab Office 2000 verfügbar), würde uns VBA hierbei helfen, da ab dieser Version die Funktion Split zur Verfügung steht, welche einen String anhand eines speziellen Kriteriums aufteilt und in einem Array speichert. Da wir für diesen Workshop die Version VBA 5 berücksichtigen, müssen wir dies selbst erledigen…eine gute Übung um mit Strings zu arbeiten.

Beispiel:

' Section auslesen
Public Function GetMySection(ByVal sIniFilePath As String, ByVal sSection As String, _
                             ByRef ausData() As INI_SECTION_DATA, _
                             ByRef sError As String) As Boolean
 
    Dim lDims       As Long     'Dimensionenzähler für Rückgabe-Array
    Dim lResult     As Long     'API-Rückgabewert
    Dim lLength     As Long     'Dateilänge der INI-Datei
    Dim lOffeset    As Long     'Hilfvariable
    Dim sBuffer     As String   'String für den Rückgabewert
    Dim sRecord     As String   'Daten eines Eintrags (Schlüssel=Wert)
   'Fehlerhandling einschalten, falls es die Datei nicht gibt
    On Error Resume Next
   'Dateilänge ermitteln
    lLength = FileLen(sIniFilePath)
   'Länge (und Fehler) auswerten
    If lLength = 0 Or Err.Number <> 0 Then Exit Function
   'Fehlerhandling wieder ausschalten
    On Error GoTo 0
   'Rückgabe-Array initialisieren
    Erase ausData
   'Rückgabestring dimensionieren
    sBuffer = Space(lLength)
   'API-Funktion ausführen
    lResult = GetPrivateProfileSection(sSection, sBuffer, lLength, sIniFilePath)
   'Rückgabewerte überprüfen
    If lResult > 0 Then
       'Unnötigen 'Anhang' abschneiden
        sBuffer = Left$(sBuffer, lResult)
        While Len(sBuffer) > 0
            lOffeset = InStr(sBuffer, vbNullChar) 'nächstes Trennzeichen ermitteln
            If lOffeset > 0 Then
               'Aktuellen Schlüssel nebst Wert auslesen
                sRecord = Left$(sBuffer, lOffeset - 1)
               'Gesamtstring verkürzen
                sBuffer = Mid$(sBuffer, lOffeset + 1)
               'Dimensionenzähler inkrementieren und Array redimensionieren
                lDims = lDims + 1
                ReDim Preserve ausData(lDims)
               'Schlüssel und Schlüsselwert separat in Struktur schreiben;
               'als Trennzeichen wird "=" vorausgesetzt (Standard bei INI-Dateien)
                ausData(lDims - 1).sKeyName = Left$(sRecord, InStr(sRecord, "=") - 1)
                ausData(lDims - 1).sKeyValue = Mid$(sRecord, InStr(sRecord, "=") + 1)
            End If
        Wend
        GetMySection = True
    ElseIf Err.LastDllError <> 0 Then
       'API-Fehlerbeschreibung ermitteln und zurückgeben
        sError = GetDllErrorDescription(Err.LastDllError)
       'Funktionsrückgabewert setzen
        GetMySection = False
    End If
 
End Function

Als Test für die zuvor beschriebene Funktion dient folgende Routine:

Beispiel:

' Einsatz des Wrappers
Sub INI_Sample3()
 
    Dim sINIPath    As String
    Dim sError      As String
    Dim sOutput     As String
    Dim lLoop       As Long
    Dim ausData()   As INI_SECTION_DATA
 
   'Pfad zum Windows-Ordner ermitteln
    sINIPath = API_GetWindowsDir()
   'Backslash prüfen und ggf. hinzufügen
    If Right$(sINIPath, 1) <> "\" Then sINIPath = sINIPath & "\"
   'Unseren INI-Dateinamen anfügen
    sINIPath = sINIPath & "Dummy.ini"
   'Jetzt können wir die Wrapper-Funktion aufrufen
    If GetMySection(sINIPath, "Section 01", ausData, sError) Then
        For lLoop = LBound(ausData) To UBound(ausData)
            If Len(ausData(lLoop).sKeyName) > 0 Then
                sOutput = "Eintrag " & Str(lLoop) & ": " & _
                           ausData(lLoop).sKeyName & "=" & _
                           ausData(lLoop).sKeyValue
                Debug.Print sOutput
            End If
        Next
    Else
        MsgBox sError
    End If
 
End Sub