Comment générer un document avec des variables calculées, à partir d'un .odt

J'ai récemment eu besoin de générer des documents dont certaines zones de texte devaient être remplacées par un contenu calculé.

Le but final étant de générer un PDF, je connaissais quelques moyens de parvenir à mes fins (avec une bonne librairie Python), mais aucun ne pouvait réellement répondre à ma contrainte principale : le document source devait rester modifiable par un utilisateur lambda. C'est à dire que mon document LibreOffice Writer devait pouvoir être modififé de manière tout à fait conventionnelle et il devait aussi pouvoir être utilisé par mon script pour remplacer certaines zones de textes par des valeurs calculées.

La solution que j'ai utilisé, et qui m'a été suggérée par mon collègue Corentin repose donc sur un document LibreOffice Writer (multiplateforme) et un script shell (dans un envrionnement Linux donc).

Création du document modèle contenant des variables

Commençons donc pas créer le document que l'on souhaite dans LibreOffice Writer. Il n'y a aucunes contraintes sur le contenu ni la mise en page. Il faut simplement introduire aux emplacements souhaités des mots clés (nos variables) que l'on souhaitera remplacer par un contenu généré. Dans mon exemple j'ai choisi d'insérer VARIABLE1 et VARIABLE2 dans mon document.

Il est intéressant d'enregistrer le document au format .ott (Modèle de texte ODF) pour éviter que le document modèle ne soit écrasé par un utilisateur lambda qui aurait remplacé les variables et fait "Enregistré" au lieu de "Enregistré sous".

Script de remplacement des variables

Dans notre script shell nous allons faire quatre étapes : 1. faire une copie du document source (pour ne pas modifier notre document modèle) 2. chercher nos variables et les remplacer par les valeurs souhaitées 3. exporter notre document en PDF 4. supprimer la copie modifée (le PDF suffit)

Un fichier LibreOffice Writer étant une archive zip contenant (entre autre) un fichier XML décrivant le contenu du document, il est nécessaire d'extraire ce fichier content.xml avant de pouvoir remplacer les variables avec sed, puis de mettre à jour l'archive avec ce nouveau document XML.

#!/bin/sh

SOURCE_FILE_PATH="$1"
DESTINATION_DIRECTORY=`dirname "$SOURCE_FILE_PATH"`
MODIFIED_FILE_NAME="modified-file.odt"
DESTINATION_FILE_PATH="${DESTINATION_DIRECTORY}/${MODIFIED_FILE_NAME}"

# We will work with a copy of the source file
cp "$SOURCE_FILE_PATH" "${DESTINATION_FILE_PATH}"

# Extract content.xml from ODT file
cd "${DESTINATION_DIRECTORY}"
unzip -oq "${MODIFIED_FILE_NAME}" content.xml
# -o = overwrite without prompting, -q = quiet

# Replace variables
CUSTOM_VALUE="$(date)"
sed -e "s/VARIABLE1/something/g" \
    -e "s/VARIABLE2/${CUSTOM_VALUE}/g" \
    -i content.xml # -i = in place

# Rebuild the ODT file with the modified content.xml
zip -q "${MODIFIED_FILE_NAME}" content.xml # -q = quiet

# Export to PDF
libreoffice --headless --convert-to pdf "${MODIFIED_FILE_NAME}"

# Remove the modified versions of the source file and content.xml
rm content.xml
rm "${DESTINATION_FILE_PATH}"

Télécharger le script depuis Gitlab

Le script, que l'on peut nommer great-replacement.sh, s'utilise comme ceci :

> great-replacement.sh chemin/vers/mon/fichier.ott

Les variables qui sont remplacées peuvent exploiter la puissance du shell pour faire tous les calculs nécessaires (appel à une API, lecture d'une base de données, utilisation de scripts Python, …)

Solutions alternatives