Passer au contenu du pied de page
UTILISATION DE IRONPDF

Comment lire les données des fichiers PDF dans ASP.NET Core

Le problème de la génération manuelle de bons de livraison et d'étiquettes

Page d'accueil d'IronPDF Sur un sol d'entrepôt traitant 500 commandes par jour sur deux équipes, le cycle d'emballage-préparation-expédition n'a pas de tolérance pour la friction. Imprimer des bons de livraison un par un depuis l'écran OMS, copier les détails de commande dans un modèle d'étiquette à la main, ou attendre un outil logiciel d'étiquette qui ne s'intègre pas correctement avec le backend .NET, chacun de ces éléments ajoute des secondes par commande qui se transforment en réelles pertes de débit en fin de poste.

Le risque d'erreur se multiplie aux côtés du coût temporel. Lorsque les adresses d'expédition sont transcrites manuellement plutôt qu'extraites directement de l'enregistrement de commande, des incidents d'expédition se produisent. Un envoi retourné en raison d'une adresse erronée coûte plus en main-d'œuvre et en frais de transporteur que la marge sur la plupart des commandes individuelles. Les outils d'étiquette fournis par les transporteurs résolvent le problème d'adresse mais ne produisent pas le bon de livraison détaillé dont le sol de l'entrepôt a besoin pour vérifier le contenu des cartons avant de les sceller, ceux-ci nécessitent encore une impression séparée à partir d'un système différent.

L'impression par lots est l'endroit où la plupart des approches échouent complètement. Un responsable des opérations libérant une vague de 200 commandes a besoin de ces bons de livraison prêts dès le début du poste, non générés un par un via une interface web qui ouvre une nouvelle boîte de dialogue d'impression par commande. Le format doit fonctionner sur chaque imprimante sur le sol, qu'elle soit laser, à jet d'encre ou thermique, sans installer de pilotes propriétaires sur les stations de travail de l'entrepôt.

Les scénarios sont cohérents : une marque directe au consommateur emballant des centaines de commandes par jour, un distributeur B2B générant des bons multi-lignes pour les expéditions sur palettes, un service de box par abonnement imprimant des listes de vérification d'articles pour les travailleurs de la chaîne d'assemblage, un prestataire 3PL produisant des bons de marque pour le compte de plusieurs clients marchands avec différents logos et adresses de retour.

La solution : des fichiers PDF prêts à imprimer générés directement à partir des données de commande avec la bibliothèque IronPDF

IronPDF permet à l'OMS .NET de générer des bons de livraison et étiquettes PDF prêts à imprimer directement à partir des données de commande. Lorsqu'une commande entre dans l'étape "prête à emballer", l'application extrait les éléments de ligne, l'adresse d'expédition, les informations de transporteur, et les instructions spéciales, remplit un modèle HTML dimensionné pour le format de papier cible, et ChromePdfRenderer produit le PDF.

Le personnel de l'entrepôt imprime le résultat sur n'importe quelle imprimante standard ou thermique, un document par commande ou un PDF multi-pages pour toute une vague de prélèvement en un seul travail d'impression. Il n'y a pas de logiciel d'étiquette propriétaire à installer, aucun étape d'entrée de données manuelle, et pas de frais par étiquette API. Le rendu s'exécute à l'intérieur de l'application .NET existante en tant qu'un seul package NuGet sans processus externes.

Comment ça marche en pratique

1. Les commandes entrent dans la file d'attente de préparation

Une commande passe à "prête à emballer" soit automatiquement après la confirmation de paiement soit lorsqu'un responsable de l'entrepôt lance une vague de prélèvement depuis l'OMS. L'application interroge la base de données de commandes pour chaque commande du lot, les éléments de ligne avec SKU, nom du produit, et quantité; adresse d'expédition; transporteur et niveau de service; numéro de suivi préassigné si disponible; et toutes instructions de manipulation spéciales ou messages cadeaux.

Chaque commande dans la vague reçoit son propre PDF généré à partir du même modèle HTML, rempli avec ses données spécifiques. Pour une vague de 200 commandes, cela fait 200 rendus - chacun prenant quelques millisecondes - avant que les résultats ne soient fusionnés en un seul document pour le travail d'impression.

2. Les modèles gèrent les deux types de format

Le modèle de bon de livraison (lettre ou A4) inclut un tableau d'éléments de ligne avec des cases à cocher pour que l'emballeur vérifie chaque élément, le numéro de commande, l'adresse de livraison, et un ID de commande scannable. Le modèle d'étiquette cible 4×6 pouces (la taille standard d'une étiquette thermique) et inclut les adresses de livraison et de retour, la zone de code-barres du transporteur, et le poids de l'envoi.

Les deux modèles sont des fichiers HTML et CSS appartenant à l'équipe d'application. Mettre à jour le bon de livraison pour ajouter une nouvelle colonne, modifier le logo d'un marchand sur un bon 3PL, ou ajuster les marges de l'étiquette pour un nouveau modèle d'imprimante thermique est un changement de fichier modèle, pas de recompilation, pas de redéploiement de la logique métier.

Exemple de modèle de fichier HTML

Pdf Packing Slips Shipping Labels 2 related to Exemple de modèle de fichier HTML

3. Rendu par lot et fusionné en un seul travail d'impression

using IronPdf;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;

renderer.RenderingOptions.MarginTop = 10;

renderer.RenderingOptions.MarginBottom = 10;

string slipTemplate = await File.ReadAllTextAsync("Templates/packing-slip.html");

var slipPdfs = new List<PdfDocument>();

foreach (var order in pickWave)
{
    string lineItemRows = string.Concat(order.Items.Select(i =>
        $"<tr><td><input type='checkbox'></td><td>{i.Sku}</td><td>{i.ProductName}</td><td>{i.Quantity}</td></tr>"));

    string html = slipTemplate
        .Replace("{{OrderNumber}}", order.OrderNumber)
        .Replace("{{ShipTo}}", order.ShippingAddress.Formatted)
        .Replace("{{LineItems}}", lineItemRows)
        .Replace("{{SpecialInstructions}}", order.SpecialInstructions ?? "None");

    slipPdfs.Add(renderer.RenderHtmlAsPdf(html));
}

PdfDocument waveBatch = PdfDocument.Merge(slipPdfs);

waveBatch.SaveAs($"wave-{pickWave.WaveId}-slips.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;

renderer.RenderingOptions.MarginTop = 10;

renderer.RenderingOptions.MarginBottom = 10;

string slipTemplate = await File.ReadAllTextAsync("Templates/packing-slip.html");

var slipPdfs = new List<PdfDocument>();

foreach (var order in pickWave)
{
    string lineItemRows = string.Concat(order.Items.Select(i =>
        $"<tr><td><input type='checkbox'></td><td>{i.Sku}</td><td>{i.ProductName}</td><td>{i.Quantity}</td></tr>"));

    string html = slipTemplate
        .Replace("{{OrderNumber}}", order.OrderNumber)
        .Replace("{{ShipTo}}", order.ShippingAddress.Formatted)
        .Replace("{{LineItems}}", lineItemRows)
        .Replace("{{SpecialInstructions}}", order.SpecialInstructions ?? "None");

    slipPdfs.Add(renderer.RenderHtmlAsPdf(html));
}

PdfDocument waveBatch = PdfDocument.Merge(slipPdfs);

waveBatch.SaveAs($"wave-{pickWave.WaveId}-slips.pdf");
Imports IronPdf
Imports System.IO

Dim renderer As New ChromePdfRenderer()

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter

renderer.RenderingOptions.MarginTop = 10

renderer.RenderingOptions.MarginBottom = 10

Dim slipTemplate As String = Await File.ReadAllTextAsync("Templates/packing-slip.html")

Dim slipPdfs As New List(Of PdfDocument)()

For Each order In pickWave
    Dim lineItemRows As String = String.Concat(order.Items.Select(Function(i) $"<tr><td><input type='checkbox'></td><td>{i.Sku}</td><td>{i.ProductName}</td><td>{i.Quantity}</td></tr>"))

    Dim html As String = slipTemplate _
        .Replace("{{OrderNumber}}", order.OrderNumber) _
        .Replace("{{ShipTo}}", order.ShippingAddress.Formatted) _
        .Replace("{{LineItems}}", lineItemRows) _
        .Replace("{{SpecialInstructions}}", If(order.SpecialInstructions, "None"))

    slipPdfs.Add(renderer.RenderHtmlAsPdf(html))
Next

Dim waveBatch As PdfDocument = PdfDocument.Merge(slipPdfs)

waveBatch.SaveAs($"wave-{pickWave.WaveId}-slips.pdf")
$vbLabelText   $csharpLabel

Exemple de document de sortie PDF

Exemple de sortie IronPDF PdfDocument.Merge() combine chaque bon individuel en un seul PDF multipage. L'équipe de l'entrepôt envoie un seul travail d'impression pour toute la vague, un clic sur une station de travail, un seul bac de sortie à récupérer.

4. Les dimensions de l'étiquette sont définies via les options de rendu

using IronPdf;

var renderer = new ChromePdfRenderer();

// 4x6 inch thermal label — 288 x 432 points
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Custom;
renderer.RenderingOptions.CustomPaperWidth = 4;
renderer.RenderingOptions.CustomPaperHeight = 6;
renderer.RenderingOptions.MarginTop = 0;
renderer.RenderingOptions.MarginBottom = 0;
renderer.RenderingOptions.MarginLeft = 0;
renderer.RenderingOptions.MarginRight = 0;

string labelHtml = $@"
    <div style='font-family:monospace; padding:4px;'>
        <p><strong>SHIP TO:</strong><br/>{order.ShippingAddress.Formatted}</p>
        <p><strong>FROM:</strong><br/>{order.ReturnAddress.Formatted}</p>
        <p>Order: {order.OrderNumber} | Weight: {order.WeightLbs:F1} lbs</p>
        <p>Carrier: {order.CarrierName} — {order.ServiceLevel}</p>
    </div>";

PdfDocument label = renderer.RenderHtmlAsPdf(labelHtml);

label.SaveAs($"label-{order.OrderNumber}.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();

// 4x6 inch thermal label — 288 x 432 points
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Custom;
renderer.RenderingOptions.CustomPaperWidth = 4;
renderer.RenderingOptions.CustomPaperHeight = 6;
renderer.RenderingOptions.MarginTop = 0;
renderer.RenderingOptions.MarginBottom = 0;
renderer.RenderingOptions.MarginLeft = 0;
renderer.RenderingOptions.MarginRight = 0;

string labelHtml = $@"
    <div style='font-family:monospace; padding:4px;'>
        <p><strong>SHIP TO:</strong><br/>{order.ShippingAddress.Formatted}</p>
        <p><strong>FROM:</strong><br/>{order.ReturnAddress.Formatted}</p>
        <p>Order: {order.OrderNumber} | Weight: {order.WeightLbs:F1} lbs</p>
        <p>Carrier: {order.CarrierName} — {order.ServiceLevel}</p>
    </div>";

PdfDocument label = renderer.RenderHtmlAsPdf(labelHtml);

label.SaveAs($"label-{order.OrderNumber}.pdf");
Imports IronPdf

Dim renderer As New ChromePdfRenderer()

' 4x6 inch thermal label — 288 x 432 points
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Custom
renderer.RenderingOptions.CustomPaperWidth = 4
renderer.RenderingOptions.CustomPaperHeight = 6
renderer.RenderingOptions.MarginTop = 0
renderer.RenderingOptions.MarginBottom = 0
renderer.RenderingOptions.MarginLeft = 0
renderer.RenderingOptions.MarginRight = 0

Dim labelHtml As String = $"
    <div style='font-family:monospace; padding:4px;'>
        <p><strong>SHIP TO:</strong><br/>{order.ShippingAddress.Formatted}</p>
        <p><strong>FROM:</strong><br/>{order.ReturnAddress.Formatted}</p>
        <p>Order: {order.OrderNumber} | Weight: {order.WeightLbs:F1} lbs</p>
        <p>Carrier: {order.CarrierName} — {order.ServiceLevel}</p>
    </div>"

Dim label As PdfDocument = renderer.RenderHtmlAsPdf(labelHtml)

label.SaveAs($"label-{order.OrderNumber}.pdf")
$vbLabelText   $csharpLabel

Exemple de fichier PDF de sortie et d'étiquette d'expédition

Exemple de bordereau d'emballage et étiquette d'expédition générés Les marges nulles permettent au contrôle CSS de gérer tous les espacements jusqu'au bord de l'étiquette, essentiel pour les formats d'étiquettes thermiques où la zone de code-barres de transport doit atteindre à quelques millimètres de la limite du papier.

Avis Réels

Efficacité par lots. Une vague de prélèvement complète fusionnée en un seul PDF signifie un seul travail d'impression au lieu de centaines. Le temps de démarrage de l'équipe diminue lorsque le personnel de l'entrepôt n'attend pas que les boîtes de dialogue d'impression individuelles se chargent pour chaque commande.

Compatibilité d'impression. Le PDF s'affiche de manière cohérente sur les imprimantes laser, à jet d'encre et thermiques sans installation de pilotes propriétaires ou de logiciels d'étiquettes sur les postes de travail de l'entrepôt. Le format produit par le système de gestion des commandes (OMS) est le format accepté par chaque imprimante sur le terrain.

Précision. Les lignes d'articles et les adresses sont extraites directement de l'enregistrement de la commande. Aucune étape de transcription manuelle n'est nécessaire et il n'y a aucune possibilité pour qu'une adresse ou un SKU soit mal saisi avant qu'il n'atteigne l'emballeur.

Formats flexibles. Le même pipeline de génération produit des bons de livraison au format lettre et des étiquettes 4×6 en changeant le modèle HTML et les options de taille de page. Pas d'outil séparé, pas d'intégration séparée.

Image de marque multi-locataires. Les fournisseurs 3PL remplissent une variable merchantId dans le chemin du modèle et chargent un fichier HTML spécifique au marchand, les bons de chaque client portent leur propre logo, adresse de retour, et couleurs de marque via le même pipeline sans logique supplémentaire.

Pas de coûts par étiquette. Le rendu s'effectue en interne. Il n'y a pas d'API externe pour les étiquettes appelée à chaque impression, pas de mesure d'utilisation, et pas de modèle de tarification qui rendrait un changement à fort volume plus cher qu'un à faible volume.

Conclusion

Le cycle de prélèvement-emballage-expédition est un problème de débit. Chaque étape manuelle entre l'entrée d'une commande dans la file d'attente d'emballage et la sortie d'une boîte étiquetée est une contrainte, et la génération de bons de livraison et d'étiquettes est une étape simple à automatiser au sein même de l'OMS.

Un modèle HTML par format, un appel de rendu par commande, un PDF fusionné par vague, un travail d'impression par équipe. IronPDF gère l'ensemble du cycle de vie de la génération de PDF en C# sur ironpdf.com, de la rendu des modèles HTML à la fusion, l'enregistrement et la diffusion de documents. Si vous êtes prêt à tester le pipeline avec vos propres données de commande et configuration d'impression, démarrez votre essai gratuit de 30 jours et faites fonctionner un générateur de bons de livraison par lots avant la fin de la semaine.

Curtis Chau
Rédacteur technique

Curtis Chau détient un baccalauréat en informatique (Université de Carleton) et se spécialise dans le développement front-end avec expertise en Node.js, TypeScript, JavaScript et React. Passionné par la création d'interfaces utilisateur intuitives et esthétiquement plaisantes, Curtis aime travailler avec des frameworks modernes ...

Lire la suite

Équipe de soutien Iron

Nous sommes en ligne 24 heures sur 24, 5 jours sur 7.
Chat
Email
Appelez-moi