上方廣告

Lady Kukki 手作糖霜餅乾

2013年12月6日 星期五

NET產生PDF

NET本身沒有提供產生PDF的API,但在實務上不免會遇到需要產生PDF檔案的情況,因此網路上有人分享綜多產生PDF的方法,其中最常見的就是透過iTextSharp來產生PDF。但iTextSharp固然好用,但產生PDF必須透過程式的寫法來決定PDF各文字的位置,這憑空想像沒有視覺畫介面來輔助,在開發效率上實在是有點差,雖然網路上有人使用HTML來產生PDF,但確會有字型無法呈現等問題。

好加在NET本身雖然沒有辦法產生PDF,但是確可以透過ReportViewer控制項來達成這樣的需求,透過rdlc先拉好要呈現的報表畫面,再透過程式將資料來源將資料塞入報表中,就可以輕易的產生出PDF檔,要使用此功能必須先安裝【Microsoft 報表檢視器 2010 可轉散發套件】,下面我就大概說明一下要如何開發簡單的PDF下載。
以下操作使用Visual Studio2010進行開發,首先要先拉好資料集,此步驟的目的是為了讓報表檔可以讀取到資料來源的資料結構。

拉好資料集後就是設計報表畫面,產生一個rdlc檔後將想要的報表畫面位置拉好,且將資料表的對應關係設定好後,PDF的畫面設計基本上就到這裡就結束了。

接下來就是產生PDF的重點了,在這裡使用網頁來產生PDF,故接下來幾個重點步驟設定好後,我們想要的PDF就可以輕鬆的產生出來了。
1.先將ReportViewer物件宣告好。
2.且定該物件使用的LocalReport的名稱對應。
3.設定報表資料來源。
4.設定報表使用的參數。
5.透過物件的LocalReport.Render來產生PDF二進制文件,第一個參數就是要產生的檔案類型,MSDN提到目前支援的類型有Excel,PDF,Image。
6.輸出PDF檔案。

主要產生PDF的Methods如下語法
/// 產生PDF or Excel
/// 檔案類型
/// 檔案名稱
private void GenerateFile(string filetype, string fileName)
{
    //變數宣告
    Warning[] warnings;
    string[] streamIds;
    string mimeType = string.Empty;
    string encoding = string.Empty;
    string extension = string.Empty;

    //宣告ReportViewer物件
    ReportViewer viewer = new ReportViewer();
    viewer.ProcessingMode = ProcessingMode.Local;
    viewer.LocalReport.ReportPath = "WOBooking.rdlc";

    //設定資料來源
    viewer.LocalReport.DataSources.Clear();
    viewer.LocalReport.DataSources.Add(new Microsoft.Reporting.WebForms.ReportDataSource("WOBookingSource", GetDataSource()));
    viewer.LocalReport.Refresh();

    //設定報表參數
    ReportParameter rp1 = new ReportParameter("wocode", "WO201312060001");
    ReportParameter rp2 = new ReportParameter("oemname", "PrimeEagle Studio");
    viewer.LocalReport.SetParameters(new ReportParameter[] { rp1, rp2 });

    //透過Render的方式取得PDF二進位檔案
    byte[] bytes = viewer.LocalReport.Render(filetype, null, out mimeType, out encoding, out extension, out streamIds, out warnings);

    //產生下載檔
    Response.Buffer = true;
    Response.Clear();
    Response.ContentType = mimeType;
    Response.AddHeader("content-disposition", "attachment; filename=" + fileName + "." + extension);
    Response.BinaryWrite(bytes);
    Response.Flush();

}

若要產生Excel檔,除了先前有提過的使用NPOI,也可以透過此種方式來產生,但透過rdlc來產生Excel檔案有個不方便的地方就是在設計畫面每一個TextBox要是沒有對齊的話,所產生的Excel Cell會多出一個,有點醜陋,且rdlc的頁尾會跑不出來,故若比較複雜的Excel表,我還是習慣先拉好一個Excel Template,然後再透過NPOI來載入該Template塞入資料對應的位置。

本文參考
iTextSharp參考

本文示意圖

本文範例
WebSite_ExportPDF.zip