Einzelne Begriffe aus PDF in Excel per VBA auslesen
Hallo zusammen,
ich verwende das folgende Skript PDF auslesen und per VBA in Excel schreiben, um bestimmte Begriffe aus meiner PDF-Datei auszulesen und in eine Excel-Tabelle zu übertragen.
Bei meinen PDFs handelt es sich um Bestellungen. Die Struktur/Aufbau der PDFs macht mir dabei Schwierigkeiten.
Die Bestellung sieht folgendermaßen aus:
Nun möchte ich von jeder Position (01, 02, ..., n) den Artikelname, den Liefertermin und wenn möglich die Stückzahl in eine Excel-Tabelle übertragen.
Momenten sieht es so aus, dass ich erst einzeln nach jeder Position von 01 ... n suche:
Geht das auch einfacher?
Dann suche ich nach allen Lieferterminen und sortiere diese der Reihe nach in die Zeilen ein (neben den zugehörigen Pos.-Nr. 01, 02, ...; bedingt durch die Reihenfolge der Pos.-Abfrage oben):
Was muss ich machen, damit nur der Artikelname oder nur der Liefertermin extrahiert wird, ohne die komplette Zeile dahinter?
Bei der Generierung der txt-Datei werden auch manchmal die Stückzahlen nicht neben die zugehörige Pos.-Nr. geschrieben, sondern weiter oben!? Das macht das ganze echt schwierig.
Kann mir jemand weiterhelfen?
Vielen Dank
Gruß
Joha
ich verwende das folgende Skript PDF auslesen und per VBA in Excel schreiben, um bestimmte Begriffe aus meiner PDF-Datei auszulesen und in eine Excel-Tabelle zu übertragen.
Bei meinen PDFs handelt es sich um Bestellungen. Die Struktur/Aufbau der PDFs macht mir dabei Schwierigkeiten.
Die Bestellung sieht folgendermaßen aus:
Pos Artikel Menge ME
01 X123456789 30 Stück
Artikel 456 mit ABC
Entwurf: 2010
Bereitstellung
2 St. DEF
Liefertermin: 20.04.15
02 X012345678 30 Stück
Artikel 123 mit ABC
Entwurf: 2010
Bereitstellung
2 St. DEF
Liefertermin: 11.07.15
Nun möchte ich von jeder Position (01, 02, ..., n) den Artikelname, den Liefertermin und wenn möglich die Stückzahl in eine Excel-Tabelle übertragen.
Momenten sieht es so aus, dass ich erst einzeln nach jeder Position von 01 ... n suche:
'Bestellung Pos.01 auslesen
regex.Pattern = "^01 ([^\r\n]+)"
Set matches = regex.Execute(strTXT)
If matches.Count > 0 Then
rngLastRow.Cells(2, 1).Value = matches(0).submatches(0) 'Artikel in Spalte A schreiben
End If
'Bestellung Pos.02 auslesen
regex.Pattern = "^02 ([^\r\n]+)"
Set matches = regex.Execute(strTXT)
If matches.Count > 0 Then
rngLastRow.Cells(3, 1).Value = matches(0).submatches(0) 'Artikel in Spalte A schreiben
End If
...
Geht das auch einfacher?
Dann suche ich nach allen Lieferterminen und sortiere diese der Reihe nach in die Zeilen ein (neben den zugehörigen Pos.-Nr. 01, 02, ...; bedingt durch die Reihenfolge der Pos.-Abfrage oben):
' Liefertermin auslesen
regex.Pattern = "Liefertermin: ([^\r\n]+)"
regex.Global = True
regex.MultiLine = True
Set matches = regex.Execute(strTXT)
i = 2
For Each Match In matches
rngLastRow.Cells(i, 2).Value = Match.submatches(0)
i = i + 1
Next
Was muss ich machen, damit nur der Artikelname oder nur der Liefertermin extrahiert wird, ohne die komplette Zeile dahinter?
Bei der Generierung der txt-Datei werden auch manchmal die Stückzahlen nicht neben die zugehörige Pos.-Nr. geschrieben, sondern weiter oben!? Das macht das ganze echt schwierig.
Kann mir jemand weiterhelfen?
Vielen Dank
Gruß
Joha
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 301368
Url: https://administrator.de/forum/einzelne-begriffe-aus-pdf-in-excel-per-vba-auslesen-301368.html
Ausgedruckt am: 23.04.2025 um 14:04 Uhr
20 Kommentare
Neuester Kommentar

Hallo Joha!
Anhand Deines Beispieltextes sollte es so gehen:
Gruß Dieter
[edit] Code an die neue Vorlage (weiter unten) angepasst [/edit]
Anhand Deines Beispieltextes sollte es so gehen:
Sub PDF2Excel()
'.........
arrValues = GetMatchValues(FSO.OpenTextFile(colTFiles.Item(i)).ReadAll)
If IsArray(arrValues) Then
intNextLine = Cells(Rows.Count, "A").End(xlUp).Row + 1
Cells(intNextLine, "A").Resize(UBound(arrValues, 1) + 1, UBound(arrValues, 2) + 1).Value = arrValues
Else
'keine treffer
End If
'.....
End Sub
Private Function GetMatchValues(ByRef strText) As Variant
Dim objMatches As Object, arrValues As Variant, i As Long
With CreateObject("VBScript.RegExp")
.Global = True
.MultiLine = True
.IgnoreCase = True
.Pattern = "^\d+\s+(\w+)\s+(\d+)\s+St.*\s+([^\r.]+)\s+.*\s+.*\s+.*\s+Liefertermin:\s+([\.\d]+)"
Set objMatches = .Execute(strText)
End With
If objMatches.Count Then
ReDim arrValues(0 To objMatches.Count - 1, 0 To 3)
For i = 0 To UBound(arrValues)
arrValues(i, 0) = objMatches(i).SubMatches(0) 'Artikelnummer
arrValues(i, 1) = Trim(objMatches(i).SubMatches(2)) 'Artikel
arrValues(i, 2) = CLng(objMatches(i).SubMatches(1)) 'Menge
arrValues(i, 3) = CDate(objMatches(i).SubMatches(3)) 'Termin
Next
GetMatchValues = arrValues
End If
End Function
Gruß Dieter
[edit] Code an die neue Vorlage (weiter unten) angepasst [/edit]

Hallo Joha!
Ist die Frage, ob die Daten in der Pdf-Datei auch verschoben sind? Wenn nein, dann könntest Du bei der PdfToText mal die Option (-raw) weglassen und schauen, ob die Text-Dateien anders/besser aussehen...Ansonsten mal mit 3 Matches-Objecten versuchen:
Gruß Dieter
Ist die Frage, ob die Daten in der Pdf-Datei auch verschoben sind? Wenn nein, dann könntest Du bei der PdfToText mal die Option (-raw) weglassen und schauen, ob die Text-Dateien anders/besser aussehen...Ansonsten mal mit 3 Matches-Objecten versuchen:
Private Function GetMatchValues(ByRef strText) As Variant
Dim objMatchesA As Object, objMatchesM As Object, objMatchesT As Object
Dim arrValues As Variant, i As Long
With CreateObject("VBScript.RegExp")
.Global = True
.MultiLine = True
.Pattern = "^\d+\s+\w+.*\n\s+([^\r]+)" 'Artikel
Set objMatchesA = .Execute(strText)
.Pattern = "\s+(\d+)\s+Stück" 'Menge
Set objMatchesM = .Execute(strText)
.Pattern = "Liefertermin:\s+([\.\d]+)" 'Termin
Set objMatchesT = .Execute(strText)
End With
If objMatchesA.Count Then
If objMatchesA.Count = objMatchesM.Count And objMatchesA.Count = objMatchesT.Count Then
ReDim arrValues(0 To objMatchesA.Count - 1, 0 To 2)
For i = 0 To UBound(arrValues)
arrValues(i, 0) = Trim(objMatchesA(i).SubMatches(0)) 'Artikel
arrValues(i, 1) = CLng(objMatchesM(i).SubMatches(0)) 'Menge
arrValues(i, 2) = CDate(objMatchesT(i).SubMatches(0)) 'Termin
Next
GetMatchValues = arrValues
End If
End If
End Function
Gruß Dieter

Oder mal die Option -table verwenden wie im Beitrag empfohlen wurde.
Gruß jodel32
Gruß jodel32

Zitat von @joha1908:
Hallo Dieter,
deine Prozedur auf mein oben angegebenes Beispiel funktioniert mit der Option -table wunderbar. Vielen Dank dafür!
Allerdings sind in der Bestellung noch weitere Angaben, die ich oben weggelassen habe. Diese führen dazu, dass u.a. die Telefonnr., Bankdaten usw. als Artikelnr. interpretiert werden.
Das ganze Dokument sieht in etwa so aus:
Hallo Dieter,
deine Prozedur auf mein oben angegebenes Beispiel funktioniert mit der Option -table wunderbar. Vielen Dank dafür!
Allerdings sind in der Bestellung noch weitere Angaben, die ich oben weggelassen habe. Diese führen dazu, dass u.a. die Telefonnr., Bankdaten usw. als Artikelnr. interpretiert werden.
Das ganze Dokument sieht in etwa so aus:
Kannst Du mir nochmal helfen?
Perfekt wäre es, wenn bei den einzelnen Positionen die Artikelnr. "X12345..." sowie die Zeile darunter "Artikel blabla..." mit in die excel Tabelle geschrieben wird.
Das bekommst du z.B. hiermit hin:Perfekt wäre es, wenn bei den einzelnen Positionen die Artikelnr. "X12345..." sowie die Zeile darunter "Artikel blabla..." mit in die excel Tabelle geschrieben wird.
Set regex = CreateObject("vbscript.regexp")
Set fso = CreateObject("Scripting.FileSystemObject")
regex.Global = True: regex.IgnoreCase = True: regex.MultiLine = True
regex.Pattern = "^(\d+)\s+([^\s]+)\s+(\d+)\s?([^\s]*)\s+([\d\.,]+)([\s\S]+?)(?=^\d+|^Firma)"
Set matches = regex.Execute(strText)
if matches.count > 0 then
For Each Match In matches
'Positionsnummer
strPos = CInt(Match.submatches(0))
'Artikelnummer
strArtNr = Match.submatches(1)
'Menge
intMenge = CInt(Match.submatches(2))
'Einheit
strEinheit = Match.submatches(3)
' Einzelpreis
strEinzelpreis = Match.submatches(4)
'Beschreibung
strBeschreibung = Trim(Replace(Match.submatches(5), vbNewLine, ""))
'Nur zur Demo in MSGBOX ausgeben
MsgBox Join(Array(strPos, strArtNr, intMenge, strEinheit, strEinzelpreis, strBeschreibung), vbNewLine)
Next
else
msgbox "Kein Match.",vbExclamation
End if
Gruß jodel32

Hallo zusammen!
Meinen obigen Code habe ich auch entsprechend der neuen Vorlage angepasst
Gruß Dieter
Meinen obigen Code habe ich auch entsprechend der neuen Vorlage angepasst
Gruß Dieter

Ist es sinnvoll für jede PDF (Bestellung) einen eigenen Ordner zu erstellen?
Würde ich gar nicht machen, sondern die Umwandlung nur in eine temporäre Datei im Temp-Verzeichnis erstellen und Daten auslesen.Wieso eine Excel-Datei extra als Zwischenschritt erstellen? Du kannst den VBA-Code doch direkt in Outlook einbinden, dort das NewMailEx Event Abfragen und bei jeder neuen Mail prüfen ob Anhang passt, dann die Daten per Regex extrahieren und davon direkt neue Termine in Outlook erstellen und von mir aus zusätzlich die Daten in eine Datenbank (MySQL,Access,SQL-Server ...) schreiben. Excel käme da bei mir gar nicht mehr zum Einsatz.

Such mal nach NewMailEx hier im Forum und auch hier rein für das extrahieren der Attachments in Outlook:
PDF-Dokument in Tiff konvertieren und in einem Verzeichnis ablegen - als Funktion
Das sollte an Info massig reichen um es zu realisieren.
PDF-Dokument in Tiff konvertieren und in einem Verzeichnis ablegen - als Funktion
Das sollte an Info massig reichen um es zu realisieren.

Naja in Zeile 11 hast du ja auch zwei Anführungszeichen zu viel drin , da hast du dir den Ursprungscode nicht genau genug angesehen, und wenn du kein Textfile für die Ausgabe von pdftotext definierst liegt das Textfile mit gleichem Namen wie die PDF im Temp-Verzeichnis.
Alles andere mach ich hier nicht mehr kostenlos.
Zum Termine erstellen gibt es hier ebenfalls bereits Code en masse im Forum, einfach mal die Suchfunktion anwerfen!
Alles andere mach ich hier nicht mehr kostenlos.
Zum Termine erstellen gibt es hier ebenfalls bereits Code en masse im Forum, einfach mal die Suchfunktion anwerfen!

Mit for each Schleife die Mails im Posteingang durchgehen.
VBA Referenz für Outlook
for each mail in Application.Session.Stores("NAMEDESSTORES").GetDefaultFolder(olFolderInbox).Items
'mail enthält das item ...
next