在我們開發某個系統的時候,客戶總會提出一些特定的報表需求,固定的報表格式符合他們的業務處理需要,也貼合他們的作業場景,因此我們盡可能做出符合他們實際需要的報表,這樣我們的系統會得到更好的認同感,本篇隨筆介紹如何基于FastReport報表工具,生成報表PDF檔案展示醫院處方箋的內容,
之前在隨筆《在Winform開發中使用FastReport創建報表》介紹過FastReport這個強大的報表工具,雖然介紹了各種報表的處理代碼,不過主要的案例還是官方的案例,本篇隨筆介紹基于某個醫院的處方箋的格式報表的處理,
FastReport.Net是一款適用于Windows Forms, ASP.NET和MVC框架的功能齊全的報表分析解決方案,FastReport.Net以C#語言撰寫而成并只包含可托管的代碼,它與.NET Framework 2.0以及更高版本兼容,支持在報表中添加文本、影像、線條、形狀、陳述句、條形碼、矩陣、表格、RTF、選擇框等,串列報表、分組報表、主從報表、多列報表,子報表都可以實作處理,通可以為終端用戶提供一個報表設計器,讓用戶可以方便的修改現有報表和創建自定義報表,
1、定義報表模板
和其他常規的報表工具一樣,FastReport.Net報表工具也需要定義好報表模板檔案,然后再基于這個報表模板進行內容的呈現,報表模板一般定義標題、報表頁眉、明細內容、頁腳等資訊,
我們來看看大概的需求效果,這個是處方箋的常規格式,

我大概需要弄個類似格式的處方箋的報表,其中處方藥需要動態生成,以及患者資訊、醫生審核簽字的地方需要動態生成,當然,二維碼,條碼等內容也需要一并根據資訊動態生成出來,由于我主要想通過PDF展示,因此使用報表工具生成PDF檔案,已經預覽或者下載即可,
我們先來看看最終設計好的報表模板,在FastReport設計器里面的效果如下所示,

其中,標題部分,主要在頁眉,需要展示處方串列的在資料區展示,頁腳放置一些聯系資訊等,這樣就構建了一個完整的報表模板,
創建一個報表模板,我們先要定義報表頁面格式,報表報表的寬度,高度是自定義的還是標準的,還要設定它的頁邊距等資訊,如下所示,

頁邊距設定如下所示,

由于這個報表包含了主表資訊,和明細表的資訊,我們主表動態資訊,可以通過引數的系結方式系結,明細表則通過系結DataTable的方式動態處理即可,
采用引數系結,我們需要在報表設計器里面定義好我們需要的引數,如下所示,

我們一般預先定義好相關的引數,然后系結在模板里面,并設定好內容的對其格式即可,
如報表頁面里面,我們放置了一個表格,定義好表格的行列和寬度后,雙擊表格單元格,就可以設定表格單元格的文本內容為對應的引數了,如下界面所示,

為了展示每項的序號,我們也需要使用到系統變數,如我們需要展示下面的內容,

那么需要定義好每項的序號,和資料欄位名稱,

對于動態展示的明細串列部分,我們需要定義一個資料源的方式,從而可以讓報表模板系結對應的欄位名稱,

我根據資料表的資訊,生成一個用于系結明細串列的資料源,如下所示,

這樣我們在代碼系結的時候,只需要指定Detail的名稱和對應的欄位名稱即可,有了這些定義,我們可以在報表設計中使用欄位系結了,

在資料區拖入對應的欄位定義,并調整文本大小和對其,就可以設計出明細的部分欄位系結了,
對于二維碼和條碼,我們可以從報表工具列里面拖入對應的控制元件,并設定對應的系結引數和顯示內容即可(這些也可以通過引數,運行的時候進行動態系結),

最后設計好的報表如開始介紹那樣,是一個完整的報表模板了,

預覽的時候,我們可以看到內容系結的地方都是空白,因為我們沒有系結資料源的原因,不過整個報表的格式已經出來了,大概就是我們需要的結果,

2、生成報表PDF內容
通過上面報表模板的設計,我們基本的前期作業就準備好了,需要的就是根據實際業務的需要,動態呈現資料了,
在系結資料并生成PDF格式報表的時候,我們需要先構建一個報表物件,如下代碼所示,
//生成PDF報表檔案到具體檔案 Report report = new Report(); report.Load(reportPath);
由于資料我們是動態構建的,因此我們需要準備引數資料源和欄位資料源兩個部分,引數我們用字典來承載,欄位資料,我們用DataTable來承載,如下所示,
//定義引數和資料格式 var dict = new Dictionary<string, object>(); var dt = DataTableHelper.CreateTable("ProductName,Quantity|int,Unit,Specification,HowTo,Frequency");
然后我們根據系統需要填入動態的資料,如下代碼所示,
//準備資料 dict.Add("Name", info.PatientName); dict.Add("Gender", info.Gender); var age = info.BirthDate.GetAge(); dict.Add("Age", age); dict.Add("Telephone", info.Telephone); dict.Add("CreateTime", info.CreateTime); var checkDoctor = BLLFactory<User>.Instance.GetFullNameByOpenID(info.CheckDoctor); dict.Add("CheckDoctor", !string.IsNullOrEmpty(checkDoctor) ? checkDoctor : "未知"); var CheckPharmacist = BLLFactory<User>.Instance.GetFullNameByOpenID(info.CheckPharmacist); dict.Add("CheckPharmacist", !string.IsNullOrEmpty(CheckPharmacist) ? CheckPharmacist : "未知"); var SendUser = BLLFactory<User>.Instance.GetFullNameByOpenID(info.SendUser); dict.Add("SendUser", !string.IsNullOrEmpty(SendUser) ? SendUser : "未知"); var qrcode = string.Format("{0}/h5/PrescriptionDetail?id={1}", ConfigData.WebsiteDomain, info.ID); dict.Add("QrCode", qrcode); dict.Add("BarCode", info.PrescriptionNo); if(detailList != null) { foreach(var item in detailList) { var dr = dt.NewRow(); dr["ProductName"] = item.ProductName; dr["Quantity"] = item.Quantity; dr["Unit"] = item.Unit; dr["Specification"] = ""; dr["HowTo"] = item.HowTo; dr["Frequency"] = item.Frequency; dt.Rows.Add(dr); } }
最后根據上面的資料,系結并生成PDF報表即可,如下代碼所示,
//重繪資料源 report.RegisterData(dt, "Detail"); foreach (string key in dict.Keys) { report.SetParameterValue(key, dict[key]); } //運行報表 report.Prepare(); //匯出PDF報表 PDFExport export = new PDFExport(); report.Export(export, realPath); report.Dispose();
由于這個功能我們是在微信公眾號里面集成的一個報表呈現,因此我們可以通過PDF預覽的方式,或者直接打開PDF檔案,、
如果采用PDF在線預覽方式,可以參考我隨筆《實作在線預覽PDF的幾種解決方案》介紹的那樣,最終采用PDFJS的在線預覽方案,不管在微信端,還是Web端都是比較不錯的效果,
如果采用PDFJS預覽方式,那么JS代碼如下所示,
var baseUrl = "@ViewBag.WebsiteDomain/Content/JQueryTools/pdfjs/web/viewer.html"; var url = baseUrl + "?file=" + filePath;//實際地址 location.href = https://www.cnblogs.com/wuhuacong/p/url;
如果是直接打開PDF,我們我們就直接傳遞給瀏覽器一個PDF檔案路徑即可
location.href = https://www.cnblogs.com/wuhuacong/p/filePath
在微信端預覽的效果如下所示,

使用FastReport報表,總體來說,作業量主要是在設計報表模板這里,通過代碼實作資料系結的作業反而非常簡單,只需要指定對應的引數和欄位資料表即可,而報表的設計是一項精細的作業,我們需要根據實際情況,反復調整格式和呈現的效果才能做到盡善盡美,不過整體來說FastReport提供了非常強大的報表設計和處理程序,使得我們可以在設計一些復雜報表的時候,可以更加高效,
3、采用其他報表設計-銳浪報表設計展現
在選項使用FastReport報表呈現的時候,我也試過銳浪報表的處理方式,銳浪報表的整體呈現效果也是非常不錯的,這里順便介紹一下銳浪報表的設計、運行時系結資料源等的步驟代碼,以供參考,
首先我們需要定義好一個報表的模板資訊,和FastReport報表模板一樣,也是類似的定義方式,報表模板設計如下所示,

上面我們可以看到,它也是有引數系結和欄位系結兩種方式,
實作資料系結的代碼如下所示,
//生成PDF報表檔案到具體檔案 GridExportHelper helper = new GridExportHelper(reportPath); var json = FileUtil.FileToString(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Report/Pres.json"), Encoding.UTF8); bool success = helper.ExportPdf(json, realPath, HttpContext); if (success) { result = Content(exportPdfPath);//回傳Web相對路徑 } helper.Dispose();//銷毀物件
其中ExportPdf接收一個JSON字串,實作代碼如下所示,
/// <summary> /// 匯出PDF /// </summary> /// <typeparam name="T">串列物件型別</typeparam> /// <param name="list">串列物件</param> /// <param name="filePath">存盤路徑</param> /// <param name="context"></param> /// <returns></returns> public bool ExportPdf(string json, string filePath, HttpContextBase context) { //從對應檔案中載入報表模板資料 Report.LoadFromFile(this.ReportPath); //加載JSON物件 Report.LoadDataFromXML(json); IGRExportOption ExportOption = Report.PrepareExport(GRExportType.gretPDF); var exportPdf = Report.ExportToBinaryObject(); Report.UnprepareExport(); var succeeded = exportPdf.SaveToFile(filePath); return succeeded; }
最后呈現的大概效果如下所示,

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/117679.html
標籤:C#
