用代碼實現標簽打印的三種方式


最近項目中要實現標簽打印的功能,有幾個條件

  • 標簽模板可以事先生成,用的是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;
        }

    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM