开源的报告自动化解决方案

网站和移动应用程序的开发人员通常需要控制PDF页面的准备,以便打印或通过邮件将其发送给客户。

PDF文件可以完全控制页面上文本和图形的显示。 不幸的是,PHP,JS(Web),Java或Swift(分别为Android和iOS)的标准工具中没有包含用于生成动态填充PDF文件的库。 在本文中,我想向您介绍用于生成PDF文件的开源解决方案。



JasperReports是一个开源Java库,用于生成动态填充的文件。 它具有许多用于创建复杂报告表格的工具,包括PDF格式,但也可以使用其他格式:RTF,DOCX,HTML,XLS,XLS,CSV和XML。 换句话说,开发一种表格,制作一种布局就足够了,并且可以将其导出为上述任何一种格式。

也有不错的库,例如PHP的PDFLib(商业版)及其PDFLib-Lite的开源版本。 确实,该库非常昂贵,并且lite版本仅在源代码中分发,并且在开发环境中安装它时,此限制可能会成为问题。

PDFbox是另一个用于处理PDF文档的开源Java库。 它使您可以创建新的PDF文档,管理现有文档并能够从中提取内容。 但是与JasperReports不同,它没有UI(用户界面)。

我认为JasperReports在与报告相关的大型项目中特别有用,不仅限于PDF格式。 它具有在项目中实现它所需的一切:轻松创建复杂的报表表单,方便布局的UI,服务器应用程序以及与前端的简单集成。

在本文中,我将介绍以下主题:

  • 安装开发环境和服务器应用程序。
  • 创建自动从数据库填充的PDF文件。
  • 将服务器应用程序与前端集成,以获取创建的PDF。

要在您的项目中开始使用JasperReports,您需要下载两个应用程序:JaspersoftStudio(以下称为工作环境 )和JasperServer(称为服务器应用程序)

JaspersoftStudio是具有内置JasperReports Java库的基于Eclipse的开发环境,在其中开发了动态或静态PDF文件:例如,票据,收据,合同,分析图等。

JasperServer是一个服务器应用程序,从JaspersoftStudio部署和存储文件。 可以从移动或Web应用程序访问它们。 JasperServer有一个UI,使用它可以查看报告,为不同用户创建帐户并为他们提供适当的访问权限。 您还可以配置邮件列表到电子邮件(计划程序)。

设置工作环境和服务器应用程序


您可以使用上面的链接下载和安装应用程序。 设置两个应用程序后,有必要建立从工作环境到服务器应用程序的连接。

服务器→创建JasperReports服务器连接→指定首选的服务器名称, URL ,用户名和密码。 单击测试连接以验证与服务器的连接已建立。 如果看到成功 ,请继续。



创建一个动态填充的PDF并将其发布


我们安装了开发环境,服务器并在它们之间建立了连接。 现在,让我们创建一个动态填充的原始PDF文件,该文件在启动(生成)时将从PostgreSQL中获取数据,并将其安装在服务器应用程序上。

首先,您应该将数据源(在我们的示例中为PostgreSQL)固定到工作环境中,PDF将在该工作环境中获取数据。 然后,让我们开始开发第一个PDF文件。

数据适配器→创建数据适配器→数据库JDBS连接并指定连接数据:

  1. JDBC驱动程序 -PostgreSQL(org.postgresql.Driver)。 如果您的DBMS没有驱动程序,则可以在“驱动程序类路径”选项卡中安装必要的驱动程序。
  2. JDBC URL-由它们的主机,端口和数据库名称组成。
  3. 用户名密码 -从您的DBMS帐户登录。



我们单击已经熟悉的“ 测试”按钮,并成功(成功)连接数据库-Finish

从该数据库中,将在生产环境中填充PDF。 由于我们计划将第一个PDF文件部署到服务器,因此让我们将相同的数据源安装到服务器应用程序中:

数据源→添加资源→数据源,然后重复以上所有步骤。

现在您可以创建PDF了。 JasperReports中的源以JRXML格式存储-这是具有有线标签和JasperReports API可以使用的属性的XML。

单击文件→新建→Jasper报告→空白A4→指定JRXML文件的名称→完成



创建新项目后,您将看到以下图片:



七个不同的块-每个块都有自己的行为,这些行为与其他块不同。 您可以在文档中阅读有关此内容的更多信息。 通过单击源代码,您可以看到这些块的结构:

<?xml version="1.0" encoding="UTF-8"?> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Example" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ae9517f6-ff0b-41bb-a8dc-82196190e940"> <queryString> <![CDATA[]]> </queryString> <background> <band splitType="Stretch"/> </background> <title> <band height="79" splitType="Stretch"/> </title> <pageHeader> <band height="35" splitType="Stretch"/> </pageHeader> <columnHeader> <band height="61" splitType="Stretch"/> </columnHeader> <detail> <band height="125" splitType="Stretch"/> </detail> <columnFooter> <band height="45" splitType="Stretch"/> </columnFooter> <pageFooter> <band height="54" splitType="Stretch"/> </pageFooter> <summary> <band height="42" splitType="Stretch"/> </summary> </jasperReport> 

因此,让我们删除五个额外的块,仅保留两个:标题和详细信息。 删除按钮(Windows)或Backspace (OS X)将帮助我们完成此任务。

现在添加两个元素。 您可以通过两种方式添加新元素:在XML结构中注册容器(“ 源”按钮),或从右上方的“ 调色板面板”窗口-静态文本中拖动所需的元素,其中将包含字段名称和文本字段,在其中填充从数据库中提取的变量字段:

 <?xml version="1.0" encoding="UTF-8"?> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Example" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ae9517f6-ff0b-41bb-a8dc-82196190e940"> <queryString> <![CDATA[]]> </queryString> <background> <band splitType="Stretch"/> </background> <title> <band height="30" splitType="Stretch"> <staticText> <reportElement x="0" y="0" width="100" height="30" uuid="7b697ed9-f52a-483c-965e-f0b2dc6130c1"/> <text> <![CDATA[Static Text]]> </text> </staticText> </band> </title> <detail> <band height="169" splitType="Stretch"> <textField> <reportElement x="0" y="0" width="100" height="20" uuid="41002e0b-ddb2-4e4b-a049-10810ab51208"/> <textFieldExpression> <![CDATA["Text Field"]]> </textFieldExpression> </textField> </band> </detail> </jasperReport> 

可以在queryString标记中编写数据库中的查询,也可以单击“数据集和查询编辑器”对话框按钮。 之后,将打开一个新窗口,您需要在其中选择数据源(1),编写查询(2)并声明字段变量。 读取字段按钮(3)将在有效请求后自动读取所有字段。 要查看数据,请单击数据预览 (4)。



太好了! 我们得到了四个String类型的字段,现在我们几乎可以对它们执行任何操作。 例如,我们只列出它们并写一些逻辑。

我们在“静态文本”元素中打印必填字段的名称,并将其放置在“标题”容器中。 我们将在“细节”容器的“文本字段”元素中指示变量字段,因为它们会相乘。 我们的PDF将显示姓名,城市和电子邮件地址。 为了不感到无聊,让我们在文本字段元素中使用第四个字段(客户的性别,性别)编写一个简单的逻辑。

我们执行以下操作:如果委托人是女性,则如果女士是女士,则将在姓名前添加女士。 为此,请使用Java三元运算符:

 <textFieldExpression> <![CDATA[$F{sex}.equals( "male" )?"Mr. "+$F{name}:"Mrs. "+$F{name}]]> </textFieldExpression> 

通过单击“ 源”按钮旁边的“ 预览” ,可以看到结果:



从屏幕截图中可以看到,PDF已成功组装:它获取了所有值并应用了逻辑,正确放下了Mrs. 和先生

我们还将获取City输入参数,以便可以按城市过滤数据。 这可以通过单击“大纲”窗口中的“ 参数”→“创建参数 ”,或通过添加具有名称属性的新参数标签来完成:

 <parameter name="City" class="java.lang.String"/> 

仅保留将参数添加到SQL查询中:

 SELECT Id, name, sex, city, email FROM users WHERE city = $P{City} 

我们将值San Francisco传递给City参数(在下一段中我将告诉您如何操作),然后点击数据预览以查看结果。



通过成功过滤数据收集了PDF。 我们走得更远

由于我们已经有了一个动态填充的PDF文件,因此我们可以将其上传到服务器,以便与前端应用程序进一步集成。 为此,请单击“将报告发布到JasperReports服务器”按钮→双击以打开服务器→选择要在其中下载PDF的服务器文件夹(在本例中为Reports )→ 下一步→从存储库中选择数据源→选择先前在服务器应用程序上创建的数据源→ 完成

前端整合


JasperReports API包括其自己的用于客户端与服务器交互的RESTful实现-REST v2 。 如果不合适,则可以使用简单的对象访问协议SOAP

我们将考虑REST v2。

可以使用四种主要的CRUD(创建-读取-更新-删除)操作方法:GET(获取),POST(添加,更改,删除),PUT(添加,替换),DELETE(删除)。 所有详细信息都可以在上面链接的文档中找到。

我们将考虑本文更通用和相关的GET方法。

 http://<host>:<port>/jasperserver[pro]/rest_v2/reports/path/to/report.<format>?<arguments> 

上面是一个同步请求,通过该请求,您可以在一个请求响应中获得文件(完成的PDF)输出(您可以在此处找到异步调用)。

我认为主机和端口一切都清楚了, / reports / path / to / report是被调用文件的URI。 由于我们将PDF文件的源代码(Example.jrxml)部署到了报表服务器文件夹,因此URI的完整版本将为:/ reports / reports / Example。

格式是一种格式(在我们的示例中为PDF)。
参数是参数。

上面,我们添加了City参数,并将其在请求中传递给值San Francisco,以过滤该城市的数据。

如果呼叫不是来自授权区域,则需要添加另外两个参数/属性: j_usernamej_password (用于授权的日志传递)。 默认情况下,服务器上的用户名和密码为jasperadmin

因此,我们得到以下URL:

 http://localhost:8080/jasperserver/rest_v2/reports/reports/Example.PDF?city=San Francisco&j_username=jasperadmin&j_password=jasperadmin 

这样我们得到了一个已经生成的PDF。 例如,当您通过浏览器的地址栏调用此URL时,文件应自动下载。

您可能需要显示PDF图像。 例如,如果客户只想查看文件,则可以PNG格式显示文档,如果要下载,则可以PDF格式显示。

以Java为例,使用PDFbox库,我们将了解如何从外部应用程序生成和选择PDF文件,然后将其转换为PNG。

下面是PullPDF类,其中的一种方法采用URL作为参数。

 import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.util.Base64; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.tools.imageio.ImageIOUtil; public class PullPDF { public String ConvertPDF2PNG(String valuefromParam) throws IOException { BufferedInputStream input_file = new BufferedInputStream(new URL(valuefromParam).openStream()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { PDDocument document = PDDocument.load(input_file); PDFRenderer pdfRenderer = new PDFRenderer(document); for (int page = 0; page < document.getNumberOfPages(); ++page) { BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB); ImageIOUtil.writeImage(bim, "png", baos); baos.flush(); byte[] encodedBytes = Base64.getEncoder().encode(baos.toByteArray()); valuefromParam = new String(encodedBytes); } } catch (Exception e) { } return valuefromParam; } } 

您可以使用例如Spring Framework获得相同的结果。 但是我试图展示一种通用的方法,在使用Java时可以在Android和Web上应用。

结论


如果要自动生成在线商店的简单支票,并且创建时间有限,那么建议您使用项目的本机工具或熟悉的框架。 由于花了很多时间安装JasperReports,因此可能不了解熟悉用于开发更复杂的报告表单的文档。 在其他情况下,JasperReports是报告自动化的良好开源解决方案。

Source: https://habr.com/ru/post/zh-CN461719/


All Articles