MaltReport 是我几年前写的开源单据、报表引擎,最近进行了较大的更新,尤其是几年来在生产项目中应用取得了非常好的效果,特别写篇介绍文字给大家分享一下。
首先先介绍几个名词:
- OpenDocument:国际标准文档格式,开源办公软件 OpenOffice.org/LibreOffice 的 ODT/ODS 即为 OpenDocument 格式。
- OpenOfficeXML:同样是国际标准文档格式,由 Microsoft 定义,MS-Office 的 DOCX/XLSX 等即为 OpenOfficeXML 格式。
简介
MaltReport 实际上是一个通用的模板文档生成系统,其用途不仅用于生成报表,也可以用来生成合同、预算报告、标书等等任何需要格式与数据相结合的文档,其中的 XLS/ODS 模板尤其适合大量数据导出的场合。
简单来说,MaltReport 是通过直接在内存中解析操作 OpenDocument 和 OpenOfficeXML 文件来实现报表和单据的生成,整个理念非常接近于 ASP.NET MVC 的 Razor 模板,只不过 Razor 生成 HTML 而 MaltReport 生成 ODT/ODS/DOC/XLS 文件。
MaltReport 的优点:
所见即所得
- 通过在 OpenDocument 或 OpenOfficeXML 文件里嵌入简单易学的 Velocity 模板语言来开发模板,实际上我们将 MS-Office 和 LibreOffice 作为我们的所见即所得的报表模板编辑器。
- 生成后的报表是通用的 XLS/DOC/ODT/ODS 文件,打印、格式转换等均不是问题。
- 简单易用的 API,三行代码实现报表生成。
性能与可靠性
直接在内存中操作 odt/ods/xls/doc 文件,采用 NVelocity 模板引擎进行内容的替换,生成报表不依赖 Libreoffice/MS-Office 等软件,适合服务器端运行。因为 Word/Excel 这些桌面软件不是为服务器长期运行设计的,之前有些 Word 文档生成工具之类需要通过 Word 的 COM 接口操作 docx 文件,数量一大很有可能耗尽服务器的内存。
MaltReport 报表引擎本身不负责报表的排版和显示,因此没有其他采用像素定位设计的报表工具所存在的中文换行、对齐等等布局问题,极大提高了报表生成的性能。经实际使用的经验显示,生成报表的速度仅受限于磁盘 IO 速度.
特性完整
- 可以利用 LibreOffice Calc 或 MS-Excel 电子表格的强大功能,进行二次汇总分析或绘制图表。
- 支持图像数据,可以在文档中嵌入用户提供的图像数据。
还有最后不能不提及的,免费开源,MIT 协议授权,可在商业产品中自由使用。
使用说明
下面以 Word 报表为例介绍 MaltReport 的使用。
第一步,在 nuget 中加入项目引用:
MaltReport 已发布到 nuget.org 中,可通过 nuget 引入您的项目,参考:
https://www.nuget.org/packages/MaltReport2
第二步,创建报表模板
新建一个 Word 文档,并另存为【Word 2003 XML】格式,然后把文件扩展名从 xml 改回 doc,然后使用 Word 重新打开。
在 Word 中创建模板,报表引擎通过特殊的超链接及 Velocity 模板标记来识别,一点简单的小介绍:
- $xxx 是模板的占位符,通过 RenderContext 提供的数据进行替换,也支持 $xxx.yyy.zzz 或 ${xxx.yyy.zzz}这样的格式。
- 若表达式太长可使用超链接,超链接使用 rtl://$xxx.yyy.zzz/ 或rtl://${xxx.yyy.zzz} 的格式。
- 支持 foreach 循环和 if-then-else 条件等,尤其是表格可以按行或按列循环。
实际例子可参考 Velocity 的 VTL 语言文档及本项目的演示。
当模板创建完成以后保存并关闭 Word。
第三步,在 C# 代码里加载、渲染并生成报表
1 var dt = new DataTable("Employees"); 2 3 //Fill the DataTable 4 var connectionString = @"Version=3,uri=file://./Database/northwind.db"; 5 using (var connection = new SqliteConnection(connectionString)) 6 { 7 var sql = "SELECT FirstName, LastName, HireDate, BirthDate, Address FROM Employees"; 8 var adapter = new SqliteDataAdapter(); 9 adapter.SelectCommand = new SqliteCommand(sql, connection); 10 adapter.FillSchema(dt, SchemaType.Source); 11 adapter.Fill(dt); 12 } 13 14 var renderContext = new Dictionary<string, object>() 15 { 16 //Plain old types 17 {"title", "EMPLOYEES"}, 18 {"property1", "Property 1"}, 19 {"property2", "Property 2"}, 20 21 //Strong types 22 {"orm_employees", 23 new List<Employee>() 24 { 25 new Employee("Micheal Scott", "Address 1", 22), 26 new Employee("Andy Bernard", "Address 3", 33), 27 new Employee("Dwight Shurte", "Address 1", 22), 28 new Employee("Jim Halpert", "Address 2", 27), 29 new Employee("Pam Beesly", "Address 4", 19), 30 } 31 }, 32 33 {"employees", dt}, //DataTable is ok 34 35 {"now", DateTime.Now}, //DateTime is ok too 36 };
上面的代码演示了 RenderContext 的概念用法,RenderContext 为模板中所包含的数据的容器,本身是一个 IDictionary<string, object> 类型,key 为变量名,value 为变量值,变量值支持原始类型、强类型类、结构、DataTable 等。
有了模板和要填充到模板中的数据我们只需加载模板、编译模板然后渲染模板即可,非常简单直观的 API:
1 var template = new WordMLTemplate(); 2 3 template.Load("template1.doc"); //第一步加载模板文件 4 5 template.Compile(); //第二步编译模板 6 7 //第三部渲染模板 8 var resultDoc = template.Render(ctx); 9 10 //第四步,保存生成的报表文件,也可保存到 MemoryStream 11 using (var resultFile3 = File.Open("result.doc", FileMode.Create, FileAccess.ReadWrite)) 12 { 13 resultDoc.Save(resultFile3); 14 }
生成了名为“result.doc”的报表文件,试着用 Word 打开:
Voila! 全部搞定!
在项目的源代码里包含 Sandwych.Reporting.Demo 演示程序,里面包含生成 DOC/XLS/ODT/ODS 的全部样例。
项目地址及其他
联系我: oldrev AT gmail.com 也可加我 QQ: 55-43-1671
项目 github: https://github.com/oldrev/maltreport
项目 nuget:https://www.nuget.org/packages/MaltReport2