Warum das überhaupt?

Weil Du jeden Tag dieselbe Frage hast:
„Was steht in diesem PDF – und wohin gehört es im System?“
Access kann Dir das nicht alleine beantworten.
Aber mit OCR, GPT und ein bisschen JSON schon.

Ich zeig Dir, wie Du aus PDF-Dateien automatisch strukturierte Auftragsdaten bekommst.
Auftragskopf. Positionen. Fertig zum Import.

Was Du brauchst

  • Tesseract OCR oder Azure OCR für Texterkennung
  • OpenAI GPT (oder Azure OpenAI) für das Parsing
  • PDF-Datei (z. B. E-Mail-Anhang)
  • Access mit VBA
  • Tabellen für Kopf, Position, Fehlerprotokoll

Tabellenstruktur (Beispiel)

TabelleZweck
tblImportPDFQuelldateien + OCR-Text
tblAuftraegeAuftragskopf (Kunde, Datum…)
tblPositionenEinzelpositionen
tblImportFehlerParsing- oder OCR-Fehler

Schritt 1: Text aus PDF extrahieren (per Tesseract)

Sub OCR_PDF(pfad As String)
    Dim cmd As String
    Dim tempTxt As String

    tempTxt = Environ("TEMP") & "\ocr_output.txt"
    cmd = "tesseract """ & pfad & """ """ & Replace(tempTxt, ".txt", "") & """ -l deu pdf"

    Shell cmd, vbHide
    Application.Wait Now + TimeValue("00:00:05")

    Dim txt As String
    txt = LadeTextdatei(tempTxt)

    CurrentDb.Execute "INSERT INTO tblImportPDF (Dateipfad, OCRText, Zeitstempel) VALUES ('" & _
                      Replace(pfad, "'", "''") & "', '" & Replace(txt, "'", "''") & "', Now())"
End Sub

Hilfsfunktion: Textdatei laden

Function LadeTextdatei(pfad As String) As String
    Dim f As Integer
    Dim inhalt As String
    f = FreeFile
    Open pfad For Input As #f
    inhalt = Input$(LOF(f), f)
    Close f
    LadeTextdatei = inhalt
End Function

Schritt 2: Text per GPT zerlegen lassen

Du gibst dem Modell den OCR-Text und sagst:
„Bitte extrahiere mir den Auftragskopf und alle Positionen als JSON.“

Prompt-Vorlage

Lies den folgenden Text aus einem PDF-Auftrag.  
Extrahiere den Auftragskopf (z. B. Kundennummer, Bestellnummer, Lieferdatum)  
und die Positionen (Menge, Artikelnummer, Beschreibung, Preis)  
als JSON mit zwei Objekten: "kopf" und "positionen".

TEXT:
[...OCR-Text...]

API-Aufruf aus Access

Function RufeParsingGPT(ocrText As String) As String
    Dim http As Object
    Dim apiKey As String
    Dim prompt As String
    Dim json As String

    apiKey = "DEIN_API_KEY"
    prompt = "Lies folgenden Auftrag und gib Kopf- und Positionsdaten als JSON zurück:" & vbCrLf & ocrText

    json = "{" & _
        """model"":""gpt-4""," & _
        """messages"":[{""role"":""user"",""content"":""" & Replace(prompt, """", "\""") & """}]" & _
        "}"

    Set http = CreateObject("MSXML2.ServerXMLHTTP")
    http.Open "POST", "https://api.openai.com/v1/chat/completions", False
    http.setRequestHeader "Content-Type", "application/json"
    http.setRequestHeader "Authorization", "Bearer " & apiKey
    http.Send json

    RufeParsingGPT = http.responseText
End Function

JSON auslesen

Function ParseKopfUndPositionen(json As String) As Boolean
    Dim sc As Object
    Dim kopf As String
    Dim positionen As String

    Set sc = CreateObject("ScriptControl")
    sc.Language = "JScript"
    sc.AddCode "function kopf(j){return JSON.parse(JSON.parse(j).choices[0].message.content).kopf;}"
    sc.AddCode "function pos(j){return JSON.parse(JSON.parse(j).choices[0].message.content).positionen;}"
    
    kopf = sc.Run("kopf", json)
    positionen = sc.Run("pos", json)

    Call SpeichereKopf(kopf)
    Call SpeicherePositionen(positionen)

    ParseKopfUndPositionen = True
End Function

Schritt 3: Daten speichern

Auftragskopf

Sub SpeichereKopf(json As String)
    ' Beispielhafte Umsetzung, musst Du konkret parsen
    ' Angenommen: json = {"kundennummer":"4711", "bestellnummer":"A123", "lieferdatum":"2025-06-01"}
    Dim sc As Object
    Set sc = CreateObject("ScriptControl")
    sc.Language = "JScript"
    sc.AddCode "function parse(j){var d=JSON.parse(j); return d.kundennummer + '|' + d.bestellnummer + '|' + d.lieferdatum;}"
    Dim teile() As String
    teile = Split(sc.Run("parse", json), "|")
    CurrentDb.Execute "INSERT INTO tblAuftraege (Kundennummer, Bestellnummer, Lieferdatum) VALUES ('" & teile(0) & "', '" & teile(1) & "', #" & teile(2) & "#)"
End Sub

Positionen

Sub SpeicherePositionen(jsonArray As String)
    ' jsonArray = [{"menge":5,"artikelnummer":"12345","text":"Dichtung","preis":12.50}, {...}]
    Dim sc As Object
    Set sc = CreateObject("ScriptControl")
    sc.Language = "JScript"
    sc.AddCode "function parse(j){var arr=JSON.parse(j);var r='';for(var i=0;i<arr.length;i++){r+=arr[i].menge+'|'+arr[i].artikelnummer+'|'+arr[i].text+'|'+arr[i].preis+'\n';}return r;}"
    Dim zeilen() As String
    Dim teile() As String
    Dim i As Long

    zeilen = Split(sc.Run("parse", jsonArray), vbLf)

    For i = 0 To UBound(zeilen)
        If Trim(zeilen(i)) <> "" Then
            teile = Split(zeilen(i), "|")
            If UBound(teile) = 3 Then
                CurrentDb.Execute "INSERT INTO tblPositionen (Menge, Artikelnummer, Beschreibung, Einzelpreis) VALUES (" & _
                                  teile(0) & ", '" & teile(1) & "', '" & Replace(teile(2), "'", "''") & "', " & teile(3) & ")"
            End If
        End If
    Next i
End Sub

Fehlerbehandlung

Falls GPT Mist liefert – loggen. Nicht raten.

Sub LogFehler(pfad As String, fehlertext As String)
    CurrentDb.Execute "INSERT INTO tblImportFehler (Dateipfad, Fehlertext, Zeitstempel) VALUES ('" & _
                      Replace(pfad, "'", "''") & "', '" & Replace(fehlertext, "'", "''") & "', Now())"
End Sub

Was Du beachten musst

  • OCR ist nie perfekt → Eingabequalität zählt
  • GPT kann mal halluzinieren → bei Auftragsnummern auf Plausibilität achten
  • API-Limits und Laufzeiten beachten (Timeouts)
  • Ggf. Zwischenprüfung per Vorschau vor dem Import

„Was vorher Chaos war, wird jetzt strukturierter Auftrag – mit Access als Dirigent.“

Wenn Du’s ernst meinst mit automatischem Auftragseingang:
Meld Dich. Ich bau Dir das robust.
Nicht fancy. Aber funktionierend.

Tags:

No responses yet

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert