Ein Schadensteam liefert ein mit Delphi erzeugtes Einwilligungsformular aus, das in Acrobat makellos aussieht: jedes Kontrollkästchen wird gerendert, jede Beschriftung sitzt richtig, das Layout entspricht dem Papieroriginal. Drei Wochen später weist der Intake-Dienst ein Drittel aller Übermittlungen zurück. Das Backend erwartet, dass das Einwilligungs-Kontrollkästchen den Wert Y sendet; das Formular exportiert Yes, weil beim Erstellen angenommen wurde, Beschriftung und Exportwert seien dasselbe. Auf der gerenderten Seite ist dieser Unterschied nicht zu sehen. Genau das prägt AcroForm-Entwicklung: das sichtbare Widget und der darunterliegende Datenvertrag sind getrennte Strukturen, und nur eine davon wird geprüft, wenn jemand die Datei öffnet und anschaut.
HotPDF ist eine native VCL-Komponente, die AcroForm-Feld-Dictionaries direkt aus Delphi- und C++Builder-Code schreibt, sodass beide Strukturen unter expliziter Programmkontrolle stehen, und beide unabhängig voneinander falsch sein können. Der folgende Text behandelt Felderzeugung, Button-Aktionen und feldbezogenes JavaScript, mit besonderem Blick auf die Stellen, an denen Seitenvorschau und Formulardaten still auseinanderlaufen.
Feldnamen sind Routing-Schlüssel, keine Beschriftungen
Jedes AcroForm-Feld trägt einen vollständig qualifizierten Namen, und ISO 32000-1 §12.7.3 definiert diesen Namen, niemals die sichtbare Beschriftung, als Schlüssel, unter dem der Feldwert in FDF, XFDF und HTTP-Formularübermittlungen übertragen wird. Daraus folgen zwei Konsequenzen, die Entwickler mit VCL-Formularhintergrund regelmäßig überraschen, weil der Name eines Steuerelements dort kaum mehr als ein Codebezeichner ist.
Erstens sind zwei Felder mit demselben vollständig qualifizierten Namen nicht zwei Felder. Das PDF-Modell behandelt sie als zwei Widget-Annotationen eines einzigen Felds, die einen gemeinsamen Wert teilen: Eingaben in einem Feld aktualisieren das andere sofort. Einen Kundennamen auf jeder Vertragsseite zu wiederholen, ist ein legitimer Einsatz dieses Verhaltens. Es versehentlich zu erhalten, weil eine Generierungsschleife 'Field1' über drei Seiten wiederverwendet, ist ein Fehler, den keine Sichtprüfung findet. Jede Seite zeigt weiterhin ihr eigenes Widget, und die Spiegelung fällt erst auf, wenn ein Benutzer zu tippen beginnt.
Zweitens bauen punktierte Namen wie applicant.email eine Hierarchie auf: der Elternknoten applicant gruppiert seine Kinder für Reset- und Submit-Operationen, die nur einen Teil eines Formulars betreffen. Felder von Anfang an hierarchisch zu benennen kostet nichts und zahlt sich aus, sobald das empfangende System „nur den Antragstellerblock“ anfordert.
Radiobuttons bringen eine dritte Regel mit: Buttons, die gemeinsam umschalten sollen, müssen einen Gruppennamen teilen. In HotPDF hängen AddRadioButton-Aufrufe mit demselben Gruppennamen ihre Widgets an ein gemeinsames Elternfeld, und der Exportwert jedes Buttons, etwa 'basic' oder 'full', identifiziert die ausgewählte Option. Wenn jeder Button stattdessen einen eigenen Namen bekommt, entstehen unabhängige Ein/Aus-Schalter statt einer gegenseitig ausschließenden Gruppe.
Das Feldset seitenweise aufbauen
HotPDF platziert Felder über Methoden von THPDFPage, deshalb gehört jedes Feld zu dem Seitenobjekt, das es erzeugt hat. Eine Reihenfolge-Falle dominiert hier: AddPage richtet CurrentPage sofort auf die neue Seite aus. Jeder danach ausgeführte Feldaufruf landet also auf der neuen Seite, selbst wenn er logisch zur vorherigen gehört. Erstellen Sie jede Seite vollständig, gezeichnete Inhalte und Felder zusammen, bevor Sie AddPage aufrufen.
procedure BuildClaimForm(Pdf: THotPDF);
begin
// Page 1: applicant block
Pdf.CurrentPage.AddTextField('applicant.name', '', Rect(50, 700, 300, 722));
Pdf.CurrentPage.AddTextField('applicant.email', '', Rect(50, 660, 300, 682));
Pdf.CurrentPage.AddCheckBox('consent', 'Y', Rect(50, 620, 70, 640), False);
Pdf.CurrentPage.AddRadioButton('coverage', 'basic', Rect(50, 580, 70, 600), True);
Pdf.CurrentPage.AddRadioButton('coverage', 'full', Rect(90, 580, 110, 600), False);
Pdf.CurrentPage.AddComboBox('plan', 'Standard',
['Basic', 'Standard', 'Premium'], Rect(50, 540, 200, 565));
Pdf.AddPage; // CurrentPage now points at page 2
Pdf.CurrentPage.AddListBox('riders', 'None',
['None', 'Flood', 'Earthquake'], Rect(50, 500, 200, 600));
end;
Koordinaten folgen der PDF-Konvention: Der Ursprung liegt links unten auf der Seite, dieselbe Konvention, die TextOut für gezeichneten Text verwendet. Rect(50, 100, 200, 120) liegt daher auf einer Letter-Seite nahe am unteren Rand, nicht oben. Teams, die Layouttabellen aus VCL portieren, wo Y von oben nach unten wächst, erzeugen im ersten Entwurf zuverlässig vertikal gespiegelte Felder. Rechnen Sie Koordinaten in einem gemeinsamen Helfer um, nicht an jeder Aufrufstelle, damit die Korrektur überall gleichzeitig greift.
Buttons mit URI-, JavaScript- und Submit-Aktionen verdrahten
Ein Push-Button tut nichts, bis eine Aktion an ihn gebunden ist. HotPDF stellt die Aktionstypen aus ISO 32000-1 §12.6.4 über die Enumeration THPDFButtonAction bereit, also baURI, baJavaScript, baSubmitURL, baResetForm, baHide, baShow und baNamed, plus zwei Methoden, die den Button erstellen und seine Aktion in einem Schritt binden.
// Open a help page in the system browser
Pdf.CurrentPage.AddPushButtonWithAction('btnHelp', 'Help',
'https://www.example.com/claims-help', Rect(320, 700, 420, 730), baURI);
// Run viewer-side JavaScript
Pdf.CurrentPage.AddPushButtonWithAction('btnRecalc', 'Recalculate',
'app.alert("Totals updated.");', Rect(320, 660, 420, 690), baJavaScript);
// Submit as XFDF and keep empty fields in the payload
Pdf.CurrentPage.AddPushButtonWithSubmitAction('btnSubmit', 'Submit claim',
'https://api.example.com/claims', Rect(320, 620, 420, 650),
[sffXFDF, sffIncludeNoValueFields]);
Die Submit-Flags verdienen mehr Entwurfsaufmerksamkeit, als sie meist bekommen. AddPushButtonWithSubmitAction übernimmt eine THPDFSubmitFormFlags-Menge, und eine leere Menge erzeugt einen einfachen URL-kodierten POST, ein Format, das viele Beispielendpunkte akzeptieren und viele Produktionsendpunkte nicht. sffXFDF schaltet die Nutzdaten auf XFDF um; sffGetMethod ändert das HTTP-Verb; sffIncludeNoValueFields lässt leere Felder in den Nutzdaten erscheinen, statt sie still zu entfernen, was wichtig ist, wenn der Verbraucher zwischen „fehlt“ und „leer“ unterscheidet. Die Flag-Menge ist faktisch Teil Ihres Schnittstellenvertrags mit dem empfangenden Endpunkt. Wählen Sie sie also gemeinsam mit dem Team, das die Übermittlung parst, nicht erst nach der ersten zurückgewiesenen Charge.
Feldbezogenes JavaScript: Keystroke, Format, Validate
Neben Button-Klicks hängt HotPDF JavaScript an feldbezogene Ereignisse, die scriptfähige Viewer während der Dateneingabe auslösen. Die drei Trigger gehören zu unterschiedlichen Momenten im Eingabezyklus: Keystroke-Aktionen laufen beim Eintreffen von Zeichen, Format-Aktionen schreiben den angezeigten Wert nach dem Übernehmen einer Änderung um, und Validate-Aktionen akzeptieren oder verwerfen den übernommenen Wert.
// Reject committed values that are not plausible email addresses
Pdf.AttachFieldKeyStrokeAction('applicant.email',
'if (event.willCommit && !/^[\w.-]+@[\w.-]+\.\w+$/.test(event.value)) event.rc = false;');
// Display US phone numbers as (NNN) NNN-NNNN
Pdf.AttachFieldFormatAction('applicant.phone',
'event.value = event.value.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");');
// Refuse applicants under 18 at commit time
Pdf.AttachFieldValidateAction('applicant.age',
'if (parseInt(event.value) < 18) event.rc = false;');
Das Setzen von event.rc = false in einem Keystroke- oder Validate-Skript lässt den Viewer die Eingabe ablehnen. Die Grenze bleibt wichtig: Dieser Code läuft nur in Viewern mit JavaScript-Engine. Acrobat und einige Desktop-Produkte führen ihn aus; die meisten mobilen Reader, browserintegrierten Renderer und Druckpipelines ignorieren ihn vollständig. Feldskripte erhöhen die Datenqualität für die Benutzer, bei denen sie laufen. Sie sind keine Sicherheitsgrenze, und jeder übermittelte Wert muss beim Eingang weiterhin serverseitig validiert werden.
Defekte, die eine Sichtprüfung bestehen
Einige Formularfehler sind für eine Öffnen-und-Anschauen-Prüfung strukturell unsichtbar. Diese vier verursachen den größten Teil der AcroForm-Eskalationen beim Support, und jeder davon lässt sich vor der Freigabe mechanisch erkennen:
- Abweichende Exportwerte. Ein mit
AddCheckBox('consent', 'Yes', ...)erzeugtes Kontrollkästchen sendetYes; ein Verbraucher, der aufYprüft, weist jede Übermittlung zurück, während die Seite perfekt aussieht. Exportieren Sie das ausgefüllte Formular aus Acrobat als XFDF und vergleichen Sie die Werte mit dem Schema des Verbrauchers. - Versehentliche Wertspiegelung. Doppelte vollständig qualifizierte Namen verschmelzen Felder zu einem einzigen. Das Symptom erscheint bei der Dateneingabe, nie bei der Erzeugung. Testen Sie also durch Tippen in das Formular, nicht durch Rendern.
- Combo-Werte außerhalb der Optionsliste. Wenn der aktuelle Wert, der an
AddComboBoxübergeben wird, nicht unter den Optionen ist, unterscheiden sich Viewer darin, ob sie ihn anzeigen, leeren oder markieren. Halten Sie den Standardwert innerhalb der Liste. - Felder bleiben nach Abschluss des Workflows editierbar. HotPDF hat keinen Appearance-Flattening-Aufruf für AcroForm-Felder; der unterstützte Weg, ein abgeschlossenes Formular einzufrieren, ist das Erzeugen von Feldern mit dem Flag
ffReadOnly, wodurch der Wert über den eigenen Appearance-Stream des Felds gerendert bleibt, Bearbeitungen aber blockiert werden. Ein schreibgeschütztes Feld bleibt ein lebendes Formularobjekt, das nachgelagerte Montage- und Signaturwerkzeuge berechenbar behandeln.
Ein viewerabhängiges Verhalten verdient einen Regressionshinweis, auch wenn keine Codeänderung es behebt: Acrobat-Installationen in Unternehmen können JavaScript deaktivieren oder Submit-Ziele per Richtlinie einschränken. Eine Aktion, die während der Entwicklung funktionierte, kann auf einem Kundendesktop daher wirkungslos sein. Geben Sie Übermittlungen einen sichtbaren Fallback, mindestens eine gedruckte Anweisung, falls der Button nichts tut.
Wo Formulararbeit mit dem restlichen Dokument zusammenhängt
Ein Signaturfeld ist selbst ein AcroForm-Feldtyp. Ein Formular, das später zertifiziert oder gegengezeichnet wird, sollte dieses Feld daher schon bei der Erzeugung reservieren, statt es nachträglich einzupatchen; die Mechanik auf Byteebene behandelt der Begleitartikel zu digitalen Signaturen und PAdES-Signaturen mit HotPDF. Wenn Ihre Eingaben als XFA-Pakete statt als native AcroForm-Strukturen ankommen, ist das Flattening von XFA in AcroForm-Felder ein eigener Workflow mit eigenem Verlustmodell, da beide Formulartechnologien in einer einzelnen Datei gegenseitig exklusiv sind.
Die hier gezeigten Feld-, Aktions- und Trigger-Methoden gehören zur Standard-API von HotPDF Component für Delphi und C++Builder; die Produktseite verlinkt die vollständige Referenz, einschließlich der Feld-Flag-Überladungen und der kompletten Submit-Flag-Enumeration.