用代码实现标签打印的三种方式

最近项目中要实现标签打印的功能,有几个条件

  • 标签模板可以事先生成,用的是CodeSoft软件
  • 标签模板里面有二维码
  • 标签模板里面有一些变量,要求打印的时候自动填充
  • 产线电脑上没有安装CodeSoft,即便安装也不能使用,因为没有License

从开始计划做标签打印开始,做了三套解决方案,难度和依赖条件各不相同

  1. 利用Excel
  2. CodeSoft API
  3. ZPL+Win32 API
  • 利用Excel

这是一个半自动化的方案,主要想法是在Excel里面做好模板,变量的部分通过编写VBA脚本,读取SQL Server数据库里面的内容进行填充,填充好了之后,手动打印。缺点是没有办法生成二维码。 --- Pass

代码

Public Sub SynTableConfig()
Dim cnn As New ADODB.Connection, sh As Worksheet
Dim rs As New ADODB.Recordset
Dim cnnStr As String, SQL As String
   
'建立与SQL Server数据库服务器的连接
cnnStr = "Provider=SQLOLEDB;Initial Catalog=" & myDataBase & ";User ID=" & myname & ";Password=" & mypassword & ";Data Source=" & serverip
cnn.ConnectionString = cnnStr
cnn.Open
SQL = "select  * from sys_table where id='123' order by 表名称"
Set rs = cnn.Execute(SQL)
While Not rs.EOF
.............
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
cnn.Close
Set cnn = Nothing
End Sub
  • CodeSoft API

CodeSoft企业版提供了ActiveX控件,可以在C#中添加对Lppx2.tlb的引用,调用相关API对CodeSoft编辑好的Label文件进行变量替换等操作,然后打印。编程难度不大,但是有个致命限制,要安装CodeSoft软件并插入usbkey。公司虽然买了license,但是仅限于工程师编辑Label模板文件,产线电脑上没有安装软件,更不可能插入usbkey,因为很贵。--- Pass

代码如下

class CodeSoft
    {

        string _printerName = "";
        

        public CodeSoft(string printerName)
        {

            _printerName = printerName;

        }

        public void Print(string labelFileName, Dictionary<string,string> parameters)
        {

            LabelManager2.Application labApp = null;

            LabelManager2.Document doc = null;

            string labFileName = System.Windows.Forms.Application.StartupPath + @"" + labelFileName;

            try
            {

                if (!File.Exists(labFileName))
                {
                    throw new FileNotFoundException("File not exsit", labFileName);
                }

                labApp = new LabelManager2.Application();

                labApp.Documents.Open(labFileName, false);

                doc = labApp.ActiveDocument;

                doc.Printer.SwitchTo(_printerName);

                string printerName = labApp.ActivePrinterName;

                foreach (string parameterName in parameters.Keys)
                {

                    doc.Variables.FormVariables.Item(parameterName).Value = parameters[parameterName];

                }

                doc.PrintDocument(1);

            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                labApp.Documents.CloseAll(true);
                //doc.Quit();
                doc = null;
                doc = null;
                GC.Collect(0);
            }

        }

    }
  • ZPL+Win32 API

ZPL是Zebra公司的标签标记语言,描述了标签上有哪些内容,何种字体,何种颜色等等。大部分标签打印机应该都支持,最起码我们的430t是可以支持的。具体打印的思路是利用CodeSoft软件,生成一个PRN文件(具体怎么生成不知道)。PRN文件里面的内容就是用ZPL描述的标签。我用程序读入这个PRN文件,将里面的变量替换掉,生成一个新文件,然后调用系统Native的打印功能,进行打印。

代码如下

class PrinterHelper
    {

        // Structure and API declarions:
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public class DOCINFOA
        {
            [MarshalAs(UnmanagedType.LPStr)]
            public string pDocName;
            [MarshalAs(UnmanagedType.LPStr)]
            public string pOutputFile;
            [MarshalAs(UnmanagedType.LPStr)]
            public string pDataType;
        }
        [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

        [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool ClosePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

        [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndDocPrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartPagePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndPagePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

        // SendBytesToPrinter()
        // When the function is given a printer name and an unmanaged array
        // of bytes, the function sends those bytes to the print queue.
        // Returns true on success, false on failure.
        public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
        {
            Int32 dwError = 0, dwWritten = 0;
            IntPtr hPrinter = new IntPtr(0);
            DOCINFOA di = new DOCINFOA();
            bool bSuccess = false; // Assume failure unless you specifically succeed.

            di.pDocName = "My C#.NET RAW Document";
            di.pDataType = "RAW";

            // Open the printer.
            if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
            {
                // Start a document.
                if (StartDocPrinter(hPrinter, 1, di))
                {
                    // Start a page.
                    if (StartPagePrinter(hPrinter))
                    {
                        // Write your bytes.
                        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                        EndPagePrinter(hPrinter);
                    }
                    EndDocPrinter(hPrinter);
                }
                ClosePrinter(hPrinter);
            }
            // If you did not succeed, GetLastError may give more information
            // about why not.
            if (bSuccess == false)
            {
                dwError = Marshal.GetLastWin32Error();
            }
            return bSuccess;
        }


        public static bool SendFileToPrinter(string szPrinterName, string szFileName, Dictionary<string, string> parameters)
        {


            string fileName = AssignValueToVariables(szFileName, parameters);

            return SendFileToPrinter(szPrinterName, fileName);

        }
        public static bool SendFileToPrinter(string szPrinterName, string szFileName)
        {
            // Open the file.
            FileStream fs = new FileStream(szFileName, FileMode.Open);
            // Create a BinaryReader on the file.
            BinaryReader br = new BinaryReader(fs);
            // Dim an array of bytes big enough to hold the file's contents.
            Byte[] bytes = new Byte[fs.Length];
            bool bSuccess = false;
            // Your unmanaged pointer.
            IntPtr pUnmanagedBytes = new IntPtr(0);
            int nLength;

            nLength = Convert.ToInt32(fs.Length);
            // Read the contents of the file into the array.
            bytes = br.ReadBytes(nLength);
            // Allocate some unmanaged memory for those bytes.
            pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
            // Copy the managed byte array into the unmanaged array.
            Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
            // Send the unmanaged bytes to the printer.
            bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
            // Free the unmanaged memory that you allocated earlier.
            Marshal.FreeCoTaskMem(pUnmanagedBytes);
            return bSuccess;
        }

        private static string AssignValueToVariables(string szFileName, Dictionary<string, string> parameters)
        {

            StreamReader sr = new StreamReader(szFileName, Encoding.Default);

            string line;

            StringBuilder sb = new StringBuilder();

            while ((line = sr.ReadLine()) != null)
            {

                sb.AppendLine(line);

            }

            string newContent = UpdateVariable(sb.ToString(), parameters);

            return WriteToFile(szFileName, newContent);

        }

        private static string WriteToFile(string szFileName, string newContent)
        {

            string fullFileName = szFileName + ".new.PRN";

            if (File.Exists(fullFileName))
            {

                File.Delete(fullFileName);

            }

            using (FileStream fs = new FileStream(fullFileName, FileMode.Create))
            {

                using (StreamWriter sw = new StreamWriter(fs))
                {

                    sw.Write(newContent);

                    sw.Flush();
                }

            }

            return fullFileName;

        }

        private static string UpdateVariable(string content, Dictionary<string, string> parameters)
        {

            string newContent = content;

            foreach (string parameterName in parameters.Keys)
            {

                string parameterValue = parameters[parameterName];

                newContent = newContent.Replace(string.Format("_tag${0}$tag_", parameterName), parameterValue);

            }

            return newContent;

        }

        public static bool SendStringToPrinter(string szPrinterName, string szString)
        {
            IntPtr pBytes;
            Int32 dwCount;
            // How many characters are in the string?
            dwCount = szString.Length;
            // Assume that the printer is expecting ANSI text, and then convert
            // the string to ANSI text.
            pBytes = Marshal.StringToCoTaskMemAnsi(szString);
            // Send the converted ANSI string to the printer.
            SendBytesToPrinter(szPrinterName, pBytes, dwCount);
            Marshal.FreeCoTaskMem(pBytes);
            return true;
        }

    }
原文地址:https://www.cnblogs.com/QiuTianBaBa/p/6730829.html