Datensätze¶
Mit forms liest und schreibst du Datensätze anderer Formulare — ganz
ohne SQL. Ein Datensatz ist dabei einfach ein Objekt mit den Feldnamen:
{ kunde: "Meyer", betrag: 120 }.
Ausführliches dazu: forms — Datensätze per Skript.
Das Übungsformular
Die Beispiele arbeiten mit einem Formular uebung_bestellung. Wer
mitmachen will, legt es im Formular-Editor mit diesen Feldern an:
| Feld | Typ | Hinweis |
|---|---|---|
kunde |
Text | Pflichtfeld |
betrag |
Zahl | |
status |
Auswahl | neu, freigegeben, erledigt |
datum |
Datum | |
positionen |
Detail-Tabelle | Spalten artikel (Text), menge (Ganzzahl), preis (Zahl) |
forms arbeitet immer mit der Formular-ID (hier uebung_bestellung)
und der Datensatz-Nummer (id).
Einsteiger¶
1. Einen Datensatz anlegen¶
forms.create speichert einen neuen Datensatz und gibt seine Nummer zurück.
var id = forms.create("uebung_bestellung", {
kunde: "Meyer",
betrag: 120,
status: "neu",
datum: "2026-09-01"
});
log.info("Neuer Datensatz Nr. " + id);
2. Einen Datensatz lesen¶
forms.get holt einen Datensatz über seine Nummer.
var id = forms.create("uebung_bestellung", { kunde: "Schulz", betrag: 75.5, status: "neu" });
var satz = forms.get("uebung_bestellung", id);
log.info("Kunde " + satz.kunde + ", Betrag " + satz.betrag);
3. Gibt es den Datensatz?¶
4. Wenn es den Datensatz nicht gibt¶
Statt eines Fehlers liefert forms.get dann null. Prüfe das, bevor du auf
Felder zugreifst.
var satz = forms.get("uebung_bestellung", 999999);
if (satz == null) {
log.info("Datensatz nicht gefunden");
} else {
log.info("Kunde: " + satz.kunde);
}
5. Alle Datensätze zählen¶
forms.list liefert alle Datensätze als Liste.
6. Einen Wert ändern¶
forms.update ändert nur die Felder, die du angibst. Alles andere bleibt,
wie es ist.
var id = forms.create("uebung_bestellung", { kunde: "Wagner", betrag: 40, status: "neu" });
forms.update("uebung_bestellung", id, { status: "freigegeben" });
var satz = forms.get("uebung_bestellung", id);
log.info("Status jetzt: " + satz.status + ", Betrag weiter: " + satz.betrag);
7. Einen Datensatz löschen¶
var id = forms.create("uebung_bestellung", { kunde: "Löschtest" });
forms.delete("uebung_bestellung", id);
log.info("noch da: " + forms.exists("uebung_bestellung", id));
8. Alle Datensätze durchlaufen¶
forms.forEach ruft deine Funktion für jeden Datensatz einmal auf.
var summe = 0;
forms.forEach("uebung_bestellung", function (satz) {
summe += satz.betrag || 0; // leere Beträge zählen als 0
});
log.info("Gesamtbetrag: " + summe);
Fortgeschritten¶
9. Mit Positionen anlegen¶
Die Zeilen einer Detail-Tabelle gibst du als Liste von Objekten mit.
var id = forms.create("uebung_bestellung", {
kunde: "Becker",
status: "neu",
positionen: [
{ artikel: "Stift", menge: 10, preis: 1.20 },
{ artikel: "Block", menge: 5, preis: 2.50 },
{ artikel: "Ordner", menge: 2, preis: 3.90 }
]
});
var satz = forms.get("uebung_bestellung", id);
log.info("Bestellung " + id + " mit " + satz.positionen.length + " Positionen");
10. Positionen auswerten¶
forms.get liefert die Detail-Zeilen mit. So rechnest du die Summe aus.
var id = forms.create("uebung_bestellung", {
kunde: "Hoffmann",
positionen: [
{ artikel: "Stift", menge: 10, preis: 1.20 },
{ artikel: "Block", menge: 5, preis: 2.50 },
{ artikel: "Ordner", menge: 3, preis: 4.20 }
]
});
var summe = 0;
forms.get("uebung_bestellung", id).positionen.forEach(function (p) {
summe += p.menge * p.preis;
});
log.info("Summe: " + summe.toFixed(2));
list ohne Positionen
forms.list lässt die Detail-Zeilen weg, damit lange Listen schnell
bleiben. Brauchst du sie, holst du den einzelnen Satz mit forms.get.
11. Nur bestimmte Datensätze¶
forms.list liefert alles — aussuchen kannst du mit filter.
var neue = forms.list("uebung_bestellung").filter(function (s) {
return s.status === "neu";
});
log.info(neue.length + " neue Bestellungen");
12. Die drei größten Bestellungen¶
var liste = forms.list("uebung_bestellung")
.filter(function (s) { return s.betrag != null; })
.sort(function (a, b) { return b.betrag - a.betrag; }) // größter zuerst
.slice(0, 3);
liste.forEach(function (s, i) {
log.info((i + 1) + ". " + s.kunde + ": " + s.betrag + " €");
});
13. Vorher prüfen¶
forms.validate prüft Werte gegen das Formular — ohne zu speichern. Eine
leere Liste bedeutet: alles in Ordnung.
var fehler = forms.validate("uebung_bestellung", {
betrag: "zwölf", // keine Zahl
status: "unbekannt" // nicht in der Auswahl
// kunde fehlt, ist aber Pflicht
});
log.info("Probleme: " + fehler.length);
fehler.forEach(function (f) {
log.info("- " + f.field + ": " + f.message);
});
14. Nur speichern, wenn alles stimmt¶
Mit { validate: true } bricht create bei Fehlern ab — gespeichert wird
dann nichts.
try {
forms.create("uebung_bestellung", { betrag: 10 }, { validate: true });
log.info("Gespeichert");
} catch (e) {
log.info("Nicht gespeichert: " + e.message);
}
15. Eingaben aus dem aktuellen Formular übernehmen¶
Ein Button-Skript legt aus den Eingaben eine Bestellung an.
var id = forms.create("uebung_bestellung", {
kunde: ctx.form.name,
betrag: ctx.form.betrag,
status: "neu",
datum: new Date().format("yyyy-MM-dd")
});
ctx.form.ergebnis = "Bestellung " + id;
log.info("Bestellung für " + ctx.form.name + " angelegt");
16. Mehrere Datensätze auf einmal ändern¶
var geaendert = 0;
forms.list("uebung_bestellung").forEach(function (s) {
if (s.status === "neu" && s.betrag != null && s.betrag < 100) {
geaendert += forms.update("uebung_bestellung", s.id, { status: "freigegeben" });
}
});
log.info(geaendert + " kleine Bestellungen freigegeben");
update gibt zurück, wie viele Datensätze geändert wurden (0 oder 1).
17. Wem gehört der Datensatz?¶
Normalerweise gehört ein neuer Datensatz dem angemeldeten Benutzer. Beim
Import legst du mit owner einen anderen Eigentümer fest.
var id = forms.create("uebung_bestellung",
{ kunde: "Import GmbH", status: "neu" },
{ owner: "import" });
var nurMeine = forms.get("uebung_bestellung", id, { scope: "mine" });
log.info("Eigentümer: import – für mich sichtbar mit scope 'mine': " + (nurMeine != null));
scope: "mine" beschränkt Lesen, Ändern und Löschen auf die eigenen
Datensätze. Ohne diese Angabe sieht ein Skript alle.
Profi¶
18. Import aus einer CSV-Datei¶
Zeile für Zeile prüfen und anlegen. Fehlerhafte Zeilen werden gesammelt statt den ganzen Import abzubrechen.
var text = "kunde;betrag;status\n"
+ "Nord GmbH;250;neu\n"
+ ";90;neu\n" // Kunde fehlt → abweisen
+ "Süd AG;1200;freigegeben\n";
var angelegt = 0, abgewiesen = [];
var zeilen = csv.parse(text, { separator: ";", header: true });
// Indizierte Schleife wegen der Zeilennummer — forEach gibt auf einer
// Host-Liste keinen Index her.
for (var i = 0; i < zeilen.length; i++) {
var zeile = zeilen[i];
var werte = {
kunde: zeile.kunde,
betrag: Number(zeile.betrag),
status: zeile.status
};
var fehler = forms.validate("uebung_bestellung", werte);
if (fehler.length === 0) {
forms.create("uebung_bestellung", werte, { owner: "import" });
angelegt++;
} else {
abgewiesen.push("Zeile " + (i + 2) + ": " + fehler[0].message);
}
}
log.info(angelegt + " angelegt, " + abgewiesen.length + " abgewiesen");
abgewiesen.forEach(function (m) { log.info(m); });
19. Anlegen oder aktualisieren¶
Gibt es den Kunden schon, wird sein Satz geändert — sonst neu angelegt. So entstehen bei einem wiederholten Import keine doppelten Einträge.
function speichere(werte) {
var vorhanden = forms.list("uebung_bestellung").filter(function (s) {
return s.kunde === werte.kunde;
})[0];
if (vorhanden) {
forms.update("uebung_bestellung", vorhanden.id, werte);
return "aktualisiert";
}
forms.create("uebung_bestellung", werte);
return "neu angelegt";
}
log.info("erster Lauf: " + speichere({ kunde: "Einmalig KG", betrag: 10 }));
log.info("zweiter Lauf: " + speichere({ kunde: "Einmalig KG", betrag: 20 }));
20. Positionen ersetzen¶
Gibst du bei update eine Positionsliste mit, ersetzt sie die bisherige
vollständig.
var id = forms.create("uebung_bestellung", {
kunde: "Umbau AG",
positionen: [{ artikel: "Stift", menge: 1, preis: 1 }, { artikel: "Block", menge: 1, preis: 2 }]
});
var vorher = forms.get("uebung_bestellung", id).positionen.length;
forms.update("uebung_bestellung", id, {
positionen: [{ artikel: "Drucker", menge: 1, preis: 199 }]
});
var nachher = forms.get("uebung_bestellung", id).positionen;
log.info("vorher " + vorher + ", nachher " + nachher.length + ": " + nachher[0].artikel);
21. Einen Datensatz kopieren¶
Ohne id und mit neuem Status wird aus einer alten Bestellung eine neue.
var original = forms.create("uebung_bestellung", {
kunde: "Stammkunde", betrag: 55, status: "erledigt",
positionen: [{ artikel: "Toner", menge: 1, preis: 55 }]
});
var vorlage = forms.get("uebung_bestellung", original);
var kopie = {
kunde: vorlage.kunde,
betrag: vorlage.betrag,
status: "neu",
datum: new Date().format("yyyy-MM-dd"),
positionen: vorlage.positionen.map(function (p) {
return { artikel: p.artikel, menge: p.menge, preis: p.preis }; // ohne interne Nummern
})
};
var neu = forms.get("uebung_bestellung", forms.create("uebung_bestellung", kopie));
log.info("Kopie hat " + neu.positionen.length + " Positionen, Status " + neu.status);
22. Umsatz je Kunde¶
Gruppieren mit einem Objekt als „Sammelbehälter".
var jeKunde = {};
forms.forEach("uebung_bestellung", function (s) {
if (s.betrag == null) return;
jeKunde[s.kunde] = (jeKunde[s.kunde] || 0) + s.betrag;
});
Object.keys(jeKunde).sort().forEach(function (kunde) {
log.info(kunde + ": " + jeKunde[kunde]);
});
23. Ergebnis als Tabelle ins Formular¶
Eine Übersicht wird zur Detail-Tabelle im aktuellen Formular — etwa in einem
Bericht-Formular mit einer Tabelle positionen.
ctx.form.positionen = forms.list("uebung_bestellung")
.filter(function (s) { return s.status === "freigegeben"; })
.map(function (s) {
return { artikel: s.kunde, menge: 1, preis: s.betrag };
});
log.info(ctx.form.positionen.length + " Zeilen in der Übersicht");
24. Viele Datensätze: lieber mit SQL¶
forms ist bequem, holt aber jeden Datensatz einzeln ins Skript. Für
Auswertungen über Tausende Sätze ist SQL schneller. Die Tabelle heißt
form_ + Formular-ID.
var r = db.query(
"SELECT status, COUNT(*) AS anzahl, SUM(betrag) AS summe " +
"FROM form_uebung_bestellung GROUP BY status ORDER BY status");
r.forEach(function (z) {
log.info(z.status + " – Anzahl: " + z.anzahl + ", Summe: " + z.summe);
});
Für Änderungen bleibt forms die bessere Wahl: Es kümmert sich um
Positionen, Anlagen und Änderungsprotokoll.
25. Aufräumen¶
Erledigte Bestellungen löschen — forms.delete entfernt auch die
Positionen, Dateianlagen und das Änderungsprotokoll.