MaltReport2:通用文档生成引擎
UPDATED: 本文仅适用 MaltReport 2.x ,3.x 版本文档还在撰写当中,目前请参考项目中的 Samples。
MaltReport 是我几年前写的开源单据、报表引擎,最近进行了较大的更新,尤其是几年来在生产项目中应用取得了非常好的效果,特别写篇介绍文字给大家分享一下。
首先先介绍几个名词:
- OpenDocument:国际标准文档格式,开源办公软件 OpenOffice.org/LibreOffice 的 ODT/ODS 即为 OpenDocument 格式。
- OfficeOpenXML:同样是国际标准文档格式,由 Microsoft 定义,MS-Office 的 DOCX/XLSX 等即为 OfficeOpenXML 格式。
简介
MaltReport 实际上是一个通用的模板文档生成系统,其用途不仅用于生成报表,也可以用来生成合同、预算报告、标书等等任何需要格式与数据相结合的文档,其中的 XLS/ODS 模板尤其适合大量数据导出的场合。
简单来说,MaltReport 是通过直接在内存中解析操作 OpenDocument 和 OfficeOpenXML 文件来实现报表和单据的生成,整个理念非常接近于 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】格式,命名为“template1.xml”。注意这里 Word 会把文件的扩展名设为 XML。
在 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。
Excel 的模板也是类似的操作:
注意,显示为 #VALUE! 的单元格是因为我们把此单元格设为数字格式,但是模板占位符不是数字所以 Excel 报错,但并不影响报表生成。
第三步,在 C# 代码里加载、渲染并生成报表
var dt = new DataTable("Employees"); //Fill the DataTable
var connectionString = @"Version=3,uri=file://./Database/northwind.db";
using (var connection = new SqliteConnection(connectionString))
{
var sql = "SELECT FirstName, LastName, HireDate, BirthDate, Address FROM Employees";
var adapter = new SqliteDataAdapter();
adapter.SelectCommand = new SqliteCommand(sql, connection);
adapter.FillSchema(dt, SchemaType.Source);
adapter.Fill(dt);
} var renderContext = new Dictionary<string, object>()
{
//Plain old types
{"title", "EMPLOYEES"},
{"property1", "Property 1"},
{"property2", "Property 2"}, //Strong types
{"orm_employees",
new List<Employee>()
{
new Employee("Micheal Scott", "Address 1", ),
new Employee("Andy Bernard", "Address 3", ),
new Employee("Dwight Shurte", "Address 1", ),
new Employee("Jim Halpert", "Address 2", ),
new Employee("Pam Beesly", "Address 4", ),
}
}, {"employees", dt}, //DataTable is ok {"now", DateTime.Now}, //DateTime is ok too
};
上面的代码演示了 RenderContext 的概念用法,RenderContext 为模板中所包含的数据的容器,本身是一个 IDictionary<string, object> 类型,key 为变量名,value 为变量值,变量值支持原始类型、强类型类、结构、DataTable 等。
有了模板和要填充到模板中的数据我们只需加载模板、编译模板然后渲染模板即可,非常简单直观的 API:
var template = new WordMLTemplate(); template.Load("template1.xml"); //第一步加载模板文件 template.Compile(); //第二步编译模板 //第三部渲染模板
var resultDoc = template.Render(ctx); //第四步,保存生成的报表文件,也可保存到 MemoryStream
using (var resultFile3 = File.Open("result.doc", FileMode.Create, FileAccess.ReadWrite))
{
resultDoc.Save(resultFile3);
}
生成了名为“result.doc”的报表文件,试着用 Word 打开:
Voila! 全部搞定!
在项目的源代码里包含 Sandwych.Reporting.Demo 演示程序,里面包含生成 DOC/XLS/ODT/ODS 的全部样例。
下一步的开发计划
- 支持最新版 MS-Office 的 DOCX/XLSX 文档格式,因为我比较喜欢用 LibreOffice 做报表及打印工具,所以 MS-Office 的格式支持度没有 ODS/ODT 高;
- 支持二维码一维码图片生成及文档嵌入;
- 异步 IO 支持;
- 移植到 .Net Core,不过应该是个长期的过程,最少得等 .Net Core 2.0 出来以后。
常见问题解答
Q: 这到底是特么的什么东西?
A: 一句话来说 MaltReport 是 DOC/XLS/ODT/ODS 文档生成器。
Q: 这跟 NPOI 有什么区别?
A: MaltReport 只能生成不能读取 MS-Office 文件,但是单论生成的话 MaltReport 的性能远远超过 NPOI,而且不止一个数量级。MaltReport 跟 NPOI 的理念不同,不需要你用代码去设置 XLS/DOC 文件的样式、表格高度之类的格式工作,你直接在 Excel/Word 里设置好让 MaltReport 照着模板生成就可以了,程序需要提供的只是填充模板的数据。
Q: ODT/ODS 是什么文件,我怎么没见过?
A: ODT/ODS 是 LibreOffice/OpenOffice 使用的文档格式,ODT 等同于 DOCX、ODS 等同于 XLSX。LibreOffice 类似于免费开源版的 MS-Office。我们主力支持 ODS/ODT 文件是因为我们推荐使用 LibreOffice 作为报表设计、查看、打印及格式转换工具。举个例子来说,你可以把 LibreOffice 的“绿色版”打包到你的程序里,直接用作报表工具,这样难道不是很科学。还有更秒的是 LibreOffice 支持无界面后台网络服务的“无头”模式,你可以通过 RPC 直接访问 LibreOffice 的文件转换、打印各种功能。
关于调用 LibreOffice 实现文件格式转换请参考代码里的 Sandwych.Reporting.JODConverterDemo 项目。
项目地址及其他
联系我: oldrev AT gmail.com 也可加我 QQ: 55-43-1671
项目 github: https://github.com/oldrev/maltreport
项目 nuget:https://www.nuget.org/packages/MaltReport2
附加福利:支持图片、支持 .NET Standard 1.6 的开发版本在 vnext 分支里。
很惭愧,就做了一点微小的工作。如果觉得本项目对您有用,您可以在 github 上给我点星星/fork,或者点击本文下方的“推荐”,您的赞赏是我不断完善本项目的动力。
MaltReport2:通用文档生成引擎的更多相关文章
- “Word自动更改后的内容保存到通用文档模板上。是否加载该模板?“的解决办法
在win7系统下,Word2010出现了不能正常关闭.打开一个已有word文档,点击右上角关闭按钮后,先提示"word已停止工作,windows正在检查该问题的解决方案",随后提示 ...
- 安装doxygen(一个自动文档生成工具)+Graphviz图形可视化软件
参考文章: http://www.fmddlmyy.cn/text21.html http://www.cnblogs.com/duguguiyu/archive/2008/06/29/1231852 ...
- 【C#附源码】数据库文档生成工具支持(Excel+Html)
[2015] 很多时候,我们在生成数据库文档时,使用某些工具,可效果总不理想,不是内容不详细,就是表现效果一般般.很多还是word.html的.看着真是别扭.本人习惯用Excel,所以闲暇时,就简单的 ...
- 微软开源全新的文档生成工具DocFX
微软放弃Sandcastle有些年头了,微软最近开源了全新的文档生成工具DocFX,目前支持C#和VB,类似JSDoc或Sphinx,可以从源代码中提取注释生成文档之外,而且还有语法支持你加入其他的文 ...
- DBImport v3.44 中文版发布:数据库数据互导及文档生成工具(IT人员必备)
前言: 距离上一个版本V3.3版本的文章发布,已经是1年10个月前的事了. 其实版本一直在更新,但也没什么大的功能更新,总体比较稳定,所以也不怎么写文介绍了. 至于工作上的事,之前有半年时间跑去学英语 ...
- .NET平台开源项目速览(4).NET文档生成工具ADB及使用
很久以前就使用ADB这个工具来生成项目的帮助文档.功能强大,在学习一些开源项目的过程中,官方没有提供CHM帮助文档,所以为了快速的了解项目结构和注释.就生成文档来自己看,非常好用.这也是一个学习方法吧 ...
- (转)Doxygen文档生成工具
http://blog.csdn.net/lostaway/article/details/6446786 Doxygen 是一个支持 C/C++,以及其它多种语言的跨平台文档生成工具.如同 Java ...
- Sandcastle----强大的C#文档生成工具
最近客户索要产品的二次开发类库文档,由于开发过程中并没有考虑过此类文档,而且项目规范比较,持续时间比较长,经手人比较多,还真是麻烦,如果人工制作文档需要是一个比较大的工程.还好有这个文档生成工具,能够 ...
- JAVA基础学习之命令行方式、配置环境变量、进制的基本转换、排序法、JAVA文档生成等(1)
1.命令行方式 dos命令行,常见的命令: dir:列出当前目录下的文件以及文件夹 md:创建目录 rd:删除目录 cd:进入指定目录 cd..:退回到上一级目录 cd/:退回到根目录 del:删除文 ...
随机推荐
- 《Java 多线程编程核心技术》- 笔记
作为业务开发人员,能够在工作中用到的技术其实不多.虽然平时老是说什么,多线程,并发,注入,攻击!但是在实际工作中,这些东西不见得用得上.因为,我们用的框架已经把这些事做掉了. 比如web开发,外面有大 ...
- Dash by Plotly 学习笔记
一.介绍 1.dash 是什么 dash 是一个基于 Flask (Python) + React 的 web 框架. 入门指南:https://dash.plot.ly/getting-starte ...
- 消除浏览器对input的自动填充
在做登录相关的页面时,常遇到这样的现象,浏览器input的自动填充行为. 原因 设置 input 的 type 属性为 password 后,当页面进行过提交,并且允许浏览器记住密码后,那么再次加载该 ...
- AI - 学习路径(Learning Path)
初见 机器学习图解 错过了这一篇,你学机器学习可能要走很多弯路 这3张脑图,带你清晰人工智能学习路线 一些课程 Andrew Ng的网络课程 HomePage:http://www.deeplearn ...
- git push 到github时,报错:ERROR: Permission to xxx.git denied to user
之前我电脑的本地git已经登录了一个github账号,今天想换另外一个新的github账户来提交项目,相当于同一台电脑使用两个github账户. 于是我先修改用户名和邮箱. git config -- ...
- 【原】以setTimeout来聊聊Event Loop
平时的工作中,也许你会经常用到setTimeout这个方法,可是你真的了解setTimeout吗?本文想通过总结setTimeout的用法,顺便来探索javascript里面的事件执行机制. setT ...
- ES6躬行记(1)——let和const
古语云:“纸上得来终觉浅,绝知此事要躬行”.的确,不管看了多少本书,如果自己不实践,那么就很难领会其中的精髓.自己研读过许多ES6相关的书籍和资料,平时工作中也会用到,但在用到时经常需要上搜索引擎中查 ...
- MySQL:测试题
一,表关系的练习测试 请创建如下表关系,并建立相关约束 一,创建表结构数据: 创建的话肯定先创建没有关联的表,老师,课程(关联老师),年级,班级(关联年级),学生(关联班级), 班级任职表 (关联老师 ...
- 【Javascript系列】变量作用域
问题描述 本篇文章主要讲解javascript变量及其作用域. 1 内容区 在js中,变量大致可分为全局变量(全局作用域)和局部变量(局部作用域): 用关键字var定义变量(全局变量,可以省略va ...
- Linux上磁盘热插拔
首先获取scsi设备的信息. [root@server2 ~]# lsscsi [:::] disk VMware, VMware Virtual S 1.0 /dev/sda [:::] cd/dv ...