function performsmartrule(records) {
const jetzt = new Date();
datumSetzen(records, jetzt);
}
function datumSetzen(records) {
const gruppen = records.whose({ _match: [ObjectSpecifier().type, "group"] })();
gruppen.forEach(g => {
g.date = jetzt;
datumSetzen(g.children, jetzt);
})
}
Warum? Die Aufgabe war ursprünglich, nur das Datum von Gruppen zu ändern. Das macht Dein Code jetzt aber nicht mehr, denn performsmartrule setzt im forEach an allen records das date, ohne Rücksicht auf die Art des Datensatzes.
Die komplett rekursive Implementierung macht das wirklich nur für die Gruppen. Wenn du natürlich in der intelligenten Regel selbst nur Gruppen als records zulässt, würde es auch so funktionieren, wie du es hingeschrieben hast.
on performSmartRule (Error: TypeError: records.whose is not a function. (In 'records.whose({ _match: [ObjectSpecifier().type, "group"] })', 'records.whose' is undefined))
Das passiert allerdings immer, wenn man “records.whose…” im ersten Teil (function performsmartrule (records)) benutzt. Verstehe das Problem allerdings nicht…
Vermutlich könnte @cgrunenberg was dazu sagen. Ich bin davon ausgegangen, dass man whose auf alle Listen anwenden kann. Möglicherweise gilt das nicht für selectedRecords?
Nicht auf jede Liste, sondern nur auf sogenannte One-To-Many-Relationships. Bei Properties, die eine Liste zurück liefern wie selection funktioniert das zum Beispiel nicht, bei selected records, parents, children etc. schon.
Zumindest im Falle von AppleScript, keine Garantie für JXA
Haha. No worries, tatsächlich geht es mit selectedRecords auch in JXA. Beispiel, das die Namen aller derjenigen ausgewählten Datensätze ausgibt, die vom Typ “Markdown” sind:
Allerdings geht es hier ja um performsmartrule und dessen Parameter records. Sollte mit dem whose funktionieren? Man kann ja nicht so recht sehen, ob das eine List-Property ist oder eine One-To-Many-Relation oder irgendwas anderes.
Und AppleScript
on performSmartRule(theRecords)
tell application id "DNtp"
set md to theRecords whose type is "markdown"
end tell
end performSmartRule
wirft auch einen Fehler. Was entweder auf einen Fehler in meinem Code hinweist (wahrscheinlich) oder darauf, dass theRecords eben whose nicht versteht.
Edit: auch wenn ich in AppleScript whose auf a reference to theRecords loslasse,
set recs to a reference to theRecords
set md to recs whose type is "markdown"
bekomme ich einen Fehler. Aber einen anderen:
on performSmartRule („theRecords whose type = “markdown”“ kann nicht gelesen werden. Zugriff nicht erlaubt.)
Nachtrag: Offenbar ist selectedRecords ein JavaScript-Array (bzw. eine AppleScript-Liste?). Und das Array hat keine whose-Methode (wenig überraschend). Wie das mit der AppleScript-Liste (? wenn es eine ist) aussieht, weiß ich nicht.
set md to theRecords whose type as string is "markdown"
funktionieren. Allerdings kommt hier eine weitere Einschränkung zum Tragen, d.h. whose-Abfragen funktionieren meiner Erfahrung nach nur beim direkten Zugriff auf One-To-Relationships wie selected records, nicht bei zugewiesenen Variablen oder übergebenen Parametern.
Ich denke, nicht, dass es das sollte, denn class of theRecords in AppleScript liefert “list”
und (wenig überraschend) typeof theRecords in JavaScript liefert “Array”
Weder eine AppleScript list noch ein JavaScript Array haben die Methode whose. Das scheint mir die simple Erklärung in diesem Fall zu sein.
Andererseits liefert selected records whose type is "markdown" eine leere Liste als Ergebnis
während selected records whose type is markdown korrekt eine Liste mit zwei Elementen liefert.
So steht es übrigens auch in der Dokumentation: Die Werte von type sind offenbar keine Strings, sondern Konstante (Enums? keine Ahnung, wie das in AppleScript heißt). In JavaScript sind es jedenfalls Strings.
Folgende Smart Rule habe ich versucht, nur leider funktioniert es nicht…
Ziel der Aktion soll sein, dass alle PDF-Dokumente überprüft werden, ob das “Erstellt”-Datum in DT von den ersten 8Stellen im Dateinamen abweichend ist.
In erster Instanz hätte ich dann gerne im Protokollfenster eine Listausgabe der Einträge, welche abweichend sind.
Wie oben schon beschrieben habe ich eine Liste von PDF´s, die mit YYYYMMDD_ beginnen.
Vereinzelt sind aber auch PDF´s dabei, wo kein Datum vorne gelistet ist, sondern irgendwie mit andern Bezeichnungen starten. Das habe ich versucht mit der IF - Schleife rauszufiltern.
Es scheitert bei mir aber schon daran, dass ich keinerlei Ausgabe im Protokollfenster bekomme, obwohl definitiv Einträge vorhanden sind, wo der beginnende Dateiname mit z.B 20000101_ beginnt und “Erstellt” 20220422 ist.
Ich habe versucht mich auch mit den app.logMessages ran zu tasten um zu sehen, was im Namen steht und was das creationDate dazu liefert… Aber ich habe nur eine leere Liste…
Der aktuelle Code:
function performsmartrule(records) {
let app = Application('DEVONthink 3');
records.forEach((r) => {
let name = r.name();
let dateFull = name.match(/^(\d{4})(\d\d)(\d\d)/);
if (dateFull !== null && dateFull.length === 3) {
let creationDate = new Date(dateFull[1], dateFull[2] - 1, dateFull[3]);
r.creationDate = creationDate;
app.logMessage(name);
app.logmessage(creationDate);
}
});
}
(() => {
let app = Application('DEVONthink 3');
performsmartrule(app.selectedRecords());
})();
Wie man sieht gibt es einige abweichende Dateinamen…
Der Rest unten stimmt wieder.
ich befürchte, ich habe irgendwo einen Fehler im Auslesen des Datums aus dem Dateinamen…
ohne diesen Zusatz wird das Datum korrekt herausgelöst und das createdDate korrekt gesetzt; allerdings funktioniert app.logMessage nicht, ich erhalte Error -50: Parameter error.
Denkfehler: dateFull.length muss === 4 sein
Denn: match liefert ein Array zurück, dessen erstes Element der gesamte Treffer ist. Es folgen die einzelnen capturing groups. Das sind bei Dir drei Stück (Jahr, Monat, Tag).
Noch ein paar warme Worte zum Code:
let sollte man nur dann benutzen, wenn sich die Werte ändern können. Das ist hier in keinem Fall so, deshalb solltest Du const verwenden (ja, auch innerhalb des forEach).
die if-Bedingung ist zu kompliziert. dateFull kann überhaupt nur dann !== null sein, wenn der reguläre Ausdruck passte. Die Prüfung auf length ist überflüssig, und ich würde (Geschmacksfrage!) if (dateFull) { … } schreiben.
es heißt wirklich logMessage, nicht mal logMessage, mal logmessage.
die anonyme selbst ausführende Funktion am Ende solltest Du in einem Smart-Rule-Script nicht haben (ich weiß, ich habe das vor Monaten hier mal als tolle Idee vorgestellt) – damit wird performsmartrule zweimal ausgeführt, was man nicht unbedingt will.
Du hast ja auch keinen Code und keine Regel die das verhindern würde. Falls du dich jetzt entscheidest r.creationDate und creationDate in einer wenn/dann zu vergleichen, bin ich mir unsicher ob das funktionieren wird; r.creationDate müsste die Uhrzeit beinhalten, während creationDate das nicht tut.
Wie schon weiter oben aufgeführt, app.logMessage nimmt die Variable creationDate nicht an; entschuldigt meine JS-Ignoranz, gibt es hier eine “as string” Funktion für Variablen?