如果您具有业务应用程序开发的经验,那么很可能会遇到要求该应用程序具有灵活的报告机制的需求。 我工作的公司主要专注于开发业务解决方案,而报告是必不可少的,的确,它必须包含我们开发的所有企业系统的方面。 为了在我们的系统中实现灵活的报告,我们已经开发了自己的开源报告生成器-YARG (又一个报告生成器), 该开源文件 (根据Apache 2.0许可分发)。 现在,YARG是CUBA平台报告的核心-CUBA 平台本身就是我们开发的所有系统的基础。

为什么需要开发一个新的

首先,让我指出我们不是车轮发明家。 只要这些解决方案适合我们,我们就一直在寻找与之集成的解决方案。 不幸的是,在这种情况下,我们找不到符合我们确定的以下要求的任何开源工具:

  • 以模板格式生成报告和/或将输出转换为PDF
  • 避免使用外部工具来创建报告模板(Microsoft Office或Libreoffice应该足够了)
  • 支持各种格式的模板: DOC,ODT,XLS,DOCX,XLSX,HTML
  • 能够将复杂的XLSXLSX模板与图表,公式等配合使用。
  • 能够使用HTML布局和插入/嵌入图像
  • 拆分出数据层(报告结构和数据获取)和表示层(报告模板)
  • 启用各种数据获取方法,例如SQL,JPQL或Groovy脚本
  • 与IoC框架( SpringGuice )集成的能力
  • 将该工具用作独立应用程序的功能,以便能够在Java生态系统之外使用它(例如,使用PHP生成报告)
  • 以透明XML格式存储报告结构

我们可以找到的最接近的工具是JasperReports ,但是有一些阻止程序使我们无法使用它:

  • 免费版本无法生成DOC报告(有一个提供此功能的商业库)
  • XLS报告非常有限,无法使用图表,公式和单元格格式
  • 要创建报告,必须具有一定的技能和知识,以及如何使用非常特定的工具(例如iReports
  • 数据层和表示层之间没有明确的分隔

当然,我们研究了许多其他不同的工具,但是我们发现的所有其他库都集中在某种特定格式上。 我们希望有一个万能的报表功能-一种用于所有报表的工具。

考虑到以上列出的所有观点和想法,我们决定开发另一种定制的报告生成工具。

什么是内幕

当我们启动YARG时,找到用于XLS集成的库( POI-HSSFJXLS等)不是问题。 我们决定选择Apache POI作为最受欢迎和受支持的库。

DOC集成的情况则完全相反。 开源市场( POI-HWPFCOMUNO Runtime )只有很少的选择。 POI-HWPF库在许多方面都非常有限,我们不认为它是合适的选择。 我们必须在COMUNO运行时之间进行选择这实际上是用于OpenOffice服务器端集成的API。

因此,经过深入调查,我们决定选择UNO Runtime ,主要是因为成功将其用于以完全不同的语言编码的系统(例如Python,Ruby,C#等)的人们的积极反馈。

尽管POI-HSSF的使用非常简单(图表除外),但我们在集成UNO Runtime时面临许多挑战:

  1. 没有明确的API可用于表格
  2. 每次生成报告时,OpenOffice都会启动。 最初,我们使用bootstrapconnector来管理OpenOffice进程,但后来很明显,在许多情况下,它不会在生成报告后终止该进程。 因此,我们不得不重新实现OpenOffice启动和关闭的逻辑(感谢jodconverter开发人员,他们在此问题上指出了许多好主意)
  3. 此外, UNO Runtime (和OpenOffice Server本身)在线程安全方面也存在严重问题,如果发生内部错误,这可能导致服务器冻结或终止自身。 为了克服这个问题,我们必须实现一种机制,以便在服务器发生故障时重新启动报告,这显然会对性能造成不利影响

后来,当DOCX4J库变得非常成熟和流行时,我们支持XLSX / DOCX。 DOCX4J库的主要优点是,它提供了对文档结构的必要的低级访问(基本上,您使用XML进行操作)。 使用DOCX4J的另一个好处是,它不需要OpenOffice服务器集成即可生成DOCX报告。

另外,还可以使用带有Freemarker标记的文档作为报告模板。 我们通常使用它来生成非常自定义的HTML报表,然后将结果转换为PDF

最后,YARG基础结构是以可扩展的方式开发的,因此有经验的用户可以自己实现与任何其他模板类型的集成。

你好世界报告

让我们认识一下YARG。 报告生成器的主要思想是将数据层和表示层分开。 数据层使脚本编制或直接SQL查询能够获取所需的信息,而表示层则代表所获取数据的标记。

YARG的所有报告均由所谓的“乐队”组成Band是将数据和表示层链接在一起的东西。 因此,每个乐队都知道从何处获取数据以及将数据放置在模板中的位置。

例如,我们希望将所有员工打印到Excel电子表格中。 我们将需要创建“ Staff”乐队并定义一个SQL查询以获取员工列表:

select name, surname, position from staff

Java代码

ReportBuilder reportBuilder = new ReportBuilder();
ReportTemplateBuilder reportTemplateBuilder = new ReportTemplateBuilder().documentPath("/home/haulmont/templates/staff.xls").documentName("staff.xls").outputType(ReportOutputType.xls).readFileFromPath();
reportBuilder.template(reportTemplateBuilder.build());
BandBuilder bandBuilder = new BandBuilder();
ReportBand staff= bandBuilder.name("Staff").query("Staff", "select name, surname, position from staff", "sql").build();
reportBuilder.band(staff);
Report report = reportBuilder.build();Reporting reporting = new Reporting();
reporting.setFormatterFactory(new DefaultFormatterFactory());
reporting.setLoaderFactory(new DefaultLoaderFactory().setSqlDataLoader(new SqlDataLoader(datasource)));ReportOutputDocument reportOutputDocument = reporting.runReport(new RunParams(report), new FileOutputStream("/home/haulmont/reports/staff.xls"));

剩下的唯一事情就是创建XLS模板:

开始了! 只需运行该程序即可享受效果!

没有Java的进阶范例

假设我们有一个书店网络。 需要生成一个XLS报告,以显示已售书的列表,并参考售书的书店。 而且,我们没有Java开发人员,只有拥有XMLSQL基本技能的系统管理员。

首先,我们需要为报告创建XLS模板:

如您所见,我们定义了两个命名区域(对应于乐队):商店(蓝色)和书籍实例(白色)。

现在,我们必须从数据库中获取所需的数据:

select shop.id as "id", shop.name as "name", shop.address as "address"
from store shopselect book.author as "author", book.name as "name", book.price as "price",  count(*) as "count"
from book book where book.store_id = ${Shop.id}
group by book.author, book.name, book.price

最后,我们使用XML声明报告的波段结构:

<?xml version="1.0" encoding="UTF-8"?>
<report name="report"><templates><template code="DEFAULT" documentName="bookstore.xls" documentPath="./test/sample/bookstore/bookstore.xls" outputType="xls" outputNamePattern="bookstore.xls"/></templates><rootBand name="Root" orientation="H"><bands><band name="Header" orientation="H"/><band name="Shop" orientation="H"><bands><band name="Book" orientation="H"><queries><query name="Book" type="sql"><script>select book.author as "author", book.name as "name", book.price as "price",  count(*) as "count" from book  where book.store_id = ${Shop.id} group by book.author, book.name, book.price</script></query></queries></band></bands><queries><query name="Shop" type="sql"><script>select shop.id as "id", shop.name as "name", shop.address as "address" from store shop</script></query></queries></band></bands><queries/></rootBand>
</report>

让我们启动报告并查看结果(下面的“ 独立”部分描述了如何运行报告):

该用例表明,您可以引用父带:book.store_id = $ {Shop.id}。 这使我们能够过滤每个特定书店出售的书籍。

一个更高级的例子

现在,我们创建一个发票报告。 我们将创建DOCX文档,然后转换为不可变形式– PDF文档。 为了说明如何加载数据的另一种方式,我们将使用groovy脚本,而不是直接的SQL查询:

<?xml version="1.0" encoding="UTF-8"?>
<report name="report"><templates><template code="DEFAULT" documentName="invoice.docx" documentPath="./test/sample/invoice/invoice.docx" outputType="pdf" outputNamePattern="invoice.pdf"/></templates><formats><format name="Main.date" format="dd/MM/yyyy"/><format name="Main.signature" format="${html}"/></formats><rootBand name="Root" orientation="H"><bands><band name="Main" orientation="H"><queries><query name="Main" type="groovy"><script>return [['invoiceNumber':99987,'client' : 'Google Inc.','date' : new Date(),'addLine1': '1600 Amphitheatre Pkwy','addLine2': 'Mountain View, USA','addLine3':'CA 94043','signature':<![CDATA['<html><body><b><font color="red">Mr. Yarg</font></b></body></html>']]>]]</script></query></queries></band><band name="Items" orientation="H"><queries><query name="Main" type="groovy"><script>return [['name':'Java Concurrency in practice', 'price' : 15000],['name':'Clear code', 'price' : 13000],['name':'Scala in action', 'price' : 12000]]</script></query></queries></band></bands><queries/></rootBand>
</report>

您可能已经注意到,Groovy脚本返回List <Map <String,Object >>对象。 因此,每个项目都表示为一个键(参数名称)和值(参数值)。

最后,我们需要创建一个DOCX模板:

要将底部表格链接到书籍列表,我们使用## band = Items标记。

生成报告后,我们得到以下输出:

IoC框架集成

如前所述,其中一项要求是提供集成到IoC框架( SpringGuice )的能力。 我们将YARG用作CUBA平台(我们用于企业应用程序开发的高级Java框架)中强大的报告引擎的一部分。 CUBA采用Spring作为IoC机制,让我们看一下YARG如何集成到平台中:

<bean id="reporting_lib_Scripting" class="com.haulmont.reports.libintegration.ReportingScriptingImpl"/>
<bean id="reporting_lib_GroovyDataLoader" class="com.haulmont.yarg.loaders.impl.GroovyDataLoader"><constructor-arg ref="reporting_lib_Scripting"/>
</bean>
<bean id="reporting_lib_SqlDataLoader" class="com.haulmont.yarg.loaders.impl.SqlDataLoader"><constructor-arg ref="dataSource"/>
</bean>
<bean id="reporting_lib_JpqlDataLoader" class="com.haulmont.reports.libintegration.JpqlDataDataLoader"/>
<bean id="reporting_lib_OfficeIntegration"class="com.haulmont.reports.libintegration.CubaOfficeIntegration"><constructor-arg value="${cuba.reporting.openoffice.path?:/}"/><constructor-arg><list><value>8100</value><value>8101</value><value>8102</value><value>8103</value></list></constructor-arg><property name="displayDeviceAvailable"><value>${cuba.reporting.displayDeviceAvailable?:false}</value></property><property name="timeoutInSeconds"><value>${cuba.reporting.openoffice.docFormatterTimeout?:20}</value></property>
</bean>
<bean id="reporting_lib_FormatterFactory"class="com.haulmont.yarg.formatters.factory.DefaultFormatterFactory"><property name="officeIntegration" ref="reporting_lib_OfficeIntegration"/>
</bean>
<bean id="reporting_lib_LoaderFactory" class="com.haulmont.yarg.loaders.factory.DefaultLoaderFactory"><property name="dataLoaders"><map><entry key="sql" value-ref="reporting_lib_SqlDataLoader"/><entry key="groovy" value-ref="reporting_lib_GroovyDataLoader"/><entry key="jpql" value-ref="reporting_lib_JpqlDataLoader"/></map></property>
</bean>
<bean id="reporting_lib_Reporting" class="com.haulmont.yarg.reporting.Reporting"><property name="formatterFactory" ref="reporting_lib_FormatterFactory"/><property name="loaderFactory" ref="reporting_lib_LoaderFactory"/>
</bean>

为了将YARG集成到Spring Framework中,应注册以下bean:

  1. reporting_lib_Reporting –提供对核心报告生成功能的访问。 report_lib_FormatterFactory –将输出管理为不同的格式(DOCX,XSLX,DOC等)
  2. reporting_lib_LoaderFactory –提供数据加载功能(包含与不同源相对应的多个Bean)
  3. reporting_lib_OfficeIntegration –将报表生成器与OpenOffice服务器集成(生成DOC和ODT报表所需)

如您所见,YARG可以轻松地嵌入到您的应用程序中。

独立使用

YARG的另一个有价值的功能是它可以用作独立的应用程序。 从技术上讲,如果已安装JRE,则可以从命令提示符下运行报告生成器。 例如,如果您有服务器端PHP应用程序,并且想要在应用程序中启用报告,则只需创建一个XLS模板,以XML声明报告结构,然后从命令提示符下启动YARG:

yarg -rp ~/report.xml -op ~/result.xls “-Pparam1=20/04/2014”

CUBA平台提供的更多功能

YARG已深入集成到CUBA平台中,并充当该平台中实现的强大报告机制的核心引擎。

首先,您可以使用CUBA Studio一键式嵌入报告( 此处提供只读演示版):

CUBA为报表管理提供了方便的用户界面:

  • 报告浏览器,带有导入/导出和运行报告的选项。
  • 报告编辑器允许您创建任何复杂性的报告(定义带,输入参数,管理模板,使用Groovy,SQL和JPQL选择数据):
  • CUBA引入了报告向导功能。 借助向导,即使对编程的了解有限,任何用户都可以快速创建报告:

总结这篇文章,让我跳过通常无聊的深层思考(特别是因为可以在此处找到所有信息),并提出了一些我最喜欢的报告:

因此,如果您有兴趣,请点击链接并了解更多信息! 请注意,YARG是完全免费的,可以在GitHub上使用 。

翻译自: https://www.javacodegeeks.com/2015/09/yet-another-report-generator.html

还有另一个报告生成器?相关推荐

  1. 用一个程序生成另一个程序_还有另一个报告生成器?

    用一个程序生成另一个程序 如果您具有业务应用程序开发的经验,那么很可能会遇到要求该应用程序具有灵活的报告机制的需求. 我工作的公司主要专注于开发业务解决方案,而报告是必不可少的,实际上,它必须包含我们 ...

  2. aurelia.js_Aurelia.io中的组成:创建报告生成器

    aurelia.js 在学习新框架时,我们经常会看到一些描述框架基本功能的简单演示,例如著名的TodoMVC Application . 太好了–我的意思是谁不喜欢Todo应用,对吗? 今天好了,我们 ...

  3. linux 日志报告生成器,Linux报告生成器工具awk

    Linux报告生成器工具awk awk:根据输入的信息格式化后显示出来 1.1.awk基本用法 awk [options] 'script' file1,file2,.... 或 awk [optio ...

  4. 可视化报告生成器FastReport VCL创建条形码教程指南

    报表生成器FastReport VCL是用于在软件中集成商务智能的现代解决方案.它提供了可视化模板设计器,可以访问最受欢迎的数据源,报告引擎,预览,将过滤器导出为30多种格式,并可以部署到云,Web, ...

  5. 《JAVA练习题目7》 定义一个素数生成器类PrimeGenerator,用于生成给定区间内的所有素数。(类PrimeGenerator都由类Main代替)

    题目内容: 定义一个素数生成器类PrimeGenerator,用于生成给定区间内的所有素数.要求PrimeGenerator类具有: 属性:start(区间起始值),end(区间终止值),两个属性均为 ...

  6. 利用 Laravel 花 2 小时撸一个 RSS 生成器

    Wait no longer! Create RSS feeds for all websites you care about and read them from the comfort of y ...

  7. 有趣的深度学习——使用TensorFlow 2.0 + RNN 实现一个古体诗生成器

    一.前言 很早之前,我曾经写过一个古体诗生成器(详情可以戳TensorFlow练手项目二:基于循环神经网络(RNN)的古诗生成器),那个时候用的还是Python 2.7和TensorFlow 1.4. ...

  8. 收藏一个字帖生成器,在线生成字帖

    我自用的实用工具网站收藏 一个字帖生成器网站,可以在线生成字帖 学习巴士,www.3415.cn 挺好用的,几十个字帖生成功能.

  9. c语言中定义密码为英文字母,请设计 一个密码生成器,要求随机生成4组10位密码(C语言)...

    请设计 一个密码生成器,要求随机生成4组10位密码(密码只能由字母和数字组成),每一组必须包含至少一个大写字母,每组密码不能相同,输出生成的密码. #include #include #include ...

最新文章

  1. Codeforces Round #383 (Div. 1) C(二分图)
  2. mariadb mysql同步_mysql/mariadb 主从复制实现数据库同步
  3. 交互式SQL(数据定义部分)
  4. H5新增的标签以及属性
  5. 【Ubuntu】Windows硬盘安装Ubuntu14.04
  6. 合并两个无序数组java_Java实现十大排序算法(上)
  7. 【建议收藏】这个工具专门用于寻找路由器中的安全漏洞
  8. MS SQL开发命名规则
  9. C#.NET快速开发框架-企业版V4.0截图打包下载
  10. 小米扫地机器人换了边刷很响_科沃斯除菌地宝N8 PRO VS 小米扫拖一体机,谁更强?...
  11. vs2008软件测试实战 3 web test(1)
  12. 写c++好的软件_族谱家谱制作怎么写?专业的家谱族谱编辑制作软件哪个好
  13. java触屏改_一个JAVA游戏改键改触屏的教程!
  14. C语言关于链表的代码看不懂?一篇文章让你拿捏二级指针并深入理解函数参数列表中传参的多种形式
  15. vue2中provide/inject的使用和响应式传值
  16. android系统文件夹
  17. Python自定义排序规则:functools.cmp_to_key()
  18. 【Android工具】免费好用无广告安卓手机解压缩软件工具:ZArchiver
  19. Python 调用Vpython编写三体运动模型(不含碰撞)
  20. 【英语阅读】经济学人 | 零售商纷纷撤离商业街之际,宜家为何反其道而行之?

热门文章

  1. 数据库的实现【笔记】
  2. SpringBootAdmin
  3. ReactiveLodeBalancerClientFilter响应式负载均衡代理
  4. SpringMVC中使用作用域对象完成数据的流转
  5. mysql update field_mysql-更新表与另一个选择,但字段是SUM(someField)
  6. 公式冒号是什么意思_三角学中,这么一堆公式其实就说了2个事而已
  7. qq空间说说服务器维护,如何解决QQ空间说说发表不了
  8. nginx应用领域分类+事件模型
  9. java动态代理和cglib动态代理
  10. wxpay-api:pay_J2Pay – API响应