Geschrieben von: Christian Holm
Kategorie: Datenbank
This printed page brought to you by AlphaSierraPapa
Manchmal stellt sich einem die Aufgabe, Datenbanksysteme aus irgendwelchen Gründen zu wechseln. Die Daten müssen transferiert werden - und als kleinster gemeinsamer Nenner zwischen den Systemen bleibt meist nur das CSV Format. Dieser Artikel zeigt einen von vielen Wegen um eine CSV-Datei in eine Access Datenbank zu konvertieren - und das, ohne daß Access installiert sein muß.
Wie Sie sicher schon aus der Überschrift entnehmen konnten, zeige ich Ihnen heute den umgekehrten Weg den der Artikel CSVs aus MDBs leicht gemacht beschrieben hat. Abermals habe ich eine VBScript Klasse geschrieben, um den Konvertierungsvorgang zu vollziehen. Man kann damit leicht den Vorgang automatisieren und das Script läßt auch einige Konfigurationsoptionen zu.
Beginnen wir also gleich mit der Klasse CSV2MDB, die den Konvertierungsvorgang vollzieht, und in der CSV2MDB.Class.asp Datei zu finden ist.
Class CSV2MDB Public FirstLineContainsFieldNames Public UseTextQualifier Public CreateNewDB Public TableExists Public Sub ConvertToMDB(ByVal strMDBPath, ByVal strTableName, _ ByVal strCSVPath, ByVal strCSVFileName) Const ForReading = 1 Const ForWriting = 2 strDB = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strMDBPath
Zuerst werden einige Properties deklariert, mit denen man das Objekt leicht an die speziellen Wünsche anpassen kann. Die Properties nehmen die Werte true oder false an. Mit der FirstLineContainsFieldNames Property können Sie angeben, ob die erste Zeile der CSV-Datei die Spaltennamen der Datentabelle enthält. Mit der entsprechenden Angabe von UseTextQualifier signalisieren Sie die Verwendung von doppelten Anführungszeichen als zusätzliche Spaltenbegrenzer. Diese Formatierung ist besonders dann nützlich, wenn Datensätze Beistriche etc. verwenden, die als Delimiter mißinterpretiert werden könnten.
Die CreateNewDB Property bietet die Möglichkeit eine neue Datenbank für die Importdaten anlegen zu lassen. Diese Datenbank kann entweder im selben Verzeichnis, wo das Script ausgeführt wurde, abgelegt werden oder in einem beliebigen Pfad gespeichert werden. Diese Pfadinformationen werden der strMDBPath Variable entnommen, die der ConvertToMDB Sub-Prozedur als Parameter übergeben wird. (Die ConvertToMDB Sub-Prozedur enthält die Konvertierungsfunktionalität in mdb-Dateien.)
Die letzte Property ist TableExists. Falls diese Property auf true gesetzt wurde, wird eine eventuell schon vorhandene Tabelle gleichen Namens gelöscht. Dieser Fall tritt nur dann ein, wenn auf die Erstellung einer neuen Access Datenbank verzichtet wurde (CreateNewDB = false).
Zusätzlich zu den oben besprochenen Parametern, die der ConvertToMDB Sub-Prozedur übergeben werden müssen, muß noch der Pfad, wo sich die CSV-Datei befindet (strCSVPath) und ihr Dateiname (strCSVFileName) angegeben werden. Die beiden angeführten Konstanten ForReading und ForWriting werden in einem späteren Abschnitt des Sourcecodes für die Dateioperationen mit dem FileSystemObject benötigt. Die strDB Variable enthält die für eine Access Datenbank benötigten Providerinformationen und den Pfad zu dieser. Diese Variable wird entweder für die Erstellung einer neuen Datenbank oder zur Öffnung der Verbindung zu einer bestehenden Datenbank benötigt.
Da die Erstellung einer neuen Access Datenbank unabhängig von Access geschehen soll, verwenden wir ADOX (Microsoft ADO Extensions for DDL and Security) um dies zu erledigen:If (CreateNewDB) Then Set objNewCatalog = Server.CreateObject("ADOX.Catalog") objNewCatalog.Create strDB Set objNewCatalog = Nothing End If
Da nur eine neue Datenbank erstellt werden soll, wenn auch die CreateNewDB auf true gesetzt ist, verwenden wir hier eine If-Verzweigung. Da die strDB in Kombination mit dem übergebenen Parameter strMDBPath alle Informationen für einen Datenbank enthält, können wir also mit der Create Methode eine neue erstellen. Diese wird gemäß den Pfadangaben der strMDBPath Variable angelegt.
Falls in einer vorhandenen Datenbank bereits eine Tabelle gleichen Namens existiert, löscht die folgende Anweisung mittels DROP diese:
If (TableExists) Then Set objDropTableConn = Server.CreateObject("ADODB.Connection") objDropTableConn.Open strDB objDropTableConn.Execute "DROP TABLE " & strTableName objDropTableConn.Close Set objDropTableConn = Nothing End If
Nun sind wir soweit, daß wir eine neue Tabelle in der bereits existierenden bzw. neu erstellten Datenbank erstellen können. Dies geschieht wiederum mit Hilfe von ADOX:
Set objCatalog = Server.CreateObject("ADOX.Catalog") objCatalog.ActiveConnection = strDB Set objTable = Server.CreateObject("ADOX.Table") Set fso = Server.CreateObject("Scripting.FileSystemObject") objTable.Name = strTableName objCatalog.Tables.Append objTable Set CVSFile = fso.OpenTextFile(strCVSFileFullPath, ForReading) strFields = CVSFile.ReadLine CVSFile.Close Set CVSFile = Nothing Set fso = Nothing
Zusätzlich treffen wir eine Vorbereitung für die Erstellung der Spaltennamen. Hier wird die erste Zeile (ReadLine Methode des FileSystemObjects) der mit den Variablen strCSVPath und strCSVFileName angegebenen CSV-Datei eingelesen. Diese Information, welche in der strFields Variable abgelegt ist, wird später entweder für die Feldnamen selbst, oder für die Bestimmung der Spaltenanzahl verwendet.
Als nächstes schreiben wir die Spaltenüberschriften in die neu erstellte Tabelle. Hier gibt es wie schon erwähnt zwei Möglichkeiten: entweder entspricht die erste Zeile der CSV-Datei den Spaltenüberschriften oder nicht. Die erste Zeile der CSV-Dateien haben wir ja schon in der strFields gespeichert und können nun per Split Funktion den String in die einzelnen Spalten aufteilen und jede einzelne der Tabelle als Überschrift zuweisen.
Hier tritt wieder der Fall ein, daß man überprüfen muß, ob die Spalten doppelte Anführungszeichen als zusätzliche Delimiter haben. Wenn ja, dann werden diese mit der Replace Funktion entfernt:
If (FirstLineContainsFieldNames) Then If (UseTextQualifier) Then strFields = Replace(strFields, """","") End If arFields = Split(strFields,",") For Each item In arFields objTable.Columns.Append item Next Else arFields = Split(strFields,",") nCount = 0 For Each item In arFields nCount = nCount + 1 objTable.Columns.Append "Field" & nCount Next End If
Wenn aber die erste Zeile in der CSV-Datei nicht die Spaltenüberschriften enthält, schreiben wir Standardwerte mit einer fortlaufenden Nummer als Überschriften. Die fortlaufende Nummer wird durch die Anzahl der Substrings des Arrays arFields bestimmt. Die neu generierten Standardüberschriften, die sich nachträglich ändern lassen, da ja keine Beziehungen zu anderen Tabellen existieren, werden wiederum mit Hilfe der ADOX Methode Append den Spalten zugewiesen.
Jetzt können wir endlich die Daten aus der CSV-Datei in die Access Datenbank importieren. Da standardmäßig für Access immer die erste Zeile einer CSV-Datei als Spaltenüberschriften herangezogen wird, müssen wir im Fall, daß keine angegeben wurden und welche generiert werden mußten, ein wenig tricksen. Es sollen ja weder die erste Zeile, welche die eigentlichen Daten enthält als Überschrift verwendet werden, noch Komplikationen während des Einfügens der Daten per SQL Statement auftreten.
Wir erstellen uns also mit dem FileSystemObject eine temporäre Datei (temp.csv), die in der ersten Zeile unsere vorher generierten Überschriften enthält. Nach diesem Eintrag werden dann die eigentlichen Daten aus der ursprünglichen CSV-Datei mittels der ReadAll Methode des FileSystemObjects eingefügt. Weiters ist hier wieder auf die Möglichkeit der zusätzlichen Delimiter zu achten, damit die ersten Felder korrekt formatiert werden:
If Not (FirstLineContainsFieldNames) Then Set objFSO = Server.CreateObject("Scripting.FileSystemObject") Set objTempFile = objFSO.OpenTextFile(strCSVPath & "temp.csv", ForWriting, True) If (UseTextQualifier) Then For n=1 To nCount objTempFile.Write """Field" & n If n <> nCount Then objTempFile.Write """," End If Next Else For n=1 To nCount objTempFile.Write "Field" & n If n <> nCount Then objTempFile.Write "," End If Next End If objTempFile.Write """" objTempFile.WriteBlankLines(1) Set CVSFile = objFSO.OpenTextFile(strCVSFileFullPath, ForReading) strCVSContent = CVSFile.ReadAll CVSFile.Close Set CVSFile = Nothing objTempFile.Write strCVSContent objTempFile.Close
Nun da diese temporäre Datei erfolgreich erstellt wurde, können wir mit einem angepaßten SQL Statement die Daten aus dieser Datei in unsere Tabelle einfügen:
strSQLAlt = "INSERT INTO " & strTableName & " SELECT * FROM [temp.csv" strSQLAlt = strSQLAlt & "] IN """ & strCSVPath & """ ""TEXT;""" objConn.Execute strSQLAlt Set objTempFile = objFSO.GetFile(strCSVPath & "temp.csv") objTempFile.Delete
Da wir nun die Temporärdatei nicht mehr benötigen, wird sie am Schluß wieder gelöscht. Die Alternative (Spaltenüberschiften in der ersten Zeile) ist um einiges weniger aufwendig. Hier reicht das Einfügen der Daten aus der mit strCSVPath und strCSVFileName angegebenen CSV-Datei mittels SQL Statement. Dieses ist in der Variable strSQL enthalten:
strSQL = "INSERT INTO " & strTableName & " SELECT * FROM [" & strCSVFileName strSQL = strSQL & "] IN """ & strCSVPath & """ ""TEXT;""" objConn.Execute strSQL
Als Abschluß möchte ich noch die zwei möglichen Hauptvarianten in Form von Beispielscripts präsentieren. Zunächst nehmen wir an, daß die CSV-Datei in der ersten Zeile die Datenspaltenüberschrift enthält. Für diesen Fall wäre dieser Sourcecode in Verbindung mit der besprochenen VBScript Klasse notwendig (TestDrive.asp):
<!-- #include file="CSV2MDB.Class.asp" --> <% Dim objCSV2MDB Set objCSV2MDB = New CSV2MDB strMDBPath = Server.MapPath("csv2mdb.mdb") strTableName = "tProducts" strCSVPath = Server.MapPath("./") & "\" strCSVFileName ="test.csv" objCSV2MDB.FirstLineContainsFieldNames = true objCSV2MDB.UseTextQualifier = true objCSV2MDB.CreateNewDB = true objCSV2MDB.TableExists = false objCSV2MDB.ConvertToMDB strMDBPath, strTableName, strCSVPath, strCSVFileName Set objCSV2MDB = Nothing %>
Zuerst wird die CSV2MDB.Class.asp ASP-Datei, welche die Klasse enthält, per include-Anweisung eingebunden. Danach ist ein neues Objekt mit der Referenz zu der VBScript Klasse zu instanzieren. Weiters sind den der Sub-Prozedur zu übergebenden Parametern entsprechende Werte zuzuweisen, und die Properties des Objektes zu setzen. Schließlich und endlich erfolgt der Aufruf der Prozedur mit der Übergabe der Parameter - fertig.
Die verwendete Beispiel-CSV-Datei sieht wie folgt aus:
Das Ergebnis - die Access Datenbank - sieht nach erfolgreicher Erstellung aus der CSV-Datei so aus:
Für den Fall, daß keine Spaltenüberschriften vorhanden sind, sind im Beispielscript TestDrive.asp folgende Änderungen in der Zeile, die die FirstLineContainsFieldNames Property enthält, durchzuführen:
objCSV2MDB.FirstLineContainsFieldNames = false
Dies ergibt bei entsprechender CSV-Datei folgendes Ergebnis:
Natürlich sind dann im Einsatz des Scriptes die Properties und Pfadeinstellungen ensprechend dem Anwendungsfall anzupassen.
Das gezeigte Beispiel läßt sich wie Sie sicherlich erkannt haben, leicht an den Anwendungsfall anpassen und vor allem z.B. für mehrere Dateien automatisieren. Zwar gehen bei einem solchen Konvertierungsvorgang alle Relationships zwischen den Tabellen oder auch anderen externen Datenbanken verloren, diese sind aber meist einfacher und schneller wieder herzustellen als die Datensätze.
This printed page brought to you by AlphaSierraPapa
Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20010607.zip
CSVs aus MDBs leicht gemacht
http:/www.aspheute.com/artikel/20010605.htm
Klassen in VBScript
http:/www.aspheute.com/artikel/20000526.htm
Tabellenerstellung mit ADOX
http:/www.aspheute.com/artikel/20000626.htm
Yet Another Access Database Administration Tool
http:/www.aspheute.com/artikel/20020410.htm
©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.