你知道的越多,你不知道的越多
點贊再看,養成習慣
如果您有疑問或者見解,歡迎指教:
企鵝: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 {// 需要進行轉換的excelString 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;}@Overridepublic void invoke(Map<Integer, String> data, AnalysisContext context) {cachedDataList.add(data);}@Overridepublic void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {cachedHead = ConverterUtils.convertToStringMap(headMap, context);}@Overridepublic 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 傳遞到監聽器也可以通過這種注入方式實現。