===== Variable Logos in ZPL =====
==== Anforderung ====
Auch beim Einsatz von Etikettendruckern kommt der Wunsch auf, bei statischem Etikettendesign ein Logo abhängig von irgendeiner Mandanteninformation auszutauschen. Der Brute-Force-Ansatz, einfach für jeden Mandanten ein eigenes Etikett zu gestalten und in (p2f) abzulegen, kommt schnell an seine Grenzen, wenn die Zahl der Mandanten oder die Zahl der Varianten von Etiketten steigt.
Der Änderungsaufwand einer solchen Lösung ist beträchtlich. Ändert sich ein Etikett, muss es in so vielen Varianten abgeändert werden, wie es Mandanten gibt. Ändert sich bei einem Mandanten etwas, muss jede Etikettenvariante angefasst werden.
Es wäre wünschenswert, einen Lösungsansatz zu finden, der diese Multiplikation der Aufwände verhindert, und bestenfalls einen linearen Aufwand verursacht.
\\
\\
==== Realisierung ====
Die allermeisten Etikettendrucker bieten die Möglichkeit, Graphiken in den Drucker zu laden und diese Graphiken dann über eine Kennung zu referenzieren. Das ist insbesondere auch bei ZPL-Druckern so. Anhand der Etikettendruckersprache ZPL soll aufgezeigt werden, wie die oben beschriebene Anforderung realisiert werden kann.
Zunächst muss einmal festgestellt werden, dass es in (p2f) für Etikettenprozesse keine Unterstützung für irgendetwas gibt, was den für PCL-Drucker verfügbaren Ressourcenfeldern entspricht. Nur die 'nichtdruckenden' Felder, wie Suchfelder, HTTP- und ODBC-Felder, sind auch mit Etikettendruckern nutzbar.
Deshalb scheidet die für PCL-Drucker ganz offensichtliche Realisation über ein Ressourcenfeld hier aus.
\\
\\
Grundidee für eine alternative Herangehensweise ist die Überlegung, die Auswahl des einzudruckenden Logos in Form einer Liste von bedingten Unterformularen zu realisieren.
Dazu müssen zunächst einmal alle in Frage kommenden Logos als Ressource importiert und in einem zweiten Schritt als Formular angelegt werden.
Das nachfolgende ZPL-Beispiel soll die nicht ganz intuitive Lösung illustrieren.
\\
\\
==== Logos ====
Ausgangspunkt sind im Beispiel drei unterschiedliche Logos, die auch für das blosse Auge leicht zu unterscheiden sind. Es ist wichtig, dass alle Graphiken einen eineindeutigen Namen haben, der später leicht auf das Unterscheidungsmerkmal in den Nutzdaten abgebildet werden kann. Im Beispiel hier wird als Referenz einfach eine Ziffer an das Wort //LOGO// angehängt, weil wir später aus den Nutzdaten eine Ziffer zur Auswahl des Logos extrahieren.
Die Referenz muss keine Zahl sein. Es wäre auch denkbar, die Logos direkt mit dem Namen eines Mandanten zu versehen, und die Referenz darüber herzustellen - das erhöht sogar die Wartbarkeit, weil direkt klar ist, zu wem das Logo gehört.
\\
\\
~DGR:LOGO1.GRF,00080,010,
FFFFF000000000000000
00F00000000000000000
00F00000000000000000
00F00000000000000000
00F00000000000000000
00F00000000000000000
00F00000000000000000
FFFFF000000000000000
~DGR:LOGO2.GRF,00080,010,
FFFFF00FFFFF00000000
00F000000F0000000000
00F000000F0000000000
00F000000F0000000000
00F000000F0000000000
00F000000F0000000000
00F000000F0000000000
FFFFF00FFFFF00000000
~DGR:LOGO3.GRF,00080,010,
FFFFF00FFFFF00FFFFF0
00F000000F000000F000
00F000000F000000F000
00F000000F000000F000
00F000000F000000F000
00F000000F000000F000
00F000000F000000F000
FFFFF00FFFFF00FFFFF0
\\
Die Logos werden einfach importiert, ohne dass irgendwelche Platzhalter definiert werden. Anschliessend wird für jedes Logo ein Formular mit dem gleichen Namen angelegt:
{{print2forms:tips:0068-1.png}}
{{print2forms:tips:0068-2.png}}
\\
==== Etikett ====
Das Etikett, welches die variablen Logos enthalten soll, muss als nächstes definiert werden. In der nachfolgenden Abbildung ist zu sehen, dass dort eine Graphik mit dem Namen //LOGONUMMER.GRF// aufgerufen wird. Dabei ist die Zeichenkette //NUMMER// als Platzhalter gedacht, der später gegen die tatsächliche Nummer des Logos ausgetauscht wird.
^XA
^LH10,10
^FO20,10^AD^FDVariables Logo für Kunde Nummer^FS
^FO20,40^XGR:LOGONUMMER.GRF,1,1^FS
^XZ
Beim Import des Etiketts werden folgerichtig dieser Platzhalter und der Text //Nummer// in der Textzeile darüber mit einem Wert aus den zu druckenden Nutzdaten für das Etikett verbunden. (Die Aufzeichnung der Nutzdaten zeigt drei Seiten!)
{{print2forms:tips:0068-3.png}}
\\
\\
\\
\\
Nach dem erfolgreichen Import ist beim Betrachten der Ressource zu sehen, dass es zwei Platzhalter gibt, die der gleichen Position in den Nutzdaten zugeordnet sind.
Folglich zeigt der Text auf dem Etikett auch immer direkt an, welches Logo gerade angezeigt wird.
Die beiden Platzhalter unterscheiden sich für (p2f), weil Gross-/Kleinschreibung berücksichtigt wird.
Nachdem das alles soweit vorbereitet ist, müssen jetzt die zwei entscheidenden Formulare erzeugt werden.
{{print2forms:tips:0068-4.png}}
==== Formulare ====
Als erstes muss das Formular //Variables Kundenlogo laden// angelegt werden (Abbildung rechts).
Das Entscheidende an diesem Formular ist die Liste von untergeordneten Formularen. Für jedes Logo wird eine Bedingung formuliert, die sich auf exakt die gleich Position in den Nutzdaten bezieht, wie beim Import des Etiketts angegeben.
Leicht sind die drei Bedingungen für die drei Logos auszumachen.
\\
\\
Jetzt kann das Formular für das eigentlich Etikett festgelegt werden (Abbildung unten),
Hier ist es wichtig zu wissen, dass (p2f) zunächst alle untergeordneten Formulare erzeugt, bevor das aktuelle Formular selbst gedruckt wird.
Deshalb kann ganz einfach als untergeordnetes Formular unser eben geschriebenes Formular //Variables Kundenlogo laden// und als Formularressource das eigentliche Etikett angegeben werden.
Durch die Druckreihenfolge wird also garantiert, dass zuerst die Graphik für das Logo zum Drucker geschickt wird, bevor das eigentliche Etikett genau diese Graphik referenziert. Die Graphik ist immer vorher da!
\\
\\
{{print2forms:tips:0068-6.png}}
\\
\\
Als letztes muss noch ein einfacher Etikettenprozess angelegt werden, der das Formular //Etikett// nutzt. Auf eine Darstellung kann hier verzichtet werden.
{{print2forms:tips:0068-5.png}}
==== Ausgabe ====
Jetzt ist alles soweit eingerichtet und ein erster Test mit den Nutzdaten kann erfolgen.
Zum besseren Verständnis sind die Nutzdaten (PCL-Datenstrom) nachfolgend abgebildet:
{{print2forms:tips:0068-7.png}}
Es ist zu erkennen, dass zuerst ein Etikett für den Kunden 2, dann zwei für den Kunden 1, dann eines für den Kunden 3 und am Schluss wieder eines für den Kunden 1 gedruckt werden soll.
Im Listing auf der rechten Seite ist zu sehen, welchen ZPL-Datenstrom (p2f) aus diesen Nutzdaten erzeugt.
Als erstes wird die Graphik für das Logo 2 geladen und anschliessend im Etikett aufgerufen. Es ist deutlich zu sehen, wie die beiden Platzhalter aus der Etikettenressource gegen die Ziffer 2 ausgetauscht worden sind.
Anschliessend wird die Graphik für das Logo 1 geladen und ein Etikett mit diesem Logo gedruckt. Beim zweiten Etikett mit dem Logo 1 ist zu sehen, dass die Graphik nicht wieder geladen wurde. (p2f) weiss, dass die Graphik bereits im Drucker ist, und unterdrückt das wiederholte Laden der Graphiken.
Schliesslich wird die Graphik für das Logo 3 geladen und ein Etikett mit diesem Logo gedruckt. Beim anschliessenden erneuten Druck eines Etiketts mit dem Logo 1 wird wieder keine Graphik nachgeladen.
\\
\\
\\
Die hier vorgestellte Lösung sorgt also dafür, dass nur die Graphiken in den Drucker geladen werden, die auch wirklich benötigt werden. Die Reihenfolge des Ladens ist die Reihenfolge, in der die Graphiken gebraucht werden.
~DGR:LOGO2.GRF,00080,010,
FFFFF00FFFFF00000000
00F000000F0000000000
00F000000F0000000000
00F000000F0000000000
00F000000F0000000000
00F000000F0000000000
00F000000F0000000000
FFFFF00FFFFF00000000
^XA
^LH10,10
^FO20,10^AD^FDVariables Logo für Kunde 2^FS
^FO20,40^XGR:LOGO2.GRF,1,1^FS
^XZ
~DGR:LOGO1.GRF,00080,010,
FFFFF000000000000000
00F00000000000000000
00F00000000000000000
00F00000000000000000
00F00000000000000000
00F00000000000000000
00F00000000000000000
FFFFF000000000000000
^XA
^LH10,10
^FO20,10^AD^FDVariables Logo für Kunde 1^FS
^FO20,40^XGR:LOGO1.GRF,1,1^FS
^XZ
^XA
^LH10,10
^FO20,10^AD^FDVariables Logo für Kunde 1^FS
^FO20,40^XGR:LOGO1.GRF,1,1^FS
^XZ
~DGR:LOGO3.GRF,00080,010,
FFFFF00FFFFF00FFFFF0
00F000000F000000F000
00F000000F000000F000
00F000000F000000F000
00F000000F000000F000
00F000000F000000F000
00F000000F000000F000
FFFFF00FFFFF00FFFFF0
^XA
^LH10,10
^FO20,10^AD^FDVariables Logo für Kunde 3^FS
^FO20,40^XGR:LOGO3.GRF,1,1^FS
^XZ
^XA
^LH10,10
^FO20,10^AD^FDVariables Logo für Kunde 1^FS
^FO20,40^XGR:LOGO1.GRF,1,1^FS
^XZ
==== Hinweise ====
* Unter dem Aspekt der Wartbarkeit ist diese Lösung deutlich besser als der Brute-Force-Ansatz. Ändert sich etwas bei den Mandanten, muss lediglich das Formular //Variables Kundenlogo laden// modifiziert werden. Anschliessend steht der neue Mandant automatisch auf allen Etikettenvarianten zur Verfügung.\\ Muss ein neues Etikett angelegt werden, muss nur dafür gesorgt werden, dass als untergeordnetes Formular das Formular //Variables Kundenlogo laden// aufgerufen wird, und es steht automatisch mit allen Logos zur Verfügung.
* Das Laden der Graphiken für die Logos erfolgt mit jedem Druckauftrag. (p2f) //vergisst// am Ende eines Druckauftrags alle geladenen Graphiken. Das ist gewollt, weil (p2f) bei einem über das Netzwerk angeschlossenen Drucker nicht weiss, ob der nicht zwischenzeitlich ausgeschaltet war, oder ob von einer anderen Applikation, die den Drucker ebenfalls verwendet, die Graphiken gelöscht wurden.
* Nicht Bestandteil der gezeigten Lösung ist das dedizierte Löschen der Graphiken aus dem Speicher des Druckers. Das ist auch nicht ohne weiteres möglich, weil das verlangt, das am Ende des Druckauftrags Löschkommandos ausgegeben werden. Da aber (p2f) keinerlei Kenntnis über die Steuersequenzen der angeschlossenen Etikettendrucker hat, ist das nicht machbar.\\ Wenn also die Menge der geladenen Graphiken nicht mehr in den Druckerspeicher passt, bleibt als Lösung nur ein 'Schlussetikett', dass als Nebenwirkung den Druckerspeicher löscht. Das verhindert allerdings trotzdem nicht, dass sich im Laufe eines einzigen Druckauftrags so viele Graphiken ansammeln können, dass es zum Speicherüberlauf kommt.
* Wenn Unmengen von Graphiken gedruckt werden müssen - zum Beispiel Produktbilder, o.ä. - muss jedes Etikett in einem eigenen Prozess gedruckt werden, dessen Etikettensequenzen dann mit einem Löschen des Druckerspeichers enden. Einzelne Etiketten lassen sich gegebenenfalls mit einem vorgeschalteten Dokumentprozess erzwingen.