上一集講到Crystal Report的報表檔怎麼完成。
這一集就說說怎麼把正確的資料丟到報表檔呈現出來。
這是我自己常用的方式,也把它做成抽象類別,如果有人有更好或更方便的方法,也請不吝指教。
--套資料--
整體來說,我們可以把步驟分作幾個抽象動作:
- 我們要先從資料庫把資料找出來
- 把找出來的資料,依照自己的格式丟到自己在做的DataSet
- 宣告一個ReportDocument,路徑、DataSource設定好。
- 就可以輸出了。
1. 從資料庫裡撈資料
端看個人習慣使用什麼方式在做資料庫的存取。
我的考量是:報表通常都會輸出一些不同table在JOIN來JOIN去的結果,所以就算系統裡有使用Entity Framework之類的物件關聯式資料庫,在查報表的時候我還是習慣直接寫SQL Script。
不管怎麼樣,輸出是一個DataTable還是SqlDataReader都好,只要能正確把資料讀出來、正確了解各個欄位的定義就好。
Dim Command as SqlCommand = New SqlCommand()
Command.Connection = new SqlConnection(ConnectionString)
Command.CommandText = "SELECT * FROM [TableName] " + vbNewLine 'SQL Script
Command.Connection.Open()
Dim SearchResult as DataTable = CommandToDataTable(Command)
2. 整理格式,丟到DataSet
這裡指的DataSet是指在做報表時做的那個自訂DataSet。
有的時候我們從資料抓出來的資料會需要做一些格式的轉換才會顯示在頁面上,就在這個階段的來完成。
我個人在這裡常做的事是把存在DB裡的7碼民國年把年月日用斜線隔開,或是把代碼檔轉換成中文。
Dim dtReturn As dtDepartmentDocRegisteredList = New dtDepartmentDocRegisteredList()
For Each row As DataRow In SearchResult.Rows
Dim dr As DataRow = dtReturn.DataTable1.NewRow()
dr("ReceivedDate") = FormatMandarinDate(row("ReceivedDate").ToString(), "/")
dr("DocumentType") = DictionaryManager.GetValue(GetType(CodeDocumentType), row("DocumentType"))
dr("Organizer") = row("Organizer")
dr("SendDate") = FormatMandarinDate(row("SendDate").ToString(), "/")
dtReturn.DataTable1.Rows.Add(dr)
Next
Return dtReturn
3. 宣告、設定ReportDocument
ReportDocument是Crystal Report Runtime裡的元件,應該是早就安裝好了。要用的時候Include或Import一下應該就有了。
必備的設定是報表檔的路徑,還有用該元件的SetDataSource方法把整理好的DataSet設定給他。
如果要完成的報表比較複雑,你可能還會加參數、設定一些雜七雜八的東西。
Dim doc As ReportDocument = New ReportDocument()
doc.Load("C:\XXXXX\XXX.rpt") '磁碟路徑。我要用的話都會用MapPath來讓Framework自己轉。
doc.SetDataSource(dtReturn) '整理出來的DataSet丟進去
4. 匯出
這裡介紹的匯出動作會把報表含你輸出的資料一起弄成特定格式的檔案,再存到主機裡。
在我近期所做的專案裡,他們匯出報表的方式統一採用先存成檔案,再供Client端做檔案下載。所以該方式還算堪用。
Dim oExDo As New DiskFileDestinationOptions
'輸出的檔案名稱,ExportFormatType.PortableDocFormat是指PDF。
Dim FileName As String = String.Format("{0}_{1}.{2}", ReportName, DateTime.Now.Ticks, GetReportExtension(ExportFormatType.PortableDocFormat))
oExDo.DiskFileName = "C:\XXXXX\" + FileName
doc.ExportOptions.ExportDestinationType = ExportDestinationType.DiskFile
doc.ExportOptions.ExportFormatType = FileType
doc.ExportOptions.DestinationOptions = oExDo
doc.Export() 'Export to PDF
doc.Close()
doc.Dispose()
中間有任何一個地方壞掉或不合Crystal Report的規則,會直接噴Exception出來。
--功德圓滿--
到後來,我都把一些常用的程式片段另外取出來放在Utils裡。
像報表匯出、加參數等常用的東西,要我直接寫出來我還不會寫,都直接從網路上咖過來整理一下就可以用了。