LaTeX : créer des formulaires PDF éditables

Une des fonctionnalités récentes apportées au format PDF est celle des formulaires éditables par l’utilisateur. Celle-ci lui permet ainsi de remplir un certain nombre de champs avant l’impression, directement depuis son viewer préféré. De plus, l’implantation des fonctions JavaScript sous Acrobat Reader étendent encore les possibilités de ces formulaires.

La création de formulaires PDF nous est tout simplement offerte par le classique package hyperref.

Exemple minimal

\documentclass{minimal}
\usepackage{hyperref}
 
\begin{document}
  \begin{Form}
    \TextField[name=name,width=10em]{Name:}
    \TextField[name=surname,width=10em]{Surname:}
 
    \medskip
    Hello there, I am \TextField[name=name]{} \TextField[name=surname]{}, glad to meet you!
  \end{Form}
\end{document}

Dans cet exemple, on commence par définir deux champs. On donne à chacun d’eux un nom et une largeur. Grâce à leurs noms, on peut donc répéter leur contenu autant de fois que nécessaire dans le formulaire, comme illustré sur la phrase d’après.

Autres types de champ

Dans l’exemple ci-dessus, on a utilisé un champ de texte éditable, mais on retrouve en fait les même types de champ qu’en HTML :

\ChoiceMenu[combo,name=country,default=France]{Country:}{Spain,Uganda,Moon,Other}

Cases d’option (ou « boutons radio »)

\ChoiceMenu[radio,default=Male,name=sex]{Sex:}{Male,Female}

Cases à cocher

\CheckBox[name=highschool]{High School}

 

Exécuter des actions entre les champs

Dans l’exemple de code minimal donné plus haut, on réutilise un champ en l’appelant par son nom, mais cette technique ne marche donc que si l’on souhaite le même type de champ. Grâce à l’utilisation de JavaScript dans le formulaire, il est possible d’extraire la valeur d’un champ pour l’utiliser dans un autre.

Affecter une valeur à un champ

Le plus simple pour cela est d’ajouter un bouton à notre formulaire, et d’utiliser une action onclick pour changer les valeurs des champs. Exemple avec des champs de type ChoiceMenu :

\begin{Form}
  \TextField[name=name,width=3cm,charsize=12pt]{Name:}
  \ChoiceMenu[combo,name=country,width=5cm,charsize=12pt,default=France]{Country:}
             {Spain,Uganda,Moon,Other=an Unknown country} \\
  \ChoiceMenu[radio,default=male,name=sex,charsize=14pt]{Sex:}{Male=male,Female=female}
  \PushButton[name=Remplissage,
              onclick={
                this.getField("sextxt").value= this.getField("sex").value;
                this.getField("countrytxt").value= this.getField("country").value;
                      }
              ]{Remplir}
 
In a word: \TextField[name=name,readonly=true]{} is a \TextField[name=sextxt,readonly=true]{} from \TextField[name=countrytxt,readonly=true]{}
\end{Form}

Ici, un premier formulaire demande des informations à l’utilisateur. Quand celui-ci clique sur le bouton « Remplir », les champs présents dans la phrase de résumé sont automatiquement remplis. Ces champs sont non éditables (option readonly). Vous noterez que j’ai donné de façon surabondante les valeurs possibles des champs éditables (ex : « Male=male »), ceci permet d’utiliser une valeur alternative à celle réellement affichée lors de la sélection (qui est donc celle à gauche du signe « = »).

Opérations mathématiques

Vous vous en doutez, JavaScript est assez malin pour permettre les opérations mathématiques entre différentes variables, qui peuvent être extraites des champs. Exemple ultra simple pour faire la moyenne de deux valeurs :

\begin{Form}
  \TextField[name=nb1,value=0]{Valeur numero 1}\\
  \TextField[name=nb2,value=0]{Valeur numero 2}\\
  \TextField[name=moy]{Moyenne des deux}\\
  \PushButton[name=go,
              onclick={var a = this.getField("nb1");var b=this.getField("nb2");
                       var moy=this.getField("moy");moy.value=(a.value+b.value)/2
                       }
              ]{Cliquez ici pour calculer}
\end{Form}

On utilise ici des variables intermédiaires pour stocker les valeurs des champs. Les paramètres « value » servent à imposer les valeurs par défaut.

Personnalisation des champs

Champs de texte

Par défaut, les champs de texte sont encadrés de rouge, ce qui est à mon sens loin d’être élégant. Pour virer ce truc, et en prime changer la police de saisie :

\TextField[name=prenom,value=Prenom,
           format={var f = this.getField('prenom');
                       f.strokeColor = ['T'];f.fillColor=['T'];
                       f.textFont ='Verdana'
                   },
            width=10em]{Pr\'{e}nom}

 Boutons radio

Là encore, le symbole par défaut n’est pas très conventionnel (une étoile). Si vous souhaitez un style plus académique (le même qu’en HTML) :

\ChoiceMenu[radio,radiosymbol=\ding{108},
           default=male,name=sex,charsize=14pt]
           {Sex:}{Male=male,Female=female}

Si vous souhaitez plus d’infos à ce propos, je vous invite à consulter cette page.

Compilation avec Babel en Français

Vous aurez noté que, JavaScript oblige, l’utilisation des point-virgules est plus que fréquente ici. Il faut donc « désactiver » temporairement ce caractère. On utilise donc la même méthode qu’avec TikZ :

\shorthandoff{;}
\begin{Form}
  % Notre formulaire en français, tranquille
\end{Form}
\shorthandon{;}

Débugage

S’il y a une erreur dans votre code JavaScript, ce n’est surement pdfLaTeX qui va vous le dire ! Sachez alors que dans les préférences d’Adobe Reader, onglet ‘JavaScript’, on peut activer le débogueur de scripts.

Pour aller plus loin

Vous pouvez bien entendu commencer par la documentation officielle de hyperref, mais elle manque un peu d’épaisseur à ce sujet. Je ne vais pas non plus vous faire un cours de JavaScript (je laisse ça au site du zéro), mais sachez qu’une page d’Adobe est spécialement dédiée à l’utilisation de JavaScript pour Acrobat.

LaTeX  : créer des formulaires PDF éditables
4.8 (95 %) 4 votes
  • Pingback: Afficher (franchement) des zones de saisie de texte | Le Blog de Dorian()

  • Jean-Luc

    Bonjour

    Très bon article; j’ai testé avec une source latex de type article : cela marche très bien mes quelques lecteurs PDF (sauf avec mon lecteur MuPdf sous linux).

    Par contre, je ne comprends pas l’intérêt de la classe documentclass{minimal}
    mais cela sort peut-être du cadre de cet article.

    Bravo pour la qulité du site.

    Cordialement

    Jean-Luc

    • Bonjour !
      La classe minimal sert simplement, comme son nom l’indique, à obtenir un document minimal : les commandes par défaut sont réduites au strict nécessaire (pas de titre, pas de sections etc.). Ce qui, pour mon exemple, permet d’éviter les éventuels conflits et d’avoir à spécifier les dimensions du document.

    • Bonjour !
      La classe minimal sert simplement, comme son nom l’indique, à obtenir un document minimal : les commandes disponibles par défaut sont réduites au strict nécessaire (pas de titre, pas de sections etc.). Ce qui, pour mon exemple, permet d’éviter les éventuels conflits et d’avoir à spécifier les dimensions du document.

  • Frédéric Stévenot

    Bonjour,
    Je voulais présenter les résultats de mes élèves sous la forme d’un formulaire : exactement ce que je voulais. Toutefois, comme je reprends les mêmes critères d’item en item (OK, bof, pas terrible…), je pensais à un tableau (avec tabularx ou tabular) dans quoi ces critères apparaitraient seulement dans l’en-tête, et il n’y aurait qu’une série de boutons-radio en regard de chaque item. Mais j’obtiens une abomination…
    Merci de votre aide,
    Frédéric

  • Frédéric Stévenot

    À la place d’un tableau, j’ai trouvé cette solution (devinez à partir de quoi…) :
    `item Précision des localisations : hfill
    ChoiceMenu[radio,radiosymbol=ding{108},
    name=option5,charsize=10pt]
    {}{Insuffisant , À améliorer , Assez satisfaisant , OK }
    vspace{0.15cm} `

    Et j’ai une nouvelle question : comment régler la hauteur d’un champ ? La doc. d’hyperref ne rien à ce propos. Ainsi, j’aimerais bien avoir la largeur de la page, et de quoi écrire sur 3-4 lignes dans cet ex. :
    ` TextField[name=note-rem,width=14cm,height=0cm,charsize=12pt]{Note et remarques : }`
    Merci d’avance