a.grothe
Goto Top

XML Dateien in Excel importieren

Hallo zusammen,

ich möchte zwei XML Dateien (bzw. mehrere) nach Excel importieren.

Mit folgendder Sache klappt es auch ansatzweise.

Im Verzeichnis D:\_TEST\

liegen zwei Dateien TEST.xml und TEST1.xml, leider liest er mir nach Excel immer nur die erste Datei ein die zweite nimmt er nicht.

Wo liegt mein Fehler die Struktur der beiden Dokumente ist gleich?

Sub XML_Dateien_Einlesen()
'
Dim Datei$, Pfad$, DateiMatch$
Dim AnfZelle As Range, Wb As Workbook, Ws As Worksheet
On Error Resume Next

Set Wb = ActiveWorkbook
Set Ws = Wb.ActiveSheet

Set AnfZelle = Ws.Range("A1") '<== Anfangszelle im aktiven Arbeitsblatt der aktiven Arb.Mappe

Pfad$ = "D:\_TEST\" '<== Pfad zum Verzeichnis einstellen
DateiMatch$ = "TEST*.xml" '<== Datei-Matching, um gewünschte Dateien zu filtern

Datei$ = Dir(Pfad$ & DateiMatch$, vbNormal)

Do Until Len(Datei$) = 0
Wb.XmlImport URL:=Pfad$ & Datei$, ImportMap:=Nothing, Overwrite:=True, Destination:=AnfZelle
Datei$ = Dir()
Set AnfZelle = AnfZelle.Offset(1)
Loop

End Sub

Content-Key: 222998

Url: https://administrator.de/contentid/222998

Printed on: April 19, 2024 at 02:04 o'clock

Member: colinardo
colinardo Nov 26, 2013, updated at Nov 27, 2013 at 11:30:10 (UTC)
Goto Top
Hallo a.grothe,
es funktioniert nur der erste Import, weil du beim zweiten Durchlauf der Schleife als "Destination" einen Bereich angibst der nach dem ersten Import bereits der ersten Datenquelle gehört, bzw. in dem bereits die Daten des ersten Imports stehen. Da ein XML-Import immer mit einer Zuordnung zur XML-Datei durchgeführt wird darf kein anderer Import diesen Bereich überschreiben. Du musst also nach dem ersten Import die nächste leere Zelle ermitteln und dann dort hinein importieren.
Do Until Len(Datei$) = 0
  Wb.XmlImport URL:=Pfad$ & Datei$, ImportMap:=Nothing, Overwrite:=True, Destination:=AnfZelle
  Datei$ = Dir()
  Set anfZelle = anfZelle.End(xlDown).Offset(1, 0)
Loop
Beachte dabei das dann in allen Zeilen des Imports in Spalte A ein Wert stehen muss. Wenn du das nicht sicherstellen kannst, musst du die nächste freie Zelle es über die Eigenschaft "ListRows" des ListObjects ermitteln wie hier:
  counter = 1
  Do Until Len(Datei$) = 0
    Wb.XmlImport URL:=Pfad$ & Datei$, ImportMap:=Nothing, Overwrite:=True, Destination:=AnfZelle
    Datei$ = Dir()
    intNextOffset = Ws.ListObjects(counter).ListRows.Count
    Set AnfZelle = AnfZelle.Offset(intNextOffset, 0)
    counter = counter + 1
  Loop
Noch als Tipps zur Hilfe während der Entwicklungsphase:
Damit du solche Fehler in Zukunft gemeldet bekommst musst du das On Error Resume Next auskommentieren. Außerdem kannst du dann im VBA-Editor mit Breakpoints und dem Einzelschritt-Modus, Zeile für Zeile den Code ausführen, so siehst du schneller wo es hakt...

Grüße Uwe
Member: a.grothe
a.grothe Nov 27, 2013 at 11:00:35 (UTC)
Goto Top
Hallo Uwe, danke für die Hilfe: Aber er nimmt immer noch nur die erste Datei obwohl eine TEST und eine TEST1.xml im Verzeichnis liegen.

Sub XML_Dateien_Einlesen()
'
Dim Datei$, Pfad$, DateiMatch$
Dim AnfZelle As Range, Wb As Workbook, Ws As Worksheet
On Error Resume Next

Set Wb = ActiveWorkbook
Set Ws = Wb.ActiveSheet

Set AnfZelle = Ws.Range("A1") '<== Anfangszelle im aktiven Arbeitsblatt der aktiven Arb.Mappe

Pfad$ = "D:\_TEST\" '<== Pfad zum Verzeichnis einstellen
DateiMatch$ = "TEST*.xml" '<== Datei-Matching, um gewünschte Dateien zu filtern

Datei$ = Dir(Pfad$ & DateiMatch$, vbNormal)

counter = 1
Do Until Len(Datei$) = 0
Wb.XmlImport URL:=Pfad$ & Datei$, ImportMap:=Nothing, Overwrite:=True, Destination:=AnfZelle
Datei$ = Dir()
intNextOffset = Sheet.ListObjects(counter).ListRows.Count
Set AnfZeile = AnfZeile.Offset(intNextOffset, 0)
counter = counter + 1
Loop
End Sub
Member: colinardo
colinardo Nov 27, 2013 updated at 11:05:58 (UTC)
Goto Top
sorry, hatte eine Variable nicht an deine verwendete angepasst:
hier das "Sheet" durch dein "Ws" ersetzen:
intNextOffset = Sheet.ListObjects(counter).ListRows.Count
das es so aussieht:
intNextOffset = Ws.ListObjects(counter).ListRows.Count
und vergessen nicht, wenn du die Sachen erneut importieren willst musst du erst den gesamten Range löschen
und mach das On Error Reume Next mal raus damit du eventuelle Fehler siehst !!
Grüße Uwe
Member: a.grothe
a.grothe Nov 27, 2013 at 11:23:49 (UTC)
Goto Top
Danke klappt wunderbar. Mit dem Error war auch ein guter Tipp, da AnfZeile noch in AnfZelle geändert werden musste. face-smile Kann man irgendwie die Spaltenüberschriften ausblenden beim import? bzw. bei der zweiten Datei weglassen? Brauche das nur in der ersten Zeile (Kennzeichen Id Tor CreateTime SendTime CloseTime ClosedBy SendErfolg).

Kennzeichen Id Tor CreateTime SendTime CloseTime ClosedBy SendErfolg
BZ-XX 191 1 H2/ 1 2013-11-08T11:26:38.747+01:00 2013-11-08T11:30:40.531+01:00 2013-11-08T12:10:42.016+01:00 user WAHR
Kennzeichen Id Tor CreateTime SendTime CloseTime ClosedBy SendErfolg
AC-XX 4427 1 H2/ 5 2013-11-07T09:10:15.435278+01:00 2013-11-07T09:10:52.074278+01:00 2013-11-07T12:04:33.289+01:00 user WAHR
Member: colinardo
colinardo Nov 27, 2013 updated at 12:30:28 (UTC)
Goto Top
Das geht nur über einen Umweg:
Sub XML_Dateien_Einlesen()

    Dim Datei$, Pfad$, DateiMatch$
    Dim AnfZelle As Range, Wb As Workbook, Ws As Worksheet, lo As ListObject, mainLO As ListObject, col As ListRow
    On Error Resume Next
    
    Set Wb = ActiveWorkbook
    Set Ws = Wb.ActiveSheet
    
    'Range vorher löschen bevor wir importieren  
    Ws.Range("A:H").Delete  
    
    Set AnfZelle = Ws.Range("A1") '<== Anfangszelle im aktiven Arbeitsblatt der aktiven Arb.Mappe  
    
    Pfad$ = "D:\_TEST\" '<== Pfad zum Verzeichnis einstellen  
    DateiMatch$ = "TEST*.xml" '<== Datei-Matching, um gewünschte Dateien zu filtern  
    
    Datei$ = Dir(Pfad$ & DateiMatch$, vbNormal)
    
    counter = 1
    Do While Datei$ <> ""  
        Wb.XmlImport URL:=Pfad$ & Datei$, ImportMap:=Nothing, Overwrite:=True, Destination:=AnfZelle
        If counter > 1 Then
            Set lo = Ws.ListObjects(2)
            Set mainLO = Ws.ListObjects(1)
            Set col = mainLO.ListRows.Add
            lo.DataBodyRange.Copy col.Range
            intNextOffset = lo.ListRows.Count
            lo.Delete
        Else
            Set lo = Ws.ListObjects(1)
            intNextOffset = lo.ListRows.Count
        End If
        Set AnfZelle = AnfZelle.Offset(intNextOffset, 0)
        Datei$ = Dir()
        counter = counter + 1
    Loop
End Sub
Grüße Uwe
Member: a.grothe
a.grothe Nov 27, 2013 at 12:42:27 (UTC)
Goto Top
Hallo Uwe,

vielen Dank. Kannst du ein Buch (eBook) empfehlen um das besser zu verstehen?
Member: colinardo
colinardo Nov 27, 2013 at 12:45:23 (UTC)
Goto Top
Member: colinardo
colinardo Nov 27, 2013 updated at 12:50:29 (UTC)
Goto Top
Das Script macht folgendes:
Es importiert die erste CSV-Datei normal, beim Import der zweiten wird eine neue Zeile in der ersten Tabelle erstellt und der Inhalt der zweiten Tabelle ans Ende der ersten Tabelle kopiert, danach wird das ListObject in dem die zweite CSV-Datei importiert wurde wieder gelöscht, usw. Übrig bleibt nur noch eine Tabelle mit dem kompletten Inhalt aller XML-Dateien.
Grüße Uwe
Member: a.grothe
a.grothe Nov 28, 2013 at 06:54:37 (UTC)
Goto Top
Danke. Es klappt nun wunderbar. Kann man den Pfad noch so anpassen, das er auch Unterverzeichnisse durchsucht?
Member: colinardo
colinardo Nov 28, 2013 at 09:59:38 (UTC)
Goto Top
Zitat von @a.grothe:
Danke. Es klappt nun wunderbar. Kann man den Pfad noch so anpassen, das er auch Unterverzeichnisse durchsucht?
Kann man, das erfordert aber einen radikalen Umbau. Ich habe die Zeilen mal kommentiert, damit du es hoffentlich besser verstehst:
Dim AnfZelle As Range, TempZelle As Range, fso As Object, Wb As Workbook, Ws As Worksheet, Prefix As String, extension As String, firstImport As Boolean
Sub XML_Dateien_Einlesen()
    Set Wb = ActiveWorkbook
    Set Ws = Wb.ActiveSheet
    'Filesystem Object erstellen  
    Set fso = CreateObject("Scripting.FileSystemObject")  
    
    'Root-Pfad zu den Dateien  
    Pfad = "D:\_TEST"  
    'Prefix der zu importierenden Dateien  
    Prefix = "TEST"  
    'Extension der Dateien  
    extension = "xml"  
    'Import-Bereich löschen damit neu importiert werden kann/ wenn die importierten XML-Dateien mehr Spalten als 8 haben entsprechend anpassen  
    Ws.Range("A:H").Delete  
    'Import-Anfangszelle setzen  
    Set AnfZelle = Ws.Range("A1")  
    ' Temporäre Zelle für den Import von weiteren XML-Dateien  
    Set TempZelle = Ws.Range("Z1")  
    firstImport = True
    'Ordner mit Funktion rekursiv durchsuchen  
    parseFolder fso.GetFolder(Pfad), True
    'Garbage collection  
    Set fso = Nothing
    Set Wb = Nothing
    Set Ws = Nothing
End Sub

'Diese Funktion durchläuft die Unterordner rekursiv  
Function parseFolder(strFldr, boolRecursion)
    For Each f In strFldr.Files
        'Wenn Datei die Extension 'xml' hat und mit 'TEST' beginnt dann...  
        If LCase(extension) = LCase(fso.GetExtensionName(f.Path)) And Left(fso.GetFilename(f.Path), 4) = Prefix Then
            If Not firstImport Then
                ' Importiere weitere XML-Dateien  
                Wb.XmlImport URL:=f.Path, ImportMap:=Nothing, Overwrite:=True, Destination:=TempZelle
                'ListObject an der temporär importierten Zelle  
                Set lo = Ws.ListObjects(2)
                'Haupt ListObject in das wir den Inhalt des anderen ListObject importieren werden  
                Set mainLO = Ws.ListObjects(1)
                'Eine neue Reihe im Haupt ListObject hinzufügen  
                Set col = mainLO.ListRows.Add
                'Inhalt des temporären ListObject in das Haupt ListObject kopieren  
                lo.DataBodyRange.Copy col.Range
                'temporäres ListObject wieder löschen  
                lo.Delete
            Else
                'Importiere erste XML-Datei  
                Wb.XmlImport URL:=f.Path, ImportMap:=Nothing, Overwrite:=True, Destination:=AnfZelle
                ' Die erste XML-Datei ist importiert also setze firstImport = False  
                firstImport = False
            End If
        End If
    Next
    
    'Funktion rekursiv für alle Unterordner ausführen  
    If boolRecursion Then
        For Each subFolder In strFldr.SubFolders
            parseFolder subFolder, True
        Next
    End If
End Function
Grüße Uwe
Member: a.grothe
a.grothe Nov 28, 2013 at 11:33:07 (UTC)
Goto Top
Danke für die Hilfe es klappt.
Member: colinardo
colinardo Nov 28, 2013 at 11:34:53 (UTC)
Goto Top
Dann den Beitrag bitte noch als gelöst markieren. Merci.
Grüße Uwe