{"id":55000454,"date":"2024-12-01T00:00:00","date_gmt":"2025-03-10T20:24:14","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=454"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"VBA_und_Textdateien_Alles_ueber_Open_Close_und_Co","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/VBA_und_Textdateien_Alles_ueber_Open_Close_und_Co\/","title":{"rendered":"VBA und Textdateien: Alles &uuml;ber Open, Close und Co."},"content":{"rendered":"<p><b>VBA bietet einige M&ouml;glichkeiten f&uuml;r das Erstellen, F&uuml;llen, &Auml;ndern und Auslesen von Textdateien. Mit diesen kann man zwar nicht alle Aufgaben bew&auml;ltigen, aber f&uuml;r einfache Zwecke lohnt sich ein Blick auf diese Sammlung. Wir meinen damit Anweisungen wie Open, Close, Print, Input und einige weitere, die spannenderweise im Objektkatalog noch nicht einmal erw&auml;hnt werden. Wir werden uns in diesem Artikel eingehend mit diesen Anweisungen besch&auml;ftigen und in verschiedenen Beispielen zeigen, wie sich damit immer wiederkehrende Aufgaben wie das Schreiben oder Lesen von Textdateien leicht bew&auml;ltigen l&auml;sst.<\/b><\/p>\n<p>Im Artikel <b>Dateien mit VBA-Bordmitteln verwalten <\/b>(<b>www.vbentwickler.de\/453<\/b>) haben wir uns angesehen, welche Elemente die Klasse <b>FileSystem <\/b>f&uuml;r uns bereith&auml;lt.<\/p>\n<p>Hier finden wir einige Anweisungen, mit denen wir Verzeichnisse erstellen und l&ouml;schen, Dateien und Verzeichnisse durchlaufen und weitere Dinge erledigen k&ouml;nnen.<\/p>\n<p>Die Klasse <b>FileSystem <\/b>enth&auml;lt jedoch auch einige Elemente, die wir in diesem Zusammenhang gar nicht ben&ouml;tigen. Sie sind vielmehr f&uuml;r den Einsatz mit einigen Anweisungen vorgesehen, die wir nicht in der Klasse <b>FileSystem<\/b> und sogar noch nicht einmal &uuml;berhaupt im Objektkatalog des VBA-Editors finden.<\/p>\n<p>Dabei geht es um solche Anweisungen wie Open, Close, Write et cetera:<\/p>\n<ul>\n<li><b>Close<\/b>: Schlie&szlig;t eine oder mehrere zuvor mit Open ge&ouml;ffnete Dateien.<\/li>\n<li><b>Get<\/b>: Dient dem Bin&auml;rzugriff auf Dateien und wird in diesem Artikel nicht erl&auml;utert.<\/li>\n<li><b>Input #<\/b>: Erlaubt das Einlesen der <\/li>\n<li><b>Line Input #<\/b>: Erlaubt das zeilenweise Einlesen von Inhalten einer Textdatei.<\/li>\n<li><b>Open<\/b>: &Ouml;ffnet eine Datei f&uuml;r den lesenden oder schreibenden Zugriff oder erstellt eine neue Datei f&uuml;r den schreibenden Zugriff.<\/li>\n<li><b>Print #<\/b>: Schreibt Freitext in Dateien.<\/li>\n<li><b>Put<\/b>: Dient dem Bin&auml;rzugriff auf Dateien und wird in diesem Artikel nicht erl&auml;utert.<\/li>\n<li><b>Seek<\/b>: Ruft die aktuelle Position beim Bin&auml;rzugriff ab oder setzt diese. Wird in diesem Artikel nicht erl&auml;utert.<\/li>\n<li><b>Width<\/b>: Erlaubt die Begrenzung der Zeilenl&auml;nge beim Schreiben mit <b>Print<\/b>.<\/li>\n<li><b>Write #<\/b>: Schreibt strukturierte Daten in Dateien.<\/li>\n<\/ul>\n<p>Neben diesen Anweisungen erl&auml;utern wir in diesem Artikel auch noch diese Elemente, die Teil der Klasse <b>FileSystem <\/b>sind:<\/p>\n<ul>\n<li><b>EOF<\/b>: Abk&uuml;rzung f&uuml;r <b>End Of File<\/b>. Erwartet die Angabe einer Dateinummer einer mit <b>Open <\/b>ge&ouml;ffneten Datei. F&uuml;r diese Datei wird angegeben, ob beim Lesen das Ende der Datei erreicht wurde.<\/li>\n<li><b>FileLen<\/b>: Gibt die Gr&ouml;&szlig;e einer Datei oder eines Verzeichnisses (immer 0) in Bytes zur&uuml;ck und erwartet den Pfad zu des Elements als Parameter.<\/li>\n<li><b>FreeFile<\/b>: Gibt eine verf&uuml;gbare Dateinummer zur&uuml;ck, die wir mit der <b>Open<\/b>-Anweisung nutzen k&ouml;nnen, um eine Datei zu &ouml;ffnen. Keine Parameter.<\/li>\n<li><b>Loc<\/b>: Gibt die Position innerhalb einer mit <b>Open <\/b>ge&ouml;ffneten Datei aus.<\/li>\n<li><b>LOF<\/b>: Abk&uuml;rzung f&uuml;r <b>Length Of File<\/b>. Liefert die L&auml;nge einer ge&ouml;ffneten Datei in Bytes. Erwartet die Dateinummer als Parameter.<\/li>\n<li><b>Reset<\/b>: Schlie&szlig;t alle mit Open ge&ouml;ffneten Dateien.<\/li>\n<li><b>Seek<\/b>: Setzt die aktuelle Schreibposition innerhalt einer Datei oder gibt diese zur&uuml;ck. Der erste Parameter erwartet die Dateinummer. Wenn der zweite Parameter gesetzt ist, wird die Schreibposition an die angegebenen Position gesetzt. Ist der zweite Parameter leer, wird die Schreibposition zur&uuml;ckgegeben.<\/li>\n<\/ul>\n<h2>&Ouml;ffnen oder Erstellen einer Datei mit Open<\/h2>\n<p>Wenn wir bestehende Datei &ouml;ffnen oder eine neue Datei erstellen wollen, ben&ouml;tigen wir die <b>Open<\/b>-Anweisung.<\/p>\n<p>Die <b>Open<\/b>-Anweisung ist nicht wie herk&ouml;mmliche VBA-Anweisungen aufgebaut, die einfach aufgerufen werden und gegebenenfalls noch einen oder mehrere Parameter entgegennehmen.<\/p>\n<p>Die <b>Open<\/b>-Anweisung besteht vielmehr aus mehreren Teilen, die nacheinander notiert werden m&uuml;ssen. Hier ist die grundlegende Syntax:<\/p>\n<pre>Open pathname For mode [ Access access ] [ lock ]<span style=\"color:blue;\"> As <\/span>[ # ] filenumber [ <span style=\"color:blue;\">Len<\/span> = reclength ]<\/pre>\n<p>Wir finden hier verschiedene Bestandteile, die wir wie Pflichtparameter oder optionale Parameter angeben k&ouml;nnen:<\/p>\n<ul>\n<li><b>pathname<\/b>: Pfad zu der zu erstellenden oder zu &ouml;ffnenden Datei <\/li>\n<li><b>mode<\/b>: Modus, in dem die Datei ge&ouml;ffnet werden soll. Hier stehen die Werte <b>Append<\/b>, <b>Binary<\/b>, <b>Input<\/b>, <b>Output <\/b>oder <b>Random <\/b>zur Verf&uuml;gung.<\/li>\n<li><b>access<\/b>: Wird beginnend mit dem Schl&uuml;sselwort <b>Access <\/b>mit einem der Werte <b>Read<\/b>, <b>Write <\/b>oder <b>Read Write <\/b>kombiniert.<\/li>\n<li><b>lock<\/b>: Gibt an, ob und wie andere Prozesse noch auf die ge&ouml;ffnete Datei zugreifen k&ouml;nnen sollen. Hier gibt es die Werte <b>Shared<\/b>, <b>Lock Read<\/b>, <b>Lock Write <\/b>und <b>Lock Read Write<\/b>.<\/li>\n<li><b>filenumber<\/b>: Enth&auml;lt eine Nummer f&uuml;r diesen Dateizugriff, der auch von folgenden Anweisungen zum Lesen oder Schreiben der Datei verwendet werden muss. Der Wert kann von <b>1 <\/b>bis <b>511 <\/b>reichen. Mit der Funktion <b>FreeFile <\/b>k&ouml;nnen wir die n&auml;chste Nummer ermitteln, die in der aktuellen Session noch nicht f&uuml;r den Zugriff auf eine Datei verwendet wird.<\/li>\n<li><b>reclength<\/b>: Eine Zahl, mit der die Datensatzgr&ouml;&szlig;e bei der Zugriffsart <b>Random <\/b>festgelegt wird.<\/li>\n<\/ul>\n<p>F&uuml;r einfache lesende oder schreibende Zugriff ben&ouml;tigen wir nicht unbedingt alle dieser Parameter.<\/p>\n<h2>Schlie&szlig;en einer Datei mit Close<\/h2>\n<p>Eine ge&ouml;ffnete oder neu erstellte Datei kann je nach Modus lesend und\/oder schreibend verwendet werden.<\/p>\n<p>Danach sollte sie jedoch auch wieder geschlossen werden. Das erledigt die Anweisung <b>Close<\/b>.<\/p>\n<p>Diese Anweisung erwartet keinen, einen oder mehrere Parameter. Ohne Parameter schlie&szlig;t die <b>Close<\/b>-Anweisung alle aktuell ge&ouml;ffneten Dateien wieder.<\/p>\n<p>Dateien werden mit der <b>Open<\/b>-Anweisung unter Angabe einer Dateinummer ge&ouml;ffnet. Diese k&ouml;nnen wir auch angeben, wenn wir diese Datei gezielt wieder schlie&szlig;en m&ouml;chten.<\/p>\n<p>Wenn wir mehrere Dateien ge&ouml;ffnet haben, k&ouml;nnen wir diese entweder durch mehrfaches Aufrufen der <b>Close<\/b>-Methode unter Angabe der jeweiligen Dateinummer wieder schlie&szlig;en. Wir k&ouml;nnen die Dateinummern aber auch als kommaseparierte Liste &uuml;bergeben.<\/p>\n<p>Hier ein Beispiel, das eine einfache Datei zum Schreiben anlegt oder &ouml;ffnet:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>intFile<span style=\"color:blue;\"> As Integer<\/span>\r\nintFile = FreeFile\r\nOpen CurrentProject.Path & \"\\Test.txt\" For Output<span style=\"color:blue;\"> As <\/span>#intFile\r\nClose #intFile<\/pre>\n<p>Wenn wir sicher sind, dass in der aktuellen Session nur eine Datei ge&ouml;ffnet wird, k&ouml;nnen wir auch einen festen Zahlenwert nutzen:<\/p>\n<pre>Open CurrentProject.Path & \"\\Test.txt\" For Output<span style=\"color:blue;\"> As <\/span>#1\r\nClose #1<\/pre>\n<p>Wenn wir zwei Dateien gleichzeitig ben&ouml;tigen, k&ouml;nnen wir zwei Mal die <b>FreeFile<\/b>-Methode nutzen und die Dateien nacheinander &ouml;ffnen und wieder schlie&szlig;en:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>intFile1<span style=\"color:blue;\"> As Integer<\/span>\r\n<span style=\"color:blue;\">Dim <\/span>intFile2<span style=\"color:blue;\"> As Integer<\/span>\r\nintFile1 = FreeFile\r\nOpen CurrentProject.Path & \"\\Test1.txt\" For Output<span style=\"color:blue;\"> As <\/span>#intFile1\r\nintFile2 = FreeFile\r\nOpen CurrentProject.Path & \"\\Test2.txt\" For Output<span style=\"color:blue;\"> As <\/span>#intFile2\r\nClose #intFile1\r\nClose #intFile2<\/pre>\n<p>Wichtig ist, dass wir den zweiten Aufruf von <b>FreeFile <\/b>erst starten, wenn die erste Datei bereits ge&ouml;ffnet ist. Ansonsten w&uuml;rde <b>FreeFile <\/b>wieder den gleichen Wert wie beim ersten Aufruf liefern, da dieser noch nicht verwendet wurde.<\/p>\n<p>Wir k&ouml;nnen die beiden letzten Anweisungen auch zusammenfassen:<\/p>\n<pre>Close #intFile1, #intFile2<\/pre>\n<p>Die vorherigen Beispiele legen immer leere Textdateien an. Da wir diese nicht mit Inhalt f&uuml;llen, haben diese immer eine Gr&ouml;&szlig;e von 0 Bytes.<\/p>\n<h2>Alle Dateien mit Reset schlie&szlig;en<\/h2>\n<p>Die Alternative zum Schlie&szlig;en aller ge&ouml;ffneten Dateien mit der <b>Close<\/b>-Anweisung ist die <b>Reset<\/b>-Anweisung.<\/p>\n<h2>Einfache Textdateien schreiben<\/h2>\n<p>Die folgende Prozedur erstellt eine Textdatei und f&uuml;llt diese mit f&uuml;nf Zeilen Text.<\/p>\n<p>Dabei schreiben wir zuerst den Pfad zu der zu erstellenden Datei in die Variable <b>strDateipfad<\/b>. Wir ermitteln mit der Funktion <b>FreeFile <\/b>die n&auml;chste freie Dateinummer und schreiben diese in die Variable <b>intDateinummer<\/b>. Diese verwenden wir in der <b>Open<\/b>-Anweisung, der wir als Erstes mit <b>strDateipfad <\/b>den Namen der zu erstellenden Datei &uuml;bergeben.<\/p>\n<p>Danach folgt der Teil <b>For Output<\/b>, der angibt, das wir in die Datei schreiben wollen. Schlie&szlig;lich leitet das Schl&uuml;sselwort <b>As <\/b>die Angabe der Dateinummer ein. Die Angabe des Raute-Zeichens (#) ist hier &uuml;brigens nicht verpflichtend &#8211; im Gegensatz zu den sp&auml;teren Vorkommen in Zusammenhang mit den <b>Print<\/b>&#8211; und <b>Close<\/b>-Anweisungen. Der &Uuml;bersichtlichkeit halber wollen wir das Raute-Zeichen jedoch konsequent &uuml;berall benutzen, wo die Dateinummer zum Einsatz kommt.<\/p>\n<p>Danach durchlaufen wir eine <b>For&#8230;Next<\/b>-Schleife f&uuml;nf Mal und schreiben eine Zeile wie die folgende in die Stringvariable <b>strZeile<\/b>:<\/p>\n<pre>Dies ist der Inhalt der Zeile 1<\/pre>\n<p>Danach schreiben wir den Inhalt dieser Variablen mit der <b>Print<\/b>-Methode in die Datei. Dabei geben wir als ersten Parameter die Dateinummer und als zweiten Parameter den zu schreibenden Inhalt an.<\/p>\n<p>Nachdem die Schleifendurchl&auml;ufe abgeschlossen sind, schlie&szlig;en wir mit der <b>Close<\/b>-Anweisung die Datei:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TextdateiSchreiben()\r\n     <span style=\"color:blue;\">Dim <\/span>strDateipfad<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intDateinummer<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strPraefix<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTextinhalt<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intZeile<span style=\"color:blue;\"> As Integer<\/span>\r\n     strDateipfad = CurrentProject.Path & \"\\Textdatei.txt\"\r\n     intDateinummer = FreeFile\r\n     Open strDateipfad For Output<span style=\"color:blue;\"> As <\/span>#intDateinummer\r\n     For intZeile = 1 To 5\r\n         strTextinhalt = \"Dies ist der Inhalt der Zeile \" _\r\n             & intZeile\r\n         Print #intDateinummer, strTextinhalt\r\n     <span style=\"color:blue;\">Next<\/span> intZeile\r\n     Close #intDateinummer\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis sieht im Texteditor wie in Bild 1 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_454_001.png\" alt=\"Die frisch erstellte Textdatei\" width=\"424,6267\" height=\"219,1328\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Die frisch erstellte Textdatei<\/span><\/b><\/p>\n<h2>Einfache Textdateien einlesen<\/h2>\n<p>Nun schauen wir uns die verschiedenen Methoden zum Lesen des Inhalts einer Textdatei an. Dazu geh&ouml;ren die folgenden:<\/p>\n<ul>\n<li>Einlesen des kompletten Inhalts einer Textdatei in eine Variable des Datentyps <b>String<\/b><\/li>\n<li>Zeilenweises Einlesen einer Textdatei und Zusammensetzen per VBA<\/li>\n<\/ul>\n<h2>Einlesen einer vollst&auml;ndigen Textdatei<\/h2>\n<p>Zun&auml;chst wollen wir die im vorherigen Beispiel erstellte Textdatei wieder in eine Textvariable einlesen.<\/p>\n<p>Dazu verwenden wir die folgende Prozedur. Diese weist der Variablen <b>strDateipfad <\/b>den Pfad zu der einzulesenden Datei zu. Dann pr&uuml;ft sie mit der <b>Dir<\/b>-Funktion, ob diese Datei &uuml;berhaupt vorhanden ist. Anderenfalls w&uuml;rde der Versuch, darauf zuzugreifen, anschlie&szlig;end einen Fehler ausl&ouml;sen.<\/p>\n<p>Danach schreibt sie die mit <b>FreeFile <\/b>ermittelte n&auml;chste freie Dateinummer in die Variable <b>intDateinummer<\/b>. Diese nutzt sie dann als Dateinummer beim &Ouml;ffnen der Datei aus <b>strDateipfad <\/b>mit der <b>Open<\/b>-Methode. Diese verwendet au&szlig;erdem das Schl&uuml;sselwort <b>For Input<\/b>, damit die Datei zum Lesen ge&ouml;ffnet wird. Danach liest die Prozedur den kompletten Inhalt der Datei mit einer einzigen Anweisung in die Variable <b>strInhalt <\/b>ein.<\/p>\n<p>Diese Anweisung hei&szlig;t <b>Input<\/b> und sie erh&auml;lt als ersten Parameter die Anzahl der einzulesenden Zeichen und als zweiten die Dateinummer der betroffenen Datei. Die Anzahl der einzulesenden Zeichen ermitteln wir mit der Funktion <b>LOF<\/b>, die als Parameter wiederum die Dateinummer erwartet.<\/p>\n<p>Nach dem Schlie&szlig;en der Datei mit der <b>Close<\/b>-Anweisung geben wir schlie&szlig;lich noch den eingelesenen Inhalt im Direktbereich des VBA-Editors aus:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TextdateiKomplettEinlesen()\r\n     <span style=\"color:blue;\">Dim <\/span>strDateipfad<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intDateinummer<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strInhalt<span style=\"color:blue;\"> As String<\/span>\r\n     strDateipfad = CurrentProject.Path & \"\\Textdatei.txt\"\r\n     <span style=\"color:blue;\">If <\/span>Dir(strDateipfad) = \"\"<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Die Datei existiert nicht: \" _\r\n             & strDateipfad, vbExclamation\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     intDateinummer = FreeFile\r\n     Open strDateipfad For Input<span style=\"color:blue;\"> As <\/span>#intDateinummer\r\n     strInhalt = Input(LOF(intDateinummer), intDateinummer)\r\n     Close #intDateinummer\r\n     <span style=\"color:blue;\">Debug.Print<\/span> strInhalt\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Anzahl der enthaltenen Zeichen k&ouml;nnen wir uns mit der <b>LOF<\/b>-Funktion auch im Direktbereich ausgeben lassen. Dazu f&uuml;gen wir die folgende Zeile zwischen <b>Open <\/b>und <b>Close <\/b>ein:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> LOF(intDateinummer)<\/pre>\n<p>Interessanterweise f&uuml;hrt die Angabe des Raute-Zeichens beim Parameter der <b>LOF<\/b>-Funktion zu einem Fehler.<\/p>\n<p>Hinweis: Es gibt zwei verschiedene <b>Input<\/b>-Anweisungen. Diese hier erwartet als ersten Parameter die Anzahl der einzulesenden Zeichen und als zweiten die Dateinummer. Die andere beschreiben wir weiter unten.<\/p>\n<h2>Zeilenweises Einlesen einer Textdatei<\/h2>\n<p>Es ist allerdings nicht immer gew&uuml;nscht, gleich die vollst&auml;ndige Textdatei einzulesen. Gegebenenfalls m&ouml;chte man nur soweit einlesen, bis man eine bestimmte Zeile gefunden hat. Deshalb zeigt das folgende Beispiel, wie wir eine Textdatei zeilenweise einlesen.<\/p>\n<p>Dabei weisen wir der Variablen <b>strDateipfad <\/b>wieder den Pfad zu der einzulesenden Datei zu. Dann pr&uuml;fen wir mit der <b>Dir<\/b>-Funktion, ob diese Datei &uuml;berhaupt vorhanden ist. Ist das nicht der Fall, geben wir eine entsprechende Meldung aus und brechen das Einlesen ab.<\/p>\n<p>Anderenfalls fahren wir fort und weisen <b>intDateinummer <\/b>die n&auml;chste freie Dateinummer zu. Damit rufen wir die <b>Open<\/b>-Anweisung unter Angabe des Dateipfades und der Zugriffsart <b>For Input<\/b>, also zum Lesen, und der Dateinummer aus <b>intDateinummer <\/b>auf.<\/p>\n<p>Nun durchlaufen wir alle Zeilen der Textdatei. Das Einlesen erledigen wir mit der Anweisung <b>Line Input<\/b>, der wir als ersten Parameter die Dateinummer und als zweiten die Variable &uuml;bergeben, die wir mit der aktuellen Zeile f&uuml;llen wollen. Au&szlig;erdem wird die jeweils eingelesene Zeile im Direktbereich des VBA-Editors ausgegeben.<\/p>\n<p>Die Einleseposition wird nach dem Einlesen einer Zeile automatisch in die n&auml;chste Zeile verschoben, wodurch wir im n&auml;chsten Schleifendurchlauf mit der gleichen Anweisung die folgende Zeile einlesen k&ouml;nnen.<\/p>\n<p>Die <b>Do While<\/b>-Schleife l&auml;uft solange, bis die Funktion <b>EOF <\/b>mit der Dateinummer als Parameter den Wert <b>True <\/b>zur&uuml;ckliefert. Das bedeutet, dass die Einleseposition sich hinter dem letzten lesbaren Zeichen befindet.<\/p>\n<p>Nach dem Ausgeben aller Zeilen schlie&szlig;t die Prozedur die Datei mit der <b>Close<\/b>-Anweisung wieder:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TextdateiZeilenweiseEinlesen()\r\n     <span style=\"color:blue;\">Dim <\/span>strDateipfad<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intDateinummer<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strZeile<span style=\"color:blue;\"> As String<\/span>\r\n     strDateipfad = CurrentProject.Path & \"\\Textdatei.txt\"\r\n     <span style=\"color:blue;\">If <\/span>Dir(strDateipfad) = \"\"<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Die Datei existiert nicht: \" _\r\n             & strDateipfad, vbExclamation\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     intDateinummer = FreeFile\r\n     Open strDateipfad For Input<span style=\"color:blue;\"> As <\/span>intDateinummer\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> EOF(intDateinummer)\r\n         Line Input #intDateinummer, strZeile\r\n         <span style=\"color:blue;\">Debug.Print<\/span> strZeile\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     \r\n     Close #intDateinummer\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Dateien lesen und schreiben mit Write # und Read #<\/h2>\n<p>Es gibt eine weitere Methode, um Dateien mit Daten zu f&uuml;llen. Dabei handelt es sich um die <b>Write #<\/b>-Anweisung. Diese wird in der Regel gemeinsam mit der <b>Read #<\/b>-Methode verwendet &#8211; <b>Write # <\/b>schreibt in die Datei, <b>Read # <\/b>liest aus der Datei.<\/p>\n<p>Warum werden diese als Paar genutzt? Weil <b>Write # <\/b>in einem speziellen Format schreibt, das am einfachsten mit <b>Read # <\/b>wieder eingelesen werden kann.<\/p>\n<h2>Datei mit Write # schreiben<\/h2>\n<p>Im folgenden Beispiel nutzen wir die <b>Write #<\/b>-Anweisung, um Daten strukturiert in eine Datei zu schreiben. Dazu nutzen wir eine Access-Tabelle als Datenquelle. Diese enth&auml;lt die drei Felder <b>PersonID<\/b>, <b>Person <\/b>und <b>Alter <\/b>mit einigen wenigen Datens&auml;tzen (siehe Bild 2). <\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_454_002.png\" alt=\"Daten zum Schreiben in eine Datei\" width=\"424,6267\" height=\"175,0654\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Daten zum Schreiben in eine Datei<\/span><\/b><\/p>\n<p>Die folgende Prozedur tr&auml;gt den Namen der zu erstellenden Datei in die Variable <b>strDateipfad <\/b>ein. Dann &ouml;ffnet sie ein Recordset auf Basis der oben vorgestellten Tabelle und &ouml;ffnet die Datei aus <b>strDateipfad <\/b>mit einer mit <b>FreeFile <\/b>ermittelten Dateinummer zum Schreiben (<b>For Output<\/b>).<\/p>\n<p>Danach durchl&auml;uft sie in einer <b>Do While<\/b>-Schleife das Recordset und ruft f&uuml;r jeden Datensatz einmal die <b>Write #<\/b>-Anweisung auf. Diese verwendet als ersten Parameter die Dateinummer und in den folgenden Parametern die Inhalte der Felder <b>PersonID<\/b>, <b>Person <\/b>und <b>Alter<\/b>.<\/p>\n<p>Wichtig ist, dass wir die Inhalte der numerischen Felder nochmal in den entsprechenden Datentyp konvertieren m&uuml;ssen, also <b>PersonID <\/b>mit der <b>CLng<\/b>-Funktion und <b>Alter <\/b>mit der <b>CInt<\/b>-Funktion. Wenn wir dies nicht tun, werden alle Inhalte als String interpretiert und in Anf&uuml;hrungszeichen eingeschlossen. Dadurch k&ouml;nnen sie nicht mehr korrekt eingelesen werden.<\/p>\n<p>Nachdem alle Datens&auml;tze geschrieben wurden, schlie&szlig;t sie die Textdatei und die &uuml;brigen Elemente:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>SchreibePersonenInDatei()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strDateipfad<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intDateinummer<span style=\"color:blue;\"> As Integer<\/span>\r\n     strDateipfad = CurrentProject.Path & \"\\Personen.txt\"\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"tblPersonen\")\r\n     intDateinummer = FreeFile\r\n     Open strDateipfad For Output<span style=\"color:blue;\"> As <\/span>#intDateinummer\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         Write #intDateinummer, CLng(rst!PersonID), _\r\n             rst!Person, CInt(rst!Alter)\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     Close #intDateinummer\r\n     rst.Close\r\n     <span style=\"color:blue;\">Set<\/span> rst = Nothing\r\n     <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis sehen wir in Bild 3. Jeder Datensatz ist in einer eigenen Zeile gelandet und jeder Feldinhalt wird in Anf&uuml;hrungszeichen eingefasst und durch ein Komma vom n&auml;chsten Eintrag getrennt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_454_003.png\" alt=\"Ergebnis der Write-Anweisung\" width=\"424,6267\" height=\"219,1328\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Ergebnis der Write-Anweisung<\/span><\/b><\/p>\n<h2>Datei mit Read # lesen<\/h2>\n<p>Nun wollen wir eine solche Datei auch wieder einlesen. Dazu verwenden wir die <b>Input #<\/b>-Anweisung.<\/p>\n<p>Die Prozedur aus Listing 1 ben&ouml;tigt einige weitere Variablen, da wir die Inhalte der einzelnen Felder zwischenspeichern m&uuml;ssen, bevor wir diese in die Tabelle schreiben. Sie tr&auml;gt wieder den Dateinamen in die Variable <b>strDateipfad <\/b>ein. Bevor sie die Datei zum Lesen &ouml;ffnet, pr&uuml;ft sie zuerst mit der <b>Dir<\/b>-Funktion, ob die Datei &uuml;berhaupt vorhanden ist. Falls nicht, wird die Prozedur nach Ausgabe einer entsprechenden Meldung beendet.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>LesePersonenAusDatei()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strDateipfad<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intDateinummer<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngPersonID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strPerson<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intAlter<span style=\"color:blue;\"> As Integer<\/span>\r\n     strDateipfad = CurrentProject.Path & \"\\Personen.txt\"\r\n     <span style=\"color:blue;\">If <\/span>Dir(strDateipfad) = \"\"<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Die Datei existiert nicht: \" & strDateipfad, vbExclamation\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"tblPersonen\")\r\n     intDateinummer = FreeFile\r\n     Open strDateipfad For Input<span style=\"color:blue;\"> As <\/span>#intDateinummer\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> EOF(intDateinummer)\r\n         Read #intDateinummer, lngPersonID, strPerson, intAlter\r\n         rst.Add<span style=\"color:blue;\">New<\/span>\r\n         rst!Person = strPerson\r\n         rst!Alter = intAlter\r\n         rst.Update\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     Close #intDateinummer\r\n     rst.Close\r\n     <span style=\"color:blue;\">Set<\/span> rst = Nothing\r\n     <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Prozedur zum Einlesen von Daten einer Textdatei in eine Access-Tabelle<\/span><\/b><\/p>\n<p>Anderenfalls &ouml;ffnen wir wieder das Recordset, diesmal um Datens&auml;tze hinzuzuf&uuml;gen. Au&szlig;erdem &ouml;ffnen wir die Datei aus <b>strDateipfad<\/b> f&uuml;r den lesenden Zugriff (<b>For Input<\/b>).<\/p>\n<p>Danach durchlaufen wir in einer <b>Do While<\/b>-Schleife alle Zeilen der Textdatei, bis wir das Dateiende erreicht haben. Die dazu notwendige Abbruchbedingung lautet <b>EOF (intDateinummer)<\/b>.<\/p>\n<p>Innerhalb der Schleife lesen wir mit der <b>Read #<\/b>-Methode jeweils eine Zeile ein. Der erste Parameter ist die Dateinummer, die folgenden sind die Variablen, in die wir die Daten aus dem jeweiligen Element f&uuml;llen wollen.<\/p>\n<p>Danach f&uuml;gen wir den eingelesenen Datensatz in die Tabelle <b>tblPersonen <\/b>ein. Um den neuen Datensatz anzulegen, rufen wir zun&auml;chst die <b>AddNew<\/b>-Methode auf. Dann f&uuml;gen wir die Inhalt der Variablen den entsprechenden Feldern zu.<\/p>\n<p>Dabei lassen wir das Feld <b>PersonID <\/b>aus, weil es sich hierbei um ein <b>Autowert<\/b>-Feld handelt, das automatisch gef&uuml;llt wird.<\/p>\n<p>Nach dem F&uuml;llen der Felder speichern wir den Datensatz mit der <b>Update<\/b>-Methode.<\/p>\n<p>Schlie&szlig;lich schlie&szlig;en wir die Textdatei und das Recordset und leeren die Objektvariablen.<\/p>\n<h2>Daten mit Write # an eine Datei anf&uuml;gen<\/h2>\n<p>Gegebenenfalls m&ouml;chten wir einer Datei, die bereits die Daten aus der Tabelle einer Datenbank enth&auml;lt, die Daten aus einer anderen Tabelle hinzuf&uuml;gen. Dann k&ouml;nnen wir eine &auml;hnliche Prozedur wie zuvor verwenden. Wir m&uuml;ssen lediglich die <b>Open<\/b>-Anweisung so &auml;ndern, dass diese die Datei statt mit <b>For Output <\/b>mit <b>For Append <\/b>&ouml;ffnet:<\/p>\n<pre>Open strDateipfad For Append<span style=\"color:blue;\"> As <\/span>#intDateinummer<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>VBA bietet einige M&ouml;glichkeiten f&uuml;r das Erstellen, F&uuml;llen, &Auml;ndern und Auslesen von Textdateien. Mit diesen kann man zwar nicht alle Aufgaben bew&auml;ltigen, aber f&uuml;r einfache Zwecke lohnt sich ein Blick auf diese Sammlung. Wir meinen damit Anweisungen wie Open, Close, Print, Input und einige weitere, die spannenderweise im Objektkatalog noch nicht einmal erw&auml;hnt werden. Wir werden uns in diesem Artikel eingehend mit diesen Anweisungen besch&auml;ftigen und in verschiedenen Beispielen zeigen, wie sich damit immer wiederkehrende Aufgaben wie das Schreiben oder Lesen von Textdateien leicht bew&auml;ltigen l&auml;sst.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662024,66062024,44000025],"tags":[],"yst_prominent_words":[],"class_list":["post-55000454","post","type-post","status-publish","format-standard","hentry","category-662024","category-66062024","category-VBAProgrammierung"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000454","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000454"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000454\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000454"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000454"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000454"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000454"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}