Formater, valider et transformer les données d’étiquettes avec Python avant l’impression
Une étiquette de prix qui imprime 35.00 au lieu de 3.50 n’est pas un problème de conception. C’est un problème de données — et c’est le genre de problème qui survit à chaque relecture visuelle parce que l’étiquette semble correcte.
Cet article porte sur la couche que la plupart des workflows d’étiquetage ignorent : ce qui arrive à la valeur d’un champ entre « la feuille de calcul contient une valeur » et « l’imprimante la pose sur le papier ».
La freelance qui a failli livrer une étiquette de prix erronée
Imaginez une développeuse solo — appelons-la Mara — qui accepte un petit client dans le commerce de détail : une boutique, quarante références, une feuille de calcul que la propriétaire tient elle-même. Mara crée un modèle d’étiquette, connecte la feuille de calcul comme source de données, imprime une planche de test, et la première étiquette affiche un paquet de café de 250 g à 35.00.
La feuille de calcul indiquait 3,50. Une virgule décimale. La conception de l’étiquette attendait un point, et personne ne l’a remarqué avant que l’épreuve ne revienne de la propriétaire de la boutique.
Le reste de la colonne n’est pas mieux :
- Des prix sous la forme
3.5,3,50,€ 3.50, et quelques cellules vides. - Des références (SKU) qu’Excel a silencieusement transformées en nombres, dévorant les zéros de tête dont un code-barres a besoin.
- Des dates de durabilité minimale dans trois formats sur quarante lignes.
- Des codes fournisseurs avec un préfixe
SUP-que la propriétaire veut voir supprimé pour une étiquette plus propre.
Le premier réflexe de Mara est le réflexe standard : écrire un script d’export qui nettoie le CSV, puis alimenter l’outil d’impression avec le fichier nettoyé. Ça marche — jusqu’à ce que la propriétaire modifie la feuille de calcul la semaine suivante, que le script d’export reste sur l’ordinateur portable de Mara, non documenté, et que personne ne pense à l’exécuter.
La vraie question est donc la suivante : comment nettoyer et façonner les valeurs des champs avant qu’elles n’atteignent l’imprimante, sans mettre en place et maintenir un second pipeline de données ?
La réponse dans RSJ LPSNG est l’API Python Field Script : des blocs de script attachés à des champs d’étiquette individuels, qui accèdent aux valeurs des champs et les modifient avant l’impression. Le script voyage avec l’étiquette au lieu de vivre à côté.
Soyons clairs sur le périmètre : il ne s’agit pas de concevoir l’étiquette. Si vous cherchez le côté mise en page — placer du texte, des codes-barres et des images dans l’éditeur navigateur — c’est couvert dans How to Design Barcode Labels in a Browser Layout Editor. Cet article porte sur les valeurs qui alimentent cette mise en page.
Pourquoi le contrôle des données au niveau du champ compte pour les développeurs et les utilisateurs finaux
La plupart des défauts d’étiquettes sont des défauts de données déguisés en défauts de conception. Décimales erronées, dates non formatées, zéros de tête manquants dans les codes-barres, un nom de produit tronqué qui ne tient plus — la mise en page fait exactement ce qu’on lui a demandé. L’entrée était erronée.
Le contrôle au niveau du champ compte pour deux publics très différents, pour la même raison de fond.
Pour les développeurs, il élimine toute une catégorie d’infrastructure annexe. Vous n’écrivez et ne maintenez ni script de prétraitement externe, ni tâche planifiée qui réécrit des fichiers CSV, ni code de liaison entre la source de données et le moteur d’impression. Le formatage et la validation vivent dans la définition de l’étiquette, qui est l’artefact qui en a réellement besoin.
Pour les utilisateurs finaux et les petites équipes, il produit une sortie cohérente sans exiger de quiconque qu’il comprenne les données sources. La propriétaire de la boutique continue de remplir sa feuille de calcul comme elle l’a toujours fait. C’est l’étiquette qui décide comment un prix est affiché.
L’API Python Field Script est la couche intermédiaire entre ces deux mondes :
- Elle s’exécute sur le champ, pas sur le fichier.
- Elle peut lire et modifier la valeur avant l’impression.
- Elle vit à l’intérieur de la même plateforme qui rend l’étiquette, donc aucune dérive de version entre « le nettoyeur » et « le modèle ».
La référence de l’API se trouve à lpsng.rsj.de/api.html.
Un guide pratique : formater, valider et transformer en trois passes
Traitez chaque script de champ comme trois passes sur la valeur, dans cet ordre : la formater, la prouver, puis en dériver. Les extraits ci-dessous sont du Python illustratif — l’important est la forme de la logique, pas les noms exacts des fonctions auxiliaires.
Passe 1 : formater
Normalisez la valeur brute en exactement ce que la conception de l’étiquette attend. Les prix vers un motif décimal fixe, les dates vers un seul format d’affichage, le texte vers la casse autour de laquelle la mise en page a été conçue.
import re
CURRENCY = re.compile(r"[^\d,.\-]")
def format_price(raw):
"""'€ 3,50' -> '3.50'; returns None when nothing usable is left."""
if raw is None:
return None
cleaned = CURRENCY.sub("", str(raw)).strip()
if not cleaned:
return None
if "," in cleaned and "." in cleaned:
cleaned = cleaned.replace(".", "").replace(",", ".") # 1.234,56
elif "," in cleaned:
cleaned = cleaned.replace(",", ".") # 3,50
return f"{float(cleaned):.2f}"
from datetime import datetime
DATE_FORMATS = ("%Y-%m-%d", "%d.%m.%Y", "%d/%m/%Y")
def format_date(raw, out="%d.%m.%Y"):
text = str(raw or "").strip()
for fmt in DATE_FORMATS:
try:
return datetime.strptime(text, fmt).strftime(out)
except ValueError:
continue
return None # unparseable beats guessed
def label_case(raw, style="upper"):
text = " ".join(str(raw or "").split()) # collapse stray whitespace
return text.upper() if style == "upper" else text.title()
Notez les retours None délibérés. Une valeur non formatable doit échouer visiblement à la passe suivante, et non devenir un 0.00 d’apparence plausible.
Passe 2 : valider
La validation est ce qui empêche un prix erroné d’atteindre discrètement l’imprimante. Vérifiez que les champs dont vous dépendez existent et sont bien formés, et rendez chaque message suffisamment précis pour localiser l’enregistrement.
def validate_record(record):
"""Return a list of 'field: reason' strings. Empty list means OK."""
errors = []
sku = (record.get("sku") or "").strip()
if not sku:
errors.append("sku: missing")
elif len(sku) < 8:
errors.append(f"sku: shorter than 8 characters ({sku!r})")
price = record.get("price")
if price is None:
errors.append("price: not parseable")
elif not (0.01 <= price <= 9999.99):
errors.append(f"price: out of range ({price!r})")
if record.get("best_before") is None:
errors.append("best_before: unparseable date")
return errors
Un message comme price: not parseable ('0,00') indique à un opérateur quel champ regarder et quelle valeur en est la cause. Un message comme invalid data lui dit de vous appeler.
price: not parseable ('0,00')
sku: shorter than 8 characters ('4711')
best_before: unparseable date (row: Espresso 250g)
Passe 3 : transformer
Ce n’est qu’une fois la valeur formatée et validée que vous devez en dériver des valeurs d’affichage — un code produit combiné, un préfixe fournisseur retiré, un nom court pour un champ étroit.
def product_code(record, prefix="SUP-"):
supplier = (record.get("supplier_code") or "").strip()
if supplier.startswith(prefix):
supplier = supplier[len(prefix):]
sku = (record.get("sku") or "").strip()
return f"{supplier}-{sku}".strip("-")
Où vit le script dans le workflow
Dans RSJ LPSNG, vous attachez le bloc de script à un champ d’étiquette dans la mise en page. La plateforme l’exécute dans le cadre de la tâche normale d’impression ou de rendu — la même exécution qui gère aussi la sortie PDF ou PNG et l’impression directe via l’interface de service web. Aucun processus annexe à démarrer, aucun problème d’ordonnancement à raisonner.
Cela compte pour la transmission. La règle de formatage fait partie de la définition de l’étiquette, elle se déplace donc avec le modèle plutôt que de rester sur la machine de celui qui l’a écrite.
La manière difficile vs. la manière gérée
La manière difficile est celle que Mara a failli choisir : un script séparé qui réécrit les fichiers CSV ou Excel avant qu’ils ne soient fournis à un outil d’impression. Il a sa propre histoire de déploiement, ses propres modes de défaillance, et sa propre hypothèse silencieuse que tout le monde pense à l’exécuter avant d’imprimer.
La manière gérée place le bloc de script Python sur le champ lui-même dans RSJ LPSNG. Le formatage et la validation voyagent avec l’étiquette. La même étiquette peut être rendue en PDF ou PNG, ou envoyée à l’impression directe via l’interface de service web, et la logique du champ est la même dans tous les cas parce qu’elle appartient à l’étiquette, pas à une étape externe.
Liste de contrôle pour votre premier script de champ
- Commencez par un champ et une règle. Formatez le prix, générez un PDF d’exemple et inspectez-le. Ne touchez au champ suivant qu’ensuite.
- Rendez les échecs localisables. Chaque message de validation doit nommer le champ et montrer la valeur fautive.
- Testez avec des entrées volontairement désordonnées. Cellules vides, espaces superflus, formats de date mélangés, un prix négatif, un prix de
0.00, une référence de mauvaise longueur. - Décidez entre transformation et recherche. Les fichiers Excel peuvent servir à la fois de fichiers de données et de fichiers de recherche, donc un nom de fournisseur peut avoir sa place dans une feuille de référence plutôt que d’être dérivé dans le script. Le côté source de données est couvert dans How to Print Barcoded Labels from Excel.
- Générez avant d’exécuter. Une épreuve PDF de trois enregistrements désordonnés coûte une minute ; une réimpression de quarante étiquettes de rayon erronées coûte une matinée.
Ce qu’il faut éviter
N’enfouissez pas les règles métier dans la mise en page. Gardez le formatage et la validation dans le script de champ et les décisions de conception dans l’éditeur de mise en page. Les mélanger signifie qu’un ajustement de conception peut discrètement changer un format de prix.
Ne convertissez pas silencieusement des données erronées en une valeur plausible. Une étiquette qui imprime avec assurance le mauvais prix est pire qu’une tâche qui échoue bruyamment. Retournez None et laissez la validation l’attraper.
Ne dupliquez pas la même transformation sur de nombreux champs. Si six champs ont besoin du même format de prix, une approche partagée vaut mieux que six blocs copiés-collés qui divergent. L’incohérence entre les champs d’une même étiquette est l’une des sources d’erreurs les plus courantes.
Ne devinez pas sur une entrée ambiguë. 03/04/2026 est soit le 4 mars, soit le 3 avril. Fixez le format à la source ; un script qui devine se trompera pour quelqu’un.
Ne traitez pas le script comme un substitut aux tests. Générez des étiquettes d’exemple et regardez-les. Les scripts de champ réduisent le nombre de surprises, ils n’éliminent pas le besoin de vérifier.
FAQ
Où s’exécutent les blocs de script Python dans RSJ LPSNG ?
Les blocs de script Python sont attachés aux champs d’étiquette et accèdent aux valeurs des champs et les modifient avant l’impression, dans le cadre de la définition de l’étiquette dans la plateforme.
Dois-je construire un pipeline de nettoyage de données séparé ?
Non. Le script de champ gère le formatage, la validation et la transformation à l’intérieur de l’étiquette elle-même, vous n’avez donc pas besoin d’un script annexe qui réécrit vos fichiers de données avant qu’ils n’atteignent le moteur d’impression.
Puis-je toujours soumettre des tâches par programmation ?
Oui. L’interface de service web vous permet de soumettre des tâches d’impression et de générer des étiquettes individuelles en PDF ou PNG, et le modèle OAuth2 couvre la connexion de systèmes externes avec une seule URL d’enregistrement.
La même logique de champ s’applique-t-elle au PDF, au PNG et à l’impression directe ?
Le rendu PDF/PNG et l’impression directe sont des chemins de sortie documentés de l’interface de service web, et la logique de champ appartient à la définition de l’étiquette que ces chemins utilisent. Les étiquettes électroniques de rayon constituent une piste distincte avec leur propre interface JSON neutre vis-à-vis des fournisseurs (ESLSEND) — consultez la documentation de l’interface ESL plutôt que de supposer que le chemin d’impression s’applique tel quel.
Des non-développeurs peuvent-ils utiliser une étiquette contenant des scripts de champ ?
Oui. Une fois le script attaché au champ, imprimer l’étiquette ne nécessite ni d’écrire ni de lire du Python. Celui qui lance la tâche sélectionne les données et imprime ; le formatage et la validation se font dans le cadre de l’étiquette.
Cela remplace-t-il l’éditeur de mise en page ?
Non. L’éditeur de mise en page gère la conception ; les scripts de champ Python gèrent les données qui alimentent chaque champ. Ce sont des parties complémentaires de la même étiquette.
Conclusion
La solution de Mara n’était pas un meilleur script d’export. C’était de déplacer la règle là où la valeur est réellement utilisée : un champ de prix qui formate une virgule décimale en 3.50, refuse d’imprimer une cellule vide et retire un préfixe fournisseur en sortie. La propriétaire de la boutique a gardé sa feuille de calcul. Les étiquettes ont cessé d’être erronées.
Next Generation Label Printing System est construit précisément autour de cette séparation — conception dans l’éditeur de mise en page, contrôle des données dans les scripts de champ, et une interface de service web lorsque vous voulez piloter les tâches par programmation. Commencez par un champ, une règle et un PDF généré. Puis transmettez.
Articles liés
- What Is Label Merge and How Does It Work?
- How to Design Barcode Labels in a Browser Layout Editor
- Best Label Printing Software for Developers: Buying Guide
