zplCore.comzplCore.com

12Druckaufträge & Massendruck

Ein Druckauftrag ist ein ZPL-Strom: optional ein Vorlauf-Etikett, ein Etikett pro Datensatz und optional ein Nachlauf-Etikett. Mit CutAfterLastLabel() läuft der ganze Auftrag im Abreißmodus und nur nach dem letzten Etikett wird geschnitten.

Vorlauf, Nachlauf und Schnitt (LabelBinding)

// Vor- und Nachlauf-Etikett werden an PrintJobInfo gebunden:
// JobName, Created, RecordCount, LabelCount, FirstKey, LastKey
var leading = new Label(LabelUnit.Mm, 100, 60)
    .Add(new TextItem { X = 5, Y = 5, Text = "DRUCKAUFTRAG", FontSize = 22 })
    .Add(new TextItem { X = 5, Y = 20, DataField = "JobName", FontSize = 14 })
    .Add(new TextItem { X = 5, Y = 32, Expression = "Format([Created], \"dd.MM.yyyy HH:mm\")" })
    .Add(new TextItem { X = 5, Y = 42, Expression = "[RecordCount] + \" Sendungen\"" });
var trailing = new Label(LabelUnit.Mm, 100, 60)
    .Add(new TextItem { X = 5, Y = 5, Text = "ENDE DES AUFTRAGS", FontSize = 18 })
    .Add(new TextItem { X = 5, Y = 20, Expression = "[LabelCount] + \" Labels gedruckt\"" })
    .Add(new TextItem { X = 5, Y = 30, Expression = "\"von \" + [FirstKey] + \" bis \" + [LastKey]", FontSize = 9 });
var label = new Label(LabelUnit.Mm, 100, 60)
    .Add(new TextItem { X = 4, Y = 4, DataField = "Name", FontSize = 14 })
    .Add(new TextItem { X = 4, Y = 12, DataField = "City" })
    .Add(new BarcodeItem { X = 4, Y = 22, DataField = "TrackingNo", BarHeight = 18 });

string zpl = label.For<Parcel>()
    .Job("Versand Wien", p => p.TrackingNo)   // Name + Schlüssel für FirstKey/LastKey
    .Copies(p => p.Parcels)                   // LabelCount zählt die Kopien mit
    .WithLeadingLabel(leading)
    .WithTrailingLabel(trailing)
    .CutAfterLastLabel()                      // 1. Format ^MMT (Abreißen), letztes ^MMC (Schneiden)
    .ToZpl(parcels);                          // Liste → RecordCount schon im Vorlauf bekannt
Methode / FeldBedeutung
.Job(name, keySelector)Auftragsname und Schlüssel pro Datensatz (z. B. Sendungsnummer) für FirstKey/LastKey
.WithLeadingLabel(label)Vorlauf-Etikett, gebunden an PrintJobInfo
.WithTrailingLabel(label)Nachlauf-Etikett mit Summen, gebunden an PrintJobInfo
.CutAfterLastLabel()erstes Format bekommt ^MMT (Abreißen, gilt für alle folgenden), nur das letzte Format ^MMC (Schneiden)
PrintJobInfo.JobName, CreatedName und Erstellzeit des Auftrags
PrintJobInfo.RecordCountAnzahl Datensätze – im Vorlauf bekannt, wenn eine Liste/Collection übergeben wird; im Nachlauf immer gesetzt
PrintJobInfo.LabelCountgedruckte Etiketten inkl. Kopien (Copies)
PrintJobInfo.FirstKey, LastKeySchlüssel des ersten und letzten Datensatzes

Alle Felder sind als DataField oder in Ausdrücken ([RecordCount] + " Sendungen") nutzbar. Das Ergebnis für drei Sendungen (eine davon mit zwei Kopien): 5 Formate, 6 Etiketten.

Vorlauf

Vorlauf: JobName, Created, RecordCount

Datensatz 2 (^PQ2)

Datensatz 2, Kopie 1

Nachlauf (^MMC)

Nachlauf: LabelCount, FirstKey, LastKey
Erzeugtes ZPL anzeigen

PrintJobTemplate: ein Auftrag aus JSON-Vorlagen

PrintJobTemplate fasst Vorlauf-, Datensatz- und Nachlauf-Etikett samt Optionen zusammen. Laden aus drei Label-Vorlagen (FromFiles(leading, label, trailing), Vor-/Nachlauf optional) oder aus einer JSON-Datei (ToJson/FromJson); SaveFiles zerlegt wieder in drei Dateien. For<T>() liefert die fertig konfigurierte LabelBinding<T>.

// drei JSON-Vorlagen (z. B. aus einem Designer) → EIN Druckauftrag
var job = PrintJobTemplate.FromFiles("templates/leading.json", "templates/shipping.json", "templates/trailing.json");
job.JobName = "Tagesversand";
job.CutAfterLastLabel = true;          // nur nach dem Nachlauf-Etikett schneiden
job.StoredFormatName = "R:SHIP.ZPL";   // Vorlage einmal per ^DF, danach nur ^XF + ^FN-Werte
job.KeyField = "TrackingNo";           // FirstKey/LastKey im Nachlauf
job.CopiesField = "Parcels";           // ^PQ pro Datensatz

string zpl = job.For<Shipment>().ToZpl(shipments.ToList());

// derselbe Auftrag als EINE JSON-Datei – oder wieder in drei Dateien zerlegt
File.WriteAllText("printjob.json", job.ToJson());
PrintJobTemplate same = PrintJobTemplate.FromJson(File.ReadAllText("printjob.json"));
same.SaveFiles("leading.json", "shipping.json", "trailing.json");
OptionWirkung
JobNameName für PrintJobInfo.JobName (Standard „Druckauftrag“)
CutAfterLastLabel^MMT für alle, ^MMC nur für das letzte Etikett
StoredFormatNameDatensatz-Etikett einmal per ^DF speichern, dann nur ^XF + ^FN
KeyFieldProperty-Pfad für FirstKey/LastKey
CopiesFieldProperty-Pfad für die Kopienzahl pro Datensatz

leading.json (Auszug)

printjob.json – alles in einer Datei (Auszug)

Vorlagen: leading.json · shipping.json · trailing.json · printjob.json

Massendaten-Demo: EF Core + LiteDB → eine .zpl-Datei

samples/MassDataDemo lädt die drei Vorlagen, fragt 50 Sendungen per LINQ aus SQLite (EF Core) bzw. LiteDB ab und schreibt jeweils einen Auftrag: Vorlauf, ^DF-Vorlage, 50 Versandetiketten, Nachlauf, Schnitt.

// samples/MassDataDemo: 50 Versandetiketten + Vorlauf + Nachlauf + Schnitt in EINER .zpl-Datei
var job = PrintJobTemplate.FromFiles("templates/leading.json", "templates/shipping.json", "templates/trailing.json");
job.CutAfterLastLabel = true;        // Abreißen für alle, Schnitt nach dem Nachlauf-Etikett
job.KeyField = "TrackingNo";         // erste/letzte Sendungsnummer im Nachlauf

// ---------- EF Core + SQLite ----------
using var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var options = new DbContextOptionsBuilder<ShippingDb>().UseSqlite(connection).Options;
using var db = new ShippingDb(options);
db.Database.EnsureCreated();
db.Shipments.AddRange(seedData);
db.SaveChanges();

var query = db.Shipments.AsNoTracking()          // von SQLite ausgeführt
    .Where(s => !s.Printed && s.Service == "EXPRESS")
    .OrderByDescending(s => s.Id)
    .Take(50);

job.JobName = "EF Core · Express";
job.StoredFormatName = "R:SHIP.ZPL";             // Vorlage einmal, dann nur Feldwerte
string efZpl = job.For<Shipment>()
    .Map("Total", s => s.WeightKg.ToString("0.0") + " kg")
    .ToZpl(query.ToList());
File.WriteAllText("massdata-efcore.zpl", efZpl);

// ---------- LiteDB ----------
using var lite = new LiteDatabase(new MemoryStream());
var col = lite.GetCollection<Shipment>("shipments");
col.InsertBulk(seedData);
col.EnsureIndex(s => s.Country);
var docs = col.Query().Where(s => s.Country == "AT").OrderBy(s => s.TrackingNo).Limit(50).ToEnumerable();

job.JobName = "LiteDB · Österreich";
job.StoredFormatName = null;                     // volles Format pro Etikett
string liteZpl = job.For<Shipment>()
    .Map("Total", s => s.WeightKg.ToString("0.0") + " kg")
    .ToZpl(docs.ToList());
File.WriteAllText("massdata-litedb.zpl", liteZpl);

// Vorschau des ganzen Auftrags als PDF
var renderer = new ZplRenderer(new ZplRenderSettings { OutputFormat = ZplOutputFormat.Pdf }.WithLabelSizeMm(100, 150));
File.WriteAllBytes("massdata-efcore.pdf", renderer.ProcessCommands(efZpl)[0]);
dotnet run --project samples/MassDataDemo -- samples/output samples/templates

Vorlauf (^MMT)

Vorlauf-Etikett der Demo

Versandetikett 1 von 50

Versandetikett der Demo

Nachlauf (^MMC)

Nachlauf-Etikett der Demo
massdata-efcore.zpl (Auszug)
Erzeugte Dateien: massdata-efcore.zpl (9 KB, mit ^DF/^XF) · massdata-efcore.pdf · massdata-litedb.zpl (17 KB, volle Formate) · massdata-litedb.pdf – je 52 Etiketten.

Mehr dazu auf zplCloud.com: Vorlage: Versandetikett · Vorlage: Versandlabel 100 × 150 mm mit GS1-128-SSCC