不幹膠、熱敏列印

来源:https://www.cnblogs.com/zengwei/archive/2020/05/20/12923394.html
-Advertisement-
Play Games

倉儲物流的過程中往往少不了一些使用熱敏印表機或者碳帶印表機列印一些條碼、信息貼在實物或者包裹上 最好的實現方式不過於直接使用熱敏代碼形成文本直接輸出到印表機做列印 但是熱敏代碼也是一門需要特殊的語言,需要學習 故為了更快更方便的實現,就用到了畫布繪製後形成image輸出到印表機 而image也是有要 ...


倉儲物流的過程中往往少不了一些使用熱敏印表機或者碳帶印表機列印一些條碼、信息貼在實物或者包裹上

最好的實現方式不過於直接使用熱敏代碼形成文本直接輸出到印表機做列印

但是熱敏代碼也是一門需要特殊的語言,需要學習

故為了更快更方便的實現,就用到了畫布繪製後形成image輸出到印表機

而image也是有要求的,比如輸出的格式、大小直接影響列印的質量

這裡介紹下使用微軟的報表佈局綁定數據轉image輸出到印表機的方式

1、nuget上搜索Microsoft.ReportViewer.Common、Microsoft.ReportViewer.WebForms安裝

2、創建rdlc報表,繪製指定列印輸出的模板大小,對rdlc添加數據集,可以為對象,這裡使用對象綁定(後臺查詢數據映射給對象)

  可以為界面每個項的屬性進行設置:字體、大小、數據綁定、對齊等,也可以動態使用表達式(數據源傳入指定值)

 

 

3、列印入口,為報表綁定數據

  

 DeviceInfo的詳細說明見:

  https://docs.microsoft.com/zh-cn/sql/reporting-services/image-device-information-settings?redirectedfrom=MSDN&view=sql-server-ver15

  LocalReport.Render使用見

  https://docs.microsoft.com/zh-cn/previous-versions/dd468075(v=vs.140)

  註意:OutputFormat為EMF

      PageWidth、PageHeight為rdlc的大小

  如果需要使用到條碼信息,則需要聲明byte[] 接收使用BarcodeLib.Barcode相關條碼類生成條碼圖片

  rdlc模板上添加圖像控制項欄位指向byte[]欄位,mime選擇image/png,大小顯示為:調整為合適大小

  測試時可以保存為圖片,預覽效果圖

public string PrintOutPackage(string Consignee, string ContractCode,string ConsigneeAddress, int count, int cur, string printName, int type=1)
        {
            if (string.IsNullOrWhiteSpace(printName))
            {
                return "沒有選擇印表機";
            }

            using (LocalReport report = new LocalReport())
            {
                report.ReportPath = System.Windows.Forms.Application.StartupPath + "/Content/OutPackage.rdlc";
                report.DataSources.Clear();

                var printModel = new OutPackagePrintModel() { Consignee = Consignee, ContractCode = ContractCode, ConsigneeAddress = ConsigneeAddress, PackageCount = count, CurPackageCount = cur, ConsigneeFontSize = Consignee.Length <= 3 ? "28pt" : Consignee.Length <= 12 ? "16pt" : "12px" };

                var list = new List<OutPackagePrintModel>();
                list.Add(printModel);
                ReportDataSource ds = new ReportDataSource("OutPackage", list);//綁定數據源
                report.DataSources.Add(ds);
                report.Refresh();
                string deviceInfo =
                    "<DeviceInfo>" +
                    "  <OutputFormat>EMF</OutputFormat>" +
                     "  <PageWidth>8cm</PageWidth>" +
                     "  <PageHeight>5cm</PageHeight>" +
                      "<PrintDpiX>300</PrintDpiX>" +
                      "<PrintDpiY>300</PrintDpiY>" +
                     "  <MarginTop>0pt</MarginTop>" +
                    "  <MarginLeft>0pt</MarginLeft>" +
                    "  <MarginRight>0pt</MarginRight>" +
                    "  <MarginBottom>0pt</MarginBottom>" +
                    "</DeviceInfo>";
                Warning[] warnings;
                m_streams = new List<Stream>();
                //將報表的內容按照deviceInfo指定的格式輸出到CreateStream函數提供的Stream中。
                report.Render("Image", deviceInfo, CreateStream, out warnings);
            }

            foreach (Stream stream in m_streams)
            {
                stream.Position = 0;
            }

            Image pageImage = Image.FromStream(m_streams[0]);

            if (type == 2)
            {
                //測試時保存圖片
                pageImage.Save(@"d:\" + $"{cur}_{count}" + ".emf", ImageFormat.Tiff);
                return "已保存圖片";
            }

            //正式時調用印表機列印
            var r = Printer.PrintImageData(pageImage, printName, "0", "0");
            if (!r.IsSuccess)
                return r.Message;
            return "";
        }

        private Stream CreateStream(string name, string fileNameExtension,
          Encoding encoding, string mimeType, bool willSeek)
        {
            //如果需要將報表輸出的數據保存為文件,請使用FileStream對象。
            Stream stream = new MemoryStream();
            BillPrintSteam = stream;
            m_streams.Add(stream);
            return stream;
        }

 

4、生成的圖片輸出到印表機列印:

  將生成的image在印表機端

  可使用PrinterSettings.StringCollection listPrint = PrinterSettings.InstalledPrinters;獲取所有印表機名稱

public static PrintModel PrintImageData(Image pageImage,string PrinterName,string PaperSizeWidth,string PaperSizeHeight)
        {
            bool PrintIsSuccess=false;
            Exception PrintException=null;
            //聲明PrintDocument對象用於數據的列印
            PrintDocument printDoc = new PrintDocument();
            printDoc.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
            //指定需要使用的印表機的名稱,使用空字元串""來指定預設印表機
            //傳入印表機名稱 則使用傳入的,否則使用當前服務賬戶(登錄為)的預設印表機
            if (!string.IsNullOrWhiteSpace(PrinterName))
            {
                printDoc.PrinterSettings.PrinterName = PrinterName;
            }
            //判斷指定的印表機是否可用
            if (!printDoc.PrinterSettings.IsValid)
            {
                return PrintModel.CreateFailedResult("未能找到預設的印表機!");
            }

            if (!string.IsNullOrWhiteSpace(PaperSizeWidth) && PaperSizeWidth != "0" && !string.IsNullOrWhiteSpace(PaperSizeHeight) && PaperSizeHeight != "0")
            {
                var ps = new PaperSize("Your Paper Name", int.Parse(PaperSizeWidth), int.Parse(PaperSizeHeight)) { RawKind = 120 };//自定義紙張
                printDoc.DefaultPageSettings.PaperSize = ps;
            }
            printDoc.PrintPage += new PrintPageEventHandler(delegate (object sender, PrintPageEventArgs ev)
            {
                try
                {
                    ev.Graphics.PageUnit = GraphicsUnit.Document;
                    //ev.Graphics.CompositingQuality = CompositingQuality.HighQuality;
                    //ev.Graphics.PageScale = 1;
                    if (pageImage == null) return;
                    // Adjust rectangular area with printer margins.
                    Rectangle adjustedRect = new Rectangle(
                        ev.PageBounds.Left - (int)ev.PageSettings.HardMarginX,
                        ev.PageBounds.Top - (int)ev.PageSettings.HardMarginY,
                        ev.PageBounds.Width,
                        ev.PageBounds.Height);

                    Rectangle srcRect = new Rectangle(0, 0, pageImage.Width, pageImage.Height);
                    // Draw a white background for the report
                    //ev.Graphics.FillRectangle(Brushes.White, adjustedRect);
                    // Draw the report content
                    ev.Graphics.DrawImage(pageImage, srcRect);//, srcRect, GraphicsUnit.Pixel);
                    ev.HasMorePages = false;
                }
                catch (Exception ex)
                {
                    PrintException = ex;
                    PrintIsSuccess = false;
                }
            });

            try
            {
                if (pageImage == null)
                {
                    PrintIsSuccess = false;
                }
                else
                {
                    printDoc.Print();
                    PrintIsSuccess = true;
                }
            }
            catch (Exception ex)
            {
                PrintException = ex;
                PrintIsSuccess = false;
            }

            return PrintModel.Create(PrintIsSuccess, PrintIsSuccess ? "Print Success!" : "Print Fail!", PrintException);
        }
public static List<PrinterModel> GetPrinterList()
        {
            PrinterSettings ps = new PrinterSettings();
            PrinterSettings.StringCollection listPrint = PrinterSettings.InstalledPrinters;
            List<PrinterModel> pList = new List<PrinterModel>();
            for (int i = 0; i < listPrint.Count; i++)
            {
                PrinterModel pm = new PrinterModel();
                ps.PrinterName = listPrint[i];
                pm.PrinterName = ps.PrinterName;
                pm.IsDefaultPrinter = ps.IsDefaultPrinter;
                pm.OrderBy = pm.IsDefaultPrinter ? -1 : i;
                pList.Add(pm);
            }
            return pList.OrderBy(x => x.OrderBy).ToList();
        }

 

以上cs結構下不需要特殊許可權

如果為bs結構下或者需要ajax調取印表機的(電子稱重同理可借鑒):

1、可以將列印圖片的方法作為介面宿主到windowsservice上開放埠,安裝在需要列印的電腦上。

  接收的不是image改為圖片的url,得到url後進行download後輸出到印表機

  可以增加介面判斷列印服務是否可用

在app.config增加

<services>
      <service behaviorConfiguration="EnableMetadataBehaviors" name="Shangpin.Logistic.WindowsService.ClientPrintService.ServiceLibrary.PrintService">
        <endpoint address="" binding="webHttpBinding" behaviorConfiguration="WebScriptBehavior" bindingConfiguration="HttpJsonpBinding" contract="Shangpin.Logistic.WindowsService.ClientPrintService.ServiceLibrary.IPrintService" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:41943/PrintService" />
          </baseAddresses>
        </host>
      </service>

2、形成圖片的方法作為服務端介面可得到圖片,介面url可匿名給列印服務獲取圖片

在網頁的按鈕上實現ajax跨域請求:

$.ajax({
    url: "http://localhost:41943/PrintService/Print?jsoncallback=?",
    dataType: 'jsonp',
    data: { url: imageUrl, printerName: $("#PrinterList").find("option:selected").val(), paperSizeWidth: paperSizeWidth, paperSizeHeight: paperSizeHeight },
    success: function (data) {
        if (!data.IsSuccess) {
            LG.showError("明細編號" + printArr[i] + "列印失敗:" + data.Message, function () {
                JudgePrintAgain(printArr, i, url, paperSizeWidth, paperSizeHeight);//迴圈列印
            });
        } else {
            JudgePrintAgain(printArr, i, url, paperSizeWidth, paperSizeHeight);
        }
    },
    error: function (result) {
        LG.tip('發現系統錯誤 <br />錯誤碼:' + result.status);
    }
});

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一:背景 1. 講故事 昨天繼續還技術債,優化一輪後的程式拉到線上後記憶體繼續忽高忽低,低的時候20G,高的時候30G,過了一會又下降了幾個G,毫無疑問,程式中有什麼集合或者什麼操作占用了大量記憶體,所以準備在28,29G的時候抓dump分析分析。 二:解決思路 從快照中找問題就像看病一樣,根據病象推測 ...
  • 在ASP.NET MVC中,有使用angularjs,下麵這個小功能,就是對錶格裡的checkbox進行橫向選擇。 先看下麵演示: html: 以上的checkbox ng-click事件: ...
  • 一、簡介 FluentScheduler是一個簡單的任務調度框架,定時任務管理器。 GitHub地址:https://github.com/fluentscheduler/FluentScheduler 二、示常式序 2.1、界面 新建一個WinForm程式FluentSchedulerClient ...
  • 一、簡單介紹 Quartz.NET是一個強大、開源、輕量的作業調度框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改寫,可用於WinForm和ASP.NET應用中。它靈活而不複雜,可以為執行一個作業而創建簡單或複雜的作業調度。它有很多特征,如:資料庫支持、集群、插 ...
  • 0. 前言 今天是NHibernate的第二篇內容,通過上一篇的內容,我們初步瞭解了NHibernate的創建和使用。這一篇,我繼續探索NHibernate背後的秘密。嗯,就是這樣。 1. NHibernate結構 先給小伙伴們放個圖: 這是NHibernate的整體結構圖。NHibernate通過 ...
  • 隨著信息技術對人們工作生活的影響越來越大,人們對於應用程式的依賴性也越來越大,越來越多的人使用應用程式來解決自己工作和生活中的問題,這也導致應用程式的開發需求越來越高,傳統的應用程式開發方法已經沒有辦法滿足市場的需求,低代碼開發平臺在這樣的背景下誕生了。 力軟低代碼開發平臺可以減少開發成本,代碼、功 ...
  • C#手動建立Table後,並設置列和賦值 public DataTable CreateTable() { //創建Table1 DataTable dt = new DataTable(); //對Table1添加列名,並設置列值類型 DataTable dt1 = new DataTable() ...
  • C#中的關於Table的Merge() 簡介: Merge()方法可以實現對兩個table具有相同欄位的進行Morge,也可以實現對兩個table具有不同欄位的進行Merge。但是實現後的結果可能不太一樣。 一、對兩個table具有相同的欄位進行Merge的時候,所得到Merge後的table行數小 ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...