Belegdatum aus PDF+Text ermitteln und anzeigen

Hallo zusammen.

Ich bin auf der Suche nach einer Möglichkeit aus einer PDF+Text Datei das Belegdatum auszulesen. Leider reichen meine Applescript Kenntnisse nicht soweit, dass ich die Lösung von Grund auf erstellen kann. :blush:

Hier im Forum bin ich leider nur auf einen einzigen Thread gestossen, welcher sich mit dem Parsing eines Datums aus einem Beleg beschäftigt und im Kern genau die Lösung für mein Problem aufzeigt.

[url]Automatic Renaming of Receipts to RCPT YYYY-MM-DD for $XX.XX]

Das Script von ‘jbmanos’ unterstützt standardmäßig aber leider nicht das deutsche Datumsformat. So habe ich versucht den Code zu kürzen und entsprechend seiner Kommentare so anzupassen das er nur nach dem Belegdatum in der Form DD.MM.YY oder DD.MM.YYYY sucht und mir das zunächst nur im Dialog anzeigt.

Es funktioniert nicht und ich trete seit zwei Tagen auf der Stelle. :confused:

Daher meine Frage und Bitte - hat von euch jemand bereits ein funktionierendes Script welches das deutsche Belegdatum ermittelt oder kann mir jemand die Hand führen wie ich das anhängende Script anpassen muss, damit dieses funktioniert und ich zu meinem Datum
komme.

Ich danke euch im voraus.
Efty

set mypattern to "[0-9]\\{1,2\\}[./-][0-9]\\{1,2\\}[./-][0-9][0-9]"

tell application id "com.devon-technologies.thinkpro2"
   
   try
      
      set theselection to the selection
      if theselection is {} then error "Bitte mindestens einen Beleg auswählen."     
      repeat with theRecord in theselection
         
         set rcdtext to "Oops. Es ist etwas nicht richtig gelaufen."
         try
           
            set rcdtext to the plain text of theRecord
         on error
            display alert "Die PDF Datei enthält keinen OCR Text."
         end try
         
         set mycat to rcdtext as text
         
         try
            
            --  first attempt to find date.  the pattern here looks for DD.MM.YYYY
            do shell script "echo " & quoted form of mycat & " | grep -o " & quoted form of mypattern & "[0-9][0-9]"
            set myDate to first paragraph of result
            
            --fix that pesky M format to MM
            if the first word of myDate is in {"1", "2", "3", "4", "5", "6", "7", "8", "9"} then
               set myDate to "0" & myDate
            end if
            
            --fix that even peskier D format to DD
            if the second word of myDate is in {"1", "2", "3", "4", "5", "6", "7", "8", "9"} then
               set myDay to the first word of myDate
               set myMonth to "0" & the second word of myDate
               set myYear to the third word of myDate
               set myDate to myDay & "." & myMonth & "." & myYear
            end if
            
            -- write the preferred date string
            set myDate to the third word of myDate & "." & the first word of myDate & "." & the second word of myDate
            
         on error
            
            -- if you are here in the code, then there was not a four YYYY code and grep spits out some nasty error, which is good because now we can try the 90% pattern for (m)m-dd-yy
            
            try
               do shell script "echo " & quoted form of mycat & " | grep -o " & quoted form of mypattern
               set myDate to first paragraph of result
               
               -- fix that pesky M format to MM
               if the first word of myDate is in {"1", "2", "3", "4", "5", "6", "7", "8", "9"} then
                  set myDate to "0" & myDate
               end if
               
               --fix that even peskier D format to DD
               if the second word of myDate is in {"1", "2", "3", "4", "5", "6", "7", "8", "9"} then
                  set myDay to the first word of myDate
                  set myMonth to "0" & the second word of myDate
                  set myYear to the third word of myDate
                  set myDate to myMonth & "-" & myDay & "-" & myYear
               end if

               --note to self.  there was something special about this line, but by the time you are looking for it, we'll have both forgotten.
               --write the preferred date string for record names
               set myDate to "20" & the third word of myDate & "-" & the second word of myDate & "-" & the first word of myDate
               
            on error
               
               --at this point, there are no numeric designations of month in a delimited list on your receipt.  The very, very intrepid could now begin to search for the more obscure formats by embedding deeper try blocks, for instance, this one right here could look for 'YY MMM dd forms, but well, I get tired of branch logic after a while and figure that we've explained about 98% of U.S. receipt dates to our little expert system with the first two.  If you like getting things more precise, add more date pattern tries here.
               -- This is to make the failure to find a date stand out.
               
               set myDate to "XX.XX.XXXX"
            end try                     
         end try        
      end repeat
      
      display dialog myDate
   end try
end tell

Anstatt der sprach-/systemabhängigen “word”-Befehle ist die Verwendung eigener Trennzeichen unabhängiger & flexibler, zum Beispiel:


				do shell script "echo " & quoted form of mycat & " | grep -o " & quoted form of mypattern & "[0-9][0-9]"
				set myDate to first paragraph of result
				
				set od to text item delimiters of AppleScript
				set text item delimiters of AppleScript to "."
				--fix that pesky M format to MM
				if text item 1 of myDate is in {"1", "2", "3", "4", "5", "6", "7", "8", "9"} then
					set myDate to "0" & myDate
				end if
				
				--fix that even peskier D format to DD
				if text item 2 of myDate is in {"1", "2", "3", "4", "5", "6", "7", "8", "9"} then
					set myDay to text item 1 of myDate
					set myMonth to "0" & text item 2 of myDate
					set myYear to text item 3 of myDate
					set myDate to myDay & "." & myMonth & "." & myYear
				end if
				
				-- write the preferred date string
				set myDate to text item 1 of myDate & "." & text item 2 of myDate & "." & text item 3 of myDate
				set text item delimiters of AppleScript to od

@cgrunenberg

Vielen Dank für die schnelle und zielsichere Unterstützung. Ich habe deine Änderungsvorschläge gestern eingebaut und war begeistert - es funktionierte auf Anhieb.

Nach einigen kleinen Modifikationen sucht das Script im Beleg jetzt nach einem Datum in der Form 1.3.12, 01.03.12, 1.3.2012 und 01.03.2012 und gibt das Ergebnis als 01.03.2012 formatiert aus.

Jetzt wo dieses Script sehr zuverlässig funktioniert möchte ich noch einen Schritt weiter gehen.

Es gibt tatsächlich noch Belege in denen das Belegdatum in der Form ‘1. Mrz 2012’ bzw. ‘1. März 2012’ steht. Amazon ist z. B. ein prominentes Beispiel. Kann man die zusätzliche Abfrage nach Monaten als Abkürzung oder Klarnamen noch ohne großen Aufwand im bestehenden Script einbauen, oder muss ich für jeden dieser Fälle das Script kopieren, anpassen und unten am Script anhängen was es dann unnötig aufbläht und vermeintlich zu Lasten der Laufzeit geht!?

Dann noch eine letzte Frage. Das Script findet immer das erste Datum auf das die Suchkriterien zutreffen. Jetzt möchte ich z. B. in Speditionsbelegen nicht das erste (= Belegdatum) sondern das zweite oder x-te (= Lieferdatum) auslesen. Kann man das vielleicht auch noch triggern?

Bereits vorab vielen Dank.
Efty


-- Zu suchendes Datumsformat definieren (aktuell: 0d.0m.yy oder 0d.0m.yyyy)
set mypattern to "[0-9]\\{1,2\\}[./-][0-9]\\{1,2\\}[./-][0-9]\\{2,4\\}"

tell application id "com.devon-technologies.thinkpro2"
   
   try
      set theselection to the selection
      if theselection is {} then error "Bitte mindestens einen Beleg auswählen."     
      repeat with theRecord in theselection

         set rcdtext to the plain text of theRecord
         set mycat to rcdtext as text
         
         try
            
            -- PDF Text nach der Logik des 'mypattern' durchsuchen
            do shell script "echo " & quoted form of mycat & " | grep -o " & quoted form of mypattern
            set myDate to first paragraph of result
            
            -- Ergebnis an 'text'-String übergeben
            set od to text item delimiters of AppleScript
            set text item delimiters of AppleScript to "."
            
            -- Zuweisen des Ergebnisses an die einzelnen Variablen
            set myDay to text item 1 of myDate
            set myMonth to text item 2 of myDate
            set myYear to text item 3 of myDate
            
            -- Einstellige Tage in Tage mit führender Null versehen
            if myDay is in {"1", "2", "3", "4", "5", "6", "7", "8", "9"} then
               set myDay to "0" & myDay
            end if
            
            -- Einstellige Monate in Monate mit führender Null versehen
            if myMonth is in {"1", "2", "3", "4", "5", "6", "7", "8", "9"} then
               set myMonth to "0" & myMonth
            end if
            
            -- Zweistellige Jahre in Jahrtausende umwandeln
            if count of myYear = 2 then
               set myYear to "20" & myYear
            end if
                       
            -- Ergebis für die Ausgabe formatieren
            set myDate to myDay & "." & myMonth & "." & myYear
            
            set text item delimiters of AppleScript to od   
                         
         end try        
      end repeat
      
      display dialog myDate
      
   end try
end tell

Das sollte machbar sein, erfodert allerdings einige Umbauten. Zum Beispiel sollte folgendes Muster die Monatsnamen finden:


set mypattern to "Januar|Februar|Mrz|März|April|Mai|Juni|Juli|August|September|Oktober|November|Dezember"
do shell script "echo " & quoted form of mycat & " | grep -E -o -e " & quoted form of mypattern

U.a. müsste nicht der “first paragraph”, sondern “paragraph 2” verwendet werden.

Hallo Christian.

Ich habe mich heute, mit Hilfe des ‘Reggy’ für OSX , ausgiebig mit RegEx auseinandergesetzt und ein Pattern erarbeitet was alle möglichen Datumsformate abdeckt. Leider funktioniert das Pattern nur in Reggy, nicht aber unter Applescript. Muss ich da etwas besonderes beachten?


([0-9]{1,2})([.]|[.][\s]|[-]|[/])([0-9]{1,2}|Januar|Jan|Februar|Feb|März|Mrz|April|Apr|Mai|Juni|Jun|Juli|Jul|August|Aug|September|Sep|Oktober|Okt|November|Nov|Dezember|Dez)([.]|[\s]|[.][\s]|[-]|[/])([0-9]{4}|[0-9]{2})

Mein Problem ist es dann noch, den ggf. zurückgelieferten String in alle Eventualitäten zu zerlegen. Soll heissen - aktuell trenne ich das gefundene Datum am Punkt.

-- Ergebnis an 'text'-String übergeben
set od to text item delimiters of AppleScript
set text item delimiters of AppleScript to "."

Wie bekomme ich es hin, das Datum am

  • Punkt
  • Punkt und Leerzeichen
  • Leerzeichen
  • Bindestrich
  • Schrägstrich

getrennt bekomme. Ich habe hier im Forum und im Netz keine Möglichkeit gefunden mehrere ‘Delimiters’ anzugeben.

Hast Du vielleich eine Idee wie ich das angehen kann?

Danke
Efty

Funktioniert es denn evtl. ohne Umlaute, d.h. ohne März?

Eine Möglichkeit wäre, die Trennzeichen selbst zu suchen und den Text in Wörter zu zerlegen:


set theStr to "1. 2-3 /2012"
set theWords to {}
set j to 1
repeat with i from 1 to length of theStr
	set theChar to character i of theStr
	if theChar is " " or theChar is "." or theChar is "-" or theChar is "/" then
		if i > j then set theWords to theWords & ((characters j thru (i - 1) of theStr) as string)
		set j to i + 1
	end if
end repeat
if i > j then set theWords to theWords & (((characters j thru i) of theStr) as string)
return theWords

Hallo Christian.

Hier ein kurzer Zwischenstand.

Ich habe etwas rumexperimentiert und zumindest herausgefunden das es nicht an den Umlauten liegt. Lasse ich die Monatsnamen raus und versuche meinen RegEx Code nur für die zweistelligen Monatsangaben zu verwenden, so funktioniert auch das nicht. Es scheint etwas mit den beiden Backslash (\) am Ende einer Angabe zu tun zu haben, denn das ist der einzige Unterschied zum Originalcode von ‘jbmanos’. Fehlt nur ein Backslash gegenüber dem Original - dann geht’s nicht.

Allerdings erschließt sich mir noch nicht wie und warum die gesetzt werden müssen. Eine wirkliche Logik und Notwendigkeit der Backslash’s kann ich nicht erkennen und finde dazu auch nichts im Netz. Das einzige was ich allerdings gefunden habe ist die Aussage, dass der erste sich ja wohl maskiert um den zweiten als Backslash auszugeben.

Efty

Hi Christian.

Ich gebe auf, da ich nicht mehr weiter weis. Es ist wie verhext, denn ich schaffe es nicht einen einfachen minimalen RegEx Code für den ersten Teil eines Datums zu einem Ergebnis zu bringen.

Im OCR Text steht lt. dem Applescript Log nachweislich 6. Juni 2011. Das Datum versuche ich jetzt ohne oder-Verknüpfungen zu finden.

Ich suche nach 6.


mypattern = "[0-9]\\{1,2\\}. "

Das funktioniert!

Jetzt suche ich zusätzlich nach dem Monat


mypattern = "[0-9]\\{1,2\\}. Juni"

Auch das funktioniert.

Ab sobald ich RegEx konform nach zwei möglichen Monatsnamen suche …


mypattern ="[0-9]\\{1,2\\}. (Mai|Juni)"

funktioniert es nicht mehr. Das ist auch der Fall wenn ich den Punkt und das Leerzeichen bereits in runde Klammern setzte. :cry:

Wie bereits im vorherigen Post angerissen, verstehe ich den Sinn der beiden ‘\’ nicht. Mal im Ausdruck, mal danach. Nun denn …

Ich will niemanden zu nahe treten aber kann es daher vielleicht sein, das die RegEx Implementierung in DEVONthink nicht richtig umgesetzt und ggf. fehlerhaft ist!? :frowning: Oder stell ich mich nur zu dusselig an und sehe den Wald vor lauter Bäumen nicht? :open_mouth:

Efty

Hallo nochmal.

Ich habe mein Windows Notebook nochmal aus der Versenkung geholt und den RegEx Coach genutzt um folgendes RegEx Pattern zu testen.


([0-9]{1,2})(.|.\s|-|/)([0-9]{1,2}|Januar|Jan|Februar|Feb|März|Mrz|April|Apr|Mai|Juni|Jun|Juli|Jul|August|Aug|September|Sep|Oktober|Okt|November|Nov|Dezember|Dez)(.|\s|-|/)([0-9]{4}|[0-9]{2})

Wie man im folgenden Screenshot sieht, funktioniert das Pattern auch im RegEx Coach einwandfrei. Wie auch zuvor in Reggy unter OSX wird jede Kombination eines Datumsformats erkannt.

Es ist zum verrückt werden. Unter jedem OS funktioniert die Abfrage nur da nicht, wo man es benötigt. Kennt denn keiner hier im Forum die Besonderheit im RegEx Handling unter DEVONthink gegenüber dem vom ‘normalen’ RegEx!?

Efty

Push

Ist denn hier wirklich niemand der die Besonderheit des vermeintlichen RegEx Pattern kennt und mir einen Tipp geben kann warum die Abfrage nicht funktioniert!? :open_mouth:

Erbarme sich doch bitte jemand! Danke.
Efty

DEVONthink selbst enthält keinerlei Unterstützung für RegEx, das Skript verwendet schlicht das Terminal-Kommando “grep”. D.h. eventuell enthält die Manpage von grep die nötigen Hinweise.