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

SpringBoot + iTextPDF + Acrobat 构建动态PDF表单的完整实践

需求

有个单据需要打印,单据需要自定义内容展示,单据尺寸、各个模块的布局都是固定的,内容包含文本内容以及Barcode128条形码等,该如何实现?单据部分截图如下:

在这里插入图片描述

分析

整个单据包含多个模块,如果用html网页的形式去开发,那么布局开发比较复杂,所以采用iTextPDF + Acrobat 构建动态PDF表单的方式开发。先用Acrobat制作好pdf模板,然后使用iTextPDF框架将数据写入pdf模板后直接打印。

分析下其中的难点以及关键点问题

1、springboot如何整合itextpdf ,需要引入itextpdf 的哪些包?

2、表单中的文本域有横向和纵向排列,如何设置文本域纵向展示?

3、itextpdf 如何生成Barcode128条形码?

4、itextpdf 如何将Barcode128条形码插入pdf表单中?

5、表单中的Barcode128条形码有横向和纵向排列,如何设置Barcode128条形码纵向展示?

实现过程

下面就一步步解决上述问题。

引入itextpdf 相关依赖

1、对于iText 5.x版,需要引入核心库itextpdf和中文字体支持的依赖包itext-asian,如下:

<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version>
</dependency>

2、对于iText 7.x版本,引入核心类库itext7-core即可,当前最新版是9.3.0如下。

<dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>9.3.0</version><type>pom</type>
</dependency>

iText 7采用了全新的模块化架构,将功能拆分为多个独立模块,如itext7-core(核心功能)、itext7-layout(高级布局)、itext7-forms(表单处理)等。相比之下,iText 5采用单一架构,功能较为集中,许多模块相互混杂,引入的一些类可能不会被用到。新项目推荐使用iText 7‌,因为它具有更好的模块化设计和性能优化。

写入表单

1、第二个问题如何设置文本域纵向展示?这个主要是在Acrobat中编辑pdf表单来完成,双击文本域弹出文本域属性输入框->一般->通用属性->方向设置为90度。

2、第3到第5个问题,直接上代码进行解析,代码基于iText 7。

/*** 填充PDF表单并生成新文件** @param templatePath 模板文件路径* @param outputPath   输出文件路径* @param formData     表单数据* @param barcodeData  二维码数据* @param flattenForm  是否扁平化表单(使字段不可编辑)* @throws IOException 文件操作异常*/
public static void fillPdfForm(String templatePath, String outputPath, Map<String, String> formData,Map<String, String> barcodeData,boolean flattenForm) throws IOException {// 创建PDF读取器和写入器PdfReader reader = new PdfReader(templatePath);PdfWriter writer = new PdfWriter(new FileOutputStream(outputPath));PdfDocument pdfDoc = new PdfDocument(reader, writer);Document document = new Document(pdfDoc);// 获取表单对象PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);// 填充表单数据for (Map.Entry<String, String> entry : formData.entrySet()) {String fieldName = entry.getKey();String fieldValue = entry.getValue();PdfFormField field = form.getField(fieldName);if (field != null) {field.setValue(fieldValue);} else {log.info("警告:未找到字段 '" + fieldName + "'");}}//横向条形码设置// X坐标float x = 208;// Y坐标float y = 546;// 宽度float width = 120;// 高度float height = 25;addBarcode(pdfDoc, document, x, y, width, height, barcodeData.get("barcodeData1"), false);//纵向条形码设置// X坐标float x2 = 390;// Y坐标float y2 = 520;// 宽度float width2 = 120;// 高度float height2 = 25;addBarcode(pdfDoc, document, x2, y2, width2, height2, barcodeData.get("barcodeData2"), true);// 可选:扁平化表单(使字段成为文档内容的一部分,不可编辑)if (flattenForm) {form.flattenFields();}// 关闭文档pdfDoc.close();document.close();
}

上面这个函数主要对表单进行写入数据,生成一个新的pdf文件主要方便测试查看。生成条形码的的方法如下:

/*** 添加Barcode128条形码** @param pdfDoc pdf文档对象* @param x 条形码横坐标* @param y 条形码纵坐标* @param width 条形码宽度* @param height 条形码高度* @param barcodeData 条形码数据* @param vertical 是否垂直展示*/
private static void addBarcode(PdfDocument pdfDoc, Document document, float x, float y, float width, float height, String barcodeData, boolean vertical) {// 创建Barcode128条形码Barcode128 barcode128 = new Barcode128(pdfDoc);barcode128.setCode(barcodeData);// 不显示文本barcode128.setFont(null);barcode128.fitWidth(width);barcode128.setBarHeight(height);// 将条形码转换为表单XObjectPdfFormXObject barcodeXObject = barcode128.createFormXObject(ColorConstants.BLACK, null, pdfDoc);// 在指定位置绘制条形码PdfCanvas canvas = new PdfCanvas(pdfDoc.getFirstPage());// 添加条形码标签document.add(new Paragraph(""));// 旋转90度实现纵向展示if (vertical) {// 3. 平移坐标系原点至目标位置canvas.concatMatrix(1, 0, 0, 1, x, y);// 4. 应用90度顺时针旋转变换,旋转后,原本水平绘制的条码将变为垂直canvas.concatMatrix(0, 1, -1, 0, 0, 0);barcode128.placeBarcode(canvas, null, null);} else {// 绘制条形码canvas.addXObjectAt(barcodeXObject, x, y);}
}

其中通过new Barcode128(pdfDoc)创建Barcode128条形码对象,横向展示条形码的时候通过

canvas.addXObjectAt(barcodeXObject, x, y) 将条形码插入到pdf表单的指定坐标(x,y)位置。

纵向展示的时候需要将二维码平移坐标系原点至目标位置,然后90度顺时针旋转变换,关键函数:

public PdfCanvas concatMatrix(double a, double b, double c, double d, double e, double f) {...
}

方法中的六个参数共同定义了一个用于图形变换的 3×3 矩阵,各参数具体作用如下:
参数 a‌:控制图形在 X 轴方向的缩放比例。
参数 b‌:控制图形在水平方向的倾斜程度。
参数 c‌:控制图形在垂直方向的倾斜程度。
参数 d‌:控制图形在 Y 轴方向的缩放比例。
参数 e‌:指定图形在 X 轴方向的平移距离。
参数 f‌:指定图形在 Y 轴方向的平移距离。

测试

编写main函数进行测试。

public static void main(String[] args) {try {// 准备表单数据Map<String, String> formData = new HashMap<>();formData.put("orderNo", "*77582587758258");formData.put("position", "400B ");formData.put("position_no", "C262-11 C3");//其他省略Map<String, String> barcodeData = new HashMap<>();barcodeData.put("barcodeData1","PROD-2025-001");barcodeData.put("barcodeData2","PROD-2025-002");// 填充表单并生成新文件fillPdfForm("C:\\Users\\user\\Desktop\\order.pdf", "new_order.pdf", formData,barcodeData,true);log.info("PDF表单填充完成,已生成新文件:new_order.pdf");} catch (IOException e) {log.error("处理PDF时发生错误:",e);}}
http://www.dtcms.com/a/549357.html

相关文章:

  • 如何使用Python编辑PDF文档:修改文本、添加图片、更新元数据等
  • 苹果ios系统ipa文件企业签名是什么?优势是什么?什么场合需要应用到?
  • 石家庄商城网站制作微信网站小游戏
  • Postman接口测试教程(完整版)
  • 优秀网页界面设计郑州百度搜索优化
  • 一个可本地运行的实时字幕翻译 Demo(Whisper + GPT + Streamlit),可以边说边出中英文字幕
  • 网站开发建设总结wordpress ftp存储
  • 5.2 MCP服务器
  • 建设银行 钓鱼网站如何优化一个网站
  • Android 13后台任务一键清理功能实现
  • PLC、上位机软件应用开发
  • 免费自己做网站软件建立传媒公司网站
  • STC32G12K128 串口1、2、3、定时器0、看门狗 非中断模式基本使用
  • 嵌入式下解决stat调用出现Value too large for defined data type (errno=75)的问题
  • 15、Docker swarm-2-安装与存储
  • 单片机与边缘计算机的软硬协同差异分析
  • 个股期权如何开仓的要点总结?
  • frontpage做的社交网站网站开发成本都有哪几项
  • 电商网站建设源码wordpress轮播图替换
  • 【Qt】实现单例程序,禁止程序多开的几种方式
  • React 路由权限跳转 Token判断 路由控制 登录状态控制
  • 佛山网站优化多少钱十大外贸电商平台有哪些
  • 【代码审计】emlog pro 2.2.0 文件上传漏洞分析
  • 关键链项目管理CCPM
  • MySQL的ABS函数深度解析
  • 汕尾网站建设公司苏州建设信息网站
  • 哪些大学网站做的比较好陆家网站建设
  • 标注工具使用
  • 唐宇迪2025最新机器学习课件——学习心得(2)
  • Docker 化 Node.js 项目完整部署流程