Speichern und Einlesen
von Peter Sauer
Übersicht
Im Tutorial werden verschiedene Methoden für die Speicherung und das Einlesen von Daten aus Text-, List- und Comboboxen sowie 1- und 2-dimensionalen Textarrays aufgezeigt. Verwendet werden u.A. die Funktionen Split und Join, die ab VB6 zur Verfügung stehen. Für VB5 werden Ersatzfunktionen angeboten.
Mit freundlichen Grüßen
Peter Sauer peter.k.sauer@web.de
Allgemeines
Standardvariablen in den Beispielen:
Variable | Typ | Verwendung |
---|---|---|
TxtFile | String | Aufnahme des Dateipfades und -namens |
FNr | Integer | Dateinummer, Zuweisung über FreeFile |
Msg | String | Fehlernummer und -text |
zw | String | Zwischenspeicher beim Einlesen |
TrZ | String | Trennzeichen für Elemente in einem String |
Dateien öffnen und schliessen
Um Zugang zu einer Datei zu erhalten, muss eine Datei geöffnet und nach Benutzung wieder geschlossen werden. Zum Öffnen muss eine Dateinummer zugewiesen werden. Häufig wird #1 benutzt, das ist aber schlechter Stil, wesentlich besser ist die Zuweisung über die Funktion FreeFile. FreeFile weist eine freie Dateinummer zwischen 1 und 255 zu, FreeFile 1 eine Dateinummer zwischen 256 und 511.
FNr = FreeFile Open TxtFile For Input As #FNr Open TxtFile For Output As #FNr Open TxtFile For Append As #FNr Open TxtFile For Binary As #FNr Close #FNr
Listing 1
Anweisung | Methode | Ergebnis |
---|---|---|
Input | Lesen | eine vorhandene Datei wird zum Einlesen geöffnet |
Output | Schreiben | eine bereits existierende Datei wird gelöscht falls vorhanden, eine neue Datei wird zum Schreiben angelegt, der Zeiger steht auf 0 |
Append | Schreiben | ist die Datei vorhanden, wird sie zum Schreiben geöffnet, der Zeiger auf das Dateiende gestellt, sonst wird eine neue Datei zum Schreiben angelegt, der Zeiger steht auf 0 |
Binary | Lesen | und Schreiben ist die Datei vorhanden, wird sie zum Lesen und Schreiben geöffnet, der Zeiger auf das erste Byte gestellt, sonst wird eine neue Datei angelegt, der Zeiger steht auf 0. Ist die Länge des zu schreibenden Textes kleiner als die Dateilänge, wird die Dateilänge beim Überschreiben nicht verändert. In einem derartigen Fall muss die Datei vorher gelöscht werden. |
Dateinamen zuweisen
Eine Datei muss unter ihrem Namen geöffnet werden. Dazu gehört der Pfad mit Laufwerk und der Dateiname. Die Speicherung von Daten aus Text-, List- und Comboboxen erfolgt in aller Regel im Verzeichnis der Applikation, so auch in den vorgestellten Beispielen.
Die Funktion App.Path liefert das Verzeichnis der Applikation, also das Verzeichnis, in dem die Anwendung installiert ist. Leider gibt es da eine Schwäche. Ist die Anwendung im Hauptverzeichnis installiert, liefert die Funktion einen Wert ohne Backslash wie "C:", während bei Installation in einem Unterverzeichnis ein Backslash angehängt wird, wie zum Beispiel "C:\Test\".
In den Beispielen wird daher eine Funktion zur Ermittlung des Applikationsverzeichnisses eingesetzt.
Private Function AppPathGet() As String Dim zw As String zw = App.Path If Right(zw, 1) <> "\" Then zw = zw & "\" End If AppPathGet = zw End Function Dim TxtFile As String TxtFile = AppPathGet & "TextBox.txt"
Listing 2
Ist die Datei vorhanden?
Vor dem Öffnen einer Datei zum Einlesen sollte geprüft werden, ob die Datei überhaupt vorhanden ist. Das geschieht über die Funktion Dir, die normalerweise einen Dateinamen aus einem Verzeichnis liefert. Wenn das gelieferte Ergebnis ein NullString ist, wurde die Datei nicht gefunden.
If Dir(TxtFile) = "" Then Msg = "Datei '" & TxtFile & " nicht gefunden" MsgBox Msg, , "Text einlesen" Exit Sub End If
Listing 3
Ein etwas besseres Beispiel zum Überprüfen, ob eine Datei vorhanden ist. Hier werden alle Dateien ohne Berücksichtigung des Attributes gefunden:
Public Function FileExists(Path As String) As Boolean Const NotFile = vbDirectory Or vbVolume On Error Resume Next FileExists = (GetAttr(Path) And NotFile) = 0 On Error Goto 0 End Function Sub Form_Load() ' Aufruf der Funktion If FileExists("D:\test.txt") Then MsgBox "Vorhanden" End Sub
Listing 4
Error-Routinen verwenden
Beim Arbeiten mit Dateien sollten grundsätzlich Error-Routinen eingesetzt werden. Sie ermöglichen es z.B. ein Programm ordnungsgemäss zu beenden, wenn ein Fehler auftritt. Error-Routinen werden unter VB immer auf Prozedurebene abgehandelt.
Bei On Error GoTo Sprungmarke wird das Programm bei Auftreten eines Fehlers an der Sprungmarke fortgesetzt. Dort können dann über die Funktionen Err.Number und Err.Description Fehlernummer und Fehlerbeschreibung abgerufen werden.
On Error Goto Fehler 'hier folgt der ProgrammCode: Open, Verarbeitung, Close, gefolgt von einem Exit Sub Fehler: Msg = "Fehler: " & Err.Number & vbCrLf & Err.Description MsgBox Msg, , "Einlesen Textdatei"
Listing 5
Was ist eigentlich eine Zeile?
Man sollte meinen, eine Zeile ist der Text auf der gleichen Höhe zwischen dem linken und dem rechten Rand. Früher war das so, seit Erfindung moderner Textverarbeitung mit Fliesstext und automatischem Zeilenumbruch nicht mehr. Da repräsentiert eine Zeile praktisch einen Absatz. Für die Textverarbeitung mit Textboxen spielt das keine Rolle, bei Speicherung von Daten aus List- und Comboboxen sehr wohl.
Zeilen werden durch ein CrLf getrennt, ein CarriageReturn/LineFeed (Wagenrücklauf mit Zeilenschaltung). Bei der Texterfassung wird CrLf (&H0D0A = Chr(13) & Chr(10)) über die Return Taste gesetzt. Bei der Programmierung unter VB gibt es dafür die Konstante vbCrLf oder vbNewLine.
Problematik der letzten Zeile
Beim Schreiben von Texten Zeile für Zeile in eine Datei wird der Inhalt jeder Zeile mit einem CrLf in die Datei geschrieben. Wenn das auch mit der letzten Zeile geschieht, wird eine zusätzliche Leerzeile an die Datei angefügt. Beim Einlesen erhält man dann eine zusätzliche Leerzeile bzw. bei List- und Comboboxen einen Leereintrag. Bei jeder erneuten Speicherung wird eine weitere Zeile angefügt. Man kann das aber verhindern.
Merkmale der verwendeten Schreibmethoden
Achtung: Print Anweisung einmal ohne und einmal mit folgendem Strichpunkt
Anweisung | Open For | Methode |
---|---|---|
Print #FNr, zw | Output oder Append | schreibt den Inhalt der Variablen zw an das Ende der unter FNr geöffneten Datei inkl. einem CrLf |
Print #FNr, zw; | Output oder Append | wie oben aber ohne folgenden CrLf |
Put #FNr, n, zw | Binary | schreibt den Inhalt der Variablen zw ab der Position n in die unter FNr geöffnete Datei |
#FNr, , zw | Binary | wie oben ab dem ersten Byte in der Datei, nur Nutzdaten, also ohne CrLf |
Merkmale der verwendeten Lesemethoden
Anweisung | Open For | Methode |
---|---|---|
Line Input #FNr, zw | Input | liest ab der aktuellen Position der For Input geöffneten Datei (FNr) bis zum nächsten CrLf in die Variable zw ohne den CrLf |
zw = Input(n, #FNr) | Input | liest n Zeichen ab der aktuellen Position in die Variable zw |
zw = Input(LOF(FNr),#FNr) | Input | direkt nach dem Open liest Zeichen in Länge der Datei in die Variable zw. (LOF = Len of File) |
zw = Space(n) Get #FNr, x, zw | Binary | liest ab der Position x in der For Binary geöffneten Datei (FNr) n Zeichen in die Variable zw |
zw = Space(LOF(FNr)) Get #FNr, , zw | Binary | liest ab dem 1. Byte die komplette Datei |
Dimensionierung von lokalen Variablen - Option Explicit
Die erste Anweisung im Programmteil einer Form oder in einem Modul sollte die Anweisung Option Explicit sein. Sie erzwingt die explizite Deklaration von Variablen vor deren Verwendung im Programm. Zu einem guten Stil gehört es auch, den Variablentyp festzulegen.
Option Explicit Dim TxtFile As String Dim FNr As Integer Dim Msg As String
Listing 6
Speichern von Textbox-Texten
Speichern über die Print Methode For Output
Dies ist die gebräuchlichste Art.
FNr = FreeFile Open TxtFile For Output As #FNr 'schreiben Textboxinhalt, der folgende _ 'Strichpunkt verhindert eine Leerzeile am Schluss Print #FNr, Text1.Text; Close #FNr
Listing 7
Speichern über die Print Methode For Append
Methode um bestehende Dateien zu ergänzen, Text anzuhängen
FNr = FreeFile Open TxtFile For Append As #FNr 'Zeilentrenner einfügen wenn Text bereits vorhanden If LOF(FNr) > 0 Then Print #FNr, "" End If 'schreiben Textboxinhalt, der folgende _ 'Strichpunkt verhindert eine Leerzeile am Schluss Print #FNr, Text1.Text; Close #FNr
Listing 8
Speichern über die Put Methode For Binary
Diese Methode ist eigentlich nicht gebräuchlich.
'wenn Datei existiert, löschen If Dir(TxtFile) > "" Then Kill TxtFile End If FNr = FreeFile Open TxtFile For Binary As #FNr 'schreiben Textboxinhalt Put #FNr, , Text1.Text Close #FNr
Listing 9
Speichern Zeile für Zeile
Diese Methode wird in den Beispielen nicht verwendet, da man davon ausgehen kann, dass der Text einer Textbox immer komplett gespeichert wird. Zur Abrundung eine kurze Demo.
'zusätzliche Deklaration dieser Variablen Dim myArray() As String Dim i As Long myArray() = Split(Text1.Text, vbCrLf) FNr = FreeFile Open TxtFile For Output As #FNr For i = 0 To UBound(myArray) - 1 Print myArray(i) Next 'letzte Zeile ohne CrLf Print myArray(i); Close #FNr
Listing 10
Einlesen von Textbox-Texten
Dateilänge überprüfen
Eine Textbox fasst maximal 32.767 Zeichen, das ist die grösste mit einer Integer Variablen darzustellende Zahl. Die Dateilänge sollte daher abgeprüft werden.
If FileLen(TxtFile) > 32767 Then Msg = "Datei '" & TxtFile & " zur gross für Textbox" MsgBox Msg, , "Text einlesen" Exit Sub End If
Listing 11
Die .Sel Eigenschaften der Textbox verwenden
Verwendet werden in den Beispielen die Sel Eigenschaften der Textbox wie .SelLength, .SelStart und .SelText, was den Durchsatz steigert. .SelStart verweist auf die Position des Cursors im Text und repräsentiert eine Zahl zwischen 0 und Textlänge. .SelLength gibt an, wieviele Zeichen markiert sind. .SelText repräsentiert den markierten Text.
LOF(FNr) und EOF(FNr) einsetzen
Die Funktion LOF (Length Of File) liefert nach Öffnen einer Datei die Länge der unter FNr geöffneten Datei.
Die Boolsche Variable EOF (End Of File) signalisiert beim sequentiellen Einlesen einer Datei, ob das Dateiende erreicht ist. Der Versuch über die Dateilänge hinaus einzulesen führt zu einem Fehler.
Zeilenweise einlesen
Das Auslesen Zeile um Zeile aus der Textdatei ermöglichst die kontrollierte Übernahme in eine Textbox. Bei dieser Methode können Teile der Textdatei ausgespart oder nur Teile der Datei übernommen werden.
Bei Übernahme in die Textbox muss an jede Zeile an CrLf angefügt werden, das CrLf für die letzte Zeile ist wieder zu entfernen.
FNr = FreeFile Open TxtFile For Input As #FNr 'auslesen bis zum Dateiende Do While Not EOF(FNr) 'zeilenweise auslesen und übernehmen Line Input #FNr, zw 'optional: überprüfen ob Zeile übernommen werden soll 'If ZeileUebernehmen Then Text1.SelText = zw & vbCrLf 'End If Loop Close #FNr 'den letzten CarriageReturn/LineFeed entfernen If Len(Text1.Text) > 0 Then Text1.SelStart = Len(Text1.Text) - 2 Text1.SelLength = 2 Text1.SelText = "" End If
Listing 12
Einlesen komplett über die Input Funktion
Bei dieser Methode wird die Textdatei komplett mit nur einer Anweisung eingelesen.
FNr = FreeFile Open TxtFile For Input As #FNr 'Datei komplett einlesen Text1.SelText = Input(LOF(FNr), #FNr) Close #FNr
Listing 13
Einlesen komplett über die Get Funktion
Diese Methode ist die mit Abstand schnellste.
FNr = FreeFile Open TxtFile For Binary As #FNr 'Länge der Variablen an Dateilänge anpassen zw = Space(LOF(FNr)) 'einlesen in (Zwischen)Variable Get #FNr, , zw Text1.SelText = zw Close #FNr
Listing 14
Der Umweg über ein Array
Das Auslesen Zeile für Zeile ermöglicht eine kontrollierte oder selektive Übernahme aus einer Textdatei in eine Textbox, das Auslesen komplett über Input und Get nicht. Bei Einsatz eines Arrays ist das trotzdem möglich.
'zusätzliche Deklaration dieser Variablen Dim myArray() As String Dim i As Long FNr = FreeFile Open TxtFile For Binary As #FNr 'Länge der Variablen an Dateilänge anpassen zw = Space(LOF(FNr)) Get #FNr, , zw Close #FNr MyArray() = Split(zw, vbCrLf) For i = 0 To UBound(myArray) - 1 Text1.SelText = myArray(i) & vbCrLf Next Text1.SelText = myArray(i)
Listing 15
Eine Zeile aus einem TextArray löschen
Da diese Frage häufig gestellt wird, hier eine Funktion dazu
Private Function ArrayStrElementDelete(sArray() As String, Zeile As Long) As Boolean Dim i As Long 'verschiebe alle Zeilen ab Zeile um 1 nach vorn For i = Zeile To UBound(sArray) - 1 sArray(i) = sArray(i + 1) Next 'Array um 1 verkleinern, damit letztes Element löschen ReDim Preserve sArray(LBound(sArray) To UBound(sArray) - 1) End Function
Listing 16
Funktionen zum Speichern und Einlesen von Textboxen
Bei mehreren Textboxen sind Funktionen, die mehrfach genutzt werden können, einzelnen Programmteilen vorzuziehen.
Funktion zum Schreiben eines Textboxtextes in eine Textdatei
Private Function TextboxSaveToFile _ (Tbox As TextBox, TxtFile As String, _ Optional doAppend As Boolean = False, _ Optional WithCrLf As Boolean = False, _ Optional Msg As String) As Boolean 'speichern einer Textdatei Dim FNr As Integer Msg = "" On Error Goto Fehler 'freie Dateinummer zuweisen lassen FNr = FreeFile If Not doAppend Then 'überschreiben Datei falls vorhanden Open TxtFile For Output As #FNr Else 'anfügen an Datei falls vorhanden Open TxtFile For Append As #FNr 'falls mit Text gefüllt If LOF(FNr) > 0 Then 'Zeilentrenner einfügen If WithCrLf Then Print #FNr, "" End If End If End If Print #FNr, Text1.Text; Close #FNr TextboxSaveToFile = True Exit Function Fehler: Msg = "Fehler: " & Err.Number & vbCrLf & Err.Description TextboxSaveToFile = False End Function
Listing 17
Funktion zum Einlesen einer Textdatei in eine Textbox [TextboxLoadFromFile]
Private Function TextboxLoadFromFile _ (Tbox As TextBox, TxtFile As String, _ Optional doBoxClear As Boolean = True, _ Optional Msg As String) As Boolean 'einlesen einer Textdatei in eine Textbox Dim FNr As Integer Dim zw As String Msg = "" TextboxLoadFromFile = False 'prüfen ob Datei vorhanden If Dir(TxtFile) = "" Then Msg = "Datei '" & TxtFile & " nicht gefunden" Exit Function End If 'Check auf Dateigrösse If FileLen(TxtFile) > 32767 Then Msg = "Datei '" & TxtFile & " zur gross für Textbox" Exit Function End If 'Text in Textbox löschen If doBoxClear Then Tbox.Text = "" End If 'Flackern vermindern Tbox.Visible = False On Error Goto Fehler FNr = FreeFile Open TxtFile For Binary As #FNr zw = Space(LOF(FNr)) Get #FNr, , zw Tbox.SelText = zw Close #FNr Tbox.Visible = True TextboxLoadFromFile = True Exit Function Fehler: Tbox.Visible = True Msg = "Fehler: " & Err.Number & vbCrLf & Err.Description End Function
Listing 18
Beispiel: Speichern einer Textbox mit Überschreiben eines bestehenden Textes
Dim TxtFile As String Dim Msg As String 'zuweisen Applicationpath und Filename TxtFile = AppPathGet & "TextBox.txt" 'speichern über Funktion If Not TextboxSaveToFile(Text1, TxtFile, , , Msg) Then 'Fehlermeldung MsgBox Msg, , "Text speichern" End If
Listing 19
Beispiel: Einlesen Textdatei in Textbox über Funktionen
Dim TxtFile As String Dim Msg As String 'zuweisen Applicationpath und Filename TxtFile = AppPathGet & "TextBox.txt" 'einlesen über Funktion If Not TextboxLoadFromFile(Text1, TxtFile, , Msg) Then 'Fehlermeldung MsgBox Msg, , "Text einlesen" End If
Listing 20
Speichern von Listbox-Texten
Die Eigenschaften der Listbox und der Combobox sind in Bezug auf die Datenhaltung weitgehend identisch. Die vorgestellten Methoden sind deshalb auf beide anwendbar.
MultiSelect Eigenschaften
Die Listbox bietet die Multiselect Eigenschaft. Es ist damit neben der kompletten Speicherung der Listboxdaten möglich, nur Teile zu speichern oder Teile davon auszusparen. Möglichkeiten zur Nutzung im Bereich Speichern sind in der Funktion ObjBoxSaveToFile beschrieben.
Die Eigenschaften List1.List (Index) List1.ListIndex
.List repräsentiert eine Aufzählung(Collection) von Texten innerhalb einer Listbox. Der .ListIndex verweist auf den aktuellen bzw. zuletzt ausgewählten Eintrag, eine Zahl zwischen 0 und der Anzahl der Eintragungen (ListCount -1). Bei ListIndex = -1 ist kein Eintrag ausgewählt.
Die Methode List1.AddItem Element, Index
Mit .AddItem werden Einträge in einer Listbox vorgenommen, Element repräsentiert hier den zu speichernden Text. Wird kein Index angegeben, wird der Eintrag am Ende angefügt.
Die Eigenschaften List1.ItemData (Index) List1.NewIndex
Neben der List-Eigenschaft zur Aufnahme von 1-zeiligen Texten bieten die Boxen die Datenhaltung eines nicht sichtbaren numerischen Wertes vom Typ Long pro Eintrag in der Liste ItemData. Dieser Wert kann als Index verwendet werden (z.B. bei Darstellung von Teilen eines Arrays), als Artikel-Nr, Preis etc..
Direkt nach Einfügen durch .AddItem liefert .NewIndex den Index (lfd. Nummer), unter dem der neue Eintrag vorgenommen wurde.
List1.AddItem Text2.Text List1.ItemData(List1.NewIndex) = Val(Text3.Text)
Listing 21
Darstellung und Trennen von .List (Item) und .ItemData
In den vorgestellten Beispielen werden die Werte von .List und .ItemData zusammen in einer Zeile dargestellt. Damit diese Werte, einmal ein Text, einmal ein numerischer Wert vom Typ Long, beim Einlesen wieder getrennt werden können, muss ein Trennzeichen eingefügt werden.
Das Trennzeichen wird der Variablen TrZ zugewiesen, in den Beispielen das Zeichen |.
Speicherung Daten einer Box Eintrag für Eintrag
Hier wird Eintrag für Eintrag zusammen mit ItemData ausgelesen und in die Textdatei geschrieben. Der letzte Eintrag muss ohne CrLf geschrieben werden.
TrZ = "|" FNr = FreeFile Open TxtFile For Output As #FNr 'ListCount liefert Anzahl der Elemente 'List wird aber ab 0 gezählt, deshalb ListCount - 1 For i = 0 To List1.ListCount - 1 If i < List1.ListCount - 1 Then 'mit CrLf schreiben Print #FNr, List1.ItemData(i) & TrZ & List1.List(i) Else 'letzten Eintrag ohne CrLf schreiben Print #FNr, List1.ItemData(i) & TrZ & List1.List(i); End If Next Close #FNr
Listing 22
Speichern einer Listbox über Array und Join
Bei dieser Methode wird ein (Zwischen)Array gebildet, das mit Join zu einem String konvertiert und auf einmal geschrieben wird. Als Trennzeichen für die einzelnen Zeichen wird über Join ein CrLf eingefügt. Dürfte den Durchsatz steigern.
TrZ = "|" 'Array dimensionieren und füllen ReDim wArray(List1.ListCount) 'ListCount liefert Anzahl der Elemente 'List wird aber ab 0 gezählt, deshalb ListCount - 1 For i = 0 To List1.ListCount - 1 With List1 wArray(i) = .ItemData(i) & TrZ & .List(i) End With Next FNr = FreeFile Open TxtFile For Output As #FNr 'Array komplett schreiben, über Join einen String 'aus den Elementen bilden getrennt durch CrLf If List1.ListCount > 0 Then Print #FNr, Join(wArray, vbCrLf); End If Close #FNr
Listing 23
Einlesen von Listbox-Texten
Einlesen Zeile für Zeile
Die Textdatei wird Zeile für Zeile ausgelesen. Jede Zeile wird auf das Trennzeichen geprüft. Ist das Trennzeichen vorhanden, werden List und ItemData beschickt, sonst nur List.
TrZ = "|" FNr = FreeFile Open TxtFile For Input As #FNr 'auslesen bis zum Dateiende Do While Not EOF(FNr) 'zeilenweise auslesen und übernehmen Line Input #FNr, zw 'Position des Trennzeichens i = InStr(zw, TrZ) If i > 0 Then 'eintragen List(Item) und ItemData List1.AddItem Mid(zw, i + 1) List1.ItemData(List1.NewIndex) = Left(zw, i - 1) Else 'eintragen nur List(Item) List1.AddItem zw End If Loop Close #FNr
Listing 24
Einlesen komplett in Array und Übergabe an Listbox
Bei diesen Methoden wird die Textdatei komplett über Input oder Get ausgelesen, gesplittet in ein Array und von dort aus wird die Box beschickt. Die Methode mit Get ist die schnellste.
'die Variable wArray() muss definiert sein Dim wArray() As String TrZ = "|" FNr = FreeFile Open TxtFile For Input As #FNr zw = Input(LOF(FNr), #FNr) Close #FNr 'String in Array übernehmen wArray = Split(zw, vbCrLf) For i = LBound(wArray) To UBound(wArray) j = InStr(wArray(i), TrZ) If j > 0 Then 'eintragen List(Item) und ItemData List1.AddItem Mid(wArray(i), j + 1) List1.ItemData(List1.NewIndex) = Left(wArray(i), j - 1) Else 'eintragen nur List(Item) List1.AddItem wArray(i) End If Next
Listing 25
Bei der Methode mit Get sind lediglich die folgenden Statements für den Dateizugriff zu wechseln
FNr = FreeFile Open TxtFile For Binary As #FNr zw = Space(LOF(FNr)) Get #FNr, , zw Close #FNr
Listing 26
Funktionen für List- und Combobox
Funktion zum Speichern der Daten einer List- oder Combobox in eine Textdatei
Private Function ObjBoxSaveToFile _ (objBox As Object, _ TxtFile As String, _ Optional TrZ As String = "|", _ Optional Flags As Integer = 0, _ Optional doAppend As Boolean = False, _ Optional Msg As String = "") As Boolean 'Inhalt einer Listbox oder Combobox in Textdatei schreiben 'Flags: NUR ListBox '0 = Alle List(Items) schreiben '1 = OnlySelected = alle ausgewählten Items '4 = NotSelected = alle nicht ausgewählten Items Dim FNr As Integer Dim i As Long Dim j As Long Dim TrZ As String Dim doIt As Boolean Dim wArray() As String ObjBoxSaveToFile = False 'nur zugelassen Listbox und Combobox If Not TypeOf objBox Is ListBox And _ Not TypeOf objBox Is ComboBox Then Msg = "Falscher Objekttyp" Exit Function End If 'ListCount liefert Anzahl der Elemente 'List wird aber ab 0 gezählt, deshalb ListCount - 1 j = -1 For i = 0 To objBox.ListCount - 1 doIt = True 'bei Listbox Flags abchecken If TypeOf objBox Is ListBox Then If (Flags And 1) = 1 Then 'nur Selected Items If Not objBox.Selected(i) Then doIt = False End If ElseIf (Flags And 4) = 4 Then 'nicht Selected Items If objBox.Selected(i) Then doIt = False End If End If End If If doIt Then j = j + 1 'Array um 1 Element erhöhen ReDim Preserve wArray(j) With objBox If Len(TrZ) > 0 Then wArray(j) = .ItemData(i) & TrZ & .List(i) Else wArray(j) = .List(i) End If End With End If Next 'Fehlerbehandlung On Error Goto Fehler 'freie Dateinummer zuweisen lassen FNr = FreeFile If Not doAppend Then 'überschreiben Open TxtFile For Output As #FNr Else 'an bestehenden Inhalt anhängen Open TxtFile For Append As #FNr 'ist Zieldatei belegt, Zeilentrenner anfügen If LOF(FNr) > 0 And objBox.ListCount > 0 Then Print #FNr, "" End If End If 'Array komplett schreiben über Join einen String aus 'den Elementen bilden getrennt durch CrLf If objBox.ListCount > 0 Then Print #FNr, Join(wArray, vbCrLf); End If Close #FNr ObjBoxSaveToFile = True Exit Function Fehler: Msg = "Fehler: " & Err.Number & vbCrLf & Err.Description End Function
Listing 27
Funktion zum Einlesen der Daten einer List- oder Combobox aus einer Textdatei
Private Function ObjBoxLoadFromFile _ (objBox As Object, _ TxtFile As String, _ Optional TrZ As String = "|", _ Optional doBoxClear As Boolean = True, _ Optional Msg As String = "") As Boolean 'einlesen einer Textdatei in eine Listbox oder Combobox Dim FNr As Integer Dim i As Long Dim j As Long Dim zw As String Dim wArray() As String Msg = "" ObjBoxLoadFromFile = False 'nur Listbox und Combobox zulassen If Not TypeOf objBox Is ListBox And _ Not TypeOf objBox Is ComboBox Then Msg = "Falscher Objekttyp" Exit Function End If 'prüfen ob Datei vorhanden If Dir(TxtFile) = "" Then Msg = "Datei '" & TxtFile & " nicht gefunden" Exit Function End If 'Listbox/Combo löschen If doBoxClear Then objBox.Clear End If 'Flackern vermindern objBox.Visible = False 'Fehlerbehandlung On Error Goto Fehler 'freie Dateinummer zuweisen lassen FNr = FreeFile Open TxtFile For Binary As #FNr 'Datei komplett auslesen zw = Space(LOF(FNr)) Get #FNr, , zw Close #FNr 'String in Array übernehmen wArray = Split(zw, vbCrLf) For i = LBound(wArray) To UBound(wArray) j = InStr(wArray(i), TrZ) If j > 0 And Len(TrZ) > 0 Then 'eintragen List(Item) und ItemData objBox.AddItem Mid(wArray(i), j + 1) objBox.ItemData(objBox.NewIndex) = Left(wArray(i), j - 1) Else 'eintragen nur List(Item) objBox.AddItem wArray(i) End If Next objBox.Visible = True ObjBoxLoadFromFile = True Exit Function Fehler: objBox.Visible = True Msg = "Fehler: " & Err.Number & vbCrLf & Err.Description End Function
Listing 28
Beispiele für den Aufruf der Funktionen
Speichern der Daten einer List- oder Combobox in einer Textdatei
'Inhalt Listbox in Textfile schreiben über Funktion Dim TxtFile As String Dim Msg As String TxtFile = AppPathGet & "Listbox.txt" If Not ObjBoxSaveToFile(List1, TxtFile, , , , Msg) Then MsgBox Msg, , "Listbox schreiben" End If End Sub
Listing 29
Einlesen der Daten einer List- oder Combobox aus einer Textdatei
'Textfile in Listbox über Funktion einlesen Dim TxtFile As String Dim Msg As String TxtFile = AppPathGet & "Listbox.txt" If Not ObjBoxLoadFromFile(List1, TxtFile, , , Msg) Then MsgBox Msg, , "Listbox einlesen" End If
Listing 30
Speichern von String-Arrays
1-dimensionales Array
Das Speichern von 1-dimensionalen Array ist vom Prinzip her schon in vorigen Beispielen vorgestellt worden. Das Array wird über die Funktion Join zu einem String zusammengebunden, wobei die Elemente des Arrays durch einen CrLf getrennt werden.
Der Stringinhalt wird über die Print Anweisung gefolgt von einem Strichpunkt in die Datei geschrieben, dadurch wird eine Leerzeile vermieden.
Open TxtFile For Output As #FNr Print #FNr, Join(myArray, vbCrLf); Close #FNr
Listing 31
2-dimensionales Array
Die Join Anweisung ist nur bei einem 1-dimensionalen Array anwendbar, bei einem 2-dimensionalen Array wird deshalb über ein 1-dimensionales Workarray gearbeitet. Die vorgestellten Methoden beziehen sich auf das Muster einer Adressverwaltung im Projekt.
Dimensioniert werden in der 1. Dimension 7 Elemente, in der 2. Dimension läuft der Zähler (Index).
0: Löschkennzeichen
1: Name
2: Vorname etc bis 6: Telefon
Dim AdrArray() As String Private Sub Form_Load() ReDim AdrArray(6, 0) End Sub
Listing 32
Bei neuen Adressen wird das Array über die Anweisung Redim Preserve um ein Element erweitert.
'1 Element anfügen i = UBound(AdrArray, 2) + 1 ReDim Preserve AdrArray(UBound(AdrArray), i)
Listing 33
Anzahl der Elemente
Im ersten Schritt muss die Anzahl der zu schreibenden Elemente ermittel werden. Wenn kein Löschkennzeichen (-1) im Element 0 der 1. Dimension hinterliegt ist, kann die Adresse geschrieben werden.
Dim AnzPut As Long For i = 1 To UBound(AdrArray, 2) If Val(AdrArray(0, i)) = 0 Then AnzPut = AnzPut + 1 End If Next
Listing 34
Übertragen in ein 1.dimensionales Workarray
Es wird ein Workarray in der benötigten Grösse angelegt, wobei das 1. Element den Index 0 hat.
Das Adressarray wird in der 2. Dimension ab dem Element 1 bis zum Ende durchlaufen. Ist eine Adresse zu speichern, werden die Nutzelemente der Dimension 1 ab Element 1 in einen String gepackt und durch ein Trennzeichen getrennt. Dieser String wird an das Workarray übergeben.
Dim w() As String Dim zw As String Dim TrZ As String Dim i As Long Dim j As Long TrZ = "|" 'Array anlegen ReDim w(AnzPut - 1) AnzPut = 0 For i = 1 To UBound(AdrArray, 2) If Val(AdrArray(0, i)) = 0 Then 'Adresse in String mit Trennzeichen zw = AdrArray(1, i) For j = 2 To UBound(AdrArray, 1) zw = zw & TrZ & AdrArray(j, i) Next 'String in Array stellen AnzPut = AnzPut + 1 w(AnzPut - 1) = zw End If Next
Listing 35
Schreiben in Textdatei
Das Workarray kann jetzt ganz normal geschrieben werden.
Open TxtFile For Output As #FNr If AnzPut > 0 Then 'Array zu einem String verbinden und schreiben Print #FNr, Join(w(), vbCrLf); End If Close #FNr
Listing 36
Einlesen von String-Arrays
Einlesen der Textdatei in eine Zwischenvariable
Dim zw As String Open TxtFile For Binary As #FNr zw = Space(LOF(FNr)) Get #FNr, , zw Close #FNr
Listing 37
Übernahme in Array
Im ersten Schritt wird das Adressarray in der 2. Dimension auf die Größe 0 redimensioniert. Wenn Nutzdaten gelesen werden konnten, erfolgt über einen Split die Aufteilung in ein 1-dimensionales Workarray.
Jetzt ist bekannt, wieviele Adressen eingelesen wurden und das Adressarray kann endgültig redimensioniert werden.
In einer Schleife wird das Workarray abgearbeitet. Jedes Element wird über ein weiteres Workarray in die Elemente der 1. Dimension des Adressarrays gesplittet und dahin übertragen.
Beziehung zwischen Array und Listbox herstellen
Parallel dazu werden (in dem Beispiel) die Nutzelemente 1 und 2 (Name, Vorname) per AddItem in eine Listbox eingetragen. Da diese Listbox die Eigenschaft Sorted=True hat, muss eine Beziehung zwischen Adressarray und Listbox hergestellt werden. Das erfolgt über das Datenfeld ItemData der Listbox, bei dem für jeden Eintrag die Index- oder Zählnummer der 2. Dimension des Arrays eingestellt wird.
Dim w() As String Dim w1() As String ReDim AdrArray(UBound(AdrArray), 0) If Len(zw) > 0 Then w() = Split(zw, vbCrLf) ReDim AdrArray(UBound(AdrArray), UBound(w) + 1) For i = 0 To UBound(w) w1() = Split(w(i), TrZ) For j = 0 To UBound(w1) AdrArray(j + 1, i + 1) = w1(j) Next List2.AddItem AdrArray(1, i + 1) & ", " & AdrArray(2, i + 1) List2.ItemData(List2.NewIndex) = i + 1 Next End If
Listing 38
Schlußwort
Mit Hilfe des vorliegenden Tutorials sollten Sie in der Lage sein, Daten aus Textboxen, List- und Comboboxen oder aus Arrays in Dateien zu speichern und aus diesen wieder auszulesen.
Tutorial und Beispielprojekt als Download [32900 Bytes]
Ihre Meinung
Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.