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

Java使用IText7动态生成带审批文本框的PDF文档

Java使用IText7动态生成带审批文本框的PDF文档

文章目录

  • Java使用IText7动态生成带审批文本框的PDF文档
    • 1.构建第一个框的起始坐标
    • 2.渲染第一个框
    • 3.渲染其他的审批框

测试结果示例
在这里插入图片描述

实现思路

使用Canvas进行相对定位和绝对定位来确定文本框内文字位置,用Rectangle通过坐标转换来确定文本框的位置

   <itext.version>7.1.2</itext.version>
 <!--itext--><dependency><groupId>com.itextpdf</groupId><artifactId>kernel</artifactId><version>${itext.version}</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>io</artifactId><version>${itext.version}</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>layout</artifactId><version>${itext.version}</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>forms</artifactId><version>${itext.version}</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>pdfa</artifactId><version>${itext.version}</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>pdftest</artifactId><version>${itext.version}</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>font-asian</artifactId><version>${itext.version}</version></dependency>

1.构建第一个框的起始坐标

注意:由于Rectangle构造的坐标为以文档的左下角为xy轴,为了支持计算分页顺序添加需要转换到左上角

        //第一个文本框(非审批框,高度比较大有特殊自动换行需求)// 定义文本框坐标和矩形尺寸(左上点坐标)float xLeftTop = 80;    // 左上角x坐标float yLeftTop = 100;   // 左上角y坐标float width = 450;      // 矩形宽度float height = 300;      // 矩形高度//坐标转换:默认是左下角坐标轴PdfPage firstPage = pdfDoc.getPage(1);float yBottom = firstPage.getPageSize().getHeight() - yLeftTop - height;Rectangle rect = new Rectangle(xLeftTop, yBottom, width, height);

2.渲染第一个框

使用Canvas进行相对定位和绝对定位,来确保文本框内的文字内容位置

为了防止自动换行超出框内,建议Canvas布局的宽度小于文本框的布局

    private void createIndexFieldText(Document doc, PdfFont font, String text, Rectangle rect) {// 创建Canvas进行绝对定位PdfCanvas pdfCanvas = new PdfCanvas(doc.getPdfDocument().getLastPage());//防止字体出框Rectangle textArea = new Rectangle(rect.getX(), rect.getY(), rect.getWidth()-20, rect.getHeight());Canvas canvas = new Canvas(pdfCanvas, doc.getPdfDocument(), textArea);// 绘制文本框边框pdfCanvas.setStrokeColor(ColorConstants.BLACK).rectangle(rect).stroke();//相对定位Paragraph approve = new Paragraph().setFont(font).setFontSize(12).setRelativePosition(10, 10,0,0).add("致______________:");canvas.add(approve);Paragraph approve1 = new Paragraph().setFont(font).setFontSize(12).setFirstLineIndent(25).setRelativePosition(10,  10,0,0).add("________________机构:");canvas.add(approve1);Paragraph approve2 = new Paragraph("我方承担的工程," +"已完成相关准备工作,申请开工,请予以审核,批准。").setTextAlignment(TextAlignment.JUSTIFIED).setFont(font).setFirstLineIndent(25).setRelativePosition(10, 10, 0,0).setFontSize(12);canvas.add(approve2);// 审批相关绝对定位Paragraph fieldText = new Paragraph().setFont(font).setFontSize(12).setTextAlignment(TextAlignment.RIGHT).setFixedPosition(rect.getX() + rect.getWidth()-400, rect.getY() + 40, 300).add(text);canvas.add(fieldText);// 在文本框内添加Paragraph dateText = new Paragraph().setFont(font).setFontSize(12).setTextAlignment(TextAlignment.RIGHT).setFixedPosition(rect.getX() + rect.getWidth()-400, rect.getY() + 20, 300).add("日期:                        ");canvas.add(dateText);canvas.close();}

3.渲染其他的审批框

原理同大框,需计算是否需要分页,如分页需要重置新页面的起始坐标,且由于大框高度大于其他框,需要重置高度,多个框添加时需计算y轴坐标。

   /*** 添加审批文本框*/private static void addTextField(Document doc, PdfFont font, String text, Rectangle rect,boolean page) {// 创建Canvas进行绝对定位PdfCanvas pdfCanvas = new PdfCanvas(doc.getPdfDocument().getLastPage());//防止字体出框Rectangle textArea = new Rectangle(rect.getX(), rect.getY(), rect.getWidth()-20, rect.getHeight());if(page){pdfCanvas = new PdfCanvas(doc.getPdfDocument().addNewPage());}Canvas canvas = new Canvas(pdfCanvas, doc.getPdfDocument(), textArea);// 绘制文本框边框pdfCanvas.setStrokeColor(ColorConstants.BLACK).rectangle(rect).stroke();//审核意见定位Paragraph approve = new Paragraph().setFont(font).setFontSize(12).setFixedPosition(rect.getX() + 10,  rect.getY()+rect.getHeight()-25,200).add("审核意见:");canvas.add(approve);// 在文本框内添加Paragraph fieldText = new Paragraph().setFont(font).setFontSize(12).setTextAlignment(TextAlignment.RIGHT).setFixedPosition(rect.getX() + rect.getWidth()-400, rect.getY() + 40, 300).add(text);canvas.add(fieldText);// 在文本框内添加Paragraph dateText = new Paragraph().setFont(font).setFontSize(12).setTextAlignment(TextAlignment.RIGHT).setFixedPosition(rect.getX() + rect.getWidth()-400, rect.getY() + 20, 300).add("日期:                        ");canvas.add(dateText);canvas.close();}

4.完整代码

package com.moshangshang.pdf.controller;import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;@RestController
@RequestMapping("")
public class PDFController {/*** 带文本框的审批表生成*/@GetMapping(value = "/pdf")public void test( HttpServletResponse response) throws Exception {response.setContentType("application/pdf");OutputStream os = response.getOutputStream();// 创建 PDF 文档PdfDocument pdfDoc = new PdfDocument(new PdfWriter(os));Document document = new Document(pdfDoc,PageSize.A4);PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", true);// 设置页面尺寸和边距document.setMargins(50, 50, 50, 50);Paragraph title = new Paragraph("审批测试表").setTextAlignment(TextAlignment.CENTER).setFont(font).setBold().setFontSize(22);document.add(title);List<String> unitList = Arrays.asList("测试1","测试2","测试3","测试4","测试5","测试6","测试7","测试8","测试9");//文本框绘制索引int fieldTextIndex = 1;//第一个文本框(非审批框,高度比较大有特殊自动换行需求)// 定义文本框坐标和矩形尺寸(左上点坐标)float xLeftTop = 80;    // 左上角x坐标float yLeftTop = 100;   // 左上角y坐标float width = 450;      // 矩形宽度float height = 300;      // 矩形高度//坐标转换:默认是左下角坐标轴PdfPage firstPage = pdfDoc.getPage(1);float yBottom = firstPage.getPageSize().getHeight() - yLeftTop - height;Rectangle rect = new Rectangle(xLeftTop, yBottom, width, height);for (String name : unitList) {//定位if(fieldTextIndex == 1){//开工报告第一个大框添加createIndexFieldText(document, font, name+"(签字、印章):", rect,false);}else {//其他全为同等审批框,修改高度height = 150;//默认第一页三个框,其他页默认四个if(fieldTextIndex%4==0){//如果大于单页数量,创建新页,并重置坐标float yBottom1 = firstPage.getPageSize().getHeight() - yLeftTop - height;rect = new Rectangle(xLeftTop, yBottom1, width, height);addTextField(document, font, name+" (签字、印章):", rect,true);fieldTextIndex++;continue;}rect = new Rectangle(xLeftTop, rect.getY()-height, width, height);// 绘制文本框边框addTextField(document, font, name+"(签字、印章):", rect,false);}fieldTextIndex++;}document.close();}/****/private void createIndexFieldText(Document doc, PdfFont font, String text, Rectangle rect,boolean page) {// 创建Canvas进行绝对定位PdfCanvas pdfCanvas = new PdfCanvas(doc.getPdfDocument().getLastPage());//防止字体出框Rectangle textArea = new Rectangle(rect.getX(), rect.getY(), rect.getWidth()-20, rect.getHeight());if(page){pdfCanvas = new PdfCanvas(doc.getPdfDocument().addNewPage());}Canvas canvas = new Canvas(pdfCanvas, doc.getPdfDocument(), textArea);// 绘制文本框边框pdfCanvas.setStrokeColor(ColorConstants.BLACK).rectangle(rect).stroke();//相对定位Paragraph approve = new Paragraph().setFont(font).setFontSize(12).setRelativePosition(10,  10,0,0).add("致______________(单位):");canvas.add(approve);Paragraph approve1 = new Paragraph().setFont(font).setFontSize(12).setFirstLineIndent(25).setRelativePosition(10,  10,0,0).add("________________机构:");canvas.add(approve1);Paragraph approve2 = new Paragraph("我方," +"已完成相关准备工作,具备开工条件,申请于2025年开工,请予以审核,批准。").setTextAlignment(TextAlignment.JUSTIFIED).setFont(font).setFirstLineIndent(25).setRelativePosition(10, 10, 0,0).setFontSize(12);canvas.add(approve2);// 审批相关绝对定位Paragraph fieldText = new Paragraph().setFont(font).setFontSize(12).setTextAlignment(TextAlignment.RIGHT).setFixedPosition(rect.getX() + rect.getWidth()-400, rect.getY() + 40, 300).add(text);canvas.add(fieldText);// 在文本框内添加Paragraph dateText = new Paragraph().setFont(font).setFontSize(12).setTextAlignment(TextAlignment.RIGHT).setFixedPosition(rect.getX() + rect.getWidth()-400, rect.getY() + 20, 300).add("日期:                        ");canvas.add(dateText);canvas.close();}/*** 添加审批文本框*/private static void addTextField(Document doc, PdfFont font, String text, Rectangle rect,boolean page) {// 创建Canvas进行绝对定位PdfCanvas pdfCanvas = new PdfCanvas(doc.getPdfDocument().getLastPage());//防止字体出框Rectangle textArea = new Rectangle(rect.getX(), rect.getY(), rect.getWidth()-20, rect.getHeight());if(page){pdfCanvas = new PdfCanvas(doc.getPdfDocument().addNewPage());}Canvas canvas = new Canvas(pdfCanvas, doc.getPdfDocument(), textArea);// 绘制文本框边框pdfCanvas.setStrokeColor(ColorConstants.BLACK).rectangle(rect).stroke();//审核意见定位Paragraph approve = new Paragraph().setFont(font).setFontSize(12).setFixedPosition(rect.getX() + 10,  rect.getY()+rect.getHeight()-25,200).add("审核意见:");canvas.add(approve);// 在文本框内添加Paragraph fieldText = new Paragraph().setFont(font).setFontSize(12).setTextAlignment(TextAlignment.RIGHT).setFixedPosition(rect.getX() + rect.getWidth()-400, rect.getY() + 40, 300).add(text);canvas.add(fieldText);// 在文本框内添加Paragraph dateText = new Paragraph().setFont(font).setFontSize(12).setTextAlignment(TextAlignment.RIGHT).setFixedPosition(rect.getX() + rect.getWidth()-400, rect.getY() + 20, 300).add("日期:                        ");canvas.add(dateText);canvas.close();}}
http://www.xdnf.cn/news/1969.html

相关文章:

  • 【服务器操作指南】从 Hugging Face 上下载文件 | 从某一个网址上下载文件到 Linux 服务器的指定目录
  • 用Obsidian四个插件打造小说故事关联管理系统:从模板到图谱的全流程实践
  • 692. 前K个高频单词(map的练习)
  • 【初识Trae】字节跳动推出的下一代AI原生IDE,重新定义智能编程
  • 11.ArkUI Tabs的介绍和使用
  • 【多目标进化算法】 MOEA/D算法(知识点)
  • RAG5个常见错误
  • 硬件虚拟化(如KVM、VMware)
  • Redis相关
  • PHP:点击/拖动-上传图片文件目录,并存入数据库
  • 大肠杆菌诱导蛋白时OD600=0.6-0.8添加IPTG的思考-实验操作系列-009
  • 0. Selenium工具的安装
  • 【Linux网络】TCP服务中IOService应用与实现
  • 一个非常快速的 Latex 入门教程【Part 2】
  • 2025产品经理AI效率指南:3大案例实战流程图、原型图与PRD文档
  • AI 场景落地:API 接口服务 VS 本地部署,哪种更适合?
  • 不在同一个局域网的远程桌面连接怎么设置?本地内网计算机让其他网络远程访问6种常用方法
  • 计算机界的50位大牛(23)—— 詹姆斯·尼古拉·格雷:数据库事务的缔造者
  • 客户联络中心能力与客户匹配方式
  • [论文阅读]ReAct: Synergizing Reasoning and Acting in Language Models
  • 【25软考网工】第三章(4)生成树协议、广播风暴和MAC地址表震荡
  • springboot2.x升级到3.x 惨痛经验总结
  • 每日算法-250425
  • kafka和Spark-Streaming2
  • [特殊字符]Google放大招!免费高配云主机开仓放粮,手慢无!
  • 详解 Servlet 处理表单数据
  • Linux进程学习【进程状态】
  • 【Linux】进程优先级和进程切换
  • Qt 调试信息重定向到本地文件
  • 深度学习--循环神经网络RNN