jojojo
Goto Top

Excel VBA: Infos automatisch aus html Datei suchen und in Excel einfügen

Hallo zusammen.

Ich habe mal wieder ein Excel VBA Problem. Durch googeln und "kopieren" von Skriptteilen komme ich nicht weiter.

Problem allgemein:
Es liegen etliche html Dateien in einem Ordner vor. Aus diesen müssen bestimmte Werte (Zahlen, aber teilw. auch mehrzeilige Textfolgen wie Sätze) ausgelesen werden. Die gesuchten Informationen sind mit Markern versehen bzw. man kann die Informationen finden, wenn man nach bestimmten Zeichenfolgen (=Marker) sucht.
Anbei eine "gekürzte" html Datei als Bsp.:

<html>
...
<h1 id="eine_var1">Info 1</h1>
...
<span id="eine_var2" style="color:Blue;">5.000 Einheiten</span>
...
funktion.ladeWert({"a1":1,"a2":2,"a3":3,"b1":99.9,"b2":88.8,"b3":11.1})
...
"festerbegriff":[{"text":"Text, Text, noch mehr Text und weiterer Text.","da":"1 Angabe"},{"text":"Ein weiterer Text mit noch mehr Inhalt.","da":"2 Angabe"},
...
</html>

Die gesuchten Werte sind bei dieser html Datei dann z.B.:
Info 1
5.000 Einheiten (Problem: Marker kann auch heißen: <span id="eine_var2" style="color:Yellow;">
1
2
3
99.9
88.8
11.1
Text, Text, noch mehr Text und weiterer Text.
1 Angabe
Ein weiterer Text mit noch mehr Inhalt.
2 Angabe

Problem bei den letzten 4 Infos (hinter "festerbegriff") ist, dass nicht fest definiert ist, ob es nur 4 Infos sind oder weitere (also weitere Wiederholungen der Folge {"text":"...","da":"..."}).

Für jede html Datei müsste in Excel eine Zeile mit den jeweiligen Infos "angelegt" bzw. eingefügt werden (Info 1 | 5.000 Einheiten | 1 | ...)

Mit meinen VBA Kenntnissen komme ich nicht weiter und hoffe daher auf eure Hilfe.

Kann mir jemand weiterhelfen?

Ein schönes Wochenende.
Vielen Dank.

Content-ID: 244775

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

Ausgedruckt am: 19.11.2024 um 15:11 Uhr

colinardo
Lösung colinardo 27.07.2014, aktualisiert am 29.07.2014 um 08:26:10 Uhr
Goto Top
Moin jojojo,
anhand deines HTML-Schnippsels geht folgender Code. Hierbei können die Anzahl der Werte hinter ladeWert eine beliebige Anzahl haben, ebenso wie hinter "festerbegriff".
(Pfad zu den HTML-Dateien in Zeile 3 angeben und Startzelle in Zeile 7)
Sub ImportHTML()
    'Pfad mit den HTML Dateien  
    pfad = "C:\htmldateien"  
    'Zielworksheet festlegen  
    Set ws = Worksheets(1)
    'Startzelle setzen  
    Set rngCurrent = ws.Range("A1")  
    'Objekte erzeugen  
    Set fso = CreateObject("Scripting.FilesystemObject")  
    Set regex = CreateObject("VBScript.Regexp")  
    'Eigenschaften für regex setzen  
    regex.IgnoreCase = True
    regex.Global = True
    'HTML Dateien im Verzeichnis auflisten  
    f = Dir(pfad & "\*.html")  
    While f <> ""  
        ' Inhalt der Datei holen  
        strContent = fso.OpenTextfile(pfad & "\" & f, 1).ReadAll()  
        'Regex Pattern zum extrahieren der gewünschten Fragmente  
        regex.Pattern = "<h1 id=""eine_var1"">([\s\S]*?)</h1>[\s\S]*<span id=""eine_var2"" style=""color:(Blue|Yellow);"">([\s\S]*?)</span>[\s\S]*ladeWert\(\{([^}]*)[\s\S]*festerbegriff"":\[(\{[^\]]*\})"  
        'Regex ausführen  
        Set matches = regex.Execute(strContent)
        If matches.Count > 0 Then
            'Regex Submatches Variablen zuweisen  
            strPart1 = matches(0).submatches(0)
            strPart2 = matches(0).submatches(2)
            strPart3 = matches(0).submatches(3)
            strPart4 = matches(0).submatches(4)
            
            'Ersten Wert schreiben  
            rngCurrent.Value = strPart1
            'Zweiten Wert schreiben  
            rngCurrent.Offset(0, 1).Value = strPart2
            
            ' Erstes Javascript Array auslesen  
            col = 2
            arr = Split(strPart3, ",", -1, vbTextCompare)  
            For i = 0 To UBound(arr)
                wert = Split(arr(i), ":", 2, vbTextCompare)(1)  
                rngCurrent.Offset(0, col).Value = Trim(wert)
                col = col + 1
            Next
            
            'zweites JavaScript Array auslesen  
            regex.Pattern = """text"":""(.*?)"",""da"":""(.*?)"""  
            Set matches = regex.Execute(strPart4)
            If matches.Count > 0 Then
                For Each Match In matches
                    rngCurrent.Offset(0, col).Value = Match.submatches(0)
                    rngCurrent.Offset(0, col + 1).Value = Match.submatches(1)
                    col = col + 2
                Next
            End If
        End If
        ' nächste Datei  
        f = Dir
        ' aktuelle Zelle eins nach unten verschieben  
        Set rngCurrent = rngCurrent.Offset(1, 0)
    Wend
    
    Set fso = Nothing
    Set regex = Nothing
End Sub
Viel Spaß beim Lernen von Regular Expressions. Den Regex werde ich jetzt nicht bis ins letzte Detail erläutern, Infos zu Regulären Ausdrücken findest du zu Hauf im Netz.

Viel Erfolg
Grüße Uwe
jojojo
jojojo 27.07.2014 aktualisiert um 18:24:10 Uhr
Goto Top
Hallo Uwe,

vielen Dank. Mit der Beispiel html Datei funktioniert es.

Seit heute Morgen sitze ich am PC und versuche 3 Dinge zu modifizieren:

1. Weitere Informationen aus der html Datei auslesen:
Hier habe ich in Zeile 20 bei regex. Pattern entsprechende weitere Keywords/ Marker hinzugefügt. Außerdem ab Zeile 28 weitere Submatches-Zuweisungen ("strPart5 = matches(0).submatches(5)"...). Abhängig von der Art der Information habe ich die Werte auch "zum Schreiben" hinzugefügt ("rngCurrent.Value = strPart5"...). Mit dem Ergebnis, dass gar keine Infos mehr eingelesen werden?!

2. Beim Fehlen der Information/ des Suchfragments für die fehlende Information eine "0" in die Zelle schreiben. (Bei Arrays nur einmal eine 0):
Aktuell ist es so, dass wenn eine der Variablen in der html-Datei nicht vorkommt, die ganze html-Datei nicht berücksichtigt wird. Hier habe ich versucht, nicht vorhandene Variablen durch eine 0 zu ersetzen (If strPart1 > 0 "Wert schreiben" Else strPart1 = 0 ). Hatte keine Wirkung, allerdings funktioniert das Skript weiterhin, falls die Information vorhanden ist.

3. Beim Array nach "da" steht die Information teilw. nicht in Anführungszeichen.
Es kommt teilw. vor, dass die Information des Felds "da" ohne Anführungszeichen in der html-Datei steht. Das habe ich erst jetzt gemerkt. Also so:
"festerbegriff":[{"text":"Text, Text, noch mehr Text und weiterer Text.","da":falsch},{"text":"Ein weiterer Text mit noch mehr Inhalt.","da":falsch},
Die Information wird dann nicht mehr eingelesen. Hier fäll tmir auch keine Lösung ein.

Viele Grüße
Jojojo
colinardo
Lösung colinardo 27.07.2014, aktualisiert am 29.07.2014 um 08:26:21 Uhr
Goto Top
Zitat von @jojojo:
1. Weitere Informationen aus der html Datei auslesen:
Hier habe ich in Zeile 20 bei regex. Pattern entsprechende weitere Keywords/ Marker hinzugefügt.
Arbeite dazu erst mal das verlinkte Tutorial oben durch, bevor du via Trial and Error dort Dinge einfügst, das wird sonst zu 95 % nichts. Reguläre Ausdrücke muss man erst verstehen sonst wirst du damit keinen Erfolg haben.
Außerdem ab Zeile 28 weitere Submatches-Zuweisungen ("strPart5 = matches(0).submatches(5)"...).
dazu müssen natürlich die entsprechenden Klammern an der richtigen Stelle im regex gesetzt werden.
Abhängig von der Art der Information habe ich die Werte auch "zum Schreiben" hinzugefügt ("rngCurrent.Value = strPart5"...).
du musst hier ja auch den richtigen Spalten-Offset angeben. rngCurrent ist immer die aktuelle Zeile in Spalte A im Worksheet, je nachdem in welche Spalte du also den Wert schreiben willst musst du einen Spaltenoffset wie beim zweiten und bei den anderen Werten angeben.

2. Beim Fehlen der Information/ des Suchfragments für die fehlende Information eine "0" in die Zelle schreiben.
(Bei Arrays nur einmal eine 0):
Aktuell ist es so, dass wenn eine der Variablen in der html-Datei nicht vorkommt, die ganze html-Datei nicht berücksichtigt
Das liegt daran das ich die Regex in einer einzigen zusammengefasst habe, welche alle Parts die zu extrahieren sind zusammenfasst, wenn hier einer fehlt trifft der gesammte Match nicht mehr. Bei Fehlen von bestimmten Teilen musst du den Pattern also aufsplitten und jeweils separat ausführen lassen.

3. Beim Array nach "da" steht die Information teilw. nicht in Anführungszeichen.
Es kommt teilw. vor, dass die Information des Felds "da" ohne Anführungszeichen in der html-Datei steht. Das habe
das ist kein Problem wenn der Regex in Zeile 45 folgendermaßen angepasst wird:
regex.Pattern = """text"":""([\s\S]*?)"",""da"":""?([^}]*?)""?\}"
Druch die zwei zusätzlichen Fragezeichen werden die Anführungszeichen optional. Zur Info, Einfache Anführungszeichen müssen innerhalb einer VBA-Zeichenfolge verdoppelt werden.

Grüße Uwe
jojojo
jojojo 29.07.2014 um 08:25:37 Uhr
Goto Top
Hallo Uwe,

vielen Dank für die Hinweise. Läuft jetzt so, wie ich mir das vorgestellt habe face-wink

Grüße
jojojo
jojojo
jojojo 29.07.2014 um 13:01:06 Uhr
Goto Top
... Noch eine kurze Follow-up-Frage:
Beim zweiten Array können im Inhaltsteil auch Gleichheitszeichen vorkommen. Das ist kein Problem, wenn sie in der Textmitte stehen. Wenn das "=" jedoch am Anfang steht, wie z.B. bei der folgenden Konstellation, erhalte ich jedoch ein "Laufzeitfehler 1004: Anwendungs- oder objektdefinierter Fehler" in Zeile 49:
"festerbegriff":[{"text":"=== === ======= = == Text, Text, noch mehr Text und weiterer Text.","da":"1 Angabe"},

Eigentlich müsste das doch durch [\s\S]*? gefunden werden, oder?!
Ich habe es auch schon mit [=]*? versucht, in Zeile 45.

Hast du diesbezüglich einen Tipp?

Viele Grüße
jojojo
colinardo
colinardo 29.07.2014 aktualisiert um 13:38:10 Uhr
Goto Top
Zitat von @jojojo:
Eigentlich müsste das doch durch [\s\S]*? gefunden werden, oder?!
yip, matcht quasi alles([\s\S]) lazy(?)
Hast du diesbezüglich einen Tipp?
Ja, ein Gleichheitszeichen am Anfang eines Zellwertes interpretiert Excel als eine Formel ! Du musst den Wert beim schreiben in die Zelle also mit einem einfachen Hochkomma (') maskieren.
jojojo
jojojo 29.07.2014 um 14:44:51 Uhr
Goto Top
Der Fehler muss bei dir woanders liegen ... der Regex ist in Ordnung.

Ne. Funktioniert im Ursprungscode auch schon nicht, wenn das Bsp. wie oben beschrieben aussieht.
colinardo
Lösung colinardo 29.07.2014 aktualisiert um 15:28:10 Uhr
Goto Top
Zitat von @jojojo:
Ne. Funktioniert im Ursprungscode auch schon nicht, wenn das Bsp. wie oben beschrieben aussieht.
siehe mein korrigierter Kommentar ...
Ein Gleichheitszeichen am Anfang eines Zellwertes interpretiert Excel als eine Formel ! Du musst den Wert beim schreiben in die Zelle also mit einem einfachen Hochkomma (') maskieren.
rngCurrent.Offset(0, col).Value = "'" & Match.submatches(0)
jojojo
jojojo 29.07.2014 um 15:27:58 Uhr
Goto Top
Zitat von @colinardo:
rngCurrent.Offset(0, col).Value = "'" & Match.submatches(0)


Jo. Super. Klappt!
Viele, vielen Dank.