Plaintext eines PDF-Dokuments in temp. File schreiben, zur Weiterverarbeitung mit Shell-Script o.ä

Hi,

vorweg, ich bin kein großer Apple-Script Künstler :slight_smile:
Somit bevorzuge ich es Auswertungen eines PDF-Dokuments mit einem kleinen Perl-Script auszuführen. Dazu habe ich ein Apple-Script zusammen gebastelt, welches mir den Plain-Text eines PDF’s in eine temp. Datei schreiben soll. Anschließend soll das Perlscript seinen Job durchführen und die Ergebnisse an das Apple-Script zurückgeben.

Hier mein Apple-Script

on performSmartRule(theRecords)
	
	tell application id "DNtp"
		repeat with theRecord in theRecords
			
			set this_type to ((type of theRecord) as string)
			display alert this_type
			if (this_type contains "PDF") then
				display alert "PDF"
				set thetext to plain text of theRecord
				
				set oldDelims to AppleScript's text item delimiters -- save their current state
				-- Text in temp. Datei schreiben
				set target_file to (path to temporary items folder as text) & "dummy.dat"
				set the target_file to the target_file as text
				set the open_target_file to open for access file target_file with write permission

				set eof of the open_target_file to 0
				write thetext to the open_target_file starting at eof
				
				close access the open_target_file
			
				-- temp. Datei mit perl-Script durchsuchen
				
				set return_value to do shell script "/Users/boni/perl-Scripts/get_first_date_in_txt.pl \"" & target_file & "\" "
				-- wenn String nicht gefunden wird Fehler ausgeben
				
				if (return_value contains "error") then
					display alert "Das Rechnungsdatum wurde im Document nicht gefunden"
				else
					display dialog (return_value as string)
					-- Datum setzen
					set fuTmp to the current date
					set AppleScript's text item delimiters to {"."}
					
					set the year of fuTmp to (text item 3 of return_value)
					set the month of fuTmp to text item 2 of return_value
					set the day of fuTmp to text item 1 of return_value
					
					set theDate to fuTmp
					set date of theRecord to theDate
				end if

				set AppleScript's text item delimiters to oldDelims
				
			end if
			
		end repeat
	end tell
end performSmartRule

Aufgerufen werden soll das Script über eine intelligente Regel. Beim Ausführen der Regel erhalte ich nach
set the open_target_file to open for access file target_file with write permission

on performSmartRule (Falsche Zugriffsrechte auf die Datei.)

Kann mir jemand einen Tip geben, wie ich eine temporäre Datei anlegen kann?

Grüße Detlev

Fehlt da vielleicht ein Slash zwischen Verzeichnis und Dateiname? Den Test auf PDF würde ich ohnehin nicht im Script, sondern in der Regel ansiedeln.

Ich würde das Script jedenfalls (in Javascript schreiben und) im Script editor laufen lassen, wegen der etwas leichteren Fehlersuche dort.
Btw: in Javascript kann man zumindest mit regulären Ausdrücken gut arbeiten, sodass du uU kein separates Perl-Script brauchst.

Beispiel (nicht getestet):

function performsmartrule(recs) {
  let app = Application("DEVONthink 3");
  app.includeStandardAdditions = true;
  recs.forEach(r => {
    let txt = r.plainText();
	let res = findFirstDate(txt);
	if (!res) {
	  app.displayAlert(`Kein Rechnungsdatum im Dokument "${r.name()}" gefunden`)
	} else {
	  // res[0] = "dd.mm.yy<yy>"
	  let dateStr = res[0].split(".").reverse().join("-");
	  // dateStr = "yy<yy>-mm-dd" 
	  // BEWARE: JavaScript Date constructor expects a 4 digit year!
	  r.date = new Date(dateStr);
	} 
  })
}

function findFirstDate(txt) {
  let dateRe = /\d+\.\d+.\d{2,4}/;
  return txt.match(dateRe);
  // return value is null for no match, otherwise an array with the match as its only element
}

(() => {
  let app = Application("DEVONthink 3");
  performsmartrule(app.selectedRecords());
})()

Der reguläre Ausdruck in findFirstDate ist natürlich nur ein triviales Beispiel, da muss man nachbessern.

Hi,
danke für die Infos.
Ich stehe etwas auf dem Schlauch. Wie kann ich Dein Script testen, ich habs in den Scripteditor geladen, aber wie stelle ich nun den Bezug zu einem Dokument in DTP3 her?
Oder kann das Script nur als SmartRule ausgeführt werden?

Zwei Möglichkeiten:

  • Datensätze in DT markieren (“auswählen”) und dann das Script im Editor ausführen
  • Das Script als externes in eine Smart Rule einbinden.

Die erste Methode eignet sich zum Ausprobieren, die zweite für den normalen Betrieb.

so habe ich es auch gemacht, aber leider ohne Erfolg.

Nun aber:

function performsmartrule(recs) {
  //let app = Application("DEVONthink 3");
  recs.forEach(r => {
    let txt = r.plainText();
	let res = findFirstDate(txt);
	if (!res) {
	  app.displayAlert(`Kein Rechnungsdatum im Dokument "${r.name()}" gefunden`)
	} else {
	  // res[0] = "dd.mm.yy<yy>"
	  let dateStr = res[0].split(".").reverse().join("-");
	  // dateStr = "yy<yy>-mm-dd" 
	  // BEWARE: JavaScript Date constructor expects a 4 digit year!
	  r.date = new Date(dateStr);
	}   
  })
}

function findFirstDate(txt) {
  let dateRe = /\d+\.\d+.\d{2,4}/;
  return txt.match(dateRe);
  // return value is null for no match, otherwise an array with the match as its only element
}

var app = Application("DEVONthink 3");
app.includeStandardAdditions = true 
performsmartrule(app.selection()); 

Nachdem ich das Script um die 3 letzten Zeilen ergänzt habe, läuft es nun aus dem Scripteditor heraus :slight_smile: direkt auf Anhieb.
Wenn ich die Funktion findFirstDate richtig verstehe liefert mit txt.match(dateRe); den ersten Treffer der RegEx aus dem text txt

Prima, genau das wollte ich. Leider funktioniert es nicht, wenn ich es als SmartRule einbinde.

Im Log erscheint

20:57:57: ~/Library/Application Scripts/com.devon-technologies.think3/Smart Rules/test-db2.scpt
on performSmartRule (Error: Error: Kein Fehler.)

Hmmm.

Sorry, in meinem Script fehlte ganz am Ende ein Klammerpaar. Das habe ich jetzt ergänzt. Damit werden die letzten paar Zeilen zu einer self-executing function, sodass das Script ohne Änderung im Editor bei markierten DT-Datensätzen und als externes Script in Smart Rules funktionieren sollte. “sollte”, weil DT JavaScript nicht ganz so gut unterstützt wie AppleScript. Es kommt da immer mal wieder zu Merkwürdigkeiten.

Genau. Allerdings eben nur für Daten der Form “1.1.2021”, wobei Monat und Tag mindestens einstellig sein müssen und das Jahr zwei- oder vierstellig sein darf. Das könnte man durchaus noch verbessern, aber da Du Perl kannst … Die Allianz schreibt z.B. gerne “2. November 2020”, das erwischt man damit nicht. Außerdem muss man das Jahr unbedingt noch vierstellig machen, damit in der Hauptfunktion der Aufruf von new Date(...) funktioniert.

Das ist bekannt. Passiert immer, wenn man JavaScript extern in Smart Rules verwendet. Ich vermute, dass das DTs KI-Maschine in den Philosophie-Modus schickt und sie sich mit dem Sein und dem Nichts beschäftigt…

meine Rede! :crazy_face:

Super, danke!

Heißt das, es funktioniert jetzt?

Nun ja, aus dem Script-Editor läuft es jetzt genau wie es soll, binde ich es in eine Smart-Rule ein, verabschiedet sich DT mit dem wunderschönen Farbball. Ich kann DT dann nur noch abschießen.

Ich vermute DT landet mit der Smart-Rule in einer kleinen Endlos-Schleife.

Wenn Du noch eine Idee hättest, wäre das prima, ansonsten werde ich mich mal etwas mehr dem Apple-Script zuwenden, wobei ich mich damit bisher nicht wirklich anfreunden konnte.

Grüße Detlev.

Tja, DT und Javascript pflegen nicht unbedingt eine Liebesbeziehung.
Eine Umgehung könnte sein, eine Smartgroup mit den gewünschten Bedingungen einzurichten, dann darin aller Datensätze markieren und das Script ausführen. Es lässt sich, denke ich, in der jetzigen Form auch als normales Script installieren und nutzen.
AppleScript… Dazu kann ich nicht wirklich was sagen. Ich vermute, das in der ursprünglich hier geposteten Version einfach nur der Slash zwischen Verzeichnis und Datei (bei dem tempfile) fehlte.