【Excel PDF 系列】EasyExcel + iText 库实现 Excel 转换 PDF

你知道的越多,你不知道的越多
点赞再看,养成习惯
如果您有疑问或者见解,欢迎指教:
企鹅:869192208

文章目录

        • 前言
        • 转换前后效果
        • 引入 pom 配置
        • 代码实现
            • 定义 ExcelDataVo 对象
            • 主方法
            • EasyExcel 监听器

前言

最近遇到生成 Excel 并转 PDF 的需求,磕磕碰碰总结三种方式,分别是 POI + iText 库,EasyExcel + iText 库和直接生成 PDF 表格三种方式。

本文基于 EasyExcel + iText 库实现,并将自定义 PDF 上 title 内容,将生成的 PDF 文件返回。

转换前后效果

转换前
转换后

引入 pom 配置
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel-core</artifactId>
    <version>3.3.2</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13</version>
</dependency>
代码实现
定义 ExcelDataVo 对象
@Data
public class ExcelDataVo implements Serializable {
    private static final long serialVersionUID = 1L;

    /**生成pdf的文件路径*/
    private String pdfFilePath;

    /**生成pdf的文件标题*/
    private String title;
}
主方法
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ExcelConvertService {

		public static void main(String[] args) throws Exception {
			 // 需要进行转换的excel
        String fileName = "D:\\\\对账明细报告.xlsx";
        // 重点:通过创建监听器并且将当前创建的对象传递进去
        ExcelDataVo excelDataVo = new ExcelDataVo();
        excelDataVo.setTitle("对账明细报告");
        EasyExcel.read(fileName, new NoModelDataListener(excelDataVo)).sheet().doRead();
        log.info("读取完成:{}", JSON.toJSONString(excelDataVo));
    }

EasyExcel 监听器
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.util.ConverterUtils;
import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.extern.slf4j.Slf4j;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class NoModelDataListener extends AnalysisEventListener<Map<Integer, String>> {
		// 存储读取到 excel 的每一行
    private List<Map<Integer, String>> cachedDataList = new ArrayList<>();
		// 存储读取到 excel 的列头
    private Map<Integer, String> cachedHead = new HashMap<>();

    //自定义返回结果类,也就是与传递给controller的实体类
    ExcelDataVo excelDataVo;

    //重点:通过构造器把 excelDataVo 对象传递过来
    public NoModelDataListener(ExcelDataVo excelDataVo) {
        this.excelDataVo = excelDataVo;
    }

    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        cachedDataList.add(data);
    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        cachedHead = ConverterUtils.convertToStringMap(headMap, context);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        String pdfFilePath = "D:\\对账明细报告.pdf";
        try (FileOutputStream fos = new FileOutputStream(pdfFilePath)) {
            // 创建PDF文档对象
            Document document = new Document(PageSize.A2, 50, 50, 50, 50);

            // 创建PDF输出流
            PdfWriter writer = PdfWriter.getInstance(document, fos);

            // 打开PDF文档
            document.open();

            // 创建PDF表格对象
            PdfPTable table = new PdfPTable(cachedDataList.get(0).size());
            table.setHeaderRows(1);
            //table.setWidths(new float[] {1, 2, 2, 2});

            // 设置表格宽度
            table.setWidthPercentage(100);

            // 设置表格标题
            //String sheetName = context.readSheetHolder().getSheetName();
            String sheetName = excelDataVo.getTitle();
            Paragraph title = new Paragraph(sheetName, new Font(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), 16, Font.BOLD));
            title.setAlignment(Element.ALIGN_CENTER);
            document.add(title);

            // 添加表格标题
            for (Map.Entry<Integer, String> entry : cachedHead.entrySet()) {
                String value = entry.getValue();
                PdfPCell pdfCell = new PdfPCell(new Paragraph(value, new Font(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), 12)));
                pdfCell.setBorderWidth(1f);
                pdfCell.setBorderColor(BaseColor.BLACK);
                pdfCell.setPadding(5f);
                pdfCell.setBackgroundColor(BaseColor.LIGHT_GRAY);
                table.addCell(pdfCell);
            }

            // 添加表格内容
            for (Map<Integer, String> map : cachedDataList) {
                for (Map.Entry<Integer, String> entry : map.entrySet()) {
                    PdfPCell pdfCell = new PdfPCell(new Paragraph(entry.getValue()));
                    pdfCell.setBorderWidth(1f);
                    pdfCell.setBorderColor(BaseColor.BLACK);
                    pdfCell.setPadding(5f);
                    table.addCell(pdfCell);
                }
            }

            // 添加表格到PDF文档
            table.setSpacingBefore(20f);
            table.setSpacingAfter(20f);
            table.setKeepTogether(true);
            document.add(table);

            // 关闭PDF文档
            document.close();
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }
        excelDataVo.setPdfFilePath(pdfFilePath);
        log.info("所有数据解析完成!");
    }
}

至此,就基于 EasyExcel 和 iText 库实现了 Excel 转 PDF 的逻辑,并将外部的数据传递到监听器,也从监听器拿到返回的内容,其他的比如 Service 传递到监听器也可以通过这种注入方式实现。

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

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

相关文章

2024第二次培训:win11系统下使用nginx、JDK、mysql搭建基于vue2、java前后端分离的web应用运行环境

一.背景 公司安排了带徒弟的任务&#xff0c;给培训写点材料。前面分开介绍了mysql、jdk、nginx的安装&#xff0c;都只是零星的介绍&#xff0c;只能算零散的学习。学习了有什么用呢&#xff1f;能解决什么问题&#xff1f;能完成什么工作&#xff1f; 今天我们要用之前的几篇…

TCP/UDP,HTTP、HTTPS存在什么风险会影响到网络安全吗

近年来&#xff0c;随着网络技术的飞速发展&#xff0c;互联网影响人们的方方面面&#xff0c;我们平时也接触到许多以前从未听过的东西&#xff0c;今天德迅云安全就来分享下一些互联网安全知识&#xff0c;讲解一些关于常看到的关于IP, TCP/UDP&#xff0c;HTTP、HTTPS这些名…

Docker自定义JDK镜像并拉取至阿里云镜像仓库全攻略

前言 随着容器技术的日益成熟&#xff0c;Docker已经成为现代软件开发和部署的标配工具。其中&#xff0c;自定义Docker镜像是满足特定项目需求的关键步骤。特别是在Java开发环境中&#xff0c;我们可能需要为不同的项目配置不同版本的JDK。这时&#xff0c;通过Docker自定义J…

venv、pip、conda、anaconda、miniconda的区别和优缺点,和彻底清除python多余的环境

virtualenv(venv) 这是一个虚拟环境管理器&#xff0c;它可以让你每个项目甚至每个脚本配置一个自定义的Python解释器环境&#xff0c;这最大的好处是我可以不污染开发环境。​ pip pip 是 Python 最常用的包管理器&#xff0c;它能自动处理依赖 。 conda 如果说venv是虚拟…

langchain学习笔记(九)

RunnableBranch: Dynamically route logic based on input | &#x1f99c;️&#x1f517; Langchain 基于输入的动态路由逻辑&#xff0c;通过上一步的输出选择下一步操作&#xff0c;允许创建非确定性链。路由保证路由间的结构和连贯。 有以下两种方法执行路由 1、通过Ru…

S2---FPGA-A7板级原理图硬件实战

视频链接 FPGA-A7板级系统硬件实战01_哔哩哔哩_bilibili FPGA-A7板级原理图硬件实战 基于XC7A100TFGG484的FPGA硬件设计流程图 A7核心板&#xff0c;是基于XILINX公司的ARTIX-7系列100T的XC7A100T,2FGG484I这款芯片开发的高性能核心板&#xff0c;具有高速&#xff0c;高带宽&a…

wpa_supplicant交叉编译

文章目录 源码编译openssl编译libnl交叉编译WPA 开发板测试使用 源码 wpa_supplicant官网&#xff1a;http://w1.fi/wpa_supplicant/ GIT源&#xff1a;git://w1.fi/hostap.git openssl 源码&#xff1a; https://www.openssl.org/ libnl 源码&#xff1a; https://github.c…

QT之液晶电子时钟

根据qt的<QLDNumber>做了一个qt液晶电子时钟. 结果 实时显示当前时间,左键可以拖动时钟在屏幕的位置,右键点击关闭显示. 实现过程 新建一个class文件,让这个文件的父类是QLCDNumber 相关功能变量定义和函数实现 .c文件代码 这里需要注意的一点是event->button是获取的…

力扣SQL50 产品销售分析 I 查询

Problem: 1068. 产品销售分析 I 思路 left join on&#xff1a;左连接 Code select p.product_name, s.year, s.price from Sales s left join Product p on s.product_id p.product_id

深入剖析k8s-控制器思想

引言 本文是《深入剖析Kubernetes》学习笔记——《深入剖析Kubernetes》 正文 控制器都遵循K8s的项目中一个通用的编排模式——控制循环 for {实际状态 : 获取集群中对象X的实际状态期望状态 : 获取集群中对象X的期望状态if 实际状态 期望状态 {// do nothing} else {执行…

【nmap工具介绍及常用命令】从零基础入门到精通,看完这一篇就够了。

1.功能介绍 nmap&#xff08;network mapper&#xff09;,网络映射器&#xff0c;是kali内置的一款工具&#xff0c;是网络连扫描软件&#xff0c;用来扫描网上设备开放的网络连接端。确定哪些服务运行在哪些连接端&#xff0c;并且&#xff0c;推断设备使用什么系统。 nmap的…

2024年腾讯云优惠代金券一键领取页面,太划算!

腾讯云代金券领取渠道有哪些&#xff1f;腾讯云官网可以领取、官方媒体账号可以领取代金券、完成任务可以领取代金券&#xff0c;大家也可以在腾讯云百科蹲守代金券&#xff0c;因为腾讯云代金券领取渠道比较分散&#xff0c;腾讯云百科txybk.com专注汇总优惠代金券领取页面&am…

详细介绍如何用windows自带Hyper-V安装虚拟机(windows11和ubuntu22)

通过系统自带的hyper-v安装windows11&#xff0c;舒服又惬意&#xff0c;相比用第三方虚拟机软件速度快很多。 硬件准备 准备 系统需要符合能安装 Hyper-V 的最低要求windows版本含Hyper-V的功能 电脑空间 电脑要有足够的空间来安装你这个虚拟机。根据自己的磁盘容量情况来规…

如何知道当前ubuntu的版本

查看版本&#xff1a; cat /etc/lsb-release 查看内核&#xff1a; uname -a

新算法转让(一种基于改进欧拉法开发的元启发式算法)

新算法转让&#xff08;一种基于改进欧拉法开发的元启发式算法&#xff09; 新的群智能算法转让&#xff0c;新的元启发式算法转让 1.开发完成的完整代码 2.灵感部分已完成&#xff0c;有word版本说明 3.测试结果17/30个排名第一&#xff08;算法开发完毕&#xff09;与AO、A…

面部SDF阴影锯齿问题的探索

近期做的一些工作涉及到面部SDF阴影&#xff0c;网上普遍做法是不做插值&#xff0c;直接Step硬性裁剪&#xff0c;我通过SmoothStep做了简单修改&#xff0c;看下效果。 看上去还可以是因为gif有压缩&#xff0c;但面部SDF阴影做插值有个很严重的问题&#xff1a; 插值处理后…

LangFlow——一款可轻松实验和原型化 LangChain流水线的AI项目

LangFlow——一款可轻松实验和原型化 LangChain流水线的AI项目。 前言 在人工智能兴起的当下&#xff0c;AI正在重塑着很多行业。今天介绍的是一款近期登上github热门的一款可轻松实验和原型化 LangChain[1] 流水线的AI项目—LangFlow。 Flowise——通过拖放界面构建定制的LLM…

音视频开发项目:H.265播放器:视频解码篇

视频演示 如下将演示新版播放器播放 1分钟1080p/25fps/H.265 MP4视频&#xff0c;具体视频参数如下&#xff1a; 粉丝福利&#xff0c; 免费领取C音视频学习资料包学习路线大纲、技术视频/代码&#xff0c;内容包括&#xff08;音视频开发&#xff0c;面试题&#xff0c;FFmpe…

微软自带的便笺(jian)无法连接到服务器。错误代码 0x80072EFD,同时如何在手机使用便笺

便笺的内容无法在各个设备同步&#xff0c;错误如图所示 一、问题的解决 参考自微软社区&#xff1a;Redirecting 原话&#xff1a; 此错误一般都是由于网络问题导致的。建议您首先确认您有没有开启代理&#xff0c;您可以打开设置&#xff0c;网络和Internet&#xff0c;找…

程序员缺乏经验的 7 种表现,你中招没?

一次性提交大量代码 代码写的很烂 同时开展多项工作 性格傲慢 不能从之前的错误中学到经验 工作时间处理私人事务 盲目追逐技术潮流 总结 知道这些表现&#xff0c;你才能在自己的程序员职业生涯中不犯相同的错误。 软件行业的工作经验和你从事这个行业的工作年限直接…