记一次打印机功能实现

一次,打印机,功能,实现 · 浏览次数 : 16

小编点评

**代码解析:** **1. 二维码** * 使用 `BarcodeWriter` 生成 QR CODE。 * 将 QR CODE 插入 workbook 中。 **2. 条形码** * 使用 `BarcodeWriter` 生成 CODE 128 字符串。 * 将字符串转换为 Base64 字符串。 * 将字符串转换为 GBK 编码的字节数组。 **3. 转换为 ZPL 命令** * 使用 `PDFtoZPL.Conversion.ConvertPdf()` 函数将 PDF 文件转换为 ZPL 字符串。 * 将字符串转换为 GBK 编码的字节数组。

正文

使用的是芝柯打印机,无驱动,除了文本打印外,若想打印其他表格或者模板,我的做法是利用excel填充数据,然后转换为pdf,pdf再转为zpl命令。

  1.  核心代码分为三部分:
    1. 加载打印模板,填充打印数据到模板并保存成新的打印文件
    2. 将需要打印的文件,转换为PDF格式。这一步主要是因为芝柯打印机是无驱动的,需要转换成ZPL命令发送至服务端进行打印。而PDF转换起来最为简单方便。
    3. 将PDF文件转换成ZPL命令。然后发送至服务端即可打印
  2. 第三方组件库:
    1. ZXing.Net.Bindings.Windows.Compatibility。主要用于生成二维码和条形码。网上很多教程说是ZXing.Net。但是并不行,可能跟系统有关?查了好久才发现要引用ZXing.Net.Bindings.Windows.Compatibility这个!如果只需要二维码的话,可以使用QRCoder,net6以上的话,可能得安装1.4.2版本,最新的和net6不匹配,用不了,详细可以看作者的说明。
                          #region 二维码
                          //实例一个对象,配置二维码的参数
                          var qR = new BarcodeWriter
                          {
                              //类型,QRCODE二维码,下面的条形码也是一样的,不知道类型百度一下
                              Format = BarcodeFormat.QR_CODE
                          };
                          // 设置生成的二维码的一些参数(可选)
                          EncodingOptions encodingOptions = new()
                          {
                              Width = 120, // 宽度
                              Height = 120, // 高度
                              Margin = 0 // 边距
                          };
                          qR.Options = encodingOptions;
                          //填充数据
                          Bitmap qrBitmap = qR.Write(datas[i].ID);
                          // 将 Bitmap 转换为文件流(这里是epplus插入图片的方式,其他操作excel组件自行修改)
                          using (MemoryStream qrStream = new())
                          {
                              //保存进文件流
                              qrBitmap.Save(qrStream, System.Drawing.Imaging.ImageFormat.Png);
                              //wb是一个Worksheet工作簿,往里面添加图片
                              var qrImg = wb.Drawings.AddPicture("QR", qrStream);
                              //图片的位置,四个参数(行,偏移量,列,偏移量)注意点在于,设置了第一行第一列,图片的位置会从右下角开始
                              qrImg.SetPosition(22, 0, 6, 0);
                          }
      
                          #endregion 二维码
      
                          #region 条形码
      
                          var writer = new BarcodeWriter
                          {
                              Format = BarcodeFormat.CODE_128
                          };
                          QrCodeEncodingOptions options = new()
                          {
                              DisableECI = true,
                              CharacterSet = "UTF-8",
                              Width = 180,
                              Height = 90,
                              Margin = 1
                          };
                          writer.Options = options;
                          Bitmap zx = writer.Write($"{datas[i].WAREID ?? "0000"}");
                          //插入二维码
                          using (MemoryStream stream = new())
                          {
                              zx.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                              var zximg = wb.Drawings.AddPicture("zx", stream);
                              zximg.SetPosition(9, 0, 2, 0);
                          }
      
                          #endregion 条形码
      View Code
    2.  PDFtoZPL。国外大神搞得一个转换zpl命令的包。zpl挺难搞的,主要是不懂。只能借用别人写好的了,目前这个包是我认为最简单操作的了。不过只能从PDF转换

                      #region 转换为ZPL命令
                      //加载pdf路径,转换成Base64字符串
                      byte[] pdfBytes = File.ReadAllBytes(pdfPath);
                      string base64String = Convert.ToBase64String(pdfBytes);   
                      // 设置标签尺寸(单位:点,1英寸 = 203点)
                      int labelWidthDots = 5 * 203;  // 宽度为4.5英寸
                      int labelHeightDots = (int)(7.5 * 203);   // 高度为6英寸
                      var zplCode = PDFtoZPL.Conversion.ConvertPdf(base64String, width: labelWidthDots, height: labelHeightDots);
                      //保存zpl指令
                      string zpl = string.Empty;
                      foreach (var str in zplCode)
                      {
                          zpl += str;
                      }
      
                      #endregion
                      // 将字符串转换为 GBK 编码的字节数组
                      if (zpl.Length != 0) if (zpl.LastIndexOf('\n') != zpl.Length - 1) zpl += "\n";
                      byte[] byteData = System.Text.Encoding.GetEncoding("GBK").GetBytes(zpl);
      View Code
    3. FreeSpire.XLS。Spire的免费版,用于excel转换为pdf。网上说只能转换前十页PDF,不然还是有水印。当然网上也有一堆去除水印的方法,可惜我没实验成功。也幸好我一次性不需要转换很多,所以我选择了这个。
              /// <summary>
              /// Excel转换Pdf
              /// </summary>
              /// <param name="xlsPath">输入excel地址</param>
              /// <param name="pdfPath">输出pdf地址</param>
              public static string ToPDF(string xlsPath, string pdfPath = null)
              {
                  pdfPath ??= xlsPath.Replace("xlsx", "pdf");
                  //加载模板
                  Workbook wb = new();
                  wb.LoadFromFile(xlsPath);
                  //转换成PDF
                  Worksheet ws = wb.Worksheets[0];
                  ws.SaveToPdf(pdfPath);
                  return pdfPath;
              }
      View Code
  3. 核心就这么多了。上面三段代码组合起来就可以实现一个基本的打印功能了。因为写这个博客的时候使用的是芝柯打印机,使用的是ZPL命令。若是换成其他打印机,只要支持zpl命令,也是可以使用的。但是具体怎么方便,视情况而定。

 

与记一次打印机功能实现相似的内容:

记一次打印机功能实现

使用的是芝柯打印机,无驱动,除了文本打印外,若想打印其他表格或者模板,我的做法是利用excel填充数据,然后转换为pdf,pdf再转为zpl命令。 核心代码分为三部分: 加载打印模板,填充打印数据到模板并保存成新的打印文件 将需要打印的文件,转换为PDF格式。这一步主要是因为芝柯打印机是无驱动的,需

记一次栈溢出异常问题的排查

刚修改的服务,推到开发环境之后,总是时不时的崩溃,但是不知道为什么。尝试找到他的最后一次调用,也没有复现。 没有办法,只能抓dump了。 开启崩溃自动dump,网络上很多,不赘述了。 拿到dump之后,首先看看是什么类型的异常 如图所示,是个栈溢出的异常。 打印一下堆栈,发现密密麻麻的全是这个代码。

记一次字符串末尾空白丢失的排查 → MySQL 是会玩的!

开心一刻 今天答应准时回家和老婆一起吃晚饭,但临时有事加了会班,回家晚了点 回到家,本以为老婆会很生气,但老婆却立即从厨房端出了热着的饭菜 老婆:还没吃饭吧,去洗下,来吃饭吧 我洗好,坐下吃饭,内心感动十分;老婆坐旁边深情的看着我 老婆:你知道谁最爱你吗 我毫不犹豫道:你 老婆:谁最关心你? 我:你

记一次线上问题 → Deadlock 的分析与优化

开心一刻 今天女朋友很生气 女朋友:我发现你们男的,都挺单纯的 我:这话怎么说 女朋友:脑袋里就只想三件事,搞钱,跟谁喝点,还有这娘们真好看 我:你错了,其实我们男人吧,每天只合计一件事 女朋友:啥事呀? 我:这娘们真好看,得搞钱跟她喝点 问题复现 需求背景 MySQL8.0.30 ,隔离级别是默认

记一次 Redisson 线上问题 → ERR unknown command 'WAIT' 的排查与分析

开心一刻 昨晚和一个朋友聊天 我:处对象吗,咱俩试试? 朋友:我有对象 我:我不信,有对象不公开? 朋友:不好公开,我当的小三 问题背景 程序在生产环境稳定的跑着 直到有一天,公司执行组件漏洞扫描,有漏洞的 jar 要进行升级修复 然后我就按着扫描报告将有漏洞的 jar 修复到指定的版本 自己在开发

[转帖] 记一次使用gdb诊断gc问题全过程

记一次使用gdb诊断gc问题全过程 原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介# 上次解决了GC长耗时问题后,系统果然平稳了许多,这是之前的文章《GC耗时高,原因竟是服务流量小?》然而,过了一段时间,我检查GC日志时,又发现了一个GC问题,如下:从这个图中可

记一次nginx配置不当引发的499与failover 机制失效

背景 nginx 499在服务端推送流量高峰期长期以来都是存在的,间或还能达到告警阈值触发一小波告警,但主观上一直认为499是客户端主动断开,可能和推送高峰期的用户打开推送后很快杀死app有关,没有进一步探究问题根源。 然而近期在非高峰期也存在499超过告警阈值的偶发情况,多的时候一天几次,少的时候

记一次Native memory leak排查过程

路由计算服务是路由系统的核心服务,负责运单路由计划的计算以及实操与计划的匹配。在运维过程中,发现在长期不重启的情况下,有TP99缓慢爬坡的现象。此外,在每周例行调度的试算过程中,能明显看到内存的上涨。

记一次Redis Cluster Pipeline导致的死锁问题

本文介绍了一次排查Dubbo线程池耗尽问题的过程。通过查看Dubbo线程状态、分析Jedis连接池获取连接的源码、排查死锁条件等方面,最终确认是因为使用了cluster pipeline模式且没有设置超时时间导致死锁问题。

记一次 .NET某账本软件 非托管泄露分析

一:背景 1. 讲故事 中秋国庆长假结束,哈哈,在老家拍了很多的短视频,有兴趣的可以上B站观看:https://space.bilibili.com/409524162 ,今天继续给大家分享各种奇奇怪怪的.NET生产事故,希望能帮助大家在未来的编程之路上少踩坑。 话不多说,这篇看一个.NET程序集泄