前言
一般在打印快递或者其他标签时,通常会生成PDF来打印,但是也可以直接使用ZPL指令来打印,当然前提用的是支持这种语言的打印机。阅读本文需要有一定风热zpl指令基础,可以先参考下面列出的参考文献进行简单入门。
问题
在初步了解了ZPL的语法之后,我对于如何自动生成ZPL指令产生了疑问。参考是这篇文章,主要借鉴了条形码,二维码的指令格式。标签设计语言ZPL快速入门 - 知乎
思路
指令中最重要的信息的字符位置、大小等信息。我们可以根据标签纸的大小,和想要显示的字符大小,计算出每个字符的位置,然后组装成完整的ZPL指令。
实现
使用工具类(代码在下面)
工具类主要包括两个核心方法,一个是根据所处的行与列计算出在Label上应该所在的位置,包含X轴和Y轴。使用公式inch * dpi = px,计算出Label总长宽,比如一个3x2 inch的Label,分辨率是203,那么它的长宽是609×406px。再根据row和column计算出字符应在位置。另一个则是根据所显示字符和位置来拼接每一行zpl指令,其中判断了是否要生成条形码和二维码,做出了对应的文字大小和位置的调整。有二维码和条形码的字符大小更小,位置也有相对偏移。其中使用了许多常量,这些都可以根据实际情况进行调整。
代码
package com.zzj.zebra-integration.utils;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Slf4j
public class LabelUtil {
/**
* common flag
*/
public static final String BEGIN = "^XA^FX";
public static final String END = "^XZ";
public static final String POSITION_FLAG = "^FO";
/**
* text flag
*/
public static final String DEFAULT_TEXT_SIZE = "0,45";
public static final String DEFAULT_BARCODE_TEXT_SIZE = "0,25";
public static final String DEFAULT_QR_CODE_TEXT_SIZE = "0,25";
public static final String TEXT_FONT_SIZE_FLAG = "^CF";
public static final String TEXT_BEGIN_FLAG = "^FD";
public static final String TEXT_END_FLAG = "^FS";
/**
* barcode flag
*/
public static final String BARCODE_SIZE_FLAG = "^BY";
public static final String DEFAULT_BARCODE_SIZE = "2,2,60";
public static final String BARCODE_OPTION_FLAG = "^BC";
public static final String DEFAULT_BARCODE_OPTION = "N,,N,N,N";
public static final int BARCODE_TEXT_OFFSET = 70;
/**
* qr code flag
*/
public static final String QR_CODE_OPTION_FLAG = "^BQ";
public static final String DEFAULT_QR_CODE_OPTION = "N,2,3";
public static final int QR_CODE_TEXT_OFFSET = 80;
public static String formatZpl(List<String> zplLines){
StringBuilder allZplLine = new StringBuilder();
allZplLine.append("\n");
for (String zplLine : zplLines) {
allZplLine.append(zplLine);
allZplLine.append("\n");
}
return BEGIN + allZplLine + END;
}
public static String formatZplLine(String value, boolean qrCode, boolean barCode, int[] position) {
String zplLine = "";
String textSize = DEFAULT_TEXT_SIZE;
if (qrCode) {
zplLine = POSITION_FLAG
+ Arrays.toString(position).replace("[", "").replace("]", "")
+ QR_CODE_OPTION_FLAG
+ DEFAULT_QR_CODE_OPTION
+ TEXT_BEGIN_FLAG
+ value
+ TEXT_END_FLAG;
position[1] = position[1] + QR_CODE_TEXT_OFFSET;
textSize = DEFAULT_QR_CODE_TEXT_SIZE;
} else if (barCode) {
zplLine = BARCODE_SIZE_FLAG
+ DEFAULT_BARCODE_SIZE
+ POSITION_FLAG
+ Arrays.toString(position).replace("[", "").replace("]", "")
+ BARCODE_OPTION_FLAG
+ DEFAULT_BARCODE_OPTION
+ TEXT_BEGIN_FLAG
+ value
+ TEXT_END_FLAG;
position[1] = position[1] + BARCODE_TEXT_OFFSET;
textSize = DEFAULT_BARCODE_TEXT_SIZE;
}
zplLine = zplLine
+ TEXT_FONT_SIZE_FLAG
+ textSize
+ POSITION_FLAG
+ Arrays.toString(position).replace("[", "").replace("]", "")
+ TEXT_BEGIN_FLAG
+ value
+ TEXT_END_FLAG;
return zplLine;
}
public static int[] calculatePosition(int inchLength, int inchWidth, int dpi, int row, int column, int totalRow, int totalColumn) {
int totalLength = inchLength * dpi;
int totalWidth = inchWidth * dpi;
float rowPercent = (row - 1) / (float) totalRow;
float columnPercent = (column - 1) / (float) totalColumn;
int rowPosition = (int) (totalWidth * rowPercent);
int columnPosition = (int) (totalLength * columnPercent);
return new int[]{columnPosition + 20, rowPosition + 20};
}
public static void main(String[] args) {
int[] position = calculatePosition(3, 2, 203, 2, 1, 3, 3);
log.info("position : {}", position);
String zplLine = formatZplLine("123456789", false, true, position);
log.info("zplLine : {}", formatZpl(Collections.singletonList(zplLine)));
}
}