Java使用IText根据pdf模板创建pdf文件

news2024/11/18 13:41:22

1.导包

 <dependency>
     <groupId>com.itextpdf</groupId>
     <artifactId>itextpdf</artifactId>
    <version>5.5.10</version>
 </dependency>
 <dependency>
     <groupId>com.itextpdf</groupId>
     <artifactId>itext-asian</artifactId>
     <version>5.2.0</version>
 </dependency>
 <dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

2.绘制pdf模板
在这里插入图片描述
3.示例代码

/**
 * 读取pdf模板填充生成pdf文件并转为字节数组
 * @return
 */
public byte[] createPdf() {
	//获取源数据(一般从数据库查询,此处通过构造数据简化处理)
	List<Plan> plans = this.getPlans();
       final int size = plans.size();
       //临时文件
       final String outputFilePath = "D:/" + System.currentTimeMillis() + ".pdf";
       OutputStream os = null;
       PdfStamper ps = null;
       PdfReader reader = null;
       PdfReader reader2 = null;
       Document document = null;
       ByteArrayOutputStream byteArrayOutputStream = null;
       PdfCopy pdfNew = null;
       try {
           //读入pdf表单
           reader = new PdfReader(this.getClass().getResourceAsStream("/template/test.pdf"));
           //根据表单生成一个新的pdf
           os = Files.newOutputStream(new File(outputFilePath).toPath());
           ps = new PdfStamper(reader, os);
           //获取pdf表
           AcroFields form = ps.getAcroFields();
           form.setField("contractNo", "HT2024042501");//合同号
           form.setField("paymentDate", "2022-12-01");//放款日期
           form.setField("expiredDate", "2023-12-01");//到期日期
           ps.setFormFlattening(true);
           List<AcroFields.FieldPosition> table = form.getFieldPositions("table");
           Rectangle rect = table.get(0).position;
           PdfPTable pTable = new PdfPTable(8);
           BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
           Font fontZH = new Font(bfChinese, 10f, 0);
           pTable.getDefaultCell().setHorizontalAlignment(1);
           pTable.setWidthPercentage(100.0f);
           float totalWidth = rect.getRight() - rect.getLeft() - 1;
           //计算表格宽度
           float[] columnWidth = {(float) (totalWidth * 0.05), (float) (totalWidth * 0.15), (float) (totalWidth * 0.15), (float) (totalWidth * 0.15), (float) (totalWidth * 0.15), (float) (totalWidth * 0.13), (float) (totalWidth * 0.13), (float) (totalWidth * 0.09)};
           pTable.setTotalWidth(columnWidth);
           pTable.setLockedWidth(true);
           for (Plan plan : plans) {
               Integer periodNo = plan.getPeriodNo();
               int border = (periodNo % 12 == 0 || periodNo == size) ? Rectangle.BOTTOM : Rectangle.NO_BORDER;
               pTable.addCell(generateCell(String.valueOf(periodNo), border, fontZH));
               pTable.addCell(generateCell(plan.getMatchDate(), border, fontZH));
               pTable.addCell(generateCell(plan.getRepayOriginal(), border, fontZH));
               pTable.addCell(generateCell(plan.getPenalty(), border, fontZH));
               pTable.addCell(generateCell(plan.getRepayAmount(), border, fontZH));
               pTable.addCell(generateCell(plan.getRestOriginal(), border, fontZH));
               pTable.addCell(generateCell(plan.getRepayDate(), border, fontZH));
               pTable.addCell(generateCell(plan.getRepayStatus(), border, fontZH));
           }
           pTable.setKeepTogether(true);
           pTable.setSplitLate(false);
           pTable.setSplitRows(true);
           //计算需要分页的总页数
           int totalpage = size % 12 == 0 ? size / 12 : size / 12 + 1;
           if (totalpage == 1) {
               //获table页面
               PdfContentByte under = ps.getOverContent(1);
               //添加table
               pTable.writeSelectedRows(0, -1, rect.getLeft(), rect.getTop(), under);
           } else {
               for (int i = 1; i <= totalpage; i++) {
                   PdfContentByte under = ps.getOverContent(i);
                   if (i == 1) {
                       pTable.writeSelectedRows(0, 12, rect.getLeft(), rect.getTop(), under);
                   } else {
                       pTable.writeSelectedRows((i - 1) * 12, i * 12, rect.getLeft(), rect.getTop(), under);
                   }
               }
           }
           ps.close();
           reader2 = new PdfReader(outputFilePath);
           document = new Document(reader2.getPageSizeWithRotation(1));
           byteArrayOutputStream = new ByteArrayOutputStream();
           pdfNew = new PdfCopy(document, byteArrayOutputStream);
           document.open();
           PdfImportedPage page;
           for (int i = 1; i <= totalpage; i++) {
               page = pdfNew.getImportedPage(reader2, i);
               pdfNew.addPage(page);
           }
           document.close();
           os.close();
           pdfNew.close();
           reader.close();
           reader2.close();
           FileUtils.delete(new File(outputFilePath));
           return byteArrayOutputStream.toByteArray();
       } catch (Exception e) {
       	e.printStackTrace();
       } finally {
           try {
               if (ps != null) {
                   ps.close();
               }
               if (reader != null) {
                   reader.close();
               }
               if (os != null) {
                   os.close();
               }
               if (document != null) {
                   document.close();
               }
               if (pdfNew != null) {
                   pdfNew.close();
               }
               if (reader2 != null) {
                   reader2.close();
               }
               if (byteArrayOutputStream != null) {
                   byteArrayOutputStream.close();
               }
           } catch (Exception e) {
           	e.printStackTrace();
           }
       }
	return null;
}

private List<Plan> getPlans() {
	List<Plan> plans = new ArrayList<Plan>();
	for(int i=1;i<=12;i++) {
		plans.add(new Plan(i,"2023-"+String.format("%02d", i)+"-01","999","-", "999","0","2023-"+String.format("%02d", i)+"-01", "已结清"));
	}
	return plans;
}

   private PdfPCell generateCell(String value, int border, Font fontZH) {
       PdfPCell cell = new PdfPCell(new Phrase(value, fontZH));
       cell.setBorder(border);
       cell.setHorizontalAlignment(Element.ALIGN_CENTER);
       return cell;
   }
   
   public static void main(String [] args) throws FileNotFoundException, IOException {
   	//将字节流转为pdf文件放于D盘
       OutputStream fileOut = new FileOutputStream("D:/a.pdf");
       fileOut.write(new TestPdf().createPdf());
   }

4.执行结果
在这里插入图片描述
5.所用到jar包下载地址
itextpdf-5.5.10.jar

欢迎大家积极留言交流学习心得,点赞的人最美丽!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mdk输出本语句在源程序中行数以及函数名称

代码如下&#xff1a; /* USER CODE BEGIN WHILE */while (1){printf("anlog uart1 test 2024-4-16\r\n");printf("[%s] %d\r\n",__func__,__LINE__);printf("[%s] %d",__func__,__LINE__);HAL_Delay(200);/* USER CODE END WHILE *//* USER COD…

MyBatis源码之MyBatis中SQL语句执行过程

MyBatis源码之MyBatis中SQL语句执行过程 SQL执行入口 我们在使用MyBatis编程时有两种方式&#xff1a; 方式一代码如下&#xff1a; SqlSession sqlSession sqlSessionFactory.openSession(); List<Student> studentList sqlSession.selectList("com.sjdwz.da…

AWS SES发送邮件如何正确配置?操作指南?

AWS SES发送邮件有哪些限制&#xff1f;AWS SES发信的注意事项&#xff1f; AWS SES作为亚马逊云服务提供的一项高效、可靠的电子邮件发送服务&#xff0c;受到了众多企业的青睐。然而&#xff0c;如何正确配置AWS SES发送邮件。AokSend将详细解析AWS SES发送邮件的配置过程&a…

GO语言写Prometheus自定义node-exporter的Docker容器测试

1. 安装docker-compose 执行以下命令&#xff0c;安装docker-compose到CentOS7.9环境中&#xff1a; # 下载二进制文件 sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.7/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/d…

耐酸碱腐蚀PFA冷凝回流装置进口透明聚四氟材质PFA梨形漏斗特氟龙圆底烧瓶

PFA分液漏斗&#xff1a;也叫特氟龙分液漏斗、特氟龙梨型分液漏斗。 规格参考&#xff1a;125ml、250ml、500ml、1000ml 其主要特性有&#xff1a; 1.内壁对溶剂无粘贴性和吸附&#xff0c;可完全排空&#xff0c;分界面清晰可见&#xff1b; 2.密封性好&#xff0c;可防止…

Laravel 6 - 第十七章 配置数据库

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

【C++题解】1043. 行李托运价格

问题&#xff1a;1043. 行李托运价格 类型&#xff1a;分支 题目描述&#xff1a; 某车站行李托运收费标准是&#xff1a; 10 公斤或 10 公斤以下&#xff0c;收费 2.5 元&#xff0c;超过 10 公斤的行李&#xff0c;按每超过 1 公斤增加 1.5 元进行收费。 试编一程序&#x…

python:pyqt5案例(简易浏览器)

1、上接pyqt5基础https://blog.csdn.net/weixin_73011353/article/details/138051734https://blog.csdn.net/weixin_73011353/article/details/138051734 2、基本模块 # 定义一个名为BrowserWindow的类&#xff0c;继承自QMainWindow class BrowserWindow(QMainWindow):def _…

[实验]Keil 4下仿真三星2440A芯片的汇编及CPIO控制实验

一、安装Keil uVision4 (详细安装过程忽略) 点击finish完成安装 二、新建项目&#xff0c;导入项目文件 选择对应的芯片&#xff0c;此处我们选择三星的S3C2440A&#xff0c;点击OK 在Source Group 1处右键&#xff0c;点击Add Files to "Sourcce Group 1’…将下图…

一文读懂VR数字展览会,从沉浸式体验到市场竞争力的全方位提升

在数字化转型的浪潮中&#xff0c;VR技术正逐渐成为商业展览的新趋势。VR数字展览会通过创新的展示功能和互动体验&#xff0c;为参展商和观众带来前所未有的便利和效果。 一、VR展示功能的沉浸式体验 1、全方位沉浸式体验&#xff1a; VR技术能够创造一个全方位的三维展览环…

MemFire案例-政务应急物联网实时监测预警项目

客户背景 党的十八大以来&#xff0c;中央多次就应急管理工作做出重要指示&#xff1a;要求坚持以防为主、防抗救相结合&#xff0c;全面提升综合防灾能力&#xff1b;坚持生命至上、安全第一&#xff0c;完善安全生产责任制&#xff0c;坚决遏制重特大安全事故。 面对新形势…

VSCODE自定义代码片段简述与基础使用

目录 一、 简述二 、 基础使用说明2.1 新建一个代码块工作区间2.2 语法 三、 示例四、 参考链接 一、 简述 VSCode的自定义代码片段功能允许开发者根据自己的需求定义和使用自己的代码片段&#xff0c;从而提高编码效率。 优点: 提高效率&#xff1a; 自定义代码片段能够减少…

深度学习中的子空间、线性变换和矩阵概念应用

1.表示子空间 在深度学习中&#xff0c;“不同的表示子空间”通常是指模型通过不同的参数&#xff08;例如权重矩阵&#xff09;将输入数据映射到不同的高维空间&#xff0c;这些空间被称为表示子空间。每个子空间都能够捕获输入数据中不同的特征或模式。以下是一些详细解释&am…

Python 数据可视化 boxplot

Python 数据可视化 boxplot import pandas as pd import matplotlib.pyplot as plt import numpy as np import seaborn as sns# 读取 TSV 文件 df pd.read_csv(result.tsv, sep\t)normal_df df[df["sample_name"].str.contains("normal")] tumor_df df…

详解 Wilkinson 功分器

威尔金森功分器是一款比较常用的射频器件,是由射频工程师E.J. Wilkinson 在1960年的文章中提出的,这篇文章在IEEE网站上还能下载到:An N-Way Hybrid Power Divider。方便的同学可以下载学习一下。 威尔金森功分器常见的使用场景是将一路信号按照一定的比例分成两路信号,或…

PC-3000 Mobile Pro: 智能手机及平板设备数据提取工具

天津鸿萌科贸发展有限公司从事数据安全业务20余年&#xff0c;在数据恢复、数据取证、数据备份等领域有丰富的案例经验、前沿专业技术及良好的行业口碑。同时&#xff0c;公司面向取证机构及数据恢复公司&#xff0c;提供数据恢复实验室建设方案&#xff0c;包含数据恢复硬件设…

二、OSPF协议基础

基于SPF算法&#xff08;Dijkstra算法&#xff09;的链路状态路由协议OSPF&#xff08;Open Shortest Path First&#xff0c;开放式最短路径优先&#xff09; 目录 1.RIP在大型网络中部署所面临的问题 2.Router ID 3.OSPF的报文 4.OSPF邻居建立过程 5.OSPF报文的确认机制…

LM1875L-TB5-T 音频功率放大器 PDF中文资料_参数_引脚图

LM1875L-TB5-T 规格信息&#xff1a; 商品类型音频功率放大器 音频功率放大器的类型- 输出类型1-Channel (Mono) 作业电压16V ~ 60V 输出功率25W x 1 4Ω 额外特性过流保护,热保护 UTC LM1875是一款单片功率放大器&#xff0c;可为消费类音频应 用提供极低失真和高品质的…

电力调度自动化系统,如何减少配电安全隐患?

“双碳”战略目标下&#xff0c;数据中心迎来了更多发展机遇&#xff0c;同时电力调度自动化系统也迎来更多挑战&#xff0c;如何保障持续稳定的电力供应、确保关键负载的可靠运行&#xff0c;并兼顾数字化管理、绿色可持续转型等等议题成为数据中心行业构建未来领导力的重要关…

快速构建Spring boot项目

1、Idea里新建项目 2、创建HelloController 3、运行 4、开发环境热部署 pom.xml 查看目前已有的依赖 配置properties 设置 ctrlshiftalt/ 新版本的compiler.automake.allow.when.app.running已经不在registry里面了&#xff0c;在settings里面的Advanced settings里面Allow au…