当前位置: 首页 > news >正文

使用Java动态数据生成PDF报告:简化您的报告导出流程

在当今的数据驱动世界中,能够快速且有效地将数据转化为可视化的报告是一项宝贵的技能。无论是商业分析、项目管理还是学术研究,PDF报告都是分享和存档信息的理想格式。在这篇博客中,我们将探讨如何使用Java编程语言结合iText库来动态生成包含动态数据的PDF报告。


为什么选择Java和iText?

Java作为一种广泛使用的编程语言,以其强大的功能和跨平台兼容性而闻名。iText是一个流行的Java库,专门用于处理PDF文档的创建和操作。通过结合这两者,我们可以轻松构建复杂、定制化的PDF报告,这些报告可以根据实时数据进行更新。

准备工作

在开始之前,请确保你的开发环境中已安装以下工具:

  • JDK(Java Development Kit)
  • 一个IDE(如IntelliJ IDEA或Eclipse)
  • Maven或Gradle(用于依赖管理)

还需要添加iText库作为项目的依赖项。对于Maven项目,可以在pom.xml文件中添加如下依赖:

1、引入Maven

        <!-- freemarker -->dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.30</version></dependency><!-- iText Core --><dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>7.1.16</version><type>pom</type></dependency><!-- HTML to PDF --><dependency><groupId>com.itextpdf</groupId><artifactId>html2pdf</artifactId><version>3.0.1</version></dependency>

2、创建templates文件存放模版:位置 src/main/resources/templates/invoice.html

下面是一个简单的例子,演示了如何从HTML模板生成PDF报告,并自动填充动态数据。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>${user[0].name}-测评报告</title><style type="text/css">body {font-size: 14px;font-family: 'SimSun', sans-serif; /* 注意单引号 */padding:0 30px;}.title {font-size: 24px;font-weight: bold;margin-top:0px;}</style>
</head><!--startprint-->
<body>
<p align="center" class="title">测试演示demo<br /> 测评报告
</p>
<table border="0" width="100%"><tr><td width="15%">姓名:${user[0].name}</td><td width="15%">性别:${user[0].sex}</td><td width="15%">年龄:${user[0].age}岁</td></tr>
</table>
<br/>
<table  id="tmpId"  cellpadding="2" cellspacing="0" width="100%" class="main_table"><tr><th width="45%" align="center" class="dotted_cell_right">姓名</th><th width="10%" align="center" class="dotted_cell_right">年龄</th><th width="10%" align="center" class="dotted_cell_right">性别</th></tr><#list listScore as score><tr><td class="dotted_cell_top dotted_cell_right">${score.name!}</td><td align="center" valign="middle" class="dotted_cell_top dotted_cell_right">${score.age!'-'}</td><td align="center" valign="middle" class="dotted_cell_top dotted_cell_right">${score.sex!'-'}</td></tr></#list><tr style="min-height: 40px;" ><td colspan="4" valign="top" class="dotted_cell_top ">测评结果:<br />测试很好已完成</td>
</tr>
<tr style="min-height: 40px;" ><td colspan="4" valign="top" class="dotted_cell_top">结果提示*:<br />没啥大事,多喝水就行</td>
</tr>
</table>
<p style="margin:5px 0">*本报告结果仅供临床参考,不作为诊断依据,需经专科医师明确诊断。</p>
<table border="0" width="100%"><tr><td>&nbsp;</td><td width="20%" align="right">测评者:长伞大师</td><td width="35%" align="right">报告时间:20220418</td></tr>
</table>
</body>
<!--endprint-->
</html>

3、创建项目fonts文件存放字体:将本地字体C:\Windows\Fonts\宋体 复制到src/main/resources/fonts/STSONG.TTF

4、上代码HTML转PDF生成


import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.layout.font.FontProvider;
import com.mdnov.ciipweb.examinfo.controller.SysExamController;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.springframework.stereotype.Service;import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;import java.io.ByteArrayOutputStream;
import java.io.IOException;@Service
public class PdfGeneratorService {/*** 解析 FreeMarker 模板并生成 PDF*/public byte[] generatePdf(String templateName, Map<String, Object> data) throws IOException, TemplateException {// 解析 HTMLString htmlContent = parseTemplate(templateName, data);return itexConvertHtmlToPdf(htmlContent);}/*** 解析 FreeMarker 模板,返回 HTML 字符串*/private String parseTemplate(String templateName, Map<String, Object> data) throws IOException, TemplateException {Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);cfg.setClassForTemplateLoading(SysExamController.class, "/templates");cfg.setDefaultEncoding("UTF-8");cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);Template template = cfg.getTemplate(templateName);try (StringWriter stringWriter = new StringWriter()) {template.process(data, stringWriter);return stringWriter.toString();}}/*** 将 HTML 转换为 PDF*/public byte[] itexConvertHtmlToPdf(String html) throws IOException {try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {// 创建PdfWriter实例PdfWriter writer = new PdfWriter(outputStream);// 创建PdfDocument实例并设置页面大小PdfDocument pdfDocument = new PdfDocument(writer);pdfDocument.setDefaultPageSize(PageSize.A4);// 加载支持中文的字体, 例如SIMSUNB.TTFURL fontUrl = getClass().getResource("/fonts/STSONG.TTF");if (fontUrl == null) {throw new IOException("字体文件未找到: /fonts/STSONG.TTF");}// 使用字体URL创建PdfFontPdfFont font = PdfFontFactory.createFont(fontUrl.toExternalForm(), "Identity-H", true);// 设置ConverterProperties并指定字体ConverterProperties converterProperties = new ConverterProperties();FontProvider fontProvider = new FontProvider();fontProvider.addFont(fontUrl.toExternalForm(), "Identity-H");converterProperties.setFontProvider(fontProvider);// 使用HtmlConverter将HTML转换为PDF,并应用字体HtmlConverter.convertToPdf(new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8)), pdfDocument, converterProperties);// 关闭PdfDocument对象pdfDocument.close();return outputStream.toByteArray();} catch (IOException e) {e.printStackTrace(); // 更好的错误处理方式throw e; // 或者根据需要处理异常}}}

5、开放接口调用

 (1) 将service注入到要调用的业务文件中

    private final PdfGeneratorService pdfGeneratorService;@Autowiredpublic SysExamController(PdfGeneratorService pdfGeneratorService) {this.pdfGeneratorService = pdfGeneratorService;}

(2)开始写对应接口逻辑:下面是模拟的参数,具体参数根据业务随便查询数据库也行

   /*** html生成PDF* @description TODO* @author 大博士.J* @date 2023/4/18 15:01*/@RequestMapping(value="/exportPdf")public ResponseEntity<byte[]> exportHtmlPdf(String examId) throws IOException, TemplateException {List<Map<String,Object>>  listScore = new ArrayList<>();Map<String, Object> data = new HashMap<>();data.put("name","张三");data.put("age","15");data.put("sex","女");listScore.add(data);data.put("name","李四");data.put("age","13");data.put("sex","男");listScore.add(data);Map<String, Object> dataModel = new HashMap<>();dataModel.put("user", listScore);dataModel.put("listScore", listScore);// 生成 PDF 字节流byte[] pdfBytes = pdfGeneratorService.generatePdf("ExportAssessReport.html", dataModel);// 动态设置文件名String fileName = listScore.get(0).get("name") + "-测评报告.pdf";// 设置 HTTP 头,返回 PDF 文件HttpHeaders headers = new HttpHeaders();// 对于不支持filename*的老浏览器提供一个基本的filename// Content-Disposition:attachment直接下载 inline 预览headers.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replace("+", "%20"));// 使用filename*提供UTF-8编码的文件名headers.add(HttpHeaders.CONTENT_DISPOSITION + ";**filename**", "filename*=utf-8''" + URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replace("+", "%20"));headers.setContentType(MediaType.APPLICATION_PDF);// 返回带有自定义文件名的PDF文件ByteArrayInputStream bis = new ByteArrayInputStream(pdfBytes);InputStreamResource resource = new InputStreamResource(bis);return new ResponseEntity<>(resource, headers, HttpStatus.OK);}

6、我简单的写了一个按钮调用

<input type="button" onclick="exportPdf()" title="导出Pdf"> //导出PDF
function exportPdf(examId){var url = "${pageContext.request.contextPath}/sysmanage/sysexam/exportHtmlPdf?examId=" + examId ;window.open(url);
}

7、测试成功:样式虽然难看,但你在HTML模版中可以自己写一下css这样生成的pdf更好看

总结

通过上述步骤,你可以轻松地使用Java和iText库来动态生成包含实时数据的PDF报告。这种方法不仅提高了工作效率,还增强了报告的专业性和可读性。希望这篇博客能帮助你在自己的项目中实现类似的功能。如果你有任何问题或需要进一步的帮助,请随时留言讨论!

 

相关文章:

  • AI语音助手 React 组件使用js-audio-recorder实现,将获取到的语音转成base64发送给后端,后端接口返回文本内容
  • kafka菜鸟教程
  • Android 证书 是什么
  • 在服务器上安装安装mysql
  • C#获取当前方法的命名空间、类名称、方法名称以及方法的参数信息
  • 【区块链通用服务平台及组件】京北方分布式身份管理平台 | FISCO BCOS 应用案例
  • axios 模拟实现
  • AI驱动商业变革:零售行业的智能化跃迁
  • NOIP2013提高组.货车运输
  • vue,uniapp解决h5跨域问题
  • Linux中的管道
  • UE5有些场景的导航生成失败解决方法
  • PHP使用pandoc把markdown文件转为word
  • C语言超详细结构体知识
  • C++学习:六个月从基础到就业——内存管理:new/delete操作符
  • 如何在 Electron 应用中安全地进行主进程与渲染器进程通信
  • 探索 HumanoidBench:类人机器人学习的新平台
  • 浅谈验证(Verification)和确认(Validation)
  • 【2】CICD持续集成-k8s集群中安装Jenkins
  • 小红书爬虫,小红书api,小红书数据挖掘
  • 神二十航天员公布
  • 广西大部气象干旱已达特旱
  • 华天酒店:2024年归母净亏损约1.81亿元,已连续亏损3年
  • 七大外贸省市,靠什么撑起一季度的出口?
  • 35部国产佳片入选 ,北影节·第32届大学生电影节启动
  • 泰国总理佩通坦:推迟与美国的关税谈判