TM-220B票据打印[原创]
主要是通过XML文件做模板来实现打印;
模板如下:
1<?xml version="1.0" encoding="utf-8" ?>
2<!--
3说明:
4justification
5center 中间对齐
6right 右对齐
7left 左对齐
8style
90 正常
101 倍宽
112 倍高
123 四倍角
13
14color
150 黑色
161 红色
17-->
18<root>
19<template id="OCT01" name="一卡通储值卡发卡凭证">
20<title text="一卡通发卡凭证" style="2" color="0" justification="center"/>
21<body>
22<item text="用户卡号:" value="CardSerialNumber" style="0" color="0"></item>
23<item text="卡片类型:" value="productName" style="0" color="0"></item>
24<item text="卡有效期:" value="productValidityEndDate" style="0" color="0"></item>
25<item text="发卡押金:" value="carddepositvalue" style="0" color="0"></item>
26<item text="交易时间:" value="transactionTime" style="0" color="0"></item>
27<item text="网点编号:" value="NetStationID" style="0" color="1"></item>
28<item text="操作员ID:" value="staffId" style="0" color="0"></item>
29</body>
30</template>
31<template id="OCT02" name="一卡通储值卡发卡凭证">
32<title text="充值凭证" style="2" color="0" justification="center"/>
33<body>
34<item text="用户卡号:" value="CardSerialNumber" style="0" color="0"></item>
35<item text="卡片类型:" value="productName" style="0" color="0"></item>
36<item text="卡有效期:" value="productValidityEndDate" style="0" color="0"></item>
37<item text="充值前余额:" value="balance2" style="0" color="0"></item>
38<item text="充值金额:" value="revalue" style="0" color="0"></item>
39<item text="充值后金额:" value="balance" style="0" color="0"></item>
40<item text="交易时间:" value="transactionTime" style="0" color="0"></item>
41<item text="网点编号:" value="NetStationID" style="0" color="0"></item>
42<item text="操作员ID:" value="staffId" style="0" color="0"></item>
43</body>
44</template>
45
46
47<template id="ACC01" name="一票通储值卡发卡凭证">
48<title text="一票通发卡凭证" style="2" color="0" justification="center"/>
49<body>
50<item text="用户卡号:" value="otherCardSerialNumber" style="0" color="0"></item>
51<item text="车票种类:" value="productName" style="0" color="0"></item>
52<item text="卡有效期:" value="ValidityEndDate" style="0" color="0"></item>
53<item text="发卡押金:" value="carddepositvalue" style="0" color="0"></item>
54<item text="交易时间:" value="transactionTime" style="0" color="0"></item>
55<item text="车站名称:" value="stationName" style="0" color="0"></item>
56<item text="设备编号:" value="deviceId" style="0" color="0"></item>
57<item text="操作员ID:" value="staffId" style="0" color="0"></item>
58</body>
59</template>
60<template id="ACC02" name="一票通储值卡发卡凭证">
61<title text="充值凭证" style="2" color="0" justification="center"/>
62<body>
63<item text="用户卡号:" value="otherCardSerialNumber" style="0" color="0"></item>
64<item text="车票种类:" value="productName" style="0" color="0"></item>
65<item text="卡有效期:" value="ValidityEndDate" style="0" color="0"></item>
66<item text="充值前金额:" value="" style="0" color="0"></item>
67<item text="充值金额:" value="" style="0" color="0"></item>
68<item text="充值后金额:" value="" style="0" color="0"></item>
69<item text="交易时间:" value="transactionTime" style="0" color="0"></item>
70<item text="车站名称:" value="stationName" style="0" color="0"></item>
71<item text="设备编号:" value="deviceId" style="0" color="0"></item>
72<item text="操作员ID:" value="staffId" style="0" color="0"></item>
73</body>
74</template>
75</root>
一、创建的打印类:Printer.cs
1二、PrinterCommand.cs类using System;
2using System.Collections.Generic;
3using System.Text;
4using System.IO.Ports;
5
6namespace BOM.NewUI.PrinterManager
7{
8/// <summary>
9/// 打印机
10/// </summary>
11public class Printer
12{
13/// <summary>
14/// 获取打印机状态
15/// </summary>
16/// <param name="sp">SerialPort对象</param>
17/// <param name="buffer">指令</param>
18/// <returns>状态代码</returns>
19private int GetState(SerialPort sp, byte[] buffer)
20{
21sp.Write(buffer, 0, buffer.Length);
22return sp.ReadChar();
23}
24/// <summary>
25/// 开钱箱
26/// </summary>
27/// <returns>是否打开</returns>
28public static bool OpenMoneyBox()
29{
30bool result = false;
31SerialPort sp = CreateSerialPort("票据打印机");
32try
33{
34if (!sp.IsOpen)
35sp.Open();
36WriteData(sp, PrinterCommand.CMD_OPENMONEYBOX);
37// sp.Write(new byte[] { 0x1B, 0x70, 0x30, 0x20, 0xF6 }, 0, 5);
38sp.DiscardOutBuffer();
39sp.Close();
40result = true;
41}
42catch
43{
44throw;
45}
46return result;
47}
48/// <summary>
49/// 创建串口对象
50/// </summary>
51/// <param name="portName"></param>
52/// <returns></returns>
53public static SerialPort CreateSerialPort(string portName)
54{
55ConfigManager config = new ConfigManager();
56SerialPortInfo info = config.GetConfig(portName);
57SerialPort sp = new SerialPort(info.portName, info.baudRate, info.parity, info.dataBits, info.stopBits);
58sp.ReadTimeout = 1000;
59if (!sp.IsOpen)
60sp.Open();
61return sp;
62}
63
64/// <summary>
65/// 向串口写数据
66/// </summary>
67/// <param name="sp">SerialPort对象</param>
68/// <param name="buffer">数据</param>
69public static void WriteData(SerialPort sp, byte[] buffer)
70{
71sp.Write(buffer, 0, buffer.Length);
72}
73/// <summary>
74/// 票据打印
75/// </summary>
76/// <param name="sp">SerialPort对象</param>
77/// <param name="templateID">票据模板编号</param>
78public static void Print(SerialPort sp,string templateID)
79{
80Template t = new Template();
81t.Print(sp, templateID);
82}
83}
84}
85
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace BOM.NewUI.PrinterManager
6{
7/// <summary>
8/// 打印机指令
9/// </summary>
10public abstract class PrinterCommand
11{
12/// <summary>
13/// 打印机初始化
14/// </summary>
15public static byte[] CMD_INIT = new byte[] { 0x1b, 0x40 };
16
17/// <summary>
18/// 居右
19/// </summary>
20public static byte[] CMD_RIGHT = new byte[] {0x1b,0x61,0x02 };
21
22/// <summary>
23/// 居左
24/// </summary>
25public static byte[] CMD_LEFT = new byte[] { 0x1b, 0x61, 0x00 };
26
27/// <summary>
28/// 居中
29/// </summary>
30public static byte[] CMD_CENTER = new byte[] { 0x1b, 0x61, 0x01 };
31
32/// <summary>
33/// 倍高and倍宽
34/// </summary>
35public static byte[] CMD_DOUBLEHEIGHTANDDOUBLEWIDTH = new byte[] { 0x1c, 0x21, 0x0c };
36
37/// <summary>
38/// 倍宽
39/// </summary>
40public static byte[] CMD_DOUBLEWIDTH = new byte[] { 0x1c, 0x21, 0x04 };
41
42/// <summary>
43/// 倍高
44/// </summary>
45public static byte[] CMD_DOUBLEHEIGHT = new byte[] { 0x1c, 0x21, 0x08 };
46
47/// <summary>
48/// 恢复正常
49/// </summary>
50public static byte[] CMD_NORMAL = new byte[] { 0x1c, 0x21, 0x00 };
51
52/// <summary>
53/// 进纸一行
54/// </summary>
55public static byte[] CMD_NEWLINE = new byte[] { 0x0a };
56
57/// <summary>
58/// 开钱箱
59/// </summary>
60public static byte[] CMD_OPENMONEYBOX = new byte[] { 0x1B, 0x70, 0x30, 0x20, 0xF6 };
61
62/// <summary>
63/// 获取打印机状态
64/// </summary>
65public static byte[] CMD_STATUS = new byte[] { 0x10, 0x04, 0x01 };
66
67/// <summary>
68/// 选择打印颜色红色
69/// </summary>
70public static byte[] CMD_COLOR_RED = new byte[] { 0x1B, 0x72, 0x01 };
71
72/// <summary>
73/// 选择打印颜色黑色
74/// </summary>
75public static byte[] CMD_COLOR_BLACK = new byte[] { 0x1B, 0x72, 0x00 };
76}
77}
78
三、串口类SerialPortInfo.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.IO.Ports;
5
6namespace BOM.NewUI.PrinterManager
7{
8public class SerialPortInfo
9{
10private string m_printerType;
11private string m_portType;
12private string m_portName;
13private int m_baudRate;
14private Parity m_parity;
15private int m_dataBits;
16private StopBits m_stopBits;
17
18public SerialPortInfo()
19{
20}
21public SerialPortInfo(string _printerType,string _portType,string _portName, int _baudRate, Parity _parity, int _dataBits, StopBits _stopBits)
22{
23this.m_printerType = _printerType;
24this.m_portType = _portType;
25this.m_portName = _portName;
26this.m_baudRate = _baudRate;
27this.m_parity = _parity;
28this.m_dataBits = _dataBits;
29this.m_stopBits = _stopBits;
30}
31
32public string printerType
33{
34set
35{
36this.m_printerType = value;
37}
38get
39{
40return this.m_printerType;
41}
42}
43public string portType
44{
45set
46{
47this.m_portType = value;
48}
49get
50{
51return this.m_portType;
52}
53}
54public string portName
55{
56set
57{
58this.m_portName = value;
59}
60get
61{
62return this.m_portName;
63}
64}
65
66public int baudRate
67{
68set
69{
70this.m_baudRate = value;
71}
72get
73{
74return this.m_baudRate;
75}
76}
77
78public Parity parity
79{
80set
81{
82this.m_parity = value;
83}
84get
85{
86return this.m_parity;
87}
88}
89public int dataBits
90{
91set
92{
93this.m_dataBits = value;
94}
95get
96{
97return this.m_dataBits;
98}
99}
100public StopBits stopBits
101{
102set
103{
104this.m_stopBits = value;
105}
106get
107{
108return this.m_stopBits;
109}
110}
111}
112}
113
四、配置信息类ConfigManager.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Xml;
5using System.IO.Ports;
6
7namespace BOM.NewUI.PrinterManager
8{
9public class ConfigManager
10{
11public ConfigManager()
12{
13}
14/// <summary>
15/// 配置文件路径
16/// </summary>
17private string fileName = "PrinterManager/printerConfig.xml";
18
19public SerialPortInfo GetConfig(string printerName)
20{
21XmlDataDocument doc = new XmlDataDocument();
22doc.Load(fileName);
23XmlNode rootnode = doc.DocumentElement.SelectSingleNode("/SerialPortInfo/printer[@name='" + printerName + "']");
24SerialPortInfo info = new SerialPortInfo();
25foreach (XmlNode node in rootnode.ChildNodes)
26{
27switch (node.Name.ToLower())
28{
29case "printertype":
30info.printerType = node.InnerText;
31break;
32case "porttype":
33info.portType = node.InnerText;
34break;
35case "portname":
36info.portName = node.InnerText.ToUpper();
37break;
38case "baudrate":
39info.baudRate = int.Parse(node.InnerText);
40break;
41case "parity":
42info.parity = GetParity(node.InnerText);
43break;
44case "databits":
45info.dataBits = int.Parse(node.InnerText);
46break;
47case "stopbits":
48info.stopBits = GetStopBits(node.InnerText);
49break;
50}
51}
52return info;
53}
54
55public void SetConfig(SerialPortInfo info,string printerName)
56{
57XmlDataDocument doc = new XmlDataDocument();
58doc.Load(fileName);
59XmlNode rootnode = doc.DocumentElement.SelectSingleNode("/SerialPortInfo/printer[@name='" + printerName + "']");
60foreach (XmlNode node in rootnode.ChildNodes)
61{
62switch (node.Name.ToLower())
63{
64case "printertype":
65node.InnerText = info.printerType;
66break;
67case "porttype":
68node.InnerText = info.portType;
69break;
70case "portname":
71node.InnerText = info.portName;
72break;
73case "baudrate":
74node.InnerText = info.baudRate.ToString();
75break;
76case "parity":
77node.InnerText = info.parity.ToString();
78break;
79case "databits":
80node.InnerText = info.dataBits.ToString();
81break;
82case "stopbits":
83node.InnerText = info.stopBits.ToString();
84break;
85}
86}
87doc.Save(this.fileName);
88}
89
90public Parity GetParity(string parity)
91{
92Parity p = Parity.None;
93switch (parity.ToLower())
94{
95case "even":
96p = Parity.Even;
97break;
98case "mark":
99p = Parity.Mark;
100break;
101case "none":
102p = Parity.None;
103break;
104case "odd":
105p = Parity.Odd;
106break;
107case "space":
108p = Parity.Space;
109break;
110
111}
112return p;
113}
114
115public StopBits GetStopBits(string stopBits)
116{
117StopBits sb = StopBits.One;
118switch (stopBits.ToLower())
119{
120case "none":
121sb = StopBits.None;
122break;
123case "one":
124sb = StopBits.One;
125break;
126case "onepointfive":
127sb = StopBits.OnePointFive;
128break;
129case "two":
130sb = StopBits.Two;
131break;
132}
133return sb;
134}
135}
136}
137
五、利用模板获取变量值 Templete.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Xml;
5using System.IO.Ports;
6using System.Windows.Forms;
7
8namespace BOM.NewUI.PrinterManager
9{
10/// <summary>
11/// 票据模板类
12/// </summary>
13public class Template
14{
15/// <summary>
16/// 模板路径
17/// </summary>
18private string filePath = "PrinterManager/Template.xml";
19/// <summary>
20/// 打印
21/// </summary>
22/// <param name="sp">SerialPort对象</param>
23/// <param name="templateID">模板编号</param>
24public void Print(SerialPort sp,string templateID)
25{
26XmlDataDocument doc = new XmlDataDocument();
27doc.Load(filePath);
28XmlNode root = doc.DocumentElement.SelectSingleNode(string.Format("/root/template[@id='{0}']", templateID));
29![]()
30Printer.WriteData(sp, PrinterCommand.CMD_INIT); //初始化打印机
31foreach (XmlNode node in root.ChildNodes)
32{
33switch (node.Name.ToLower())
34{
35case "title":
36PrintTitle(sp, node);
37break;
38case "body":
39PrintBody(sp, node,templateID);
40break;
41}
42}
43}
44
45/// <summary>
46/// 设置对齐方式和字体样式
47/// </summary>
48/// <param name="sp">SerialPort</param>
49/// <param name="justification">对齐方式</param>
50/// <param name="style">文本样式</param>
51/// <param name="printText">要打印的文本</param>
52/// <param name="color">颜色</param>
53private void SetJustificationAndStyle(SerialPort sp, string justification, string style ,string printText,string color)
54{
55switch( justification.ToLower())
56{
57case "center":
58Printer.WriteData(sp,PrinterCommand.CMD_CENTER);
59break;
60case "left":
61Printer.WriteData(sp,PrinterCommand.CMD_LEFT);
62break;
63case "right":
64Printer.WriteData(sp,PrinterCommand.CMD_RIGHT);
65break;
66}
67switch( style.ToLower())
68{
69case "0":
70Printer.WriteData(sp, PrinterCommand.CMD_NORMAL);
71break;
72case "1":
73Printer.WriteData(sp, PrinterCommand.CMD_DOUBLEHEIGHT);
74break;
75case "2":
76Printer.WriteData(sp, PrinterCommand.CMD_DOUBLEWIDTH);
77break;
78case "3":
79Printer.WriteData(sp, PrinterCommand.CMD_DOUBLEHEIGHTANDDOUBLEWIDTH);
80break;
81}
82switch (color.ToLower())
83{
84case "0":
85Printer.WriteData(sp, PrinterCommand.CMD_COLOR_BLACK);
86break;
87case "1":
88Printer.WriteData(sp, PrinterCommand.CMD_COLOR_RED);
89break;
90![]()
91}
92Printer.WriteData(sp,Encoding.Default.GetBytes( printText ));
93Printer.WriteData(sp, PrinterCommand.CMD_NEWLINE);
94Printer.WriteData(sp,PrinterCommand.CMD_NORMAL);
95Printer.WriteData(sp, PrinterCommand.CMD_LEFT);
96Printer.WriteData(sp, PrinterCommand.CMD_COLOR_BLACK);
97}
98/// <summary>
99/// 根据变量名称取得变量的值
100
101/// </summary>
102/// <param name="varName">变量名称</param>
103/// <returns>变量值</returns>
104private string GetValue(string varName, string templateID)
105{
106string result = string.Empty;
107switch (templateID.Substring(0, 3).ToUpper())
108{
109case "ACC"://一票通
110![]()
206break;
207case "OCT"://一卡通
208![]()
258break;
259}
260return result;
261}
262
263/// <summary>
264/// 打印票据标题
265/// </summary>
266/// <param name="sp">SerialPort对象</param>
267/// <param name="node">XmlNode对象</param>
268private void PrintTitle(SerialPort sp, XmlNode root)
269{
270string printText = root.Attributes["text"].Value;
271string justification = root.Attributes["justification"].Value;
272string style = root.Attributes["style"].Value;
273string color = root.Attributes["color"].Value;
274SetJustificationAndStyle(sp, justification, style, printText,color);
275}
276![]()
277/// <summary>
278/// 打印票据主体
279/// </summary>
280/// <param name="sp">SerialPort对象</param>
281/// <param name="root">XmlNode对象</param>
282private void PrintBody(SerialPort sp, XmlNode root, string templateID)
283{
284foreach (XmlNode node in root.ChildNodes)
285{
286string text = node.Attributes["text"].Value;
287string value = GetValue(node.Attributes["value"].Value,templateID);
288string style = node.Attributes["style"].Value;
289string color = node.Attributes["color"].Value;
290
291StringBuilder sb = new StringBuilder();
292sb.Append(text);
293sb.Append("\t");
294sb.Append(value);
295//SetJustificationAndStyle(sp, string.Empty, style, sb.ToString(),color);
296SetJustificationAndStyle(sp, "left", style, sb.ToString(), color);
297}
298}
299
300/// <summary>
301/// print report title and context
302/// </summary>
303/// <param name="sp">SerialPort对象</param>
304/// <param name="contextstr">上下文</param>
305public void PrintReport(SerialPort sp, string ReportTitle, string ReportContext)
306{
307Printer.WriteData(sp, PrinterCommand.CMD_INIT); //初始化打印机
308string alinement = "center";
309string alinement1 = "left";
310string alinement2 = "right";
311string sizeoffont = "2";//大小
312string sizeoffont1 = "0";
313string coloroffont = "0";//颜色
314string coloroffont1 = "1";
315SetJustificationAndStyle(sp, alinement, sizeoffont, ReportTitle, coloroffont1);
316SetJustificationAndStyle(sp, alinement1, sizeoffont1, ReportContext, coloroffont);
317
318}
319}
320}
321
六、打印调用BOMPrinter.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.IO.Ports;
5using System.IO;
6
7namespace BOM.NewUI.PrinterManager
8{
9public class BOMPrinter
10{
11/// <summary>
12/// 打印
13/// </summary>
14/// <param name="PrintTypeCode">ACC01 或 OCT01</param>
15public static void Printer(string PrintTypeCode)
16{
17//ACC01 or OCT01 and so on
18switch (PrintTypeCode.Substring(0, 3).ToLower())
19{
20case "acc":
21SerialPort sp = BOM.NewUI.PrinterManager.Printer.CreateSerialPort("票据打印机");
22BOM.NewUI.PrinterManager.Printer.Print(sp, PrintTypeCode);
23sp.Close();
24break;
25case "oct":
26SerialPort sp1 = BOM.NewUI.PrinterManager.Printer.CreateSerialPort("票据打印机");
27BOM.NewUI.PrinterManager.Printer.Print(sp1, PrintTypeCode);
28sp1.Close();
29break;
30default:
31break;
32}
33}
34/// <summary>
35/// 打印DG
36/// </summary>
37/// <param name="ReportTitle"></param>
38/// <param name="ReportContext"></param>
39public static void PrintReports(string ReportTitle,string ReportContext)
40{
41SerialPort sp = BOM.NewUI.PrinterManager.Printer.CreateSerialPort("票据打印机");
42Template tt = new Template();
43tt.PrintReport(sp, ReportTitle, ReportContext);
44sp.Close();
45}
46}
47}
48
七、配置文件PrinterConfig.xml
1<?xml version="1.0" encoding="utf-8" ?>
2<SerialPortInfo>
3<printer name="发票打印机">
4<printertype>TM-U220B</printertype>
5<porttype>串口</porttype>
6<portname>COM5</portname>
7<baudrate>9600</baudrate>
8<parity>None</parity>
9<databits>8</databits>
10<stopbits>One</stopbits>
11</printer>
12<printer name="票据打印机">
13<printertype>TM-U220B</printertype>
14<porttype>串口</porttype>
15<portname>COM2</portname>
16<baudrate>9600</baudrate>
17<parity>None</parity>
18<databits>8</databits>
19<stopbits>One</stopbits>
20</printer>
21</SerialPortInfo>
通过以后的工作后,若以后需要增加一些票据的话,只需在相应在XML文件中添加相应的模板信息再,再在Templete.cs文件中给啬的变量付值 ,就可以实现了。