Beim Bau eines PDF-Formulars in LaTeX – ausfüllbare Textfelder, Kontrollkästchen – tritt man stets in dieselbe Mine. Man schreibt \TextField{Name}, übersetzt, und heraus kommt ein PDF ohne Fehler, ohne Warnung und ohne irgendein Eingabefeld. Die Beschriftung „Name“ steht im Fließtext, pdfinfo antwortet Form: none, und im Inneren der Datei findet sich keine einzige Widget-Annotation. Außerhalb einer Form-Umgebung erzeugen die Feldbefehle von hyperref stillschweigend gar nichts. Diese Seite beginnt bei \begin{Form} und verfolgt messend, was jedes Feld tatsächlich ins PDF schreibt, wohin eine Submit-Schaltfläche ihre Daten standardmäßig sendet und ab wann besser ein Webformular entsteht.
Ohne Form-Umgebung entstehen keine Felder
Jedes interaktive Feld gehört in \begin{Form} … \end{Form}. Das ist keine Stilfrage, sondern verändert die Ausgabe. Übersetzt man ein Dokument mit \TextField und \CheckBox außerhalb der Umgebung, beendet sich pdflatex mit Rückgabewert 0 und ohne jede Warnung – das entstandene PDF enthält jedoch null /Widget-Annotationen, und pdfinfo meldet weiterhin Form: none. Verschiebt man dieselben Befehle nach innen, antwortet pdfinfo mit Form: AcroForm. Ein PDF-Formular besteht aus einem einzigen AcroForm-Wörterbuch, das alle Felder bündelt, und die Form-Umgebung erzeugt genau dieses Wörterbuch. Zudem genügt \usepackage{hyperref} allein – eine Treiberoption wie [pdftex] ist nicht nötig; im Log erscheint hpdftex.def von selbst.
Die Form-Umgebung nimmt, zählt man im Quelltext von hyperref nach, genau vier Schlüssel: action (wohin die Daten gehen), method, encoding und NeedAppearances. Alles zu Aussehen und Verhalten eines Feldes wird im [...] des jeweiligen Feldes gesetzt; die Optionen der Umgebung lassen sich also schlicht als Versandeinstellungen begreifen.
\documentclass{article}
\usepackage{hyperref} % no driver option needed
\begin{document}
\begin{Form}[action={https://example.org/collect},method=post]
\TextField[name=fullname,width=6cm]{Name}\par
\CheckBox[name=agree]{I agree}\par
\ChoiceMenu[combo,name=affil]{Affiliation}{University,Company,Other}\par
\Submit{Send}\quad\Reset{Clear}
\end{Form}
\end{document}Die Feldbefehle und was jeder ins PDF schreibt
Es gibt fünf Feldbefehle, und auf PDF-Seite fallen sie in drei Feldtypen zusammen: Text ist /Tx, Auswahl ist /Ch, und alles Knopfförmige – Kontrollkästchen, Schaltfläche, Submit, Reset – ist /Btn. Übersetzt man das obige Beispiel und holt die Objekte heraus, findet man genau das: zweimal /Tx, einmal /Ch, viermal /Btn. Dass die Knöpfe zusammengefasst sind, schreibt die PDF-Spezifikation so vor; der Unterschied zwischen Kontrollkästchen und Schaltfläche steckt nicht im Typ, sondern in Bits des Flag-Eintrags (/Ff). Diese Struktur – der Charakter ergibt sich aus Flags – wird im nächsten Abschnitt wichtig.
| Befehl | PDF-Feldtyp | Erzeugt |
|---|---|---|
\TextField | /Tx | Ein Textfeld; multiline, password und maxlen ändern seinen Charakter |
\CheckBox | /Btn | Ein Kontrollkästchen; Standardwert /Off, mit checked von Anfang an gesetzt |
\ChoiceMenu | /Ch oder /Btn | combo ist ein editierbares Dropdown, popdown ein Listenfeld, radio eine Radiogruppe (dann /Btn) |
\PushButton | /Btn | Eine Schaltfläche; onclick= mit JavaScript ergibt eine /S /JavaScript-Aktion |
\Submit / \Reset | /Btn | /S /SubmitForm und /S /ResetForm. Die Feldnamen lauten stets Submit und Reset; das Argument ist nur die sichtbare Beschriftung |
Ohne name= wird die Beschriftung zum Feldnamen – und die Radiogruppen-Falle
Ohne name= wird der Beschriftungstext zum Feldnamen. Im PDF aus \TextField{Your name} lautet der Feldname /T (Your name) – samt Leerzeichen. Für die datenempfangende Seite ist das ein sperriger Name, und eine deutsche Beschriftung ergibt einen deutschen Feldnamen. Die Praxis lautet daher: immer einen ASCII-Bezeichner über name= angeben. Es gibt eine zweite Folge: Schreibt man denselben name= zweimal, behandelt PDF gleichnamige Felder als ein und dasselbe Feld. Zwei \TextField-Einträge mit name=dup erzeugen zwei Objekte, die beide /T (dup) tragen, und eine Eingabe im einen füllt das andere mit demselben Wert. Das ist nützlich, wenn ein Wert absichtlich an zwei Stellen erscheinen soll; eine versehentliche Kollision ergibt dagegen einen schwer auffindbaren Fehler.
Radioknöpfe bergen ein tiefer liegendes Problem. \ChoiceMenu[radio,name=r1]{Pick}{a,b,c} ergibt drei /Btn-Objekte, alle r1 benannt – aber nur das erste steht im /Fields-Array des AcroForm-Wörterbuchs. Die anderen beiden hängen frei, von keinem Feld referenziert. Schickt man die Datei durch qpdf, sagt es das zweimal: WARNING: this widget annotation is not reachable from /AcroForm in the document catalog. Die PDF-Spezifikation verlangt für eine Radiogruppe ein Elternfeld, das seine Kinder über /Kids bündelt; hyperref legt sie stattdessen flach nebeneinander. Viele Viewer zeigen es trotzdem an, weshalb das Problem unbemerkt bleibt – es ist aber eine Struktur, die unter einem strengen PDF-Prozessor oder einer automatischen Auswertung brechen kann. Bei festen Auswahlmöglichkeiten ist combo oder popdown das ehrlichere Werkzeug.
Die wichtigsten Optionen: Was zu Flags wird und was nicht
Jedes Feld nimmt eine lange Optionsliste in [...] – hyperref definiert nahezu dreißig Schlüssel. Häufig gebraucht werden name=, width=/height=, default= (Anfangswert), bordercolor/backgroundcolor, charsize, align (0 = links, 1 = zentriert, 2 = rechts), maxlen= (Höchstzahl an Zeichen) und menulength= (angezeigte Zeilen einer Liste). Davon sind nur multiline, readonly und password wertlose Schalter, die eins zu eins auf PDF-Flags abbilden: hyperref.sty definiert ab Zeile 5283 ReadOnly als Bit 1, Multiline als Bit 13 und Password als Bit 14; baut man ein Formular und liest /Ff zurück, ergibt das genau 1, 4096 und 8192. maxlen=5 ist dagegen gar kein Flag, sondern wird als eigener Eintrag /MaxLen 5 geschrieben. Wer den Unterschied kennt, weiß, wo zu suchen ist, wenn eine Option nicht wie erwartet wirkt.
\begin{Form}
\TextField[name=notes,multiline,width=8cm,height=3cm]{Notes}\par
\TextField[name=locked,readonly,width=4cm,default={fixed}]{Locked}\par
\TextField[name=short,maxlen=5,width=3cm]{Max 5}\par
\TextField[name=email,width=5cm,align=0,
bordercolor={0 0 0},backgroundcolor={1 1 0.9}]{Email}
\end{Form}\Submit sendet standardmäßig FDF – method=post allein genügt nicht
Das ist der wichtigste Punkt dieser Seite. Schreibt man \begin{Form}[action={https://example.org/collect},method=post] und drückt die Submit-Schaltfläche, erreicht den Server kein HTML-Formular-POST, sondern FDF, Acrobats eigenes Datenformat. Die Ursache steht in Zeile 5371 von hyperref.sty: \def\Fld@export{fdf} setzt das Standardexportformat auf FDF. Übersetzt man und holt die Submit-Aktion heraus, findet man /S /SubmitForm ganz ohne /Flags-Eintrag – alle Flags null, also FDF. Und method=post? Ein Blick auf \HyField@FlagsSubmit ab Zeile 5378 klärt es: Das von method gesetzte GetMethod-Flag wird nur in den Zweigen für HTML und PDF verwendet und im FDF-Zweig vollständig ignoriert. method=post allein bewirkt also überhaupt nichts.
Damit ein gewöhnlicher Webserver die Daten empfängt, ergänzt man die Form-Umgebung um encoding=html. Dieser eigene Schlüssel führt um Zeile 5665 von hyperref.sty \def\Fld@export{html} aus; damit erhält die Submit-Aktion /Flags 4 – Bit 3, ExportFormat, ist gesetzt, also HTML-Kodierung. Schreibt man in encoding etwas anderes als html, erscheint lediglich die Warnung Form 'encoding' key with unknown value, und der Wert wird stillschweigend verworfen. Als weitere Exportformate stehen xfdf (eine XML-Variante von FDF) und pdf (das gesamte ausgefüllte PDF wird gesendet) zur Verfügung.
% FDF (the default) -- your endpoint receives an Acrobat-specific blob
\begin{Form}[action={https://example.org/collect},method=post]
% an ordinary HTML form post -- note encoding=html
\begin{Form}[action={https://example.org/collect},encoding=html,method=post]Was echte Viewer damit tun – und wann man aufgeben sollte
Die Formulare von hyperref schreiben das Erscheinungsbild eines Feldes überhaupt nicht in die Datei. Sie setzen /NeedAppearances true im AcroForm-Wörterbuch – eine Bitte an den Viewer, die Bedienelemente selbst zu zeichnen. Acrobat Reader kommt dem nach, doch die Unterstützung schwankt: In der PDF-Anzeige eines Browsers oder einem schlanken Viewer fehlt womöglich der Rahmen, oder er lässt sich nicht beschreiben. Beim JavaScript in \PushButton[onclick=...] sind Viewer, die es ausführen, ohnehin die Minderheit. Dieselbe Eigenschaft wirkt anderswo weiter: Was auf /NeedAppearances baut, kann PDF/A nicht erfüllen. Ein einziges Eingabefeld genügt, damit veraPDF die Datei an Klausel 6.3.3 scheitern lässt: „An annotation does not contain an appearance dictionary“ (ausführlich auf der PDF/A-Seite).
Fasst man das zusammen, verengen sich die Gründe für ein PDF-Formular erheblich. Für Validierung oder Skripting gibt es insdljs und AcroTeXs eforms, doch auch darauf aufbauend lässt sich nicht garantieren, dass es im Viewer des Gegenübers funktioniert. Geht es bloß darum, Antworten online einzusammeln, lautet die ehrliche Schlussfolgerung: Ein Webformular ist verlässlicher und schneller gebaut. Wirklich passend ist ein PDF-Formular dort, wo ein Vordruck zum Ausdrucken gedacht ist und die empfangende Person ihn zufällig am Rechner ausfüllt, bevor sie ihn druckt oder als PDF sichert – also dort, wo die Sendefunktion nie zum Einsatz kommt. Für diesen Zweck sind beschreibbare Felder wirklich nützlich, und zusammen mit readonly festgelegten Feldern entsteht eine stabile Vorlage.