Visual Studio內建的報表檔案(rdlc,後面提到的報表,都指rdlc報表檔案)雖然功能相對不是十分強大,但應付一般的報表要求也是綽綽有餘了。關於rdlc報表的使用和設計方法,這裡就不做講解了,本文主要介紹一下如何不使用報表預覽處理常式(ReportViewer),直接將報表的內容在印表機上列印出來。
一般情況下,我們設計好報表後,在程式啟動並執行時候,會將其載入到ReprotViewer控制項中進行預覽並列印,但有些情況下,我們不想預覽報表的內容,而直接將其在印表機上列印出來,又該怎麼做呢?要想實現直接列印的功能,我們需要用到.Net提供的2個對象,LocalReport和PrintDocument。LocalReport對象負責載入一個報表檔案產生實際的報表並將報表按照知道的格式輸出,PrintDocument對象負責將LocalReport的輸出內容發送到印表機列印。具體的實現步驟如下:
Step 1: 聲明一個LocalReport對象並載入一個報表檔案(假定我們已經設計好一個報表檔案,名稱為PrintMe.rdlc)。
1: LocalReport report = new LocalReport();
2: //設定需要列印的報表的檔案名稱。
3: report.ReportPath = @"c:\PrintMe.rdlc";
4: //建立要列印的資料來源
5: ReportDataSource source = new ReportDataSource(SourceTalbe.TableName, SourceTalbe);
6: report.DataSources.Add(source);
7: //重新整理報表中的需要呈現的資料
8: report.Refresh();
Step 2: 將報表的內容輸出為指定格式的資料流。
1: string deviceInfo =
2: "<DeviceInfo>" +
3: " <OutputFormat>EMF</OutputFormat>" +
4: " <PageWidth>8.5in</PageWidth>" +
5: " <PageHeight>11in</PageHeight>" +
6: " <MarginTop>0.25in</MarginTop>" +
7: " <MarginLeft>0.25in</MarginLeft>" +
8: " <MarginRight>0.25in</MarginRight>" +
9: " <MarginBottom>0.25in</MarginBottom>" +
10: "</DeviceInfo>";
11: Warning[] warnings;
12: //將報表的內容按照deviceInfo指定的格式輸出到CreateStream函數提供的Stream中。
13: report.Render("Image", deviceInfo, CreateStream, out warnings);
這裡使用LocalReport對象的Render方法,將報表的內容輸出到指定的資料流(Stream)中。Render方法的第一個參數指定輸出的流的格式,這裡指定為Image格式(圖形格式);第二個參數為一個XML格式的字串,用來描述輸出格式的詳細資料;第三個參數是一個回呼函數(CreateStreamCallback委託類型),你需要為這個參數聲明一個函數,Render方法會將報表的內容輸出到這個函數返回的Stream對象的執行個體中,這個函數看上去類似下面的聲明
1: //聲明一個Stream對象的列表用來儲存報表的輸出資料
2: //LocalReport對象的Render方法會將報表按頁輸出為多個Stream對象。
3: private List<Stream> m_streams;
4: //用來提供Stream對象的函數,用於LocalReport對象的Render方法的第三個參數。
5: private Stream CreateStream(string name, string fileNameExtension,
6: Encoding encoding, string mimeType, bool willSeek)
7: {
8: //如果需要將報表輸出的資料儲存為檔案,請使用FileStream對象。
9: Stream stream = new MemoryStream();
10: m_streams.Add(stream);
11: return stream;
12: }
你可以使用這個函數的參數執行更多的操作,具體內容請參考CreateStreamCallback委託。
第四個參數用來輸出報表處理過程中產生的警告資訊。
Step 3: 使用PrintDocument對象執行列印操作。
1: //用來記錄當前列印到第幾頁了
2: private int m_currentPageIndex;
3:
4: private void Print()
5: {
6: m_currentPageIndex = 0;
7:
8: if (m_streams == null || m_streams.Count == 0)
9: return;
10: //聲明PrintDocument對象用於資料的列印
11: PrintDocument printDoc = new PrintDocument();
12: //指定需要使用的印表機的名稱,使用Null 字元串""來指定預設印表機
13: printDoc.PrinterSettings.PrinterName = "";
14: //判斷指定的印表機是否可用
15: if (!printDoc.PrinterSettings.IsValid)
16: {
17: MessageBox.Show("Can't find printer");
18: return;
19: }
20: //聲明PrintDocument對象的PrintPage事件,具體的列印操作需要在這個事件中處理。
21: printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
22: //執行列印操作,Print方法將觸發PrintPage事件。
23: printDoc.Print();
24: }
具體的PrintPage事件處理常式如下:
1: private void PrintPage(object sender, PrintPageEventArgs ev)
2: {
3: //Metafile對象用來儲存EMF或WMF格式的圖形,
4: //我們在前面將報表的內容輸出為EMF圖形格式的資料流。
m_streams[m_currentPageIndex].Position = 0;
5: Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
6: //指定是否橫向列印
7: ev.PageSettings.Landscape = false;
8: //這裡的Graphics對象實際指向了印表機
9: ev.Graphics.DrawImage(pageImage, 0, 0);
10: m_streams[m_currentPageIndex].Close();
11: m_currentPageIndex++;
12: //設定是否需要繼續列印
13: ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
14: }
到此,我們的報表資料就已經列印出來了,在這個過程中,你可以根據需要添加自己的列印邏輯。