吉特仓库管理系统-.NET打印问题总结
在仓储系统的是使用过程中避免不了的是打印单据,仓库系统中包含很多单据:入库单,出库单,盘点单,调拨单,签收单等等,而且还附带着很多的条码标签的打印。本文在此记录一下一个简单的打印问题处理方式。处理问题环境如下:
在做标签打印的时候,同事说要使用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 = ;
int left = ; Brush bru = Brushes.Black;
Graphics g = e.Graphics; for (int i = ; i < listResult.Count; i++)
{
BarCodeEntity entity = listResult[i];
if (entity != null)
{
int xMo = i % ;
int yMo = i / ; int width = ;
int height = ; g.DrawString("合格证", new Font("黑体", , FontStyle.Bold), bru, new PointF(left + width * xMo + , height * yMo + top)); g.DrawString("本产品经检验合格准予出厂", new Font("黑体", 4.7f, FontStyle.Bold), bru, new PointF(left + width * xMo, height * yMo + + top + ));
g.DrawString("检验员:" + entity.Number + "号 保质期:三年", new Font("黑体", 4.7f, FontStyle.Bold), bru, new PointF(left + width * xMo, height * yMo + + top + ));
g.DrawString("生产日期:" + entity.Time, new Font("黑体", 4.7f, FontStyle.Bold), bru, new PointF(left + width * xMo, height * yMo + + top + )); float length = 7f;
float fontWidth = entity.CompanyName.IsEmpty() ? : length * (entity.CompanyName.Length * 1.0f); float fontSize = 4.4f;
int marginLeft = ;
if (entity.CompanyName.Length > )
{
fontSize = 4.0f;
}
else
{
marginLeft = (int)(( - fontWidth) / );
}
g.DrawString(entity.CompanyName, new Font("黑体", fontSize, FontStyle.Bold), bru, new PointF(left + width * xMo + marginLeft, height * yMo + + top + ));
}
} }
打印绘图简单案例
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="" Heigth="" DefaultPrinter="ZDesigner GK888t (EPL)">
<Line Height="">
<Image Left="" Top="">{{Logo}}</Image>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">预定凭条</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">保税区1店</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">No. page.</Text>
</Line>
<Line Height="">
<QRCode Left="" Top="" >{{OrderCode}}</QRCode>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">单据号:{{OrderCode}}</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">提货时间:{{DtReceive}}</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">提货点:{{ReceiveAddress}}</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">联系人:{{ReceiveUser}}</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">联系电话:{{ReceiverPhone}}</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">时间:{{DtCreate}}</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">-------------</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">序号</Text>
<Text Left="" Top="" FontSize="">货号</Text>
<Text Left="" Top="" FontSize="">品名</Text> <Text Left="" Top="" FontSize="">数量</Text>
<Text Left="" Top="" FontSize="">单价</Text>
<Text Left="" Top="" FontSize="">金额</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">-------------</Text>
</Line> <Loop Values="Detials">
<Line Height="">
<Text Left="" Top="" FontSize="">{{Index}}</Text>
<Text Left="" Top="" FontSize="">{{StrID}}</Text>
<Text Left="" Top="" FontSize="">{{StrName}}</Text> <Text Left="" Top="" FontSize="">{{DCount}}</Text>
<Text Left="" Top="" FontSize="">*</Text>
<Text Left="" Top="" FontSize="">{{DPrice}}</Text>
<Text Left="" Top="" FontSize="">=</Text>
<Text Left="" Top="" FontSize="">{{DAmount}}</Text>
</Line>
</Loop> <Line Height="">
<Text Left="" Top="" FontSize="">-------------</Text>
</Line> <Line Height="">
<Text Left="" Top="" FontSize="">联机刷卡</Text>
<Text Left="" Top="" FontSize="">人民币{{DAmount}}</Text>
</Line> <Line Height="">
<Text Left="" Top="" FontSize="">--------------</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">商品数:{{DCount}}</Text>
<Text Left="" Top="" FontSize="">总金额:{{DAmount}}</Text>
</Line>
<Line Height="">
<BarCode Left="" Top="" Width="" Height="">{{OrderCode}}</BarCode>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">--------------</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">谢谢惠顾,欢迎再次光临</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">提货凭据,请妥善保管</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize="">客服热线:*******</Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize=""></Text>
</Line>
<Line Height="">
<Text Left="" Top="" FontSize=""></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", "");
dic.Add("Number", "");
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", ""},{ "ProductNum", ""},{ "ProductName", "中华烟"},{ "Qty", ""},{ "Price", ""},{ "Amount", ""} },
new Dictionary<string, object>() { { "No", ""},{ "ProductNum", ""},{ "ProductName", "玻璃杯"},{ "Qty", ""},{ "Price", ""},{ "Amount", ""} },
new Dictionary<string, object>() { { "No", ""},{ "ProductNum", ""},{ "ProductName", "烟灰缸"},{ "Qty", ""},{ "Price", ""},{ "Amount", ""} },
new Dictionary<string, object>() { { "No", ""},{ "ProductNum", ""},{ "ProductName", "茶几"},{ "Qty", ""},{ "Price", ""},{ "Amount", ""} },
};
dic.Add("Qty", "");
dic.Add("TotalAmount", "1045.00");
dic.Add("DiscountQty", "");
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) ? "" : strWidth;
strHeigth = string.IsNullOrWhiteSpace(strHeigth) ? "" : strHeigth;
string DefaultPrinter = root.Element("Page").Attribute("DefaultPrinter").Value; //计算文档高度
if (this.IsAutoHeigth)
{
float PageHeith = ;
foreach (XElement item in root.Element("Page").Elements())
{
if (item.Name == "Line")
{
float LineHeigth = string.IsNullOrWhiteSpace(item.Attribute("Height").Value) ? : 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) ? : Convert.ToSingle(lineItem.Attribute("Height").Value);
PageHeith += LineHeigth * listValues.Count();
}
}
}
strHeigth = (PageHeith + ).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 = ;
int rowIndex = ; foreach (XElement item in root.Element("Page").Elements())
{
if (item.Name == "Line")
{
float LineHeigth = string.IsNullOrWhiteSpace(item.Attribute("Height").Value) ? : Convert.ToSingle(item.Attribute("Height").Value); foreach (XElement child in item.Elements())
{
if (child.Name == "Text")
{
float Left = string.IsNullOrWhiteSpace(child.Attribute("Left").Value) ? : Convert.ToSingle(child.Attribute("Left").Value);
float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? : Convert.ToSingle(child.Attribute("Top").Value);
float FontSize = string.IsNullOrWhiteSpace(child.Attribute("FontSize").Value) ? : 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 + , endIndex - beginIndex - );
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) ? : Convert.ToSingle(child.Attribute("Left").Value);
float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? : 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 + , endIndex - beginIndex - );
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) ? : Convert.ToSingle(child.Attribute("Left").Value);
float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? : 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 + , endIndex - beginIndex - );
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(, 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) ? : Convert.ToSingle(child.Attribute("Left").Value);
float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? : Convert.ToSingle(child.Attribute("Top").Value); float Width = string.IsNullOrWhiteSpace(child.Attribute("Width").Value) ? : Convert.ToSingle(child.Attribute("Width").Value);
float Height = string.IsNullOrWhiteSpace(child.Attribute("Height").Value) ? : 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 + , endIndex - beginIndex - );
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) ? : Convert.ToSingle(lineItem.Attribute("Height").Value); for (int i = ; 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) ? : Convert.ToSingle(child.Attribute("Left").Value);
float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? : Convert.ToSingle(child.Attribute("Top").Value);
float FontSize = string.IsNullOrWhiteSpace(child.Attribute("FontSize").Value) ? : 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 + , endIndex - beginIndex - );
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) ? : Convert.ToSingle(child.Attribute("Left").Value);
float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? : 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 + , endIndex - beginIndex - );
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) ? : Convert.ToSingle(child.Attribute("Left").Value);
float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? : 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 + , endIndex - beginIndex - );
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(, 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) ? : Convert.ToSingle(child.Attribute("Left").Value);
float Top = string.IsNullOrWhiteSpace(child.Attribute("Top").Value) ? : Convert.ToSingle(child.Attribute("Top").Value); float Width = string.IsNullOrWhiteSpace(child.Attribute("Width").Value) ? : Convert.ToSingle(child.Attribute("Width").Value);
float Height = string.IsNullOrWhiteSpace(child.Attribute("Height").Value) ? : 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 + , endIndex - beginIndex - );
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打印问题总结的更多相关文章
- 吉特仓库管理系统(开源)-如何在网页端启动WinForm 程序
在逛淘宝或者使用QQ相关的产品的时候,比如淘宝我要联系店家点击旺旺图标的时候能够自动启动阿里旺旺进行聊天.之前很奇怪为什么网页端能够自动启动客户端程序,最近在开发吉特仓储管理系统的时候也遇到一个类似的 ...
- 吉特仓库管理系统- 斑马打印机 ZPL语言的腐朽和神奇
上一篇文章说到了.NET中的打印机,在PrintDocument类也暴露一些本质上上的问题,前面也提到过了,虽然使用PrintDcoument打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...
- 吉特仓储管理系统-ERP或WMS系统中常见术语
MPS---主生产计划(Master Production schedules) MTO---订货生产(Make-to-Order) BOM---物料清单或产品结构表(Bill of material ...
- PDA无线数据采集器在仓库管理系统中的应用
条码数据采集器在仓库管理系统中的应用,条码数据采集器,顾名思义就是通过扫描货物条码,对货物进行数量分类采集,方便仓库正规化管理.条码数据采集器是现代化条码仓库管理系统中不可缺少的一部分,能提升企业的整 ...
- QT 仓库管理系统 开放源代码
IT 要走多久,要怎么走. IT 要走多久,要怎么走.这些问题,在我已经快毕业了一个年头的如今,又又一次浮如今我的脑海里.一边是工作的了了模块,一边是能够自己无聊打发的时间.这不是我当初要的路,如今的 ...
- SSH综合练习-仓库管理系统-第二天
SSH综合练习-仓库管理系统-第二天 今天的主要内容: 货物入库 页面信息自动补全回显功能:(学习目标:练习Ajax交互) 根据货物简记码来自动查询回显已有货物(Ajax回显) 根据货物名来自动查询补 ...
- 仓库如何盘点 打印扫描一体PDA盘点机提升库存盘点效率
仓库盘点是对仓储货品的收发结存等活动进行有效控制,保证仓储货品完好无损.帐物相符,确保生产正常进行,规范公司物料的盘点作业.盘点需人工操作,费时费力,PDA盘点机的出现大幅提升了盘点效率,减轻了工作人 ...
- ERP仓库管理系统查询(十)
需求: 1.根据仓库编号,获取仓库信息绑定至页面相关控件. 2.根据仓库编号,获取管理员信息绑定到页面相关控件 修改的界面: <%@ Page Language="C#" ...
- ERP仓库管理系统(九)
需求分析: 1.设计库房表,至少包括两个字段,库房名称,库房所属公司的ID(在客户资质审批表中找到对应公司的ID) 2.设计增.删.改.查一套程序,其中的删除要做限制,只要有库存数据存在则不允许删除对 ...
- hive中的几个参数:元数据配置、仓库位置、打印表字段相关参数
hive仓库位置由以下参数决定,默认位置/user/hive/warehouse: <property> <name>hive.metastore.wareho ...
随机推荐
- Jquery实现的简单轮播效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Sharepoint学习笔记—习题系列--70-576习题解析 -(Q128-Q130)
Question 128 You are designing a SharePoint 2010 solution that includes a custom site definition an ...
- 实用控件分享:自定义逼真相机光圈View
最近手机界开始流行双摄像头,大光圈功能也应用而生.所谓大光圈功能就是能够对照片进行后期重新对焦,其实现的原理主要是对拍照期间获取的深度图片与对焦无穷远的图像通过算法来实现重新对焦的效果. 在某双摄手机 ...
- SQL2008使用json.net实现XML与JSON互转
借助CLR,首先实现字符串的互转,然后使用存储过程实现JSON2table public class JsonFunction { /// <summary> ...
- Windows on Device 项目实践 1 - PWM调光灯制作
在前一篇文章<Wintel物联网平台-Windows IoT新手入门指南>中,我们讲解了Windows on Device硬件准备和软件开发环境的搭建,以及Hello Blinky项目的演 ...
- RedHat Linux RHEL6配置本地YUM源
YUM是Yellow dog Updater Modified的简称,起初是由yellow dog这一发行版的开发者Terra Soft研发,用python写成,那时还叫做yup(yellow dog ...
- Unable to determine if the owner (Domain\UserName) of job JOB_NAME has server access
早上巡检的的时候,发现一数据库的作业报如下错误(作业名等敏感信息已经替换),该作业的OWNER为一个域账号: JOB RUN: 'JOB_NAME' was run on 2016-6-1 at 7: ...
- The process could not execute 'sp_repldone/sp_replcounters' on 'ServerName'
昨天发现发布服务器S(SQL Server 2008 R2),出现大量如下错误 错误细节如下所示: Date :: PM :: PM) Source spid52 Message Replicatio ...
- 机器学习实战笔记(Python实现)-00-readme
近期学习机器学习,找到一本不错的教材<机器学习实战>.特此做这份学习笔记,以供日后翻阅. 机器学习算法分为有监督学习和无监督学习.这本书前两部分介绍的是有监督学习,第三部分介绍的是无监督学 ...
- IE8 ajax缓存问题
娘希匹,又遇到缓存问题了. 下面的代码,在其他浏览器都是正常的,但是在IE8中出现诡异问题. $.ajax({ url:dataUrl, data:encodeURI(currentjsonform) ...