此文章给出两种打印案例,
第一种是单列打印,第二种是双列打印
需要注意打印机名称的设置,程序中使用的打印机名称为999,电脑中安装打印机时名称也要为999。
以下是我在使用过程中总结的一些问题:
一 TSC打印机使用使用过程中遇到的问题
1、打印机刚连上就报警。
一般是纸张或色带安装有问题,纸张要放到档杆的下方。
2、打印机显示正常,DiagTool工具无法连接到打印机,无论点什么都提示“Port Open Error”。
如果使用USB模式,需要用线把打印机和电脑连接起来,同时打印机需插上网线。工具中,通讯接口选择USB,点击“读取状态”,正常显示待机中,点击“读取”,会重置工具中的各参数。
点击“网络设定”,指定IP地址,这里设置为192.168.50.222
如果用服务器连接打印机,这个时候已经添加了打印机,登录服务器,找到打印机,打开打印机属性-端口,打印机名称或ip地址设置为与打印机ip一致即可。
3、打印机打印完成后报警。
检查纸张,纸张安装过紧或档条没压住纸,都会导致此问题。
接下来上代码
二 打印方式
2.1 单列打印
这种打印方式示例中,打印的位置是可以配置的
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Imagine.Mes.MesTrackV3.Application.CommonTool;
using Imagine.Mes.MesTrackV3.Application.Dtos;
using Volo.Abp.DependencyInjection;
using Newtonsoft.Json;
using System.IO;
using Newtonsoft.Json.Linq;
namespace Imagine.Mes.MesTrackV3.Application.Services
{
/// <summary>
/// 打印服务
/// </summary>
public interface IPrintService
{
/// <summary>
/// 打印流程卡
/// </summary>
/// <param name="printType">打印枚举 0-二维码;1-条形码</param>
/// <param name="body">流程卡集合</param>
/// <returns></returns>
Task PrintLotAsync(PrintEnum printType, List<PrintLotInDto> body);
}
public class PrintService : IPrintService,IScopedDependency
{
private readonly ILogger<PrintService> _logger;
public PrintService(ILogger<PrintService> logger)
{
_logger = logger;
}
#region 打印流程卡
/// <summary>
/// 打印流程卡
/// </summary>
/// <param name="printType">打印枚举 0-二维码;1-条形码</param>
/// <param name="body">流程卡集合</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task PrintLotAsync(PrintEnum printType, List<PrintLotInDto> body)
{
try
{
List<PrintLotInDto> printOutboundOrderList = new List<PrintLotInDto>();
var jsonObject=await GetJsonFileAsync("CommonTool\\PrintLot.json");
for (int i = 0; i < body.Count; i++)
{
await PrintLotAsync(printType,jsonObject, new PrintLotInDto
{
LotNo = body[i].LotNo,
ProductCode = body[i].ProductCode,
ProductName = body[i].ProductName,
Quantity = body[i].Quantity,
WorkOrderNo = body[i].WorkOrderNo,
UnitName= body[i].UnitName
});
}
}
catch (Exception ex)
{
_logger.LogError($"打印流程卡错误:{ex}");
throw new Exception($"打印流程卡错误:{ex.Message}");
}
}
/// <summary>
/// 打印流程卡
/// </summary>
/// <param name="printType">打印类型:0-二维码;1-条形码</param>
/// <param name="jsonObject"></param>
/// <param name="param"></param>
/// <returns></returns>
private async Task PrintLotAsync(PrintEnum printType, JObject jsonObject, PrintLotInDto param)
{
#region 模板
string port = "999";
string currentEncoding = "utf-16";
string chineseFont = "宋体";
byte[] lotNo = Encoding.GetEncoding(currentEncoding).GetBytes($"批 次 号:{param.LotNo}");
byte[] productCode = Encoding.GetEncoding(currentEncoding).GetBytes($"产品编码:{param.ProductCode}");
byte[] productName = Encoding.GetEncoding(currentEncoding).GetBytes($"产品名称:{param.ProductName}");
byte[] quantity = Encoding.GetEncoding(currentEncoding).GetBytes($"数 量:{param.Quantity} {param.UnitName}");
byte[] workOrderNo = Encoding.GetEncoding(currentEncoding).GetBytes($"工 单 号:{param.WorkOrderNo}");
byte[] date = Encoding.GetEncoding(currentEncoding).GetBytes($"打印日期:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
byte status = TSCLIB_DLL.usbportqueryprinter();//0 = idle, 1 = head open, 16 = pause, following <ESC>!? command of TSPL manual
//打印机共享名999
int openport = TSCLIB_DLL.openport(@$"{port}");
//M 纸张宽度 ,N 纸张高度
TSCLIB_DLL.sendcommand("SIZE 100 mm, 80 mm");
TSCLIB_DLL.sendcommand("SPEED 4");
TSCLIB_DLL.sendcommand("DENSITY 12");
TSCLIB_DLL.sendcommand("DIRECTION 1");
TSCLIB_DLL.sendcommand("SET TEAR ON");
TSCLIB_DLL.sendcommand("CODEPAGE UTF-8");
TSCLIB_DLL.clearbuffer();
if (printType == PrintEnum.QRCode)//打印二维码
{
//文字(x边距,y边距,字体高度,旋转,字体样式,下划线,字体,文字内容)
TSCLIB_DLL.windowsfontUnicode(Convert.ToInt32(jsonObject["lotNo"]["x"]), Convert.ToInt32(jsonObject["lotNo"]["y"]), Convert.ToInt32(jsonObject["lotNo"]["size"]), 0, 0, 0, chineseFont, lotNo);
TSCLIB_DLL.windowsfontUnicode(Convert.ToInt32(jsonObject["productCode"]["x"]), Convert.ToInt32(jsonObject["productCode"]["y"]), Convert.ToInt32(jsonObject["productCode"]["size"]), 0, 0, 0, chineseFont, productCode);
TSCLIB_DLL.windowsfontUnicode(Convert.ToInt32(jsonObject["productName"]["x"]), Convert.ToInt32(jsonObject["productName"]["y"]), Convert.ToInt32(jsonObject["productName"]["size"]), 0, 0, 0, chineseFont, productName);
TSCLIB_DLL.windowsfontUnicode(Convert.ToInt32(jsonObject["quantity"]["x"]), Convert.ToInt32(jsonObject["quantity"]["y"]), Convert.ToInt32(jsonObject["quantity"]["size"]), 0, 0, 0, chineseFont, quantity);
TSCLIB_DLL.windowsfontUnicode(Convert.ToInt32(jsonObject["workOrderNo"]["x"]), Convert.ToInt32(jsonObject["workOrderNo"]["y"]), Convert.ToInt32(jsonObject["workOrderNo"]["size"]), 0, 0, 0, chineseFont, workOrderNo);
TSCLIB_DLL.windowsfontUnicode(Convert.ToInt32(jsonObject["date"]["x"]), Convert.ToInt32(jsonObject["date"]["y"]), Convert.ToInt32(jsonObject["date"]["size"]), 0, 0, 0, chineseFont, date);
//二维码
//QRCODE x,y,ECC Level,cell width(二维码大小),mode,rotation(旋转),[model,mask,]"content"
TSCLIB_DLL.sendcommand($"QRCODE {Convert.ToInt32(jsonObject["qRCode"]["x"])},{Convert.ToInt32(jsonObject["qRCode"]["y"])},H,{Convert.ToInt32(jsonObject["qRCode"]["size"])},A,0,M2,\"{param.LotNo}\"");
}
else// 打印条码.
{
// 在 (450, 200) 的坐标上
// 以 Code128 的条码方式
// 条码高度 300
// 打印条码的同时,还打印条码的文本信息.
// 旋转的角度为 0 度
// 条码 宽 窄 比例因子为 7:7
// 条码内容为:barCode
//BARCODE X,Y,”code type”,height,human readable,rotation,narrow,wide,[alignment,]”content“
TSCLIB_DLL.barcode("30", "30", "128", "180", "1", "0", "6", "6", $"{param.LotNo}");
}
//TSCLIB_DLL.sendcommand(String.Format("QRCODE 740,320,H,8,A,0,M2,\"{0}\"", trayCode));
//DMATRIX码 。DMATRIX 命令,740,320,90,90 指定 X 坐标,指定 Y 坐标,条码区域宽度
//TSCLIB_DLL.sendcommand($"DMATRIX 740,320,90,90,x18,30,30,\"{trayCode}\"");
int printlabel = TSCLIB_DLL.printlabel("1", "1");
TSCLIB_DLL.closeport();
#endregion
await Task.CompletedTask;
}
#endregion 打印流程卡
#region 获取json文件内容
private async Task<JObject> GetJsonFileAsync(string path)
{
try
{
// 获取文件的绝对路径
string filePath = Path.Combine(AppContext.BaseDirectory, path);
string jsonContent = string.Empty;//json内容
var exists = System.IO.File.Exists(filePath);
if (!exists) throw new Exception($"配置文件[{path.Split("\\")[path.Split("\\").Length - 1]}]不存在");
// 读取文件的内容
using (StreamReader file = File.OpenText(filePath))
{
jsonContent = await file.ReadToEndAsync();
}
// 解析JSON到JObject
JObject jsonObj = JObject.Parse(jsonContent);
// 反序列化
//var plcModel = JsonConvert.DeserializeObject<List<PLCModel>>(jsonContent);
return jsonObj;
}
catch (Exception ex)
{
_logger.LogError(ex.ToString(), ex);
throw new Exception(ex.Message);
}
}
#endregion
}
}
/// <summary>
/// 打印流程卡
/// </summary>
public class PrintLotInDto
{
/// <summary>
/// 批次号
/// </summary>
public string LotNo { get; set; }
/// <summary>
/// 产品名称
/// </summary>
public string ProductName { get; set; }
/// <summary>
/// 产品编码
/// </summary>
public string ProductCode { get; set; }
/// <summary>
/// 数量
/// </summary>
public int Quantity { get; set; }
/// <summary>
/// 工单号
/// </summary>
public string WorkOrderNo { get; set; }
/ <summary>
/ 打印日期
/ </summary>
//public DateTime Date { get; set; }
/// <summary>
/// 单位名称
/// </summary>
public string UnitName { get; set; }
}
/// <summary>
/// 打印枚举
/// </summary>
public enum PrintEnum
{
QRCode = 0,//二维码
BarCode = 1//条形码
}
PrintLot.json文件内容
{
//批次号
"lotNo": {
"x": 430, //x坐标
"y": 320, //y坐标
"size": 50 //字体大小
},
//产品编码
"productCode": {
"x": 230,
"y": 400,
"size": 50
},
//产品名称
"productName": {
"x": 230,
"y": 480,
"size": 50
},
//数量
"quantity": {
"x": 230,
"y": 560,
"size": 50
},
//工单号
"workOrderNo": {
"x": 230,
"y": 640,
"size": 50
},
//打印日期
"date": {
"x": 230,
"y": 720,
"size": 50
},
//二维码
"qRCode": {
"x": 450,
"y": 30,
"size": 10 //二维码大小
}
}
2.2 双列打印
using Imagine.Mes.MesBase.Application.CommonTool;
using Imagine.Mes.MesBase.Application.Dtos;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Imagine.Mes.MesBase.Application.Services
{
public interface IPrintService
{
/// <summary>
/// 打印库位信息
/// </summary>
/// <param name="printType"></param>
/// <param name="body"></param>
/// <returns></returns>
Task PrintWarehouselocationsAsync(PrintTypeEnum printType, List<WarehouseLocationNoParam> body);
}
public class PrintService : IPrintService, ITransientDependency
{
private readonly ILogger<PrintService> _logger;
public PrintService(
ILogger<PrintService> logger
)
{
_logger = logger;
}
public async Task PrintWarehouselocationsAsync(PrintTypeEnum printType, List<WarehouseLocationNoParam> body)
{
try
{
List<PrintWarehouseLocationParam> printQualityInspectionList = new List<PrintWarehouseLocationParam>();
for (int i = 0; i < body.Count; i += 2)
{
PrintWarehouseLocationParam printQualityInspection = new PrintWarehouseLocationParam();
printQualityInspection.QRCodeContent = body[i].QRCodeContent;
printQualityInspection.WarehouseLocationName = body[i].WarehouseLocationName;
printQualityInspection.WarehouseLocationNo = body[i].WarehouseLocationNo;
printQualityInspection.QRCodeContent2 = i + 1 < body.Count ? body[i + 1].QRCodeContent : null;
printQualityInspection.WarehouseLocationName2 = i + 1 < body.Count ? body[i + 1].WarehouseLocationName : null;
printQualityInspection.WarehouseLocationNo2 = i + 1 < body.Count ? body[i + 1].WarehouseLocationNo : null;
printQualityInspectionList.Add(printQualityInspection);
await PrintWarehouselocationAsync(printType, new PrintWarehouseLocationParam
{
QRCodeContent = printQualityInspection.QRCodeContent,
WarehouseLocationName = printQualityInspection.WarehouseLocationName,
WarehouseLocationNo = printQualityInspection.WarehouseLocationNo,
QRCodeContent2 = printQualityInspection.QRCodeContent2,
WarehouseLocationName2 = printQualityInspection.WarehouseLocationName2,
WarehouseLocationNo2 = printQualityInspection.WarehouseLocationNo2
});
}
}
catch (Exception ex)
{
_logger.LogError($"打印质检单/入库单错误:{ex}");
}
}
/// <summary>
/// 打印出库单/入库单
/// </summary>
/// <param name="printType">打印类型:0-二维码;1-条形码</param>
/// <param name="param"></param>
/// <returns></returns>
private async Task PrintWarehouselocationAsync(PrintTypeEnum printType, PrintWarehouseLocationParam param)
{
#region 模板
string port = "999";
string currentEncoding = "utf-16";
string chineseFont = "宋体";
byte[] warehouseLocationNo = null;
byte[] warehouseLocationName = null;
byte[] warehouseLocationNo2 = null;
byte[] warehouseLocationName2 = null;
warehouseLocationNo = Encoding.GetEncoding(currentEncoding).GetBytes($"{param.WarehouseLocationNo}");
warehouseLocationName = Encoding.GetEncoding(currentEncoding).GetBytes($"{param.WarehouseLocationName}");
warehouseLocationNo2 = Encoding.GetEncoding(currentEncoding).GetBytes($"{param.WarehouseLocationNo2}");
warehouseLocationName2 = Encoding.GetEncoding(currentEncoding).GetBytes($"{param.WarehouseLocationName2}");
byte status = TSCLIB_DLL.usbportqueryprinter();//0 = idle, 1 = head open, 16 = pause, following <ESC>!? command of TSPL manual
//打印机共享名999
int openport = TSCLIB_DLL.openport(@$"{port}");
//M 纸张宽度 ,N 纸张高度
TSCLIB_DLL.sendcommand("SIZE 100 mm, 30 mm");
TSCLIB_DLL.sendcommand("SPEED 2");
TSCLIB_DLL.sendcommand("DENSITY 15");
TSCLIB_DLL.sendcommand("DIRECTION 1");
TSCLIB_DLL.sendcommand("SET TEAR ON");
TSCLIB_DLL.sendcommand("CODEPAGE UTF-8");
TSCLIB_DLL.clearbuffer();
if (printType == PrintTypeEnum.QRCode)//打印二维码
{
TSCLIB_DLL.windowsfontUnicode(150, 20, 26, 0, 0, 0, chineseFont, warehouseLocationName);
TSCLIB_DLL.sendcommand($"QRCODE 180,55,H,5,A,0,M2,\"{param.QRCodeContent}\"");
TSCLIB_DLL.windowsfontUnicode(150, 180, 26, 0, 0, 0, chineseFont, warehouseLocationNo);
if (!string.IsNullOrWhiteSpace(param.QRCodeContent2))
{
TSCLIB_DLL.windowsfontUnicode(550, 20, 26, 0, 0, 0, chineseFont, warehouseLocationName2);
TSCLIB_DLL.sendcommand($"QRCODE 580,55,H,5,A,0,M2,\"{param.QRCodeContent2}\"");
TSCLIB_DLL.windowsfontUnicode(550, 180, 26, 0, 0, 0, chineseFont, warehouseLocationNo2);
}
}
else// 打印条码.
{
// 在 (450, 200) 的坐标上
// 以 Code128 的条码方式
// 条码高度 300
// 打印条码的同时,还打印条码的文本信息.
// 旋转的角度为 0 度
// 条码 宽 窄 比例因子为 7:7
// 条码内容为:barCode
//BARCODE X,Y,”code type”,height,human readable,rotation,narrow,wide,[alignment,]”content“
TSCLIB_DLL.barcode("300", "340", "128", "180", "1", "0", "6", "6", $"{param.QRCodeContent2}");
}
//TSCLIB_DLL.sendcommand(String.Format("QRCODE 740,320,H,8,A,0,M2,\"{0}\"", trayCode));
//DMATRIX码 。DMATRIX 命令,740,320,90,90 指定 X 坐标,指定 Y 坐标,条码区域宽度
//TSCLIB_DLL.sendcommand($"DMATRIX 740,320,90,90,x18,30,30,\"{trayCode}\"");
int printlabel = TSCLIB_DLL.printlabel("1", "1");
TSCLIB_DLL.closeport();
#endregion
await Task.CompletedTask;
}
}
/// <summary>
/// 打印枚举
/// </summary>
public enum PrintTypeEnum
{
QRCode = 0,//二维码
BarCode = 1//条形码
}
}
/// <summary>
/// 库位码打印参数
/// </summary>
public class WarehouseLocationNoParam
{
/// <summary>
/// 二维码内容
/// </summary>
public string QRCodeContent { get; set; }
/// <summary>
/// 库位名称
/// </summary>
public string WarehouseLocationName { get; set; }
/// <summary>
/// 库位编码
/// </summary>
public string WarehouseLocationNo { get; set; }
}
/// <summary>
/// 库位码打印参数
/// </summary>
public class PrintWarehouseLocationParam
{
/// <summary>
/// 二维码内容
/// </summary>
public string QRCodeContent { get; set; }
/// <summary>
/// 库位名称
/// </summary>
public string WarehouseLocationName { get; set; }
/// <summary>
/// 库位编码
/// </summary>
public string WarehouseLocationNo { get; set; }
/// <summary>
/// 二维码内容2
/// </summary>
public string QRCodeContent2 { get; set; }
/// <summary>
/// 库位名称2
/// </summary>
public string WarehouseLocationName2 { get; set; }
/// <summary>
/// 库位编码2
/// </summary>
public string WarehouseLocationNo2 { get; set; }
}
2.3 用到的公共类
using System.Runtime.InteropServices;
namespace Imagine.Mes.MesBase.Application.CommonTool
{
public class TSCLIB_DLL
{
[DllImport("TSCLIB.dll", EntryPoint = "about")]
public static extern int about();
[DllImport("TSCLIB.dll", EntryPoint = "openport")]
public static extern int openport(string printername);
[DllImport("TSCLIB.dll", EntryPoint = "barcode")]
public static extern int barcode(string x, string y, string type,
string height, string readable, string rotation,
string narrow, string wide, string code);
[DllImport("TSCLIB.dll", EntryPoint = "clearbuffer")]
public static extern int clearbuffer();
[DllImport("TSCLIB.dll", EntryPoint = "closeport")]
public static extern int closeport();
[DllImport("TSCLIB.dll", EntryPoint = "downloadpcx")]
public static extern int downloadpcx(string filename, string image_name);
[DllImport("TSCLIB.dll", EntryPoint = "formfeed")]
public static extern int formfeed();
[DllImport("TSCLIB.dll", EntryPoint = "nobackfeed")]
public static extern int nobackfeed();
[DllImport("TSCLIB.dll", EntryPoint = "printerfont")]
public static extern int printerfont(string x, string y, string fonttype,
string rotation, string xmul, string ymul,
string text);
[DllImport("TSCLIB.dll", EntryPoint = "printlabel")]
public static extern int printlabel(string set, string copy);
[DllImport("TSCLIB.dll", EntryPoint = "sendcommand")]
public static extern int sendcommand(string printercommand);
[DllImport("TSCLIB.dll", EntryPoint = "setup")]
public static extern int setup(string width, string height,
string speed, string density,
string sensor, string vertical,
string offset);
[DllImport("TSCLIB.dll", EntryPoint = "windowsfont")]
public static extern int windowsfont(int x, int y, int fontheight,
int rotation, int fontstyle, int fontunderline,
string szFaceName, string content);
[DllImport("TSCLIB.dll", EntryPoint = "windowsfontUnicode")]
public static extern int windowsfontUnicode(int x, int y, int fontheight,
int rotation, int fontstyle, int fontunderline,
string szFaceName, byte[] content);
[DllImport("TSCLIB.dll", EntryPoint = "sendBinaryData")]
public static extern int sendBinaryData(byte[] content, int length);
[DllImport("TSCLIB.dll", EntryPoint = "usbportqueryprinter")]
public static extern byte usbportqueryprinter();
}
}