接著上一篇:上一篇寫了安裝,這篇直接搞定批量列印,A4紙橫版豎版頁面設計,正式開始。(我的表達不怎麼好,我儘量發圖片都是程式員一點就通) 一、界面展示 忽略界面設計醜 查看預覽界面,因為有數據就不截全屏了,盒號是我自己加的,我們自己的業務邏輯。 三、核心代碼,批量列印(參考代碼鏈接,放到文章結尾處) ...
接著上一篇:上一篇寫了安裝,這篇直接搞定批量列印,A4紙橫版豎版頁面設計,正式開始。(我的表達不怎麼好,我儘量發圖片都是程式員一點就通)
一、界面展示
忽略界面設計醜
查看預覽界面,因為有數據就不截全屏了,盒號是我自己加的,我們自己的業務邏輯。
三、核心代碼,批量列印(參考代碼鏈接,放到文章結尾處)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class BillPrint : IDisposable 2 { 3 /// <summary> 4 /// 當前列印頁號 5 /// </summary> 6 static int m_currentPageIndex; 7 8 /// <summary> 9 /// RDCL轉換stream一頁對應一個stream 10 /// </summary> 11 static List<Stream> m_streams; 12 13 /// <summary> 14 /// 把report輸出成stream 15 /// </summary> 16 /// <param name="report">傳入需要Export的report</param> 17 private void Export(LocalReport report) 18 { 19 string deviceInfo = 20 "<DeviceInfo>" + 21 " <OutputFormat>EMF</OutputFormat>" + 22 //" <PageWidth>2in</PageWidth>" + 23 //" <PageHeight>20in</PageHeight>" + 24 //" <MarginTop>0in</MarginTop>" + 25 //" <MarginLeft>0in</MarginLeft>" + 26 //" <MarginRight>0in</MarginRight>" + 27 //" <MarginBottom>0in</MarginBottom>" + 28 "</DeviceInfo>"; 29 m_streams = new List<Stream>(); 30 report.Render("Image", deviceInfo, CreateStream, out Warning[] warnings); 31 foreach (Stream stream in m_streams) 32 stream.Position = 0; 33 } 34 35 /// <summary> 36 /// 創建具有指定的名稱和格式的流。 37 /// </summary> 38 private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek) 39 { 40 Stream stream = new FileStream(name + "." + fileNameExtension, 41 FileMode.Create); 42 m_streams.Add(stream); 43 return stream; 44 } 45 46 /// <summary> 47 /// 列印輸出 48 /// </summary> 49 private void PrintPage(object sender, PrintPageEventArgs ev) 50 { 51 Metafile pageImage = 52 new Metafile(m_streams[m_currentPageIndex]); 53 ev.Graphics.DrawImage(pageImage, ev.PageBounds); 54 m_currentPageIndex++; 55 ev.HasMorePages = (m_currentPageIndex < m_streams.Count); 56 } 57 /// <summary> 58 /// 設置橫版列印 59 /// </summary> 60 /// <param name="sender"></param> 61 /// <param name="e"></param> 62 void Document_QueryPageSettings(object sender, QueryPageSettingsEventArgs e) 63 { 64 e.PageSettings.Landscape = false; 65 int index = -1; 66 for (int i = 0; i < e.PageSettings.PrinterSettings.PaperSizes.Count; i++) 67 { 68 if (e.PageSettings.PrinterSettings.PaperSizes[i].PaperName == "A4") 69 { 70 index = i; 71 break; 72 } 73 } 74 if (index != -1) 75 { 76 e.PageSettings.PaperSize = e.PageSettings.PrinterSettings.PaperSizes[index]; 77 } 78 } 79 80 81 /// <summary> 82 /// 列印預處理 83 /// </summary> 84 private void Print(string printerName = null) 85 { 86 PrintDocument printDoc = new PrintDocument(); 87 if (string.IsNullOrEmpty(printerName)) 88 { 89 printerName = printDoc.PrinterSettings.PrinterName; 90 } 91 if (m_streams == null || m_streams.Count == 0) 92 return; 93 printDoc.PrinterSettings.PrinterName = printerName; 94 if (!printDoc.PrinterSettings.IsValid) 95 { 96 string msg = String.Format("Can't find printer \"{0}\".", printerName); 97 throw new Exception(msg); 98 } 99 printDoc.PrintPage += new PrintPageEventHandler(PrintPage); 100 101 //設置橫版列印 102 printDoc.QueryPageSettings += new QueryPageSettingsEventHandler(Document_QueryPageSettings); 103 104 StandardPrintController spc = new StandardPrintController(); 105 printDoc.PrintController = spc; 106 printDoc.Print(); 107 } 108 109 /// <summary> 110 /// 對外介面,啟動列印 111 /// </summary> 112 /// <param name="report"></param> 113 /// <param name="printerName">預設印表機</param> 114 public static void Run(LocalReport report, string printerName = null) 115 { 116 m_currentPageIndex = 0; 117 BillPrint billPrint = new BillPrint(); 118 billPrint.Export(report); 119 billPrint.Print(); 120 billPrint.Dispose(); 121 } 122 123 124 /// <summary> 125 /// 獲取印表機狀態 126 /// </summary> 127 /// <param name="printerName">印表機名稱</param> 128 /// <param name="status">輸出印表機狀態</param> 129 private static void GetPrinterStatus2(string printerName, ref uint status) 130 { 131 try 132 { 133 string lcPrinterName = printerName; 134 IntPtr liHandle = IntPtr.Zero; 135 if (!Win32.OpenPrinter(lcPrinterName, out liHandle, IntPtr.Zero)) 136 { 137 Console.WriteLine("print is close"); 138 return; 139 } 140 UInt32 level = 2; 141 IntPtr buffer = IntPtr.Zero; 142 Win32.GetPrinter(liHandle, level, buffer, 0, out uint sizeNeeded); 143 buffer = Marshal.AllocHGlobal((int)sizeNeeded); 144 if (!Win32.GetPrinter(liHandle, level, buffer, sizeNeeded, out sizeNeeded)) 145 { 146 Console.WriteLine(Environment.NewLine + "Fail GetPrinter:" + Marshal.GetLastWin32Error()); 147 return; 148 } 149 150 Win32.PRINTER_INFO_2 info = (Win32.PRINTER_INFO_2)Marshal.PtrToStructure(buffer, typeof(Win32.PRINTER_INFO_2)); 151 status = info.Status; 152 Marshal.FreeHGlobal(buffer); 153 Win32.ClosePrinter(liHandle); 154 } 155 catch (Exception ex) 156 { 157 throw ex; 158 } 159 } 160 161 /// <summary> 162 /// 對外介面,調去印表機信息 163 /// </summary> 164 /// <param name="printerName">印表機名稱</param> 165 /// <returns>返回印表機當前狀態</returns> 166 public static string GetPrinterStatus(string printerName) 167 { 168 uint intValue = 0; 169 PrintDocument pd = new PrintDocument(); 170 printerName = printerName == "" ? pd.PrinterSettings.PrinterName : printerName; 171 GetPrinterStatus2(printerName, ref intValue); 172 string strRet = string.Empty; 173 switch (intValue) 174 { 175 case 0: 176 strRet = "準備就緒(Ready)"; 177 break; 178 case 4194432: 179 strRet = "被打開(Lid Open)"; 180 break; 181 case 144: 182 strRet = "列印紙用完(Out of Paper)"; 183 break; 184 case 4194448: 185 strRet = "被打開並且列印紙用完(Out of Paper && Lid Open)"; 186 break; 187 case 1024: 188 strRet = "列印中(Printing)"; 189 break; 190 case 32768: 191 strRet = "初始化(Initializing)"; 192 break; 193 case 160: 194 strRet = "手工送紙(Manual Feed in Progress)"; 195 break; 196 case 4096: 197 strRet = "離線(Offline)"; 198 break; 199 default: 200 strRet = "未知狀態(unknown state)"; 201 break; 202 } 203 return strRet; 204 } 205 206 207 public void Dispose() 208 { 209 if (m_streams != null) 210 { 211 foreach (Stream stream in m_streams) 212 stream.Close(); 213 m_streams = null; 214 } 215 } 216 } 217 218 public class Win32 219 { 220 [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] 221 public static extern bool OpenPrinter(string printer, out IntPtr handle, IntPtr printerDefaults); 222 [DllImport("winspool.drv")] 223 public static extern bool ClosePrinter(IntPtr handle); 224 [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] 225 public static extern bool GetPrinter(IntPtr handle, UInt32 level, IntPtr buffer, UInt32 size, out UInt32 sizeNeeded); 226 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 227 public struct PRINTER_INFO_2 228 { 229 public string pServerName; 230 public string pPrinterName; 231 public string pShareName; 232 public string pPortName; 233 public string pDriverName; 234 public string pComment; 235 public string pLocation; 236 public IntPtr pDevMode; 237 public string pSepFile; 238 public string pPrintProcessor; 239 public string pDatatype; 240 public string pParameters; 241 public IntPtr pSecurityDescriptor; 242 public UInt32 Attributes; 243 public UInt32 Priority; 244 public UInt32 DefaultPriority; 245 public UInt32 StartTime; 246 public UInt32 UntilTime; 247 public UInt32 Status; 248 public UInt32 cJobs; 249 public UInt32 AveragePPM; 250 } 251 }View Code
代碼使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using (ReportViewer rvDoc = new ReportViewer()) 2 { 3 rvDoc.LocalReport.DataSources.Add(new ReportDataSource("DataSet1", 你的數據)); 4 //註意自己的路徑,這塊我寫到配置文件,來區分測試跟線上路徑。 5 if (PublicProperty.RdlcPath == "Debug") 6 { 7 rvDoc.LocalReport.ReportPath = @"..\..\ReportForm\GTTKWenShuArchives.rdlc"; 8 } 9 else 10 { 11 rvDoc.LocalReport.ReportPath = Application.StartupPath + "\\ReportForm\\GTTKWenShuArchives.rdlc"; 12 } 13 //開始列印,第二個參數是選擇印表機名稱 14 BillPrint.Run(rvDoc.LocalReport, (string)printerList.Invoke(new obj_delegate(() => { return printerList.SelectedItem.ToString(); }))); 15 } 16 }View Code
四、設計報表一些註意事項(可以用差之毫釐失之千里來形容)
- A4豎版列印,標頭設計寬
,長只能小於等於寬,要是大於就會出現空白頁情況。
- A4橫版列印,標頭設計寬
,長度跟豎版一樣,註意這個數字是我一點點試出來的,多一點就會出現表的列顯示不全,會跑到第二頁裡面,大家也可以自己試試。
- 要想每一頁都顯示標題,只能把標題加入到頁眉之中,註意
頁眉的底部一定要跟表重合否則到第二頁跟上邊距會跟第一頁不一樣,具體什麼樣自己試一下就知道了,
- 表要是想加實線,註意設計的時候
,這個大家一試便知。
- 要想每一頁都顯示表的標題部分可以這麼設計
-
剩下的內容的字體啊間距啊,就根據自己需求自己調吧,註意設計的時候儘量表要與兩邊重合,標題要與頂部重合,因為他預設是上下左右間距都是2CM,你要是有距離你列印出來就不好看了,這個自己試試就知道了。
五、結尾
把一些我參考的鏈接放出來,大家可以自行參考。
https://blog.csdn.net/nuptsv_ice/article/details/41821611
有個批量列印代碼鏈接找不到了,要是找到會補上去的。