【Excel & PDF 系列】EasyExcel + iText 库

你知道的越多,你不知道的越多

点赞再看,养成习惯

如果您有疑问或者见解,欢迎指教:

企鹅:869192208

文章目录

前言

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

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

转换前后效果


引入 pom 配置
xml 复制代码
<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>
代码实现
定义 ExcelDataVo 对象
java 复制代码
@Data
public class ExcelDataVo implements Serializable {
    private static final long serialVersionUID = 1L;

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

    /**生成pdf的文件标题*/
    private String title;
}
主方法
java 复制代码
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 监听器
java 复制代码
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 传递到监听器也可以通过这种注入方式实现。

相关推荐
卷到起飞的数分18 分钟前
JVM探究
java·服务器·jvm
Geek攻城猫19 分钟前
Java生产环境问题排查实战指南
java·jvm
OtIo TALL8 小时前
redis7 for windows的安装教程
java
uNke DEPH8 小时前
Spring Boot的项目结构
java·spring boot·后端
xixingzhe29 小时前
idea启动vue项目
java·vue.js·intellij-idea
wzl202612139 小时前
企业微信定时群发技术实现与实操指南(原生接口+工具落地)
java·运维·前端·企业微信
凌波粒9 小时前
Java 8 “新”特性详解:Lambda、函数式接口、Stream、Optional 与方法引用
java·开发语言·idea
曹牧9 小时前
Eclipse:悬停提示(Hover)
java·ide·eclipse
oyzz1209 小时前
Spring EL 表达式的简单介绍和使用
java·后端·spring
iNgs IMAC10 小时前
Redis之Redis事务
java·数据库·redis