因爲項目需要,開發一個使用條碼打印機打印商品條形碼和吊牌的功能,首先先上個最後的結果圖
過程中遇到了一些坑,先簡單說明一下
1:我這邊使用的是佳博的條碼打印機,最開始到佳博的開發平臺下載了相關的文檔,並按照說明文檔進行了開發,能順利打印條碼和吊牌,我採用的打印方式是使用TSCLIB,也就是將TSCLIB.dll文件拷貝到系統盤Windows/system32下,然後安裝好條碼打印機對應的驅動(但是這裏有個坑,也就是通過寫後臺代碼來實現,這種方式來實現,會發現只能自己電腦打印,換句話說,就是隻能調用服務器端的打印機驅動,也就是得在服務器端安裝驅動,和將TSCLIB.dll放到服務器上的指定文件下,而不是使用客戶端的電腦驅動打印,而且服務器一般都是使用Linux系統,所以這種方式好像沒辦法搞,坑)。網上很多這些類似調用說明的文檔,以下是TSCLIB.dll方式調用驅動的代碼
package com.xingwei.sale.common.utils;
import java.io.UnsupportedEncodingException;
/**
* @class:PrintBarcodeUtil
*@descript:java使用編程接口打印條形碼
*@author FUYONGJIN
*@date:2019年04月19日 下午16:02
*@version:V1.0
*/
public class PrintBarCodeUtils {
//加載庫文件
private static final String LOAD_LIBRARY="TSCLIB";
//打印機型號
private static final String print_model="Gprinter GP-2120TU";
/**
* @class:TscLibDll
*@descript:創建TSCLIB.dll編程接口
*動態鏈接庫TSCLIB.dll,支持大部分佳博打印機,和其他品牌的TSC系列的打印機
*@version:V1.0
*/
public interface TscLibDll extends Library {
TscLibDll INSTANCE = (TscLibDll) Native.loadLibrary ("TSCLIB", TscLibDll.class);
//顯示DLL的版本號碼
int about ();
//指定計算機端的輸出端口
int openport (String pirnterName);
//關閉指定計算機輸出端口
int closeport ();
//發送內建指令到條形碼打印機
int sendcommand (String printerCommand);
//設定標籤的寬度、高度、打印速度、打印濃度、傳感器類別、垂直間距、偏移距離
int setup (String width,String height,String speed,String density,String sensor,String vertical,String offset);
//下載單色pcx格式圖文件至打印機
int downloadpcx (String filename,String image_name);
//使用條形碼機內建條形碼打印
int barcode (String x,String y,String type,String height,String readable,String rotation,String narrow,String wide,String code);
//使用條形碼機內建文字打印
int printerfont (String x,String y,String fonttype,String rotation,String xmul,String ymul,String text);
//清楚
int clearbuffer ();
//打印標籤內容 set:打印標籤的個數,copy :打印標籤的分數
int printlabel (String set, String copy);
//跳頁,要在setup方法後使用
int formfeed ();
//設定紙張不回吐
int nobackfeed ();
//使用window ttf 字形打印文章
int windowsfont (int x, int y, int fontheight, int rotation, int fontstyle, int fontunderline, String szFaceName, String content);
}
/**
* 打印條碼接口
* @param message 條碼信息
* @param text 顯示文本
* @param sn 商品編碼
* @param num 打印條碼數量
*/
public static void printBarcode(String message,String text,String sn,Integer num) throws RuntimeException{
try {
//加載驅動
System.loadLibrary(LOAD_LIBRARY);
//解決中文亂碼
System.setProperty("jna.encoding", "GBK");
//TscLibDll.INSTANCE.about();
TscLibDll.INSTANCE.openport(print_model);
//TscLibDll.INSTANCE.downloadpcx("C:\\UL.PCX", "UL.PCX");
//TscLibDll.INSTANCE.sendcommand("REM ***** This is a test by JAVA. *****");
TscLibDll.INSTANCE.setup("40", "35", "5", "8", "0", "2", "0");
TscLibDll.INSTANCE.clearbuffer();
//TscLibDll.INSTANCE.sendcommand("PUTPCX 550,10,\"UL.PCX\"");
List<String> contentList = getBarCodeContent(text, sn,10);
for(int i = 0 ; i < contentList.size(); i ++ ){
//默認每行佔高度30,起始行y值20
Integer y = i*30+20;
if(contentList.size() < 4){
y = i*30+50;
}
TscLibDll.INSTANCE.printerfont("20",y.toString(),"TSS24.BF2", "0", "1", "1", contentList.get(i));
}
Integer barCodeY = contentList.size()*38;
if(contentList.size() < 4){
barCodeY = 150;
}
TscLibDll.INSTANCE.barcode("20", barCodeY.toString(), "128", "50", "1", "0", "2", "2", message);
//TscLibDll.INSTANCE.windowsfont(400, 200, 48, 0, 0, 1, "arial", "DEG 0");
TscLibDll.INSTANCE.printlabel("1", num.toString());
TscLibDll.INSTANCE.closeport();
} catch (Exception e) {
throw new RuntimeException("打印機連接異常!", e);
} catch (Error e) {
throw new RuntimeException("打印機連接異常!!!", e);
}
}
/**
* 吊牌打印接口
* @param attrOne 規格一:如顏色
* @param attrTwo 規格二:如大小
* @param text 文本:如商品名稱
* @param sn 編碼:如商品編碼
* @param price 直播價:如商品直播價
* @param num 打印數量
* @throws RuntimeException
*/
public static void printTag(String attrOne,String attrTwo,String price,String text,String sn,Integer num) throws RuntimeException{
try {
//加載驅動
System.loadLibrary(LOAD_LIBRARY);
//解決中文亂碼
System.setProperty("jna.encoding", "GBK");
TscLibDll.INSTANCE.openport(print_model);
TscLibDll.INSTANCE.setup("40", "35", "5", "8", "0", "2", "0");
TscLibDll.INSTANCE.clearbuffer();
List<String> contentList = getBarCodeContent(text, sn,10);
//每行的起始y座標值
Integer y = 20;
//先打印商品名稱和編碼
for(int i = 0 ; i < contentList.size(); i ++ ){
TscLibDll.INSTANCE.printerfont("20",y.toString(),"TSS24.BF2", "0", "1", "1", contentList.get(i));
//默認每行佔高度30,起始行y值20
y += 30;
}
y+=10;
//顏色過長做換行處理
List<String> attrOneList = getBarCodeContent(attrOne, null,14);
for(int i = 0 ; i < attrOneList.size(); i ++ ){
TscLibDll.INSTANCE.printerfont("20",y.toString(),"TSS24.BF2", "0", "1", "1", attrOneList.get(i));
y +=30;
}
TscLibDll.INSTANCE.printerfont("20",(y).toString(),"TSS24.BF2", "0", "1", "1", attrTwo);
y+=30;
TscLibDll.INSTANCE.printerfont("20",y.toString(),"TSS24.BF2", "0", "1", "1", price);
TscLibDll.INSTANCE.printlabel("1", num.toString());
TscLibDll.INSTANCE.closeport();
} catch (Exception e) {
throw new RuntimeException("打印機連接異常!", e);
} catch (Error e) {
throw new RuntimeException("打印機連接異常!!!", e);
}
}
/**
* 動態控制標籤內容的函數,默認一行顯示長度10
* @param content (如商品名稱)
* @param sn (如商品編碼)
* @param length 長度,一行顯示多少個字符
* @return
*/
private static List<String> getBarCodeContent(String content,String sn,Integer length){
List<String> list = new ArrayList<>();
Integer lenght = content.length();
//每行默認10個長度,去有多少行
Integer rows = lenght / length;
//去餘數,如果不整除,說明還有一行
Integer lastRowLenght = lenght % length;
for(int i = 0;i < rows ; i++){
String rowContent = content.substring(i*length, i*length+length);
list.add(rowContent);
}
if(lastRowLenght > 0){
String rowContent = content.substring(rows*length, lenght);
list.add(rowContent);
}
if(StringUtils.isNotEmpty(sn)){
list.add("貨號:"+sn);
}
return list;
}
//測試
public static void main(String[] args) throws UnsupportedEncodingException {
List<String> list=new ArrayList<String>();
list.add("KJ4.1-0127-0001(001)");
/*list.add("KJ4.1-0128-0001(001)");
list.add("KJ4.1-0129-0001(001)");
list.add("KJ4.1-0130-0001(001)"); */
String goodsName = "圓領長袖短款";
if(list!=null && list.size()>0){
for(String message:list){
printBarcode(message,goodsName,"30190422114257",1);
}
}
System.out.println("打印成功");
//printTag("黃色,藍色,白色,黑色,綠色,熒光綠,淺黃色", "S, M, L, XL, XXL", "直播價:¥39.9", "胸前釘珠蕾絲袖黑色連衣裙", "YMT0324-04366", 1);
}
}
如果這種方式能夠滿足你們的需求,你們這個工具類應該是可以直接用的了,唯一要注意的問題就是,條碼打印機的紙張大小,好像不能自動換行,所以需要自己代碼控制每行的長度比如getBarCodeContent這個方法,多行的話重複TscLibDll.INSTANCE.printerfont("20",y.toString(),"TSS24.BF2", "0", "1", "1", contentList.get(i));。
2:發現TSCLIB.dll這種方式沒法調用客戶端的打印機的時候,然後就是試了一下接下來要說的這種方法,其實也就是通過js控制來調用瀏覽器的打印功能 js 代碼:<
a
href
=
"javascrīpt:window.print()"
rel
=
"external nofollow"
target
=
"_self"
>打印</
a
>
然後通過樣式和js來控制需要打印的模塊即可,如樣式(
過濾不需要打印的模塊)
<style type="text/css">
@media print {
.noprint{
display: none;
}
}
</style>
接下來說明一下爲什麼不用這個方式,首先這個方式肯定是可以識別到客戶端的電腦打印驅動的,也能夠正常打印出來,不過問題是window.print()調用去瀏覽器打印,默認的預覽是A4紙的,而條形碼根本就不需要那麼大,而且都是默認居中,反正就是最後打印出來的結構不理想,或者說根本不能用,有些文檔說可以通過樣式來控制,也許可以,不過我調了很久樣式,根本調不到合適,也許大家可以試一下,反正我果斷放棄這種實現的想法了。
3:接下來就講一下最終使用的可以的方法
使用lodop控件來實現,控件是可以識別到客戶機的打印機驅動的,準備工作如下
PC端erp商品管理條碼打印,吊牌打印功能,連接條碼打印機功能說明:
3-1:文件夾說明 CLodop_Setup_for_Win32NT.zip 爲LODOP打印控件文件,Gprinter條碼打印機驅動.rar爲條碼打印機驅動文件
3-2: 安裝說明,使用USB數據線連接電腦,會有也U盤顯示連接,在U盤裏有打印機安裝包,拿到安裝包解壓,並按照說明安裝打印機
(如果安裝打印機失敗,可嘗試 Gprinter條碼打印機驅動 文件下的PrnInst.exe應用程序安裝,
安裝步驟參考佳博官方最新的條碼打印機驅動安裝教程:http://www.gainscha.com/cjwt/202.html)
3-3:安裝LODOP打印控件, 點擊安裝應用程序安裝即可,(建議設置成默認開機啓動) 官方控件下載路徑:http://www.lodop.net/download.html
3-4:打印機安裝準備完成.
直接上這一塊的代碼
<script language="javascript" src="${contextPath}/static/front/common/js/LodopFuncs.js"></script>
<object id="LODOP_OB" classid="clsid:2105C259-1E0C-4534-8141-A753534CB4CA" width=0 height=0>
<embed id="LODOP_EM" type="application/x-print-lodop" width=0 height=0></embed>
</object>
<script type="text/javascript">
function printBarcodeOrTag() {
LODOP=getLodop();
LODOP.PRINT_INIT("條碼打印/吊牌");
var productNumber = $("#productNumber").text();
var productIds = $("#productIds").val();
var barcodeNumber = $("#barcodeNumber").val();
var printType = $("#printType").val();
if(0 == parseInt(productNumber)){
alert("請先選擇商品!!!");
return ;
}
if(!(/(^[1-9]\d*$)/.test(barcodeNumber))){
alert("打印數量只能輸入正整數!!!");
return;
}
$.ajax({
type:"POST",
url:"${contextURL}/sales/product/getBarCodeOrTagData.jspx",
dataType:"json",
data:{"productIds":productIds},
success: function(data){
var data = data.data;
if(data.success==false ){
alert("打印失敗!"+data.errorMsg);
}else{
for (i=0;i<data.length ;i++ ){
var goodsName = data[i].name;
var goodsSn = data[i].sn;
var goodsBarcode = data[i].barCode;
var goodsAttrOne = data[i].attrOne;
var goodsAttrTwo = data[i].attrTwo;
var goodsPrice = data[i].price.toFixed(2);
var nameList = getBarCodeContent(goodsName,10);
if(printType == 'tag'){ //吊牌
LODOP.SET_PRINT_PAGESIZE(1,"5cm","3.8cm","");
var rowHei = 10;
for(var j = 0 ; j< nameList.length;j++){
LODOP.ADD_PRINT_TEXT(rowHei,10,"100%","100%",nameList[j]);
rowHei +=15;
}
LODOP.ADD_PRINT_TEXT(rowHei,10,"100%","100%","貨號:"+goodsSn);
LODOP.ADD_PRINT_TEXT(rowHei+15,10,"100%","100%",goodsAttrOne);
LODOP.ADD_PRINT_TEXT(rowHei+30,10,"100%","100%",goodsAttrTwo);
LODOP.ADD_PRINT_TEXT(rowHei+45,10,"100%","100%","直播價:¥"+goodsPrice);
LODOP.SET_PRINT_STYLEA(0,"Stretch",2);//按原圖比例(不變形)縮放模式
}else{ //條碼
LODOP.SET_PRINT_PAGESIZE(1,"5cm","3.8cm","");
var rowHei = 10;
for(var j = 0 ; j< nameList.length;j++){
LODOP.ADD_PRINT_TEXT(rowHei,10,"100%","100%",nameList[j]);
rowHei +=15;
}
LODOP.ADD_PRINT_TEXT(rowHei,10,"100%","100%","貨號:"+goodsSn);
LODOP.ADD_PRINT_BARCODE(rowHei+20,10,155,40,"128Auto",goodsBarcode);
LODOP.SET_PRINT_STYLEA(0,"Stretch",2);//按原圖比例(不變形)縮放模式
}
if(i+1 != data.length){
LODOP.NEWPAGE(); //分頁
}
}
$(".Modal_box").addClass("disNone");
$(".Modal_box").children().hide();
LODOP.SET_PRINT_COPIES(barcodeNumber); //數量
LODOP.PREVIEW(); //預覽打印
//LODOP.PRINT(); //直接打印
}
}
});
};
function getBarCodeContent(content,rowLen){
var list = new Array();
var contentLen = content.length;
//每行默認10個長度,去有多少行
var rows = parseInt(contentLen / rowLen);
//去餘數,如果不整除,說明還有一行
var lastRowLenght = contentLen % rowLen;
for(var i = 0;i < rows ; i++){
let rowContent = content.substring(i*rowLen, i*rowLen+rowLen);
list[i]=rowContent;
}
if(lastRowLenght > 0){
let rowContent = content.substring(rows*rowLen, contentLen);
list[list.length]=rowContent;
}
return list;
};
</script>
具體的大家可以參考一下其他文檔,這裏再講一下一個可能需要注意的問題,LODOP這個控件好像是需要錢的,如果不預覽直接打印,會顯示試用版打印控件字樣,通過預覽,然後再打印的話,就沒有改字樣。
4:還有一種沒有是試過的方式,先將需要打印的內容轉換成PDF圖片,然後保存到服務器,打印的時候再獲取到圖片來打印,反正看到這個說明我連試一下的想法都沒有了。
以上。
如果大家有更好的方法,希望可以分享。