D365 FO & AX 2012 has in-built capability to print labels on zebra printer. But out-of-the-box, it only works for advanced warehouse module.
This blog explains about to use the same framework to print zebra printer labels from custom code.
Prerequisites to print label
- Zebra Printer connected to the local machine and configured as Generic printer.
- Setup & connect the zebra printer & document routing between local environment and azure. https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/analytics/install-document-routing-agent
- Design the label from Zebra designer and get ZPL code http://labelary.com/viewer.html
- Design a Form in D365 to store the ZPL code.
- Create a class that does the data substitution against the ZPL code, which then sends the resulting string of data directly to the printer via Document routing agent.
Project will look like below
Form HSZPLDocumentLayout is to store the ZPL code in memo field
Class HSZPLDocumentPrint
class HSZPLDocumentPrint
{
RecordSortedList list;
public RecordSortedList getFieldList()
{
return list;
}
RecordSortedList initMenuFields()
{
TmpSysTableField tmpField;
DictField dictField;
DictTable dictTable = new DictTable(tableNum(HSZPLDocumentLabel));
int length = dictTable.fieldCnt();
int i;
for (i = 1; i <= length; ++i)
{
dictField = new DictField(tableNum(HSZPLDocumentLabel), dictTable.fieldCnt2Id(i));
if (!dictField.isSystem() || !dictField.visible())
{
tmpField.FieldId = dictField.id();
tmpField.FieldName = dictField.name();
tmpField.FieldLabel = dictField.label();
list.ins(tmpField);
}
}
return list;
}
public void new()
{
list = new RecordSortedList(tableNum(TmpSysTableField));
list.sortOrder(fieldNum(TmpSysTableField, FieldLabel));
this.initMenuFields();
}
public boolean printDocument(PrinterName _printerName,String15 _layoutId,HSZPLDocumentLabel _label)
{
str finalStr;
boolean ret;
str output;
finalStr = this.translate(HSZPLDocumentLayout::find(_layoutId).ZPLCode, _label);
WhsDocumentRouting::printLabelToPrinter(_printerName, finalStr);
info(finalStr);
return ret;
}
str translate(str _inputStr, HSZPLDocumentLabel _label)
{
TmpSysTableField tmpField;
FieldLabel label;
str outputStr;
outputStr = _inputStr;
list.first(tmpField);
while (tmpField.FieldLabel != '')
{
outputStr = strReplace(outputStr, strFmt('$%1$', tmpField.FieldName), _label.(tmpField.FieldId));
label = tmpField.FieldLabel;
tmpField.clear();
list.next(tmpField);
if (label == tmpField.FieldLabel)
{
break;
}
}
return outputStr;
}
}
To print the label from Released product form, need to design a Drop dialog form HSZPLDocumentPrintDlg
[Form]
public class HSZPLDocumentPrintDlg extends FormRun
{
/// /// ///
public void init()
{
super();
NoofCopies.value(1);
if(element.args().dataset() == tableNum(inventTable))
{
InventTable inventTable = element.args().record() as InventTable;
if(inventTable)
{
ItemId.text(inventTable.ItemId);
Itemname.text(InventTable::find(inventTable.ItemId).defaultProductName());
InventItemBarcode inventItemBarCode;
select firstOnly inventItemBarCode where inventItemBarCode.itemId == ItemId.valueStr()
&& inventItemBarCode.useForPrinting == Noyes::No ;
ItemBarCode.text(inventItemBarCode.itemBarCode);
NoofCopies.value(1);
}
}
}
[Control("String")]
class ItemId
{
/// <summary>
///
/// </summary>
/// <returns></returns>
public boolean modified()
{
boolean ret;
InventItemBarcode inventItemBarCode;
ret = super();
Itemname.text(InventTable::find(ItemId.valueStr()).defaultProductName());
select firstOnly inventItemBarCode where inventItemBarCode.itemId == ItemId.valueStr()
&& inventItemBarCode.useForPrinting == Noyes::No ;
ItemBarCode.text(inventItemBarCode.itemBarCode);
return ret;
}
}
[Control("Button")]
class Printing
{
/// <summary>
///
/// </summary>
public void clicked()
{
//super();
HSZPLLayoutID layoutId;
HSPrinterName printerName;
layoutId = HSZPLLayoutID.valueStr();
printerName = HSPrinterName.valueStr();
HSZPLDocumentLabel label;
HSZPLDocumentLayout layout;
InventTable inventTable;
ItemName itemNametxt;
select layout where layout.ZPLLayoutId == layoutId;
if(!layout)
throw error("Please setup the ZPL layout");
inventTable = InventTable::find(ItemId.valueStr());
itemNametxt = inventTable.defaultProductName();
label.ItemId = inventTable.ItemId;
label.ItemName = strUpr(strDel(itemNametxt,34,70)); //First Line 33 Character of name
label.Amount = InventTableModule::find(InventTable.ItemId,ModuleInventPurchSales::Sales).Price;
label.itemBarCode = inventTable.ItemId;
label.NoofCopies = any2Real(NoofCopies.value());
label.UserId = curUserId();
label.insert();
HSZPLDocumentPrint zplPrint = new HSZPLDocumentPrint();
zplPrint.initMenuFields();
zplPrint.printDocument(printerName,layoutId,label);
delete_from label where label.UserId == curUserId();
info("File Sent to Printer");
}
}
}
ZPL code for your reference.
^XA
^MMT
^PW305
^LL0203
^LS0
^FT17,30^A0N,20,20^FH\^FDD365 Demo LLC^FS
^BY2,3,34^FT17,80^BCN,,N,N
^FD$ItemBarCode$^FS
^FT17,100^A0N,17,16^FH\^FD$ItemId$^FS
^FT17,122^A0N,17,16^FH\^FD$ItemName$^FS
^FT205,150^A0N,20,20^FH\^FD$Amount$^FS
^PQ$NoofCopies$,0,1,Y^XZ
Final label printed on the Zebra printer will similiar to this
Hope this document will help you. Thanks.
Reference : http://jhodge65.blogspot.com/2015/03/zebra-printer-label-printing-with.html