接着上一篇:上一篇寫了安裝,這篇直接搞定批量列印,A4紙橫版豎版頁面設計,正式開始。(我的表達不怎麼好,我盡量發圖檔都是程式員一點就通)
一、界面展示
忽略界面設計醜

檢視預覽界面,因為有資料就不截全屏了,盒号是我自己加的,我們自己的業務邏輯。
三、核心代碼,批量列印(參考代碼連結,放到文章結尾處)
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
代碼使用
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 }
四、設計報表一些注意事項(可以用差之毫厘失之千裡來形容)
- A4豎版列印,标頭設計寬 ,長隻能小于等于寬,要是大于就會出現空白頁情況。
vs2017使用rdlc實作批量列印 - A4橫版列印,标頭設計寬 ,長度跟豎版一樣,注意這個數字是我一點點試出來的,多一點就會出現表的列顯示不全,會跑到第二頁裡面,大家也可以自己試試。
vs2017使用rdlc實作批量列印 - 要想每一頁都顯示标題,隻能把标題加入到頁眉之中,注意 頁眉的底部一定要跟表重合否則到第二頁跟上邊距會跟第一頁不一樣,具體什麼樣自己試一下就知道了,
vs2017使用rdlc實作批量列印 - 表要是想加實線,注意設計的時候 ,這個大家一試便知。
vs2017使用rdlc實作批量列印 - 要想每一頁都顯示表的标題部分可以這麼設計
vs2017使用rdlc實作批量列印 - 剩下的内容的字型啊間距啊,就根據自己需求自己調吧,注意設計的時候盡量表要與兩邊重合,标題要與頂部重合,因為他預設是上下左右間距都是2CM,你要是有距離你列印出來就不好看了,這個自己試試就知道了。
五、結尾
把一些我參考的連結放出來,大家可以自行參考。
https://blog.csdn.net/nuptsv_ice/article/details/41821611
有個批量列印代碼連結找不到了,要是找到會補上去的。