使用FastReport报表工具生成报表PDF文档

在我们开发某个系统的时候,客户总会提出一些特定的报表需求,固定的报表格式符合他们的业务处理需要,也贴合他们的工作场景,因此我们尽可能做出符合他们实际需要的报表,这样我们的系统会得到更好的认同感。本篇随笔介绍如何基于FastReport报表工具,生成报表PDF文档展示医院处方笺的内容。

之前在随笔《在Winform开发中使用FastReport创建报表》介绍过FastReport这个强大的报表工具,虽然介绍了各种报表的处理代码,不过主要的案例还是官方的案例,本篇随笔介绍基于某个医院的处方笺的格式报表的处理。

FastReport.Net是一款适用于Windows Forms, ASP.NET和MVC框架的功能齐全的报表分析解决方案。FastReport.Net以C#语言编写而成并只包含可托管的代码。它与.NET Framework 2.0以及更高版本兼容。支持在报表中添加文本、图像、线条、形状、语句、条形码、矩阵、表格、RTF、选择框等,列表报表、分组报表、主从报表、多列报表,子报表都可以实现处理。通可以为终端用户提供一个报表设计器,让用户可以方便的修改现有报表和创建自定义报表。

1、定义报表模板

和其他常规的报表工具一样,FastReport.Net报表工具也需要定义好报表模板文件,然后再基于这个报表模板进行内容的呈现,报表模板一般定义标题、报表页眉、明细内容、页脚等信息。

我们来看看大概的需求效果,这个是处方笺的常规格式。

640?wx_fmt=png

 我大概需要弄个类似格式的处方笺的报表,其中处方药需要动态生成,以及患者信息、医生审核签字的地方需要动态生成,当然,二维码,条码等内容也需要一并根据信息动态生成出来,由于我主要想通过PDF展示,因此使用报表工具生成PDF文档,已经预览或者下载即可。

我们先来看看最终设计好的报表模板,在FastReport设计器里面的效果如下所示。

640?wx_fmt=png

 其中,标题部分,主要在页眉,需要展示处方列表的在数据区展示,页脚放置一些联系信息等,这样就构建了一个完整的报表模板。

创建一个报表模板,我们先要定义报表页面格式,报表报表的宽度,高度是自定义的还是标准的,还要设置它的页边距等信息,如下所示。

640?wx_fmt=png

 页边距设置如下所示。

 640?wx_fmt=png

由于这个报表包含了主表信息,和明细表的信息,我们主表动态信息,可以通过参数的绑定方式绑定,明细表则通过绑定DataTable的方式动态处理即可。

采用参数绑定,我们需要在报表设计器里面定义好我们需要的参数,如下所示。

640?wx_fmt=png

 我们一般预先定义好相关的参数,然后绑定在模板里面,并设置好内容的对其格式即可。

如报表页面里面,我们放置了一个表格,定义好表格的行列和宽度后,双击表格单元格,就可以设置表格单元格的文本内容为对应的参数了,如下界面所示。

 640?wx_fmt=png

 为了展示每项的序号,我们也需要使用到系统变量,如我们需要展示下面的内容。

640?wx_fmt=png

 那么需要定义好每项的序号,和数据字段名称。

640?wx_fmt=png

 对于动态展示的明细列表部分,我们需要定义一个数据源的方式,从而可以让报表模板绑定对应的字段名称。

640?wx_fmt=png

 我根据数据表的信息,生成一个用于绑定明细列表的数据源,如下所示。

640?wx_fmt=png

 这样我们在代码绑定的时候,只需要指定Detail的名称和对应的字段名称即可,有了这些定义,我们可以在报表设计中使用字段绑定了。

640?wx_fmt=png

 在数据区拖入对应的字段定义,并调整文本大小和对其,就可以设计出明细的部分字段绑定了。

对于二维码和条码,我们可以从报表工具栏里面拖入对应的控件,并设置对应的绑定参数和显示内容即可(这些也可以通过参数,运行的时候进行动态绑定)。

640?wx_fmt=png

 最后设计好的报表如开始介绍那样,是一个完整的报表模板了。

 640?wx_fmt=png

预览的时候,我们可以看到内容绑定的地方都是空白,因为我们没有绑定数据源的原因,不过整个报表的格式已经出来了,大概就是我们需要的结果。

 640?wx_fmt=png

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 = url;

如果是直接打开PDF,我们我们就直接传递给浏览器一个PDF文件路径即可

location.href = filePath

在微信端预览的效果如下所示。

640?wx_fmt=png

使用FastReport报表,总体来说,工作量主要是在设计报表模板这里,通过代码实现数据绑定的工作反而非常简单,只需要指定对应的参数和字段数据表即可,而报表的设计是一项精细的工作,我们需要根据实际情况,反复调整格式和呈现的效果才能做到尽善尽美,不过整体来说FastReport提供了非常强大的报表设计和处理过程,使得我们可以在设计一些复杂报表的时候,可以更加高效。

3、采用其他报表设计-锐浪报表设计展现

在选项使用FastReport报表呈现的时候,我也试过锐浪报表的处理方式,锐浪报表的整体呈现效果也是非常不错的,这里顺便介绍一下锐浪报表的设计、运行时绑定数据源等的步骤代码,以供参考。

首先我们需要定义好一个报表的模板信息,和FastReport报表模板一样,也是类似的定义方式,报表模板设计如下所示。

640?wx_fmt=png

 

上面我们可以看到,它也是有参数绑定和字段绑定两种方式。

实现数据绑定的代码如下所示。

640?wx_fmt=gif

//生成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();//销毁对象

640?wx_fmt=gif

其中ExportPdf接收一个JSON字符串,实现代码如下所示。

640?wx_fmt=gif

        /// <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;
}

640?wx_fmt=gif

最后呈现的大概效果如下所示。

640?wx_fmt=png


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313355.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DXSDK_June10安装错误

今天安装DXSDK_Jun10时&#xff08;下载地址&#xff1a;http://download.microsoft.com/download/A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe&#xff09;&#xff0c;出现错误Error Code:s1023 错误原因&#xff1a; 计算机上有安装过更新版的Microsoft Vi…

相交链表

1、题目描述 编写一个程序&#xff0c;找到两个单链表相交的起始节点。 如下面的两个链表&#xff1a; 在节点 c1 开始相交。 示例 1&#xff1a; 输入&#xff1a;intersectVal 8, listA [4,1,8,4,5], listB [5,0,1,8,4,5], skipA 2, skipB 3 输出&#xff1a;Refe…

Kullback-Leibler Divergence

本文转自&#xff1a;http://www.cnblogs.com/ywl925/p/3554502.html KL距离&#xff0c;是Kullback-Leibler差异&#xff08;Kullback-Leibler Divergence&#xff09;的简称&#xff0c;也叫做相对熵&#xff08;Relative Entropy&#xff09;。它衡量的是相同事件空间里的两…

Shader 坐标转换

转自&#xff1a;http://www.ownself.org/blog/2010/kong-jian-zuo-biao-zhuan-huan.html 这个比较基础了&#xff0c;不过基础最重要&#xff0c;往往应该理解透彻&#xff0c;并且反复复习。 我们知道在3D画面渲染过程中对于模型的计算的一部分被称为Transforming and Ligh…

致所有.Net者和有梦想的朋友们 - 共勉

这篇文章很早就想写的了&#xff0c;主要是人到了一定的年纪&#xff0c;就想唠叨一些看法&#xff0c;认不认可不重要&#xff0c;重要的是生活给予你的酸甜苦辣&#xff0c;你都想一吐为快。 这里主要基于多年来自己的一个行业感受和以及生活感想&#xff0c;唠叨一下工作以及…

ReLU的起源

论文参考&#xff1a;Deep Sparse Rectifier Neural Networks 网页参考&#xff1a;http://www.mamicode.com/info-detail-873243.html 起源&#xff1a;传统激活函数、脑神经元激活频率研究、稀疏激活性 传统Sigmoid系激活函数 传统神经网络中最常用的两个激活函数&…

Asp.NET Core 轻松学-项目目录和文件作用介绍

前言上一章介绍了 Asp.Net Core 的前世今生&#xff0c;并创建了一个控制台项目编译并运行成功&#xff0c;本章的内容介绍 .NETCore 的各种常用命令、Asp.Net Core MVC 项目文件目录等信息&#xff0c;通过对命令的学习和操作&#xff0c;对项目结构的认识&#xff0c;进一步理…

Dubbo 常见服务治理策略

1、Dubbo体系结构 2、Dubbo容错机制 Dubbo集群容错架构图 各节点关系&#xff1a; 这里的Invoker是Provider的一个可调用Service的抽象&#xff0c;Invoker封装了Provider地址及Service接口信息。Directory代表多个Invoker&#xff0c;可以把它看成List&#xff0c;但与Lis…

IT技术人员的35个特点,你占几个?

作者&#xff1a;zollty&#xff0c;资深程序员和架构师&#xff0c;私底下是个爱折腾的技术极客&#xff0c;架构师社区合伙人&#xff01;1、价值观对生活的一般看法&#xff1a;追求简单&#xff0c;安定&#xff0c;可控制的生活&#xff0c;但对家庭生活的责任持消极态度草…

asp.net core 腾讯验证码的接入

asp.net core 腾讯验证码的接入Intro之前使用的验证码服务是用的极验验证&#xff0c;而且是比较旧的&#xff0c;好久之前接入的&#xff0c;而且验证码服务依赖 Session&#xff0c;有点不太灵活&#xff0c;后来发现腾讯也有验证码服务&#xff0c;而且支持小程序&#xff0…

ffmpeg加环境变量

转自&#xff1a;http://blog.csdn.net/leixiaohua1020/article/details/19016469 FFMPEG是命令行工具&#xff0c;因此使用起来多少还是会有些不方便。在这记录两点方便使用FFMPEG的方法&#xff1a; 1.任何目录下都可以使用FFMPEG 问题描述&#xff1a;需要转码&#xff08;播…

.NET Core 微信公众号小程序6种获取UnionID方法,你知道哪几种?

前言获取UnionID是开发微信公众号/小程序中很有必要的一个环节&#xff0c;特别是针对一个公司拥有多个公众号小程序而推出的机制&#xff0c;实现打通账户一体化&#xff0c;用UnionID来区分多平台的唯一性。官方的解释&#xff1a;如果开发者拥有多个移动应用、网站应用、和公…

.NET LINQ分析AWS ELB日志避免996

前言小明是个单纯的 .NET开发&#xff0c;一天大哥叫住他&#xff0c;安排了一项任务&#xff1a;“小明&#xff0c;分析一下我们 超牛逼网站上个月的所有 AWS ELB流量日志&#xff0c;这些日志保存在 AWS S3上&#xff0c;你分析下&#xff0c;看哪个 API的响应时间中位数最长…

网络摄像头实时获取信息

转自&#xff1a;http://blog.csdn.net/yong_hen/article/details/42460387#quote 转自&#xff1a;http://blog.csdn.net/leo2007608/article/details/9885219 代码&#xff1a; openCV版本&#xff1a;2.4.10. 平台&#xff1a;win7 [cpp] view plaincopy #include <op…

[ASP.NET Core 3框架揭秘] 依赖注入:依赖注入模式

IoC主要体现了这样一种设计思想&#xff1a;通过将一组通用流程的控制权从应用转移到框架之中以实现对流程的复用&#xff0c;并按照“好莱坞法则”实现应用程序的代码与框架之间的交互。我们可以采用若干设计模式以不同的方式实现IoC&#xff0c;比如我们在前面介绍的模板方法…

微软100题第5题

转载自&#xff1a;http://blog.csdn.net/littlestream9527/article/details/8104731 http://blog.csdn.net/v_july_v/article/details/6370650 http://blog.csdn.net/insistgogo/article/details/7689297 下面&#xff0c;我试图用最清晰易懂&#xff0c;最易令人理解的思维…

北京Dotnet分享会 || 精英论坛第三期

编者按&#xff1a;没有一成不变的定律&#xff0c;没有长久不衰的流行&#xff0c;更没有一劳永逸的侥幸&#xff0c;只有自己刻苦努力、脚踏实地、兢兢业业的学习和工作&#xff0c;才会成为这个社会永远不会被淘汰的中流砥柱。一、昨夜西风凋碧树昨夜西风凋碧树&#xff0c;…

微软开源微服务运行时Dapr,赋能云原生应用开发

Dapr 是一个可移植的、由事件驱动的 Serverless 运行时&#xff0c;用于跨云和边缘构建分布式应用程序。10月9日&#xff0c;正式以 MIT 协议开源。Dapr 使开发人员能够轻松地构建弹性、无状态和有状态的微服务&#xff0c;让它们在云和边缘位置上运行&#xff0c;并包含了开发…

最大堆和最小堆

堆和栈的区别&#xff1a;一、堆栈空间分配区别&#xff1a;1、栈&#xff08;操作系统&#xff09;&#xff1a;由操作系统自动分配释放 &#xff0c;存放函数的参数值&#xff0c;局部变量的值等。其操作方式类似于数据结构中的栈&#xff1b;2、堆&#xff08;操作系统&…

认知的高度 = 人生的高度

大家好&#xff0c;我是Z哥。我们每个人&#xff0c;每天要和很多不同的人打交道。我相信下面的场景每个程序员都有遇到过&#xff0c;业务方在某个模块下新提出了一个功能&#xff0c;但是你希望做新功能之前先把这个模块的低质量代码重构一下。但是&#xff0c;不管你怎么摆事…