itext - PDF模板套打

项目需求:获取列表数据之后直接将数据生成一个pdf。因此需要使用到 itext 对pdf进行直接操作。

环境配置

需要为pdf添加文字域,因此需要安装Adobe Acrobat

准备一个空的PDF文件,如果有现成的模板更好

依赖配置,我们使用itext的7版本

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

 

快速使用

使用Adobe Acrobat Pro DC打开空PDF,使用 文字域 工具为PDF添加文字域,要注意为每个文字域命名。

如果你有现成的模板PDF,直接使用识别域可以识别空白区域然后自动生成文字域,但是一般都不太准确

如果你的单个数据很多的话,可以在属性中设置多行 

 

设置完文字域之后记得保存。

代码实现

@SpringBootTest
class StickerApplicationTests {
    private static final String TEMP_PATH = "C:\\Users\\An1ong\\Desktop\\Stickers.pdf";

    //生成PDF的位置
    private static final String DEST_PATH = "C:\\Users\\An1ong\\Desktop\\StickersOut.pdf";

    //本地上字体的路径
    private static final String FONT_PATH = "";

    @Autowired
    private StickerService stickerService;

    @Test
    void contextLoads() throws IOException {

        //创建一个新的PDF文件,并写入数据
        PdfReader reader = new PdfReader(TEMP_PATH);

        // 创建一个 PdfWriter 对象以写入新的PDF
        PdfWriter writer = new PdfWriter(DEST_PATH);

        // 创建一个 PdfDocument 对象
        PdfDocument pdfDoc = new PdfDocument(reader, writer);

        // 获取 PDF 表单
        PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, false);

        //获得数据,准备填充
        List<Sticker> stickerList = stickerService.list(10);

        //文本填充
        for(int i = 0; i < stickerList.size();i++){
            Sticker sticker = stickerList.get(i);

            // 生成自定义序号,格式为 "001"、"002"、"003"
            String customId = String.format("%03d", i + 1);

            String idFieldName = "id" + (i + 1);
            String nameFieldName = "name" + (i + 1);

            PdfFormField idField = form.getField(idFieldName);
            if (idField != null) {
                idField.setValue(customId);
            }

            PdfFormField nameField = form.getField(nameFieldName);
            if (nameField != null) {
                nameField.setValue(sticker.getStickerName());
            }

        }


        //消除掉表单域
        form.flattenFields();

        //关闭流
        pdfDoc.close();
    }
}

行数也不算少,但里面的逻辑其实也很简单。这是一个Springboot的单元测试,我调用service中方法获取了一个装着对象的列表。

用PdfReader读取你要套写的模板,用PdfWriter将数据写入模板。创建出一个PdfDocument对象并将这两个参数传入就可以开始对PDF操作了。

注意,这个过程不会直接在原PDF上操作,而是生成一个新的PDF进行操作,程序结束后原PDF模版还是空白的。

 PdfAcroFrom获取PDF表单,然后PdfFormField获取其中的文字域,最后使用for循环动态的将数据套打在模板上就完成了。

最终会生成一个新的文件

最终效果:

之所以要在最后调用form.flattenFields消除掉表单域是因为如果不消除表单域的话就会变成这样。

封装

我们可以把这个在单元测试中的程序封装成工具类重复使用

public class PdfPrintUtil {

//    private static final String TEMP_PATH = "C:\\Users\\An1ong\\Desktop\\Stickers.pdf";
//
//    private static final String DEST_PATH = "C:\\Users\\An1ong\\Desktop\\StickersOut.pdf";

    public static void printPDF(String TEMP_PATH,String DEST_PATH,List<Sticker> stickerList) throws IOException {

        //创建一个新的PDF文件,并写入数据
        PdfReader reader = new PdfReader(TEMP_PATH);

        // 创建一个 PdfWriter 对象以写入新的PDF
        PdfWriter writer = new PdfWriter(DEST_PATH);

        // 创建一个 PdfDocument 对象
        PdfDocument pdfDoc = new PdfDocument(reader, writer);

        // 获取 PDF 表单
        PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, false);


        //文本填充
        for(int i = 0; i < stickerList.size();i++){
            Sticker sticker = stickerList.get(i);

            // 生成自定义序号,格式为 "001"、"002"、"003"
            String customId = String.format("%03d", i + 1);

            String idFieldName = "id" + (i + 1);
            String nameFieldName = "name" + (i + 1);

            PdfFormField idField = form.getField(idFieldName);
            if (idField != null) {
                idField.setValue(customId);
            }

            PdfFormField nameField = form.getField(nameFieldName);
            if (nameField != null) {
                nameField.setValue(sticker.getStickerName());
            }

        }

        //消除掉表单域
        form.flattenFields();

        //关闭流
        pdfDoc.close();
    }
    
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/180572.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

揭示卡尔曼滤波器的威力

一、说明 作为一名数据科学家&#xff0c;我们偶尔会遇到需要对趋势进行建模以预测未来值的情况。虽然人们倾向于关注基于统计或机器学习的算法&#xff0c;但我在这里提出一个不同的选择&#xff1a;卡尔曼滤波器&#xff08;KF&#xff09;。 1960 年代初期&#xff0c;Rudol…

基于H1ve一分钟搭好CTF靶场

写在前面 ◉ ‿ ◉ 上一篇文章给大家详细介绍了基于H1ve搭建CTF靶场&#xff0c;以及过程中可能遇到的报错及解决方法&#xff0c;那么这篇文章&#xff0c;我总结了一下&#xff0c;将不会遇到报错的方法给到大家&#xff0c;但是前提是你的服务器最好是一个全新的哦~~~ 我…

小程序订阅消息

wx.requestSubscribeMessage({tmplIds: [2IdqlWrqSbjAurzIuW8imeK-ftS8gbhYdZ0icdE],success(res) {console.log(res);// 处理用户授权结果},fail(err) {console.error(err);// 处理授权请求失败}});

淡入淡出transition: right 1s

transition: right 1s; //重点直接改变right值 操作过快 这里用该方法实现1s内淡入淡出 达到效果目标

20230511 Windows Ubuntu vscode remote-ssh 连接配置

参考 &#xff1a; VSCode SSH 连接远程ubuntu Linux 主机 VSCode通过Remote SSH扩展连接到内网Ubuntu主机 Ubuntu 安装 sudo apt-get install openssh-server vscode: 安装remote-ssh 插件 连接到服务器IP 免密登录的公钥密钥传递用filezillaUbuntu 和 Windows 文件互传 …

ios(swiftui) 画中画

一、环境 要实现画中画 ios系统必须是 iOS14 本文开发环境 xcode14.2 二、权限配置 在项目导航器中单击项目&#xff0c;然后单击Signing & Capabilities。单击 Capabilit搜索Background Modes&#xff0c;然后双击将其添加为功能。在新添加的Background Modes部分&a…

chatglm3部署使用

chatglm3部署使用 1.部署2.使用3.接入微信4.vue前端 1.部署 1.首先去github下载chatglm3代码。Huggingface下载模型一直失败&#xff0c;所以用阿里的魔塔社区下载。 git clone https://github.com/THUDM/ChatGLM3.git git clone https://www.modelscope.cn/ZhipuAI/chatglm3…

SpringMVC 基础知识

学习目标 掌握基于 SpringMVC 获取请求参数与响应 json 数据操作熟练应用基于 REST 风格的请求路径设置与参数传递能够根据实际业务建立前后端开发通信协议并进行实现基于 SSM 整合技术开发任意业务模块功能 1 SpringMVC 简介 1.1 概述 1.1.1 web程序开发流程 【执行过程】…

Hook+jsdom 解决cookie逆向

前言 记录下如何破cookie逆向 目标 目标网址:https://q.10jqka.com.cn/ 目标接口:http://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/2/ajax/1/ 对抗:cookie反爬虫处理,关键字v,如图 解决步骤 1、JS中关键字查找 如上,我们找到了关键字 v,…

etoken是什么意思,有什么作用?

EToken是一种数字货币&#xff0c;它是由以太坊区块链平台发行的智能合约&#xff0c;旨在为以太坊生态系统提供一种安全、可靠、去中心化的交易媒介。EToken具有多种作用&#xff0c;下面将详细介绍。 一、EToken的定义和发行 EToken是由以太坊智能合约创建的数字货币&#xf…

交易宝订单系统使用心得

简介 交易宝是管理订单支付的软件系统&#xff0c;可对多个应用的支付业务进行统一管理和运营&#xff0c;为你节省时间和精力&#xff0c;让你专注于核心业务&#xff0c;实现更高的效率和利润。 特点&#xff1a;无需开发&#xff0c;开箱即用&#xff0c;统一管理支付订单…

【运动规划】191 自适应跟踪kinodynamicrrt的路径

分层法&#xff1a; two layer approach 自适应控制&#xff0c;跟随轨迹。运动规划&#xff1a;扩展自由空间&#xff08;基于速度约束缩小自由空间&#xff09;为控制部分留余量&#xff0c;确保安全。 控制设计&#xff1a; 考虑平移和旋转&#xff0c;速度环控制&#xff…

什么是多要素自动气象监测设备?

WX-CQ12 随着科技的发展&#xff0c;我们对天气的预测和监测能力也在不断提高。其中&#xff0c;多要素自动气象监测设备正成为一种革命性的工具&#xff0c;帮助我们更好地理解和预测天气变化。 一、什么是多要素自动气象监测设备&#xff1f; 多要素自动气象监测设备是一种…

查看sql语句执行计划并重建索引

晚上cpu报警显示当前cpu使用率达到90%以上&#xff0c;不到10%的空闲 先查询当前sql&#xff1a; #&#xff08;ORACLE&#xff09; SQL > set line 200 pages 1000 col event for a30 col program for a30 col username for a12 col sql_id for a15 col INST_ID for 9999 …

【数据结构初阶(4)】栈的基本操作实现

文章目录 Ⅰ 概念及结构1. 栈的概念2. 栈的操作 Ⅱ 基本操作实现1. 栈的定义2. 初始化栈3. 元素入栈4. 元素出栈5. 获取栈顶元素6. 获取栈中有效元素个数7. 判断栈空8. 销毁栈 Ⅰ 概念及结构 1. 栈的概念 栈&#xff1a;栈是一种特殊的线性表&#xff0c;其只允许在固定的一端…

SAP QA11/QA32质检放行时,如何处理产生记账更改通知单时

前提&#xff1a;启用SAP wms仓库管理 场景&#xff1a; 当做移动类型321质检放行的时候&#xff0c;有时候会产生记账更改通知单&#xff0c;这个时候怎么处理&#xff1f; 解决办法&#xff1a; 使用事务码LU04,查看未清的记账更改通知单&#xff0c;进入清单列表之后&…

【深度学习】卷积神经网络(CNN)的参数优化方法

著名&#xff1a; 本文是从 Michael Nielsen的电子书Neural Network and Deep Learning的深度学习那一章的卷积神经网络的参数优化方法的一些总结和摘录&#xff0c;并不是我自己的结论和做实验所得到的结果。我想Michael的实验结果更有说服力一些。本书在github上有中文翻译的…

蓝桥杯每日一题2023.11.23

题目描述 题目分析 本题使用递归模拟即可&#xff0c;将每一个大格子都可以拆分看成几个小格子&#xff0c;先将最开始的数字进行填入&#xff0c;使每一个对应小格子的值都为大格子对应的数&#xff0c;搜索找到符合要求的即可 &#xff08;答案&#xff1a;50 33 30 41&am…

分布式篇---第二篇

系列文章目录 文章目录 系列文章目录前言一、你知道哪些分布式事务解决方案?二、什么是二阶段提交?三、什么是三阶段提交?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你…

第十七章:数据库操作

数据库基础 SQL语言 1、select 语句 select 语句用于从数据中检索数据。语法如下&#xff1a; SELECT 搜选字段列表 FROM 数据表名 WHERE 条件表达式 GROUP BY 字段名 HAVING 条件表达式(指定分组的条件) ORDER BY 字段名[ASC|DESC] 2、insert 语句 insert 语句用于向表中插入…