java項目PC端調用條碼打印機打印條碼/吊牌(JS實現)

因爲項目需要,開發一個使用條碼打印機打印商品條形碼和吊牌的功能,首先先上個最後的結果圖

條碼打印和吊牌打印

過程中遇到了一些坑,先簡單說明一下

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圖片,然後保存到服務器,打印的時候再獲取到圖片來打印,反正看到這個說明我連試一下的想法都沒有了。

以上。

如果大家有更好的方法,希望可以分享。

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章