ZPL打印中文信息

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS Agent(兼容OpenClaw),2核4GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介: 博客来源:http://www.cnblogs.com/Geton/p/3595312.html 相信各位在实际的项目中,需要开发打条码模块的也会有不少,很多同行肯定也一直觉得斑马打印机很不错,但是ZPL打印中文字符很麻烦。

博客来源:http://www.cnblogs.com/Geton/p/3595312.html

相信各位在实际的项目中,需要开发打条码模块的也会有不少,很多同行肯定也一直觉得斑马打印机很不错,但是ZPL打印中文字符很麻烦。如果购买字体卡,或者通过CODESOFT,BARTENDER,LABELVIEW等有控件的条码软件打印,成本较高,老板也不容易接受,而自己开发的程序则灵活性更好,方便适应公司的发展需要。下面把自己在实际的运用中写的关于打印中文信息的代码与大家一起分享,如果有写得不好的地方,请各位指出。以下代码是在C#环境中测试通过。先用文本排版好格式(zpl文件),然后通过填充数据打印所需要的内容。

 

// 首先是引用fnthex32.dll,它是用于斑马条码打印机打印汉子所需的dll文件

        #region 调用fnthex32.dll,用于转换中文字符
        //GETFONTHEX可以将中文字体转换为HEX字体
        //由于ZEBRA打印机本身不能打印中文,因此需要将中文进行转换,传给打印机
        [DllImport("fnthex32.dll")]
        public static extern int GETFONTHEX(
        string BarcodeText,
        string FontName,
        string FileName,
        int Orient,
        int Height,
        int Width,
        int IsBold,
        int IsItalic,
        StringBuilder ReturnBarcodeCMD);
        #endregion

 

// 读取zpl文件内容到数组 

      /******************************************************************
         ***  功能   打开文件,并读出内容,保存到数组
         ***  说明   参数sFileName文件名称
         ***  将文件内容赋给数组返回(通过)
         ******************************************************************/
        private string[] getPrintStringArray(string sFileName)
        {
            ArrayList printStringArray = new ArrayList();
            int i = 0;

            FileStream fileStream = File.OpenRead(sFileName);
            try
            {
                StreamReader reader = new StreamReader(fileStream, System.Text.Encoding.Default);
                reader.BaseStream.Seek(0, SeekOrigin.Begin);

                string strLine = reader.ReadLine();
                while (strLine != null)
                {
                    //string[] split = strLine.Split('\n');
                    //printStringArray[i] = strLine;
                    printStringArray.Add(strLine);
                    i++;
                    strLine = reader.ReadLine();

                }
                reader.Close();
                reader.Dispose();
                fileStream.Close();
                fileStream.Dispose();
                string[] values = (string[])printStringArray.ToArray(typeof(string));
                return values;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return (string[])printStringArray.ToArray(typeof(string));
            }
        }

 

     /******************************************************************
         ***  功能   检查fieldStr的内容是否包含中文
         ***  说明   fieldStr要检查的字符串数组
         ******************************************************************/
        private bool ChkChinese(string fieldStr)
        {
            int nLen, nTmp;
            string sCharTmp;
            nLen = fieldStr.Length;
            for (nTmp = 0; nTmp < nLen; nTmp++)
            {
                sCharTmp = fieldStr.Substring(nTmp, 1);
                if (Convert.ToChar(sCharTmp) > 127 || Convert.ToChar(sCharTmp) < 0)
                {
                    return true;
                }
            }
            return false;
        }

 

// 在ZPL文件中,把带_FIELD结尾的内容,以相应的数据源的字段内容去替换掉。

   /******************************************************************
         ***   功能      用DataTable中栏位的值去替换相应字段
         ***   说明      ZPLText为打印标帖的文本内容rds为数据源
         ***   将ZPLText中形如WONUM_FIELD的用rds对应的WONUM的值代替,然后还返回数组
         ******************************************************************/

        private string[] convertZPLTextFields(string[] ZPLText, DataTable rds, int currow)
        {
            string sTemp = "";
            string sTemp1 = "";
            string sTemp2 = "";
            string FieldName = "";
            int s1, s2, i, j;
            int zNum, fNum;
            string fieldStr = "";

            zNum = ZPLText.Length - 1; //数组长度

            fNum = rds.Columns.Count;  //rds列数

            for (i = 0; i <= zNum; i++)
            {
                for (j = 0; j <= fNum - 1; j++)
                {

                    FieldName = rds.Columns[j].ColumnName;
                    sTemp = FieldName + "_FIELD";
                    s1 = ZPLText[i].IndexOf(sTemp); //查找fieldName在ZPLText[i]中的索引值(位置)
                    if (s1 != -1)
                    {
                        s2 = s1 + sTemp.Length;
                        sTemp1 = ZPLText[i].Substring(0, s1);// 替换前半段
                        sTemp2 = ZPLText[i].Substring(s2, ZPLText[i].Length - s2);//替换后半段
                        //if (rds.Columns[j].GetType().ToString() == "System.String")
                        if (rds.Columns[j].DataType.Name == "String")
                        {
                            fieldStr = rds.Rows[currow][j].ToString();
                            if (ChkChinese(fieldStr))  //检查是否存在中文,如果存在则做转换
                            {
                                convertChineseToHex(fieldStr, "fchfnt" + i, 2);
                                ZPLText[i] = sTemp1 + "^XGfchfnt" + i + sTemp2; //^XG  调取图像,这里是先转中文字体为fchfnt,然后用^XG调取它
                            }
                            else
                            {
                                ZPLText[i] = sTemp1 + fieldStr + sTemp2;

                            }
                        }
                        else
                        {
                               ZPLText[i] = sTemp1 + rds.Rows[currow][j].ToString() + sTemp2;
                        }
                    }
                }
            }

            return ZPLText;
        }

 //将文件内容中的标记为中文的内容取出,进行字体转换,然后用相应的字体名替换
        private string[] convertZPLTextChinese(string[] ZPLText)
        {
            int zNum, s1, s2, i;
            string sTemp = "", sTemp1 = "";
            string[] chStrArr = null;
            string compStr, fntName, chStr;
            double nRate = 0;
            chStr = "";
            compStr = "^XGCH(";
            fntName = "chfnt";
            zNum = ZPLText.Length - 1;
            for (i = 0; i <= zNum; i++)
            {
                s1 = ZPLText[i].IndexOf(compStr);//^XGCH( 前面的字符
                if (s1 != -1)
                {
                    s2 = ZPLText[i].IndexOf(")", s1, ZPLText[i].Length - s1);//跟在^XGCH( 后面的另一半括号 )的位置
                    if (s2 != -1)
                    {
                        nRate = 3;
                        chStrArr = ZPLText[i].Substring(s1 + 6, s2 - s1 - 6).Split(';');//这里的+6就是^XGCH(  字符串的长度
                        if (chStrArr.Length - 1 == 0)
                        {
                            chStr = chStrArr[0];
                        }
                        else
                        {
                            if (IsNumeric(chStrArr[0]))
                            {
                                nRate = Convert.ToDouble(chStrArr[0]);
                                chStr = chStrArr[1];
                            }
                            //else
                            //{
                            //    chStr = chStrArr[1];
                            //}
                        }
                        sTemp = ZPLText[i].Substring(0, s1 + 3);
                        sTemp1 = ZPLText[i].Substring(s2 + 1, ZPLText[i].Length - s2 - 1);
                        convertChineseToHex(chStr, fntName + i, nRate);
                        ZPLText[i] = sTemp + fntName + i + sTemp1;
                    }
                }
            }
            return ZPLText;
        }

        //将中文转换成HEX字体送往PRINTER
        //chStr为中文内容
        //chFntName 为转换后的字体名称

        private void convertChineseToHex(string chStr, string chFntName, double nRate)
        {
            //int MAX_BUFFER, nCount;
            int nCount;
            StringBuilder cBuf = new StringBuilder(21000);
            nCount = GETFONTHEX(chStr, "宋体", chFntName, 0, Convert.ToInt32(10 * nRate), 0, 1, 0);
            
            string temp = " " + cBuf.ToString();
            temp = temp.Substring(0, nCount);
            PrintString = GetPrintSW(temp);
            
        }

 

        /******************************************************************
         ***  功能  打印标帖程序
         ***  说明  labelFileName 标帖格式文件名称
         ***        dataSource数据源,可为datatable
         ***        bTotalLabel 为TRUE表示要打印汇总标帖
        ******************************************************************/
        public void execPrintDefineLabel(string labelFileName, DataTable dataSource, bool bTotalLabel)
        {
            int i;
            string sqlStr = String.Empty;
            string[] ZPLText = null;
            string[] tempArr;
            //bool execConvertCHinese;
            int lNum;
            DataTable currrds = null;
            int labelNum;
          //  double sumqty;
           // int placeSp;
            int j = 0;
           // LoadLogo("d:\\Logo.zpl");
           

            //检测文件是否存在
            try
            {
                if (labelFileName == "" || !File.Exists(labelFileName))
                {
                    MessageBox.Show("标帖格式文件" + labelFileName + "不存在", "提示", MessageBoxButtons.OK);
                    return;
                }

                if (dataSource.Rows.Count == 0)
                {
                    MessageBox.Show("无数据打印", "提示", MessageBoxButtons.OK);
                    return;
                }

                //取出打印内容
                ZPLText = getPrintStringArray(labelFileName);

                currrds = dataSource;
                lNum = ZPLText.Length - 1;
                tempArr = new string[lNum];
                ZPLText = convertZPLTextChinese(ZPLText);
                tempArr = ZPLText;
                //sumqty = 0;
                do
                {
                    ZPLText = convertZPLTextFields(ZPLText, currrds, j);
                    //if (bTotalLabel)
                    //{
                    //    sumqty = sumqty + Convert.ToDouble(currrds.Columns["QTY"].ToString());
                    //}
                    //Printer printer = new Printer();
                    for (i = 0; i <= lNum; i++)
                    {
                        // printer.Write(" " + ZPLText[i]);
                        PrintString = GetPrintSW(" " + ZPLText[i]);
                    }
                    ZPLText = tempArr;             
                    j++;
                } while (j < currrds.Rows.Count);

                labelNum = currrds.Rows.Count;
                //string text = "";
                //for (int a = 0; a <= ZPLText.Length - 1; a++)
                //{
                //    text = text + ZPLText[a].ToString() + "\n";
                //}
                //MessageBox.Show(text, "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);


                //if (bTotalLabel)
                //{
                //    sumqty = Math.Round(sumqty, 10);
                //    lNum = currrds.Fields.Count;
                //    printer.Write("^XA");
                //    placeSp = 0;
                //    currrds.MoveFirst();
                //    for (i = 0; i <= lNum - 1; i++)
                //    {
                //        if (currrds.Fields[i].Attributes != 0 && currrds.Fields[i].Attributes == (int)ADODB.FieldAttributeEnum.adFldKeyColumn)
                //        {
                //            placeSp = placeSp + 50;
                //            printer.Write("^AFN^FO50," + placeSp.ToString() + "^FD" + currrds.Fields[i].Name + ": " + currrds.Fields[i].Value + "^FS");
                //        }
                //    }
                //    printer.Write("^AFN^FO50," + Convert.ToString(placeSp + 50) + "^FDSUM QTY: " + sumqty.ToString() + "^FS");
                //    printer.Write("^AFN^FO50," + Convert.ToString(placeSp + 100) + "^FDLABEL NUMBER: " + labelNum.ToString() + "^FS");
                //    printer.Write("^XZ");
                //}
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }

        }

 

        //判断是否为数字
        public bool IsNumeric(string text)
        {
            try
            {
                double num = Convert.ToDouble(text);
                return true;
            }
            catch
            {
                return false;
            }
        }
//  加载公司LOGO图像
        public void LoadLogo(string sFileName)
        {
            string logoText = "";

            FileStream fileStream = File.OpenRead(sFileName);
            try
            {
                StreamReader reader = new StreamReader(fileStream, System.Text.Encoding.Default);
                reader.BaseStream.Seek(0, SeekOrigin.Begin);

                string strLine = reader.ReadLine();
                while (strLine != null)
                {
                    logoText = logoText + strLine +"\n";
                    strLine = reader.ReadLine();

                }
                reader.Close();
                reader.Dispose();
                fileStream.Close();
                fileStream.Dispose();
                PrintString = GetPrintSW(logoText);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
               
            }


        }

        ///GetPrintSw方法用来构造打印文本,内部StringBuilder.AppendLine在Drawstring时单独占有一行。现改为string来构造,用换行符做为分格sting数组的条件。
        public string GetPrintSW(string strPrint)
        {
            PrintString = PrintString + strPrint + "\r\n";
            return PrintString;

        }

        public string PrintString = string.Empty;
        public string PrintName = string.Empty;
        private int countNum = 0;
        private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
        {
           
           Graphics graphic = e.Graphics;//获取绘图对象
           float linesPerPage = 0;//页面行号
           float yPosition = 0;//绘制字符串的纵向位置
           float leftMargin = e.MarginBounds.Left;//左边距
           float topMargin = e.MarginBounds.Top;//上边距
           string[] split = PrintString.Split('\n');
           string line = string.Empty;//读取的行字符串
           int currentPageLine = 0;//当前页读取的行数
           Font charFont = new Font("宋体", 9, FontStyle.Regular);//设置打印字体
           SolidBrush brush = new SolidBrush(Color.Black);//刷子
          // Point po = new Point(10, 10);

           linesPerPage = e.MarginBounds.Height / charFont.GetHeight(graphic);//每页可打印的行数

            //countNum记录全局行数,currentPageLine记录当前打印页行数。
           while (countNum <  split.Length )
            {
                if (currentPageLine < linesPerPage)
                {
                    line = split[countNum].ToString();
                    if (line.Length <= 100)
                    {
                        yPosition = topMargin + (currentPageLine * charFont.GetHeight(graphic));
                        //绘制当前行
                       graphic.DrawString(line, charFont, brush, leftMargin, yPosition, new StringFormat());
                        //graphic.DrawString(line, charFont, brush, new StringFormat());
                        countNum++;
                        currentPageLine++;
                    }
                    else
                    {
                        //拆分后的行数  这里插分多行。
                        int moreLine = line.Length / 100 + 1;
                        string tempLine;
                        for (int i = 0; i < moreLine; i++)
                        {
                            //获得当前行的子串
                            if ((line.Length - i * 100) >= 100)
                            {
                                tempLine = line.Substring(i * 100, 100);
                            }
                            else
                            {
                                tempLine = line.Substring(i * 100, line.Length - i * 100);
                            }
                            yPosition = topMargin + (currentPageLine * charFont.GetHeight(graphic));
                            //绘制当前行
                            graphic.DrawString(tempLine, charFont, brush, leftMargin, yPosition, new StringFormat());
                           // graphic.DrawString(line, charFont, brush, new StringFormat());

                            //当前打印页行数加1
                            currentPageLine++;
                        }
                        //总行数加1
                        countNum++;
                    }
                }
                else
                {
                    line = null;
                    break;
                }
            }
            //一页显示不完时自动重新调用此方法
            if (line == null)
            {
                e.HasMorePages = true;
            }
            else
            {
                e.HasMorePages = false;
            }
            //每次打印完后countNum清0;
            if (countNum >= split.Length)//(countNum >= richTextBox1.Lines.Length)
            {
                countNum = 0;
            }

        }

 

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
Java 测试技术 API
Java RESTful中的PATCH请求:局部更新与资源修改
在RESTful架构中,PATCH请求是一种用于局部更新已有资源的操作。PATCH请求允许客户端将部分数据发送到服务器,以便对资源进行局部修改,而不必替换整个资源。本文将引导您深入了解Java中使用PATCH请求构建RESTful API,探讨其特点、实现方式、用例以及在实际应用中的优势。
|
编解码 安全 Android开发
低功耗蓝牙LE Audio Profile 详细介绍
2019年底,蓝牙官方组织SIG发布了蓝牙5.2版本的核心协议,其中增加了一个重要的特性---LE Audio。蓝牙的应用协议都是从应用层到物理层完整包含的协议,LE Audio也不例外。但蓝牙5.2核心协议仅仅定义了蓝牙LE的链路层传输Audio的方式,上层协议以及完整的LE Audio规范迟迟未出,近日,蓝牙官方组织释放了LE Audio较为完整的规范文档。
低功耗蓝牙LE Audio Profile 详细介绍
|
6月前
|
存储 文字识别 数据可视化
实用代码工具:Python打造PDF选区OCR / 截图批量处理工具(支持手动/全自动模式)
一款基于Python的PDF区域OCR与截图工具,支持精准框选、文字识别、图片截取及Excel一键导出。内置手动审核与全自动批量处理模式,结合PyMuPDF、easyocr等技术,实现高效、可视化的PDF数据提取,适用于发票、报表等场景,显著提升办公效率。
923 11
|
Oracle Cloud Native 关系型数据库
Oracle Linux 10 - Oracle 提供支持 RHEL 兼容发行版
Oracle Linux 10 - Oracle 提供支持 RHEL 兼容发行版
493 11
Oracle Linux 10 - Oracle 提供支持 RHEL 兼容发行版
|
人工智能 自然语言处理 运维
Qwen3 全尺寸模型支持通过阿里云PAI-ModelGallery 一键部署
Qwen3 是 Qwen 系列最新一代的大语言模型,提供了一系列密集(Dense)和混合专家(MOE)模型。目前,PAI 已经支持 Qwen3 全系列模型一键部署,用户可以通过 PAI-Model Gallery 快速开箱!
|
缓存 安全 网络协议
使用事件日志识别常见 Windows 错误
事件查看器是Windows操作系统中的标准诊断工具,用于记录系统事件,包括硬件问题、软件中断和系统行为等详细信息。通过分析这些日志,管理员能够追踪和解决系统错误。访问方法包括使用快捷键Win + R输入eventvwr.msc,或通过控制面板进入。事件查看器中的每条记录包含事件ID、来源和描述,帮助识别和解决问题。常见错误如蓝屏死机、DLL错误、驱动程序错误等,可通过更新驱动程序、运行系统诊断、使用恢复功能等方式解决。
1551 4
|
前端开发 JavaScript
HTML+CSS如何打造撒花动画效果?3分钟学会,炫酷到爆!
HTML+CSS如何打造撒花动画效果?3分钟学会,炫酷到爆!
|
开发框架 前端开发 JavaScript
基于Admin.NET框架的前端的一些改进和代码生成处理(2)
基于Admin.NET框架的前端的一些改进和代码生成处理(2)
|
JSON 前端开发 JavaScript
革新Admin.NET框架:前端体验飞跃与代码生成自动化的双重革命,引领高效开发新时代!
【8月更文挑战第3天】Admin.NET是一款专为现代企业应用打造的高效框架,凭借强大的后台管理和灵活的扩展性深受开发者喜爱。本文探讨如何优化其前端体验与开发效率。首先,通过采用Flexbox和CSS Grid等技术实现响应式布局重构,确保了不同设备上的一致体验。其次,引入Vue.js或React实现组件化开发,提高代码复用性和维护性。再者,利用Webpack等工具进行性能优化,提升页面加载速度。此外,开发了代码生成器以自动生成CRUD模块,极大提高了开发效率。这些改进使Admin.NET前端开发更高效、灵活且易于维护。
728 0