在咱们开发某个系统的时候,客户总会提出一些特定的报表需求,固定的报表格式符合他们的业务处理须要,也贴合他们的工做场景,所以咱们尽量作出符合他们实际须要的报表,这样咱们的系统会获得更好的认同感。本篇随笔介绍如何基于FastReport报表工具,生成报表PDF文档展现医院处方笺的内容。html
以前在随笔《在Winform开发中使用FastReport建立报表》介绍过FastReport这个强大的报表工具,虽然介绍了各类报表的处理代码,不过主要的案例仍是官方的案例,本篇随笔介绍基于某个医院的处方笺的格式报表的处理。web
FastReport.Net是一款适用于Windows Forms, ASP.NET和MVC框架的功能齐全的报表分析解决方案。FastReport.Net以C#语言编写而成并只包含可托管的代码。它与.NET Framework 2.0以及更高版本兼容。支持在报表中添加文本、图像、线条、形状、语句、条形码、矩阵、表格、RTF、选择框等,列表报表、分组报表、主从报表、多列报表,子报表均可以实现处理。通能够为终端用户提供一个报表设计器,让用户能够方便的修改现有报表和建立自定义报表。json
和其余常规的报表工具同样,FastReport.Net报表工具也须要定义好报表模板文件,而后再基于这个报表模板进行内容的呈现,报表模板通常定义标题、报表页眉、明细内容、页脚等信息。浏览器
咱们来看看大概的需求效果,这个是处方笺的常规格式。微信
我大概须要弄个相似格式的处方笺的报表,其中处方药须要动态生成,以及患者信息、医生审核签字的地方须要动态生成,固然,二维码,条码等内容也须要一并根据信息动态生成出来,因为我主要想经过PDF展现,所以使用报表工具生成PDF文档,已经预览或者下载便可。框架
咱们先来看看最终设计好的报表模板,在FastReport设计器里面的效果以下所示。工具
其中,标题部分,主要在页眉,须要展现处方列表的在数据区展现,页脚放置一些联系信息等,这样就构建了一个完整的报表模板。post
建立一个报表模板,咱们先要定义报表页面格式,报表报表的宽度,高度是自定义的仍是标准的,还要设置它的页边距等信息,以下所示。this
页边距设置以下所示。url
因为这个报表包含了主表信息,和明细表的信息,咱们主表动态信息,能够经过参数的绑定方式绑定,明细表则经过绑定DataTable的方式动态处理便可。
采用参数绑定,咱们须要在报表设计器里面定义好咱们须要的参数,以下所示。
咱们通常预先定义好相关的参数,而后绑定在模板里面,并设置好内容的对其格式便可。
如报表页面里面,咱们放置了一个表格,定义好表格的行列和宽度后,双击表格单元格,就能够设置表格单元格的文本内容为对应的参数了,以下界面所示。
为了展现每项的序号,咱们也须要使用到系统变量,如咱们须要展现下面的内容。
那么须要定义好每项的序号,和数据字段名称。
对于动态展现的明细列表部分,咱们须要定义一个数据源的方式,从而可让报表模板绑定对应的字段名称。
我根据数据表的信息,生成一个用于绑定明细列表的数据源,以下所示。
这样咱们在代码绑定的时候,只须要指定Detail的名称和对应的字段名称便可,有了这些定义,咱们能够在报表设计中使用字段绑定了。
在数据区拖入对应的字段定义,并调整文本大小和对其,就能够设计出明细的部分字段绑定了。
对于二维码和条码,咱们能够从报表工具栏里面拖入对应的控件,并设置对应的绑定参数和显示内容便可(这些也能够经过参数,运行的时候进行动态绑定)。
最后设计好的报表如开始介绍那样,是一个完整的报表模板了。
预览的时候,咱们能够看到内容绑定的地方都是空白,由于咱们没有绑定数据源的缘由,不过整个报表的格式已经出来了,大概就是咱们须要的结果。
经过上面报表模板的设计,咱们基本的前期工做就准备好了,须要的就是根据实际业务的须要,动态呈现数据了。
在绑定数据并生成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 = url;
若是是直接打开PDF,咱们咱们就直接传递给浏览器一个PDF文件路径便可
location.href = filePath
在微信端预览的效果以下所示。
使用FastReport报表,整体来讲,工做量主要是在设计报表模板这里,经过代码实现数据绑定的工做反而很是简单,只须要指定对应的参数和字段数据表便可,而报表的设计是一项精细的工做,咱们须要根据实际状况,反复调整格式和呈现的效果才能作到尽善尽美,不过总体来讲FastReport提供了很是强大的报表设计和处理过程,使得咱们能够在设计一些复杂报表的时候,能够更加高效。
在选项使用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; }
最后呈现的大概效果以下所示。