File
Übersicht
Abschnitt betitelt „Übersicht“Der File-Trigger überwacht einen Ordner, den Pool. Jede Datei, die dort ankommt und zum Filter passt, startet einen Lauf. Typische Quellen sind ein ERP, das Belege als PDF ablegt, ein Scanner oder der PDF-Drucker von RUNOS.
Bevor der Lauf startet, liest der Trigger den Text der Datei. Enthält er Skriptblöcke (#RUNOS … #RUNOS), übernimmt RUNOS daraus Werte für diesen Lauf, zum Beispiel Rechnungsnummer und Empfänger aus dem ERP-Druck.
Ablauf je Datei:
- Bei jeder Prüfung (
CronExpression) listet der Trigger die passenden Dateien im Pool auf. - Er wartet kurz, bis eine Datei vollständig geschrieben und nicht leer ist. Ist sie nach etwa zwei Sekunden noch leer oder gesperrt, kommt sie bei der nächsten Prüfung dran.
- Die Datei wird in einen eigenen Jobordner verschoben:
<Pool>\Spooler\<ID>\<Dateiname>. Damit gehört sie diesem Lauf, und keine Datei wird zweimal verarbeitet. - Falls
NewNamegesetzt ist, wird sie umbenannt. - Bei
GetFileContentliest RUNOS den Text und wertet die Skriptblöcke aus. - Der Lauf startet.
| Ergebnis des Laufs | Was mit der Datei passiert |
|---|---|
erfolgreich, DeleteAfter: false |
bleibt im Jobordner im Spooler (Archiv) |
erfolgreich, DeleteAfter: true |
wird gelöscht, samt Jobordner |
| fehlgeschlagen | wird nach <Pool>\Spooler\Failed\<ID>\ verschoben. Nach dem Beheben der Ursache legen Sie sie wieder in den Pool. |
Hat eine Aktion die Datei schon woanders hin verschoben, bleibt sie dort. Mehrere laufende Workflows können denselben Pool überwachen; welcher Workflow eine Datei bekommt, bestimmen dann ihre Skriptblöcke, siehe Gemeinsamer Pool. Zwei Workflows mit demselben Namen können einen Pool nicht teilen: Der zweite startet nicht, und RUNOS nennt den Workflow, der den Ordner belegt.
Struktur
Abschnitt betitelt „Struktur“"Trigger": { "Type": "File", "Name": "Eingang", "Parameters": { "Pool": "C:\\RUNOS\\Rechnungen", "Filter": "*.pdf", "CronExpression": "0/15 * * * * ?", "ProcessMode": "Single", "ConcurrentJobs": 5, "DeleteAfter": false, "GetFileContent": true }}| Parameter | Standard | Bedeutung |
|---|---|---|
Pool |
– | Der überwachte Ordner. Wird angelegt, falls er fehlt. Platzhalter wie %userdocuments% sind erlaubt. |
Filter |
*.* |
Dateimuster, z. B. *.pdf oder RE_*.txt |
CronExpression |
0/15 * * * * ? |
Wie oft der Ordner geprüft wird, siehe Cron-Ausdrücke. Standard: alle 15 Sekunden. Speichert der PDF-Drucker eine Datei in den Pool, prüft der Trigger zusätzlich sofort. |
ProcessMode |
Single |
Single: ein Lauf je Datei. Multi: ein Lauf für alle Dateien einer Prüfung. |
ConcurrentJobs |
5 |
Im Modus Single: wie viele Dateien gleichzeitig verarbeitet werden |
DeleteAfter |
false |
true: Nach einem erfolgreichen Lauf wird der Jobordner der Datei gelöscht, mit allem, was Aktionen dort abgelegt haben (z. B. die Teile von Split im PDFEditor). Gilt für den ganzen Lauf, nicht für eine einzelne Aktion. |
NewName |
– | Neuer Dateiname im Spooler, z. B. Rechnung_%yyyy%-%MM%-%dd%. Ohne Endung bleibt die alte Endung. |
RepeatCount |
0 |
Nach so vielen Prüfungen (nach CronExpression) stoppt der Trigger. 0 = unbegrenzt. |
GetFileContent |
true |
Text der Datei lesen und als {{FileContent}} bereitstellen. Nötig für Skriptblöcke. |
RemoveScriptFromFile |
false |
Skriptblöcke nach dem Lesen aus der Datei entfernen, bei TXT, JSON, XML und PDF. Im PDF wird der Text des Blocks gelöscht, nicht überdeckt: Er ist weder sichtbar noch kopierbar, der Rest der Seite bleibt, wo er war, auch Text, der unter oder neben dem Skript steht (z. B. ein kleines Skript über der Rechnungsposition). Druckt das ERP Zeichen zwischen die Blöcke, z. B. ` |
ScriptStart, ScriptEnd |
aus den Einstellungen | Eigene Markierungen für Skriptblöcke dieses Triggers |
Single ist fast immer die richtige Wahl: Jede Datei hat ihren eigenen Lauf mit eigenen Daten. Bei Multi enthält {{Trigger.Response.Results}} alle Dateien einer Prüfung, und {{FilePath}} zeigt auf die zuletzt gelesene.
Gelesener Text
Abschnitt betitelt „Gelesener Text“| Dateityp | Wie |
|---|---|
.txt, .json, .xml |
als Text |
.pdf |
Text aller Seiten wird extrahiert. Gescannte PDFs ohne Textebene liefern keinen Text. |
| andere | kein Text; der Workflow läuft trotzdem, ohne FileContent und Skriptblöcke |
Verfügbare Werte
Abschnitt betitelt „Verfügbare Werte“| Platzhalter | Inhalt |
|---|---|
{{FilePath}} |
voller Pfad der Datei im Spooler |
{{FileName}} |
Dateiname (nach NewName) |
{{FileContent}} |
gelesener Text, bei PDF der extrahierte Text |
{{Trigger.Response.Results}} |
Bericht je Datei, siehe unten |
{{Trigger.Meta.SpoolerFolder}} |
Pfad des Spooler-Ordners |
{ "FilePath": "C:\\RUNOS\\Rechnungen\\Spooler\\3f2a…\\RE-2026-0001.pdf", "FileName": "RE-2026-0001.pdf", "OriginalName": "RE-2026-0001.pdf", "FileSize": 48211, "Content": { "Loaded": true, "Chars": 1834, "Preview": "Rechnung Nr. …" }, "Scripts": { "Found": 1, "Parsed": 1, "Ignored": 0, "Invalid": 0 }}Mit RemoveScriptFromFile steht unter Scripts zusätzlich RemovedFromFile (true, wenn die Blöcke entfernt wurden) und bei PDFs RemovedBlocks (Anzahl der entfernten Blöcke).
Skriptblöcke
Abschnitt betitelt „Skriptblöcke“Ein Skriptblock ist ein kurzer Text in der Datei, der diesen einen Lauf ändert: Er setzt Werte in InitialData, ändert Parameter von Aktionen oder fügt Aktionen hinzu. Das gespeicherte Workflow-JSON bleibt unverändert. So kann ein ERP, das nur drucken oder Textdateien schreiben kann, RUNOS sagen, an wen eine Rechnung geht und welche Daten in die XRechnung gehören.
#RUNOS InitialData.Invoice.BT1=RE-2026-0001 #RUNOS#RUNOS SendMail.To=buchhaltung@kunde.de #RUNOSEin Block steht zwischen Start- und Endmarkierung, standardmäßig beide #RUNOS (änderbar unter Einstellungen → Skriptblöcke oder mit ScriptStart / ScriptEnd). Beginnt der Inhalt mit { und endet mit }, ist er JSON; beginnt er mit Pfad=, ist er die Kurzform; alles andere wird ignoriert.
Kurzform
Abschnitt betitelt „Kurzform“Jeder Block enthält genau eine Anweisung Pfad=Wert. Der erste Teil des Pfads entscheidet das Ziel:
| Pfad beginnt mit | Ziel | Beispiel |
|---|---|---|
InitialData. |
ein Wert in InitialData dieses Laufs |
InitialData.Invoice.BT1=4711 |
| Name einer Aktion | ein Parameter dieser Aktion (.Parameters darf fehlen) |
SendMail.To=a@b.de |
newAction. |
eine neue Aktion, siehe unten | newAction.Notify=SMTP |
| alles andere | ein globaler Wert, lesbar als {{Name}} |
Kunde=ACME → {{Kunde}} |
- Der Wert reicht vom ersten
=bis zur Endmarkierung, auch über mehrere Zeilen (z. B. ein Mailtext). - Werte sind Text (
Menge=5→"5"). Als JSON geschriebene Werte werden als JSON gelesen:Tags=["a","b"]ist eine Liste. "…"behält führende und folgende Leerzeichen. Text zwischen den Textmarkierungen (Standard***) wird genau so übernommen.{{…}}-Platzhalter bleiben Text und werden später beim Ausführen der Aktion aufgelöst.
JSON-Form
Abschnitt betitelt „JSON-Form“#RUNOS {"InitialData":{"Invoice":{"BT1":"RE-2026-0001","BT2":"2026-10-08"}}} #RUNOS| Schlüssel | Wirkung |
|---|---|
InitialData |
wird über die InitialData des Laufs gelegt |
Actions |
Parameter für Aktionen, {"SendMail":{"To":"a@b.de"}}, oder Aktionsblöcke {"Name":…, "Type":…, "Parameters":{…}} |
| alles andere | globale Werte |
Schreibt ein Programm einen langen JSON-Block in ein PDF und bricht dabei die Zeile mitten in einem Wert um, fügt RUNOS den Wert wieder zusammen.
Zusammenführen, Listen und Zeilen
Abschnitt betitelt „Zusammenführen, Listen und Zeilen“- Ein vorhandener Schlüssel bekommt den neuen Wert, ein neuer wird hinzugefügt, alles andere bleibt. Objekte werden Schlüssel für Schlüssel zusammengeführt, Listen werden komplett ersetzt.
- Mehrere Blöcke werden in ihrer Reihenfolge angewendet; der spätere gewinnt.
- Ein Zahlensegment im Pfad ist eine Zeile einer Liste, gezählt ab 1:
InitialData.Positionen.2.Artikel=Mutter. Es darf keine Nummer fehlen. - Für die wiederholbaren Gruppen der XRechnung (BG-25 Positionen, BG-23, BG-17 …) geht es ohne Nummern: Ein Feld, das die aktuelle Zeile schon hat, beginnt die nächste. Siehe XRechnung-Beispiel.
Neue Aktionen
Abschnitt betitelt „Neue Aktionen“#RUNOS newAction.Hinweis=SMTP #RUNOS#RUNOS Hinweis.To=chef@example.de #RUNOS#RUNOS Hinweis.Subject=Neue Datei {{FileName}} #RUNOSSkript aus dem Editor
Abschnitt betitelt „Skript aus dem Editor“Welche Blöcke eine Datei für einen bestimmten Workflow braucht, zeigt der Workflow-Editor unter Skript (neben Visuell / JSON):
- Links haken Sie an, was die Datei liefern soll: Werte aus
InitialDataund Parameter der Aktionen, auch der Aktionen inIf,LoopundParallel. Ein Haken an einer Gruppe (z. B.InitialDataoder einer Aktion) setzt alles darunter. Listen wie Rechnungszeilen werden als Ganzes gewählt, weil ein Block eine Liste immer vollständig ersetzt. Beim ersten Öffnen istInitialDataangehakt. - Rechts steht das fertige Skript mit den aktuellen Werten des Workflows als Beispiel, in der Kurzform (ein Block pro Wert, Listen Zeile für Zeile) oder als ein JSON-Block. Die Markierungen sind die dieses Triggers bzw. aus den Einstellungen.
- Kopieren legt es in die Zwischenablage. Im ERP oder der Vorlage, die die Datei erzeugt, ersetzen Sie die Beispielwerte durch die echten.
Das Skript wird aus dem JSON im Editor erzeugt, auch ungespeichert, und kann dort nicht bearbeitet werden. Ausgeschaltete Aktionen, Aktionen ohne Namen und OnError-Aktionen fehlen, weil der Trigger sie nicht findet. Auswahl und Format merkt sich RUNOS je Workflow. Hat der Workflow keinen File-Trigger, weist die Ansicht darauf hin. In der Kurzform sind alle Werte Text (5 kommt als "5" an); wo der Typ zählt, wählen Sie JSON.
Gemeinsamer Pool
Abschnitt betitelt „Gemeinsamer Pool“Überwacht nur ein laufender Workflow den Pool, schreiben Sie die Blöcke wie oben, ohne Workflow-Namen.
Überwachen mehrere laufende Workflows denselben Pool, beginnt jeder Block mit dem Namen des Workflows, für den er gilt: Workflow.Aktion.Parameter=Wert. Jede Datei wird nur einmal aus dem Pool genommen und mit ihren Blöcken gelesen. Nur die Workflows, die die Datei nennt, laufen, jeder mit seiner eigenen Kopie in einem eigenen Jobordner und nur mit seinen eigenen Blöcken (ohne den Namen davor). Workflows, die die Datei nicht nennt, starten nicht.
#RUNOS Rechnung.InitialData.Nr=4711 #RUNOS#RUNOS Rechnung.SendMail.To=kunde@example.com #RUNOS#RUNOS Archiv.InitialData.Ordner=2026 #RUNOSHier laufen Rechnung und Archiv, ein dritter Workflow am selben Pool nicht. In der JSON-Form ist der Workflow-Name der äußere Schlüssel:
#RUNOS { "Rechnung": { "InitialData": { "Nr": "4711" } }, "Archiv": { "InitialData": { "Ordner": "2026" } } } #RUNOS- Groß-/Kleinschreibung zählt nicht. Leerzeichen und andere Zeichen außer Buchstaben, Ziffern,
_und-lassen Sie weg: Der WorkflowRechnung sendenheißt im BlockRechnungsenden. Die Kurzform braucht einen Namen, der mit einem Buchstaben beginnt; sonst nehmen Sie die JSON-Form. - Nennt eine Datei keinen der laufenden Workflows des Pools (auch: Blöcke ohne Workflow-Namen), wird sie abgelehnt und landet im
Failed-Ordner, mit einer Meldung, welche Workflows den Pool teilen. - Ein Name, den kein laufender Workflow des Pools trägt (z. B. ein Tippfehler oder ein gestoppter Workflow), wird ignoriert; das Protokoll meldet ihn als
ScriptForUnknownWorkflow. - Jeder Workflow verarbeitet seine Kopie mit seinen eigenen Einstellungen (
NewName,DeleteAfter,RemoveScriptFromFile,ProcessMode…). Welche Workflows eine Datei bekommen haben, steht im Protokoll unterFileShared. - Ob ein Pool geteilt ist, entscheidet sich beim Eintreffen der Datei: Wird ein Workflow gestoppt und bleibt nur einer übrig, gilt wieder die Form ohne Namen.
Fehlerhafte Blöcke
Abschnitt betitelt „Fehlerhafte Blöcke“Ein Block, der nicht gelesen werden kann (ungültiges JSON, Pfad=Wert nicht erkennbar, fehlende Zeilennummer, unbekannter Aktionstyp …), lehnt die Datei ab: Sie landet im Failed-Ordner, und Sie erhalten eine Meldung mit der Nummer des Blocks und dem Grund. Dasselbe gilt für eine Datei, die erkennbar Skriptdaten enthält, aber keine Markierungen. Was RUNOS gelesen hat, steht im Protokoll unter ScriptShorthandParsed bzw. ScriptJsonParsed.
Formular im Editor
Abschnitt betitelt „Formular im Editor“Im Diagramm des Workflow-Editors hat der Trigger ein Formular:
- Ordner: Überwachter Ordner (
Pool) und Dateifilter (Filter). - Prüfen: Ordner prüfen (
CronExpression) und Stoppen nach (RepeatCount). - Verarbeitung: Läufe – ein Lauf je Datei oder für alle Dateien einer Prüfung (
ProcessMode); Dateien gleichzeitig (ConcurrentJobs, nur bei einem Lauf je Datei); Datei umbenennen in (NewName); Datei nach erfolgreichem Lauf löschen (DeleteAfter). - Inhalt und Skriptblöcke: Text der Datei lesen (
GetFileContent), Skriptblöcke aus der Datei entfernen (RemoveScriptFromFile), Startmarkierung und Endmarkierung (ScriptStart,ScriptEnd).
Der Zeitplan wird ausgewählt statt getippt: Alle … Sekunden, Alle … Minuten, Jede Stunde (zur Minute …), Jeden Tag, Montag bis Freitag, An bestimmten Wochentagen (Tage anklicken) oder Einmal im Monat (Tag 1–31 oder letzter Tag), jeweils mit Uhrzeit. Darunter steht der erzeugte Cron-Ausdruck. Für alles andere wählen Sie Eigener Zeitplan (Cron-Ausdruck) und tippen den Ausdruck selbst; ein Ausdruck, den die Auswahl nicht abbildet (z. B. 0 0 8-17 ? * MON-FRI), erscheint automatisch so. Parameter, die das Formular nicht kennt, stehen unter Weitere Parameter.
Beispiel
Abschnitt betitelt „Beispiel“Jedes PDF, das im Ordner C:\RUNOS\Eingang landet, wird nach einem erfolgreichen Lauf gelöscht. Das Programm, das die PDFs erzeugt, schreibt den Empfänger als Skriptblock hinein:
#RUNOS Senden.To=kunde@example.com #RUNOS{ "Name": "Eingang mailen", "Autostart": true, "Trigger": { "Type": "File", "Name": "Eingang", "Parameters": { "Pool": "C:\\RUNOS\\Eingang", "Filter": "*.pdf", "CronExpression": "0/10 * * * * ?", "NewName": "Dokument_%yyyy%-%MM%-%dd%_%HH%%mm%%ss%", "DeleteAfter": true } }, "Actions": [ { "Type": "MAPI", "Name": "Senden", "Parameters": { "Client": "Outlook", "Mode": "Display", "To": "", "Subject": "Ihr Dokument {{FileName}}", "Attachments": "{{FilePath}}" } } ]}