Niklas
Niklas

Reputation: 13135

Print multiple different labels with Zebra printer

I want to loop through a list of Member objects and print their names and addresses, like this:

foreach (Member member in members) {
    sb.AppendLine();
    sb.AppendLine("N");
    sb.AppendLine(string.Format("A50,50,0,2,1,1,N,\"{0}\"", member.name));
    sb.AppendLine(string.Format("A50,50,0,2,1,1,N,\"{0}\"", member.address));
    sb.AppendLine("P1");

    RawPrinterHelper.SendStringToPrinter(printerName, sb.ToString());
}  

But surely there must be an easier way to pass multiple labels to the printer? Sending it once and letting the printer loop through a set of variables?

Upvotes: 2

Views: 11892

Answers (3)

Niklas
Niklas

Reputation: 13135

Finally solved this. Here's a bit more information to extend the answers from OTisley and Brad Chrisite.

I used this page to download fonts to the printer: Converting and Downloading Fonts.

And this code to loop through the members:

StringBuilder sb = new StringBuilder();

foreach (Member member in members) {
    sb.AppendLine();
    sb.AppendLine("N");
    sb.AppendLine(string.Format("A10,10,0,b,1,1,N,\"{0}\"", member.name));
    sb.AppendLine(string.Format("A10,45,0,b,1,1,N,\"{0}\"", member.address));
    sb.AppendLine("P1,1");
}

string sendThisToPrinter = sb.ToString();

Explanation of the format sent to printer:
A10 = offset left in dots
10 = offset top in dots
0 = Rotation of the text
b = The font name you set when you downloaded the fonts to the printer.
1 = Expand the text horizontally x number of times.
1 = Expand the text vertically x number of times.
N = N ormal or R eversed text.
\"{0}\" = The text to print.

Upvotes: 3

Ovi Tisler
Ovi Tisler

Reputation: 6463

What kind of Zebra printer is it? Can you use ZPL? You can't pass a set or map or array to a Zebra printer, but you can define variables in the format and later recall the label passing in only the variables. This would reduce the payload on actually printing the label.

In ZPL you would use the ^FN<Variable Number> command to create a bunch of variable inside the label you are saving. That label would be large depending on how many variables you have in your set and how much formatting information the label has.

When you wanted to print that label, all you would have to do is use the ^XF command to recall the label, and pass in only the variable data, so you don't need to pass in all the label information.

Stored Label

^XA
^DFR:SAMPLE.GRF^FS
^FO20,30^GB750,1100,4^FS
^FO20,30^GB750,200,4^FS
^FO20,30^GB750,400,4^FS
^FO20,30^GB750,700,4^FS
^FO20,226^GB325,204,4^FS
^FO30,40^ADN,36,20^FDShip to:^FS
^FO30,260^ADN,18,10^FDPart number #^FS
^FO360,260^ADN,18,10^FDDescription:^FS
^FO30,750^ADN,36,20^FDFrom:^FS
^FO150,125^ADN,36,20^FN1^FS (ship to)
^FO60,330^ADN,36,20^FN2^FS(part num)
^FO400,330^ADN,36,20^FN3^FS(description)
^FO70,480^BY4^B3N,,200^FN4^FS(barcode)
^FO150,800^ADN,36,20^FN5^FS (from)
^XZ

How you would recall the label

^XA
^XFR:SAMPLE.GRF
^FN1^FDAcme Printing^FS
^FN2^FD14042^FS
^FN3^FDScrew^FS
^FN4^FD12345678^FS
^FN5^FDMacks Fabricating^FS
^XZ

Upvotes: 1

Brad Christie
Brad Christie

Reputation: 101604

Personally, I've always created the canvas myself. I basically created a "spooler" class that is a collection labels to print. A label is essentially a class which houses the basic format of the label (some are shipping addresses, some contain part numbers, etc.) in addition to properties I can populate to dump within the label's template. I then build a print document, populate the page settings, and bind to the PrintPage event and pop labels from the queue.

I bet if you got down to the driver level of the printer you'd have better luck sending a full payload versus serializing it, but I think the one-by-one will just have to work.

I'm kind of curious though, what is a scenario where sending them one-off is undesirable?


Further insight in to how I do it:

First, Create an interface specifying what a "label [class]" must expose:

interface IPrintLabel
{
  // Get or set the printer this label should print from
  // I typically bounce between a Zebra (UPS/FedEx) printer and an in-house
  // DYNO printer, depending the label I print for shipping.
  PrinterSettings PrinterSettings { get; set; }

  // Get or set the paper size, margins, etc. Allows me to setup the canvas
  PageSettings PageSettings { get; set; }

  // Method responsible for laying out the label (send it the event args
  // from the PrintPage method of PrintDocument)
  void GenerateLabel(ref PrintPageEventArgs printArgs);

}

I then have misc classes that implement that interface., with specific properties, formatting, layouts, etc. Then I have a "spooler":

class PrintSpooler : Queue<IPrintLabel>
{
  public void PrintLabels()
  {
    // Establish a PrintDocument and bind to the PrintPage method something like:
    printDoc.PrintPage += (s, e) =>
    {
      IPrintLabel nextLabel = base.Dequeue();
      nextLabel.GenerateLabel(ref e);
      e.hasMorePages = (base.Count > 0);
    };
  }
}

All generalized, but just to give you the effect. This is ~3yr old code, so there may be better/more optimized methods, but it gets the job done here (and got me to the deadline).

Upvotes: 2

Related Questions