在仓储系统的是使用过程中避免不了的是打印单据,仓库系统中包含很多单据:入库单,出库单,盘点单,调拨单,签收单等等,而且还附带着很多的条码标签的打印。本文在此记录一下一个简单的打印问题处理方式。处理问题环境如下:

在做标签打印的时候,同事说要使用OPOS指令来打印小单据标签,但是后面送过来的打印机却是斑马打印机,不支持OPOS指令打印,于是很无奈。当时自己提出过另外一种解决方案,那就是使用第三方打印软件,然后使用.NET来调用这个软件打印,这个也是本人之前一直使用的打印方式,比较有名的第三方打印软件bartender. 但是的确这个实施不方便。于是自己使用了最原始用.NET PrintDocument 来打印输出。

  一. 打印需求

    1. 能够打印Logo,也就是打印图片

    2. 打印固定文字,并且能够控制文字大小

    3. 打印变量信息

    4. 打印列表信息

    5. 打印条码 二维码

    6. 打印纸张大小的控制

    以上是个人总结出来做单据打印的一些常用功能,也是比较实用的一些要求,相信做过打印单据的同学应该都遇到过。 在以上几点的需求上有几个比较麻烦的是打印列表,相对比较复杂。对于条码以及二维码的打印其实就是打印图片,使用相应的组件来生成图片打印即可。

  二. GDI+绘图打印

    不用多说,这个肯定是PrintDocument 打印的重点,可能一般做Web开发的同学对打印关注的较少,这里先说WinForm 客户端程序的打印,后续讲解Web上的打印问题。在博客园中搜索了一篇不错的文章介绍GDI画图

    《GDI+绘图》  可以查看了解一下GDI+绘图的基本知识

  

    PrintDocument 文档打印类中有一个Print()打印方法,用于触发打印,PrintPage 事件则在打印命令执行时触发,我们可以在这个事件的方法中绘图,用于实现要打印的内容。先看看一个简单的案例

private void Print(object sender, System.Drawing.Printing.PrintPageEventArgs e){int top = 5;int left = 4;Brush bru = Brushes.Black;Graphics g = e.Graphics;for (int i = 0; i < listResult.Count; i++){BarCodeEntity entity = listResult[i];if (entity != null){int xMo = i % 4;int yMo = i / 4;int width = 90;int height = 79;g.DrawString("合格证", new Font("黑体", 8, FontStyle.Bold), bru, new PointF(left + width * xMo + 22, height * yMo + top));g.DrawString("本产品经检验合格准予出厂", new Font("黑体", 4.7f, FontStyle.Bold), bru, new PointF(left + width * xMo, height * yMo + 13 + top + 5));g.DrawString("检验员:" + entity.Number + "号  保质期:三年", new Font("黑体", 4.7f, FontStyle.Bold), bru, new PointF(left + width * xMo, height * yMo + 26 + top + 5));g.DrawString("生产日期:" + entity.Time, new Font("黑体", 4.7f, FontStyle.Bold), bru, new PointF(left + width * xMo, height * yMo + 39 + top + 5));float length = 7f;float fontWidth = entity.CompanyName.IsEmpty() ? 0 : length * (entity.CompanyName.Length * 1.0f);float fontSize = 4.4f;int marginLeft = 0;if (entity.CompanyName.Length > 13){fontSize = 4.0f;}else{marginLeft = (int)((91 - fontWidth) / 2);}g.DrawString(entity.CompanyName, new Font("黑体", fontSize, FontStyle.Bold), bru, new PointF(left + width * xMo + marginLeft, height * yMo + 52 + top + 5));}}}

打印绘图简单案例

    Brush bru = Brushes.Black;

     Graphics g = e.Graphics;

    以上两个是绘图的重点,定义了画笔以及绘图对象。在PrintPage事件中可以获得绘图对象,我们利用此对象来绘制图片,文字,条码,二维码等

public void DrawImage(Image image, PointF point);public void DrawImageUnscaled(Image image, Point point);public void DrawLine(Pen pen, Point pt1, Point pt2);public void DrawPie(Pen pen, Rectangle rect, float startAngle, float sweepAngle);public void DrawRectangle(Pen pen, Rectangle rect);public void DrawString(string s, Font font, Brush brush, RectangleF layoutRectangle);

    以上是常用的一些绘图方法,绘制图片,直线,圆,方框,字符串等等。可以到微软MSDN官网查看更多的绘图方法

    

    以上是一个简单的打印示例,画图方式比较原始,但是包含了不同的文字,二维码图片等。

  三. PrintDocument使用的缺点

    以上代码打印出来,貌似效果还不错,在小标签纸上效果也挺漂亮.但是问题来了,有一天客户提出需求说,我现在要换打标签纸了,而且文字的排版方式也要稍微做修改。从上面的一段示例代码来看,打印无非就是输出内容(文字,线框,图片等). 然后就是定义响应的坐标即可,也就是点阵类型的打印。将标签纸作为一个画布,然后计算好坐标在相应的位置输出内容即可。 如果标签纸大小变了(排版),那么意味着坐标点也要重新计算,一下子是欲哭无泪。

    当时他们要求使用OPOS指令,ZPL指定也就是因为可以自定义模板.但是不同的打印机支持指令性质不一样,那就只能自己定义一套模板规则来满足要求,并且摆脱不同打印机厂商的限制。

<?xml version="1.0" encoding="utf-8" ?>
<Page Width="200" Heigth="700" DefaultPrinter="ZDesigner GK888t (EPL)"><Line Height="72"><Image Left="20" Top="30">{{Logo}}</Image></Line><Line Height="50"><Text Left="50" Top="2" FontSize="15">预定凭条</Text></Line><Line Height="30"><Text Left="15" Top="2" FontSize="16">保税区1店</Text></Line><Line Height="20"><Text Left="70" Top="2" FontSize="8">No.150 page.1</Text></Line><Line Height="70"><QRCode Left="20" Top="2" >{{OrderCode}}</QRCode></Line><Line Height="20"><Text Left="2" Top="2" FontSize="10">单据号:{{OrderCode}}</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="10">提货时间:{{DtReceive}}</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="10">提货点:{{ReceiveAddress}}</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="10">联系人:{{ReceiveUser}}</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="10">联系电话:{{ReceiverPhone}}</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="10">时间:{{DtCreate}}</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="18">-------------</Text></Line><Line Height="30"><Text Left="2" Top="2" FontSize="7">序号</Text><Text Left="30" Top="2" FontSize="7">货号</Text><Text Left="70" Top="2" FontSize="7">品名</Text><Text Left="30" Top="17" FontSize="7">数量</Text><Text Left="70" Top="17" FontSize="7">单价</Text><Text Left="150" Top="17" FontSize="7">金额</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="18">-------------</Text></Line><Loop Values="Detials"><Line Height="30"><Text Left="2" Top="2" FontSize="7">{{Index}}</Text><Text Left="30" Top="2" FontSize="7">{{StrID}}</Text><Text Left="70" Top="2" FontSize="7">{{StrName}}</Text><Text Left="30" Top="17" FontSize="7">{{DCount}}</Text><Text Left="60" Top="17" FontSize="7">*</Text><Text Left="70" Top="17" FontSize="7">{{DPrice}}</Text><Text Left="140" Top="17" FontSize="7">=</Text><Text Left="150" Top="17" FontSize="7">{{DAmount}}</Text></Line></Loop><Line Height="20"><Text Left="2" Top="2" FontSize="18">-------------</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="7">联机刷卡</Text><Text Left="100" Top="2" FontSize="7">人民币{{DAmount}}</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="18">--------------</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="7">商品数:{{DCount}}</Text><Text Left="100" Top="2" FontSize="7">总金额:{{DAmount}}</Text></Line><Line Height="70"><BarCode Left="20" Top="2" Width="100" Height="60">{{OrderCode}}</BarCode></Line><Line Height="20"><Text Left="2" Top="2" FontSize="18">--------------</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="7">谢谢惠顾,欢迎再次光临</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="7">提货凭据,请妥善保管</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="7">客服热线:*******</Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="7"></Text></Line><Line Height="20"><Text Left="2" Top="2" FontSize="7"></Text></Line>
</Page>

模板定义预览

    为了尽快应付工作问题,在短时间仓促定义了如上模板,用于设置定义指令。以上模板主要内容是控制坐标点以及打印内容的动态体会:

    Page标签: 用于定义打印纸张, 属性:Width 纸张宽度, Heigth 纸张高度, DefaultPrinter 默认使用打印机的名称

    Line标签: 在打印过程中预定都是以行来打印,只是打印行坐标不一样(这样可以控制交叉的情况) 。 定义打印一行, Height 打印行的高度

    Image标签: 用于打印图片 Left 用于设置距离Line 左边的距离 Top 用于设置距离Line 顶部的距离,Image 必须包含到Line标签中。

    Text标签:用于打印文本信息  Left 用于设置距离Line 左边的距离 Top 用于设置距离Line 顶部的距离,FontSize 用于设置打印字体大小, Text必须包含到Line标签中。

    QRCode标签:用于打印二维码图片, Left 用于设置距离Line 左边的距离 Top 用于设置距离Line 顶部的距离

    BarCode标签:用于打印条码图片,Left 用于设置距离Line 左边的距离 Top 用于设置距离Line 顶部的距离.Width 设置条码的长度,Height 设置条码的高度

    Loop标签:用于循环打印,必须包含Line标签,也就是循环打印Line标签。Values 设置数据源的Key值

    {{}}指令:用于替换的变量占位符

    

    画了一个草图理解标签中的属性Left,Top. Line都是以纸张横坐标为0的前提下打印的,也就是说Left是以坐标X=0的情况为计算标准, 而Top 是以Line的内聚为标准,如果有多个Line 则需要先计算上层所有Line的高度总和才能定义Top的Y轴的值。

  四. 数据源的定义

    在上面的设计中利用到了占位符,这个也是比较合理的一种做法,在打印的过程中替换占位符中的内容。 在系统启动的时候回检测模板中的所有占位符。

    数据源的定义是以Dictionary<string, object> 为基础类型,为什么什么这么做,我在占位符 比如{{Logo}} 定义如上,我们就在Dictionary 查找LogoKey的值。然后将其中的内容值替换即可

    

    如果是Loop标签的数据源如何处理: 在Loop标签中定义了Values的属性,其属性值也就是Dictionary 中的key,查找得到之后仍然是一个List<Dictionary<string,object>>的数据值,这边便于循环和Key值得查找。

    

dic = new Dictionary<string, object>();dic.Add("Logo", @"D:\222.jpg");dic.Add("OrderNO", "V3454596546565");dic.Add("Cashier", "菜霞");dic.Add("EndPoint", "634");dic.Add("Number", "120457");dic.Add("CreateTime", DateTime.Now.ToString("yyyy-MM0dd HH:mm:ss"));dic.Add("Amount", "65223.00");dic.Add("QRCode", "V3454596546565");List<Dictionary<string, object>> Info = new List<Dictionary<string, object>>(){new Dictionary<string, object>() { { "No", "1"},{ "ProductNum", "120223"},{ "ProductName", "中华烟"},{ "Qty", "2"},{ "Price", "49"},{ "Amount", "98"} },new Dictionary<string, object>() { { "No", "2"},{ "ProductNum", "565666"},{ "ProductName", "玻璃杯"},{ "Qty", "7"},{ "Price", "45"},{ "Amount", "45545"} },new Dictionary<string, object>() { { "No", "3"},{ "ProductNum", "897845"},{ "ProductName", "烟灰缸"},{ "Qty", "5"},{ "Price", "2435"},{ "Amount", "67767"} },new Dictionary<string, object>() { { "No", "4"},{ "ProductNum", "904395"},{ "ProductName", "茶几"},{ "Qty", "3"},{ "Price", "45245"},{ "Amount", "6767"} },};dic.Add("Qty", "5");dic.Add("TotalAmount", "1045.00");dic.Add("DiscountQty", "1");dic.Add("DiscountAmount", "40.00");dic.Add("Discount", "47.5");dic.Add("DiscountMon", "1958.00");dic.Add("List", Info);

数据源基本格式

public partial class DocumentPrintControl{public DocumentPrintControl() { }public DocumentPrintControl(string printName,string filePath,Dictionary<string,object> dataSource,bool isAutoHeigth){this.PrintName = printName;this.FilePath = filePath;this.DataSource = dataSource;this.IsAutoHeigth = isAutoHeigth;}/// <summary>/// 打印机名称/// </summary>public string PrintName { get; set; }/// <summary>/// 打印模板路径/// </summary>public string FilePath { get; set; }/// <summary>/// 打印数据源/// </summary>public Dictionary<string, object> DataSource { get; set; }/// <summary>/// 是否自适应高度/// </summary>public bool IsAutoHeigth { get; set; }/// <summary>/// 打印Document/// </summary>private PrintDocument printDocument;/// <summary>/// 打印对话框/// </summary>private PrintDialog printDialog;/// <summary>/// XML解析文档/// </summary>private XDocument root;/// <summary>/// 初始化/// </summary>/// <returns></returns>public DocumentPrintControl Init(){this.printDialog = new PrintDialog();this.printDocument = new PrintDocument();this.printDialog.Document = this.printDocument;this.printDocument.PrintPage += PrintDocument_PrintPage;return this;}/// <summary>/// 设置数据源/// </summary>/// <param name="dataSource"></param>/// <returns></returns>public DocumentPrintControl SetDataSource(string fileName){string line = string.Empty;this.DataSource = new Dictionary<string, object>();using (StreamReader reader = new StreamReader(fileName,Encoding.Default)){List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();while ((line = reader.ReadLine()) != null){Dictionary<string, object> dic = new Dictionary<string, object>();dic.Add("Line", line);list.Add(dic);}this.DataSource.Add("List", list);}return this;}/// <summary>/// 开始命令/// </summary>/// <returns></returns>public DocumentPrintControl Begin(){//打印模板if (!File.Exists(this.FilePath)){throw new Exception("打印模板文件不存在");}this.root = XDocument.Load(this.FilePath);string strWidth = root.Element("Page").Attribute("Width").Value;string strHeigth = root.Element("Page").Attribute("Heigth").Value;strWidth = string.IsNullOrWhiteSpace(strWidth) ? "0" : strWidth;strHeigth = string.IsNullOrWhiteSpace(strHeigth) ? "0" : strHeigth;string DefaultPrinter = root.Element("Page").Attribute("DefaultPrinter").Value;//计算文档高度if (this.IsAutoHeigth){float PageHeith = 0;foreach (XElement item in root.Element("Page").Elements()){if (item.Name == "Line"){float LineHeigth = string.IsNullOrWhiteSpace(item.Attribute("Height").Value) ? 0 : Convert.ToSingle(item.Attribute("Height").Value);PageHeith += LineHeigth;}else if (item.Name == "Loop"){string Values = item.Attribute("Values").Value;List<Dictionary<string, object>> listValues = this.DataSource[Values] as List<Dictionary<string, object>>;if (listValues != null){XElement lineItem = item.Element("Line");float LineHeigth = string.IsNullOrWhiteSpace(lineItem.Attribute("Height").Value) ? 0 : Convert.ToSingle(lineItem.Attribute("Height").Value);PageHeith += LineHeigth * listValues.Count();}}}strHeigth = (PageHeith + 10).ToString();}this.printDocument.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize(string.Format("{0}*{1}", strWidth, strHeigth), Convert.ToInt32(strWidth), (int)Math.Ceiling(Convert.ToSingle(strHeigth)));this.printDocument.PrinterSettings.PrinterName = string.IsNullOrWhiteSpace(this.PrintName) ? DefaultPrinter : this.PrintName;return this;}/// <summary>/// 触发打印/// </summary>/// <returns></returns>public bool Print(){this.printDocument.Print();return true;}/// <summary>/// 打印触发事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e){PrintTemplate(sender, e);}/// <summary>/// 打印模板 /// </summary>/// <param name="sender"></param>/// <param name="e"></param>/// <returns></returns>private void PrintTemplate(object sender, PrintPageEventArgs e){Brush bru = Brushes.Black;Graphics g = e.Graphics;float totalHeight = 0;int rowIndex = 0;foreach (XElement item in root.Element("Page").Elements()){if (item.Name == "Line"){float LineHeigth = string.IsNullOrWhiteSpace(item.Attribute("Height").Value) ? 0 : Convert.ToSingle(item.Attribute("Height").Value);foreach (XElement child in item.Elements()){if (child.Name == "Text"){float Left = string.IsNullOrWhiteSpace(child.Attribute("Left").Value) ? 0 : Convert.ToSingle(child.Attribute("Left").Value);float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? 0 : Convert.ToSingle(child.Attribute("Top").Value);float FontSize = string.IsNullOrWhiteSpace(child.Attribute("FontSize").Value) ? 0 : Convert.ToSingle(child.Attribute("FontSize").Value);Top = totalHeight + Top;string content = child.Value;if (content.Contains("{{") && content.Contains("}}")){int beginIndex = content.IndexOf("{{");int endIndex = content.LastIndexOf("}}");string key = content.Substring(beginIndex + 2, endIndex - beginIndex - 2);g.DrawString(content.Replace("{{" + key + "}}", this.DataSource[key].ToString()), new Font("宋体", FontSize, FontStyle.Bold), bru, new PointF(Left, Top));}else{g.DrawString(content, new Font("宋体", FontSize, FontStyle.Bold), bru, new PointF(Left, Top));}}else if (child.Name == "Image"){float Left = string.IsNullOrWhiteSpace(child.Attribute("Left").Value) ? 0 : Convert.ToSingle(child.Attribute("Left").Value);float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? 0 : Convert.ToSingle(child.Attribute("Top").Value);Top = totalHeight + Top;string content = child.Value;if (content.Contains("{{") && content.Contains("}}")){int beginIndex = content.IndexOf("{{");int endIndex = content.LastIndexOf("}}");string key = content.Substring(beginIndex + 2, endIndex - beginIndex - 2);Image image = Image.FromFile(this.DataSource[key].ToString());g.DrawImage(image, new PointF(Left, Top));}}else if (child.Name == "QRCode"){string content = string.Empty;float Left = string.IsNullOrWhiteSpace(child.Attribute("Left").Value) ? 0 : Convert.ToSingle(child.Attribute("Left").Value);float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? 0 : Convert.ToSingle(child.Attribute("Top").Value);Top = totalHeight + Top;content = child.Value;if (content.Contains("{{") && content.Contains("}}")){int beginIndex = content.IndexOf("{{");int endIndex = content.LastIndexOf("}}");string key = content.Substring(beginIndex + 2, endIndex - beginIndex - 2);content = content.Replace("{{" + key + "}}", this.DataSource[key].ToString());}QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);QrCode qrCode = new QrCode();qrEncoder.TryEncode(content, out qrCode);using (MemoryStream ms = new MemoryStream()){var renderer = new GraphicsRenderer(new FixedModuleSize(2, QuietZoneModules.Two));renderer.WriteToStream(qrCode.Matrix, ImageFormat.Jpeg, ms);Image image = Image.FromStream(ms);g.DrawImage(image, new PointF(Left, Top));}}else if (child.Name == "BarCode"){string content = string.Empty;float Left = string.IsNullOrWhiteSpace(child.Attribute("Left").Value) ? 0 : Convert.ToSingle(child.Attribute("Left").Value);float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? 0 : Convert.ToSingle(child.Attribute("Top").Value);float Width = string.IsNullOrWhiteSpace(child.Attribute("Width").Value) ? 0 : Convert.ToSingle(child.Attribute("Width").Value);float Height = string.IsNullOrWhiteSpace(child.Attribute("Height").Value) ? 0 : Convert.ToSingle(child.Attribute("Height").Value);Top = totalHeight + Top;content = child.Value;if (content.Contains("{{") && content.Contains("}}")){int beginIndex = content.IndexOf("{{");int endIndex = content.LastIndexOf("}}");string key = content.Substring(beginIndex + 2, endIndex - beginIndex - 2);content = content.Replace("{{" + key + "}}", this.DataSource[key].ToString());}QrCodeEncodingOptions options = new QrCodeEncodingOptions{DisableECI = true,CharacterSet = "UTF-8",Width = (int)Math.Ceiling(Width),Height = (int)Math.Ceiling(Height),};BarcodeWriter writer = new BarcodeWriter();writer.Format = BarcodeFormat.CODE_128;writer.Options = options;Bitmap bitmap = writer.Write(content);g.DrawImage(bitmap, new PointF(Left, Top));}}totalHeight += LineHeigth;rowIndex++;}else if (item.Name == "Loop"){string Values = item.Attribute("Values").Value;List<Dictionary<string, object>> listValues = this.DataSource[Values] as List<Dictionary<string, object>>;if (listValues != null){XElement lineItem = item.Element("Line");float LineHeigth = string.IsNullOrWhiteSpace(lineItem.Attribute("Height").Value) ? 0 : Convert.ToSingle(lineItem.Attribute("Height").Value);for (int i = 0; i < listValues.Count(); i++){Dictionary<string, object> dicRow = listValues[i];foreach (XElement child in lineItem.Elements()){if (child.Name == "Text"){float Left = string.IsNullOrWhiteSpace(child.Attribute("Left").Value) ? 0 : Convert.ToSingle(child.Attribute("Left").Value);float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? 0 : Convert.ToSingle(child.Attribute("Top").Value);float FontSize = string.IsNullOrWhiteSpace(child.Attribute("FontSize").Value) ? 0 : Convert.ToSingle(child.Attribute("FontSize").Value);Top = totalHeight + Top;string content = child.Value;if (content.Contains("{{") && content.Contains("}}")){int beginIndex = content.IndexOf("{{");int endIndex = content.LastIndexOf("}}");string key = content.Substring(beginIndex + 2, endIndex - beginIndex - 2);g.DrawString(content.Replace("{{" + key + "}}", dicRow[key].ToString()), new Font("宋体", FontSize, FontStyle.Bold), bru, new PointF(Left, Top));}else{g.DrawString(content, new Font("宋体", FontSize, FontStyle.Bold), bru, new PointF(Left, Top));}}else if (child.Name == "Image"){float Left = string.IsNullOrWhiteSpace(child.Attribute("Left").Value) ? 0 : Convert.ToSingle(child.Attribute("Left").Value);float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? 0 : Convert.ToSingle(child.Attribute("Top").Value);Top = totalHeight + Top;string content = child.Value;if (content.Contains("{{") && content.Contains("}}")){int beginIndex = content.IndexOf("{{");int endIndex = content.LastIndexOf("}}");string key = content.Substring(beginIndex + 2, endIndex - beginIndex - 2);Image image = Image.FromFile(dicRow[key].ToString());g.DrawImage(image, new PointF(Left, Top));}}else if (child.Name == "QRCode"){string content = string.Empty;float Left = string.IsNullOrWhiteSpace(child.Attribute("Left").Value) ? 0 : Convert.ToSingle(child.Attribute("Left").Value);float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? 0 : Convert.ToSingle(child.Attribute("Top").Value);Top = totalHeight + Top;content = child.Value;if (content.Contains("{{") && content.Contains("}}")){int beginIndex = content.IndexOf("{{");int endIndex = content.LastIndexOf("}}");string key = content.Substring(beginIndex + 2, endIndex - beginIndex - 2);content = content.Replace("{{" + key + "}}", dicRow[key].ToString());}QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);QrCode qrCode = new QrCode();qrEncoder.TryEncode(content, out qrCode);using (MemoryStream ms = new MemoryStream()){var renderer = new GraphicsRenderer(new FixedModuleSize(2, QuietZoneModules.Two));renderer.WriteToStream(qrCode.Matrix, ImageFormat.Jpeg, ms);Image image = Image.FromStream(ms);g.DrawImage(image, new PointF(Left, Top));}}else if (child.Name == "BarCode"){string content = string.Empty;float Left = string.IsNullOrWhiteSpace(child.Attribute("Left").Value) ? 0 : Convert.ToSingle(child.Attribute("Left").Value);float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? 0 : Convert.ToSingle(child.Attribute("Top").Value);float Width = string.IsNullOrWhiteSpace(child.Attribute("Width").Value) ? 0 : Convert.ToSingle(child.Attribute("Width").Value);float Height = string.IsNullOrWhiteSpace(child.Attribute("Height").Value) ? 0 : Convert.ToSingle(child.Attribute("Height").Value);Top = totalHeight + Top;content = child.Value;if (content.Contains("{{") && content.Contains("}}")){int beginIndex = content.IndexOf("{{");int endIndex = content.LastIndexOf("}}");string key = content.Substring(beginIndex + 2, endIndex - beginIndex - 2);content = content.Replace("{{" + key + "}}", dicRow[key].ToString());}QrCodeEncodingOptions options = new QrCodeEncodingOptions{DisableECI = true,CharacterSet = "UTF-8",Width = (int)Math.Ceiling(Width),Height = (int)Math.Ceiling(Height),};BarcodeWriter writer = new BarcodeWriter();writer.Format = BarcodeFormat.CODE_128;writer.Options = options;Bitmap bitmap = writer.Write(content);g.DrawImage(bitmap, new PointF(Left, Top));}}totalHeight += LineHeigth;rowIndex++;}}}}}}

打印类设置代码

      

      以上是模板打印出来的效果,也避免的打印机指令的相关问题,同时可以自定义标签纸张的大小以及打印的内容边距等等问题。

    五. 代码管理

     由于代码还未完全整理出来,后期整理好之后会托管到GitHub上,暂时有个简单的案例,如有需求可以QQ 821865130 联系我,  群号:88718955

     吉特仓储管理系统中涉及到打印的打印功能,也尝试过各种方式的打印,后面会一一总结分享。如果对吉特仓储系统想要有一定了解可以加群:  88718955  或 142050808

     吉特仓储管理系统有有开源代码: https://github.com/hechenqingyuan/gitwms   有兴趣的可以下载共同探讨

      

作者:情缘
出处:http://www.cnblogs.com/qingyuan/
关于作者:从事仓库,生产软件方面的开发,在项目管理以及企业经营方面寻求发展之路
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
联系方式: 个人QQ  821865130 ; 仓储技术QQ群 88718955,142050808 ;
吉特仓储管理系统 开源地址: https://github.com/hechenqingyuan/gitwms

吉特仓库管理系统-.NET打印问题总结相关推荐

  1. 吉特仓库管理系统-- 后台管理开源啦,源码大放送

    吉特仓储管理系统已经开发好些年了,已经不记得有多少个版本的迭代, 就针对前端UI以及项目结构等重大修改也经历了好几次.吉特仓储管理系统这个名称其实也就今年才开始使用,在此之前都已客户公司命名,基本也是 ...

  2. 3D可视化应急物资仓库管理系统-应急物资可视化系统-数字孪生

    一.系统概述 我司(DONWIT东识科技)3D可视化应急物资仓库管理系统是依托互云计算.大数据.RFID技术.数据库技术.GIS.AI.视频分析技术对应急物资进行统一管理.分析的信息化.智能化.规范化 ...

  3. 仓库管理系统怎么选?想高效管理仓库的老板,别错过这篇干货!

    每个做批发的老板都知道,仓库管理是流通环节中至关重要的一环. 除了部分购买需求稳定.消耗慢的商品之外,大部分的商品如服装.包装食品.日用品.烟酒等等,客户的消费习惯都是趋向于即时消费,销售数量变化大, ...

  4. java电子配件公司仓库管理系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署

    java电子配件公司仓库管理系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署 java电子配件公司仓库管理系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署 本源码技术栈 ...

  5. wms仓库管理系统带来的效益

    wms移动仓库管理系统是基于条码技术.RFID技术和现代化仓储精益管理思想开发出来的仓库管理系统,仓库实现自动化管理,能有效地对仓库流程和空间进行管理,实现批次.单品管理.快速出入库.货物调拨和动态盘 ...

  6. 一文读懂,WMS仓库管理系统模块功能

    对于仓库管理人员来说,仓储管理是一件需要十分负责.又精细化的工作.但实际上,很多企业是采用人工+excel方式进行管理的,这种管理模式存在效率低下.库存准确率低.成本支出高等弊端.而使用WMS仓储管理 ...

  7. wms仓库管理系统的货架摆放原则

    仓库的布局中,最重要的是货架的摆放,因为货架摆放的科学与否决定了拣货路线是否合理.到底是按照货架设计拣货路线,还是根据拣货路线设计货架位置.往往这两者是互相影响的,到底是改变货架,还是改变拣货方式,这 ...

  8. WMS仓库管理系统---(1)总体设计

    WMS仓库管理系统在当今软件行业中起着越来越重要的作用,特别是随着近几年电子商务的发展,很多企业慢慢开始做大,仓库管理方面暴露了好多问题,得不到及时解决.市场上现行的ERP软件都是针对传统行业的,而且 ...

  9. 基于php酒店仓库管理系统的设计与实现(含word文档毕业设计php和mysql)

    摘要 当下是一个信息技术高速发达的时代,企业掌握计算机管理信息的技术, 以优化管理和节约成本.随着酒店的飞速发展,该酒店的物资也日益剧增,之前一直沿用传统的人工管理模式,仓库物品种类繁多且物品繁杂,在 ...

  10. 基于SpringBoot、Layuimini、echarts的仓库管理系统(附源码)

    集成开发环境:IntelliJ IDEA(2021) 数据库:MySQL 8.0 技术栈:Springboot.mybatisPlus.jquery.echarts 适用于结课大作业,课程设计.项目练 ...

最新文章

  1. 真正实现与人更类似的智能!Jeff Hawkins:创造机器智能的路线图
  2. Swing之JTable的详细介绍(转)
  3. 【solr专题之三】Solr常见异常
  4. SQL实战篇:SQL解决连续X天的问题
  5. 【渝粤题库】陕西师范大学163201 旅游科学引论作业(专升本)
  6. Java重载和重写6_深入理解Java中的重写和重载
  7. Memcache监控小工具stats命令
  8. BZOJ2535: [Noi2010]Plane 航空管制2(拓扑排序 贪心)
  9. mysql where子句 参数_MySql——使用where子句过滤数据
  10. python中format函数怎么样提取字符串里的字符_Python中用format函数格式化字符串的用法...
  11. 六、基于UDP的服务器端/客户端
  12. php录音功能,h5做出网页录音功能
  13. matlab中readfid函数,matlab中textscan和textread函数的比较使用
  14. 新西兰梅西大学有计算机专业吗,新西兰梅西大学世界排名|怎么样|入学条件_海外院校库-柳橙网...
  15. 常见负载均衡服务器介绍
  16. msvcr120d.dll 丢失
  17. 织梦网站 mysql,织梦(DEDECMS)网站程序及数据库迁移搬家教程
  18. vue前端实现从数据库获取数据的下拉框以及带参请求
  19. 《量化交易:如何建立自己的算法交易》简介及PDF电子书下载
  20. 如何运用Common Neighbor方法进行链路预测

热门文章

  1. 联想人脸识别软件测试工资,如何使用联想人脸识别(VeriFace)功能
  2. Mysql如何升级到5.7
  3. 亿图图示------基础绘图模块图示
  4. pdfboxiText生成PDF文件格式及读取PDF文件内容的小示例--完美支持中文版
  5. 技术动态 | GNN如何建模时空信息?《时空图神经网络》综述
  6. 在字节跳动实习30天的4点成长感受
  7. python换行符使用_python正则符号,详细的换行符和制表符用法,超实用
  8. 豆瓣镜像源加快下载速度
  9. 中科大 南大计算机专业哪个好,南京大学与中国科学技术大学的计算机专业哪个好?...
  10. JS图片Switchable切换大集合