倉儲物流的過程中往往少不了一些使用熱敏印表機或者碳帶印表機列印一些條碼、信息貼在實物或者包裹上 最好的實現方式不過於直接使用熱敏代碼形成文本直接輸出到印表機做列印 但是熱敏代碼也是一門需要特殊的語言,需要學習 故為了更快更方便的實現,就用到了畫布繪製後形成image輸出到印表機 而image也是有要 ...
倉儲物流的過程中往往少不了一些使用熱敏印表機或者碳帶印表機列印一些條碼、信息貼在實物或者包裹上
最好的實現方式不過於直接使用熱敏代碼形成文本直接輸出到印表機做列印
但是熱敏代碼也是一門需要特殊的語言,需要學習
故為了更快更方便的實現,就用到了畫布繪製後形成image輸出到印表機
而image也是有要求的,比如輸出的格式、大小直接影響列印的質量
這裡介紹下使用微軟的報表佈局綁定數據轉image輸出到印表機的方式
1、nuget上搜索Microsoft.ReportViewer.Common、Microsoft.ReportViewer.WebForms安裝
2、創建rdlc報表,繪製指定列印輸出的模板大小,對rdlc添加數據集,可以為對象,這裡使用對象綁定(後臺查詢數據映射給對象)
可以為界面每個項的屬性進行設置:字體、大小、數據綁定、對齊等,也可以動態使用表達式(數據源傳入指定值)
3、列印入口,為報表綁定數據
DeviceInfo的詳細說明見:
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); } });