当前位置: 首页 > article >正文

Java 基于 poi 和 itextpdf 实现 excel 转 pdf

目录

问题

实现思路

pom

Excel2PDFUtil

Excel2PDFUtilTest 

输出结果


问题

工作中遇到一个需求,需要实现 excel 文件的预览,实现的思路就是将 excel 转成 pdf 文件,上传到文件服务器上得到文件地址,预览时只需要返回 pdf 预览文件地址即可。

所以主要的问题就是如何将 excel 转为 pdf,调研了相关的技术,最简单的就是使用 aspose 类库,直接一个api调用就搞定了。但是 aspose 并不是免费的,虽然网上有破解,但是为了规避版权风险,最好还是不用了。

可以使用 itextpdf 来平替 aspose 实现 excel 文件转换。由于需求中的 excel 就只是很常规的文本表格,使用 itextpdf 来创建表格,依次从 excel 获取每行每列的单元格依次填入即可将 excel 中的内容搬到新建的 pdf 中,从而实现 excel 到 pdf 的转换。

实现思路

poi 读取 excel 内容,得到 excel 文件中每一张 sheet,每张 sheet 中的所有单元格

InputStream in = Files.newInputStream(Paths.get(excelPath);
//workbook
Workbook workbook = excelSuffix.endsWith(".xlsx") ? new XSSFWorkbook(in) : new HSSFWorkbook(in);

//获取所有表格
Iterator<Sheet> it = workbook.sheetIterator()
Sheet sheet = it.next();

//获取单元格
Row row = sheet.getRow(rowIndex);
Cell cell = row.getCell(columnIndex);

//获取单元格值
CellType cellType = excelCell.getCellType();
String value = excelCell.getStringCellValue();

 itextpdf 创建pdf,将 excel 单元格转换成 pdf 单元格,最后写入 pdf 文件

OutputStream out = Files.newOutputStream(Paths.get(pdfPath);
//创建 pdf 文档
Document document = new Document(new RectangleReadOnly(842.0F, 595.0F));
        PdfWriter.getInstance(document, outStream);

document.open();

//创建 pdf 表格
PdfPTable table = new PdfPTable();

//船舰 pdf 单元格
PdfPCell cell = new PdfPCell();

//添加单元格到表格
table.add(cell);

//新建一页
document.newPage();

//将表格写入文档
document.add(table);

document.close();

pom

    <properties>
        <poi.version>5.2.5</poi.version>
        <itextpdf.version>5.5.13.2</itextpdf.version>
    </properties>
     
    <dependencies>
         <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${poi.version}</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>${itextpdf.version}</version>
        </dependency>
    </dependencies>

Excel2PDFUtil

public class Excel2PDFUtil {

    public static void excelToPdf(String excelPath, String pdfPath, String excelSuffix) {
        try (InputStream in = Files.newInputStream(Paths.get(excelPath));
             OutputStream out = Files.newOutputStream(Paths.get(pdfPath))) {
            excelToPdf(in, out, excelSuffix);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Excel转PDF并写入输出流
     *
     * @param inStream    Excel输入流
     * @param outStream   PDF输出流
     * @param excelSuffix Excel类型 .xls 和 .xlsx
     * @throws Exception 异常信息
     */
    public static void excelToPdf(InputStream inStream, OutputStream outStream, String excelSuffix) throws Exception {
        //设置pdf纸张大小 PageSize.A4 A4横向
        Document document = new Document(new RectangleReadOnly(842.0F, 595.0F));
        PdfWriter.getInstance(document, outStream);
        //设置页边距 宽
        document.setMargins(10, 10, 10, 10);
        document.open();
        // 输入流转workbook,获取sheet
        Workbook workbook = excelSuffix.endsWith(".xlsx") ? new XSSFWorkbook(inStream) : new HSSFWorkbook(inStream);
        for (Iterator<Sheet> it = workbook.sheetIterator(); it.hasNext(); ) {
            Sheet sheet = it.next();
            // 获取列宽度占比
            float[] widths = getColWidth(sheet);
            PdfPTable table = new PdfPTable(widths);
            table.setWidthPercentage(100);
            int colCount = widths.length;
            // 遍历行
            for (int rowIndex = sheet.getFirstRowNum(); rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                Row row = sheet.getRow(rowIndex);
                if (Objects.isNull(row)) {
                    // 插入空对象
                    for (int i = 0; i < colCount; i++) {
                        table.addCell(createPdfPCell(null, 0, 13f, null));
                    }
                } else {
                    // 遍历单元格
                    for (int columnIndex = 0; (columnIndex < row.getLastCellNum() || columnIndex < colCount) && columnIndex > -1; columnIndex++) {
                        PdfPCell pCell = excelCellToPdfCell(sheet, row.getCell(columnIndex));
                        //处理合并单元格
                        dealMergedRegion(sheet, rowIndex, columnIndex, pCell);

                        table.addCell(pCell);
                    }
                }
            }

            document.newPage();
            document.add(table);
        }
        document.close();
    }

    /**
     * 单元格转换,poi cell 转换为 itext cell
     *
     * @param sheet  poi sheet页
     * @param excelCell poi 单元格
     * @return com.itextpdf.text.pdf.PdfPCell
     */
    private static PdfPCell excelCellToPdfCell(Sheet sheet, Cell excelCell) {
        if (Objects.isNull(excelCell)) {
            return createPdfPCell(null, 0, 13f, null);
        }

        org.apache.poi.ss.usermodel.Font excelFont = getExcelFont(sheet, excelCell);
        //设置单元格字体
        com.itextpdf.text.Font pdFont = new com.itextpdf.text.Font();
        pdFont.setSize(excelFont.getFontHeightInPoints());
        pdFont.setStyle(excelFont.getBold() ? 1 : 0);
        pdFont.setColor(BaseColor.BLACK);
        Integer border = hasBorder(excelCell) ? null : 0;
        String excelCellValue = getExcelCellValue(excelCell);
        PdfPCell pCell = createPdfPCell(excelCellValue, border, excelCell.getRow().getHeightInPoints(), pdFont);
        // 水平居中
        pCell.setHorizontalAlignment(getHorAlign(excelCell.getCellStyle().getAlignment().getCode()));
        // 垂直对齐
        pCell.setVerticalAlignment(getVerAlign(excelCell.getCellStyle().getVerticalAlignment().getCode()));
        return pCell;
    }

    /**
     * 创建itext pdf 单元格
     *
     * @param content 单元格内容
     * @param border 边框
     * @param minimumHeight 高度
     * @param pdFont 字体
     * @return pdf cell
     */
    private static PdfPCell createPdfPCell(String content, Integer border, Float minimumHeight, com.itextpdf.text.Font pdFont) {
        String contentValue = content == null ? "" : content;
        com.itextpdf.text.Font pdFontNew = pdFont == null ? new com.itextpdf.text.Font() : pdFont;
        PdfPCell pCell = new PdfPCell(new Phrase(contentValue, pdFontNew));
        if (Objects.nonNull(border)) {
            pCell.setBorder(border);
        }
        if (Objects.nonNull(minimumHeight)) {
            pCell.setMinimumHeight(minimumHeight);
        }

        return pCell;
    }

    /**
     * excel垂直对齐方式映射到pdf对齐方式
     */
    private static int getVerAlign(int align) {
        switch (align) {
            case 2:
                return com.itextpdf.text.Element.ALIGN_BOTTOM;
            case 3:
                return com.itextpdf.text.Element.ALIGN_TOP;
            default:
                return com.itextpdf.text.Element.ALIGN_MIDDLE;
        }
    }

    /**
     * excel水平对齐方式映射到pdf水平对齐方式
     */
    private static int getHorAlign(int align) {
        switch (align) {
            case 1:
                return com.itextpdf.text.Element.ALIGN_LEFT;
            case 3:
                return com.itextpdf.text.Element.ALIGN_RIGHT;
            default:
                return com.itextpdf.text.Element.ALIGN_CENTER;
        }
    }

    /*============================================== POI获取图片及文本内容工具方法 ==============================================*/

    /**
     * 获取字体
     *
     * @param sheet excel 转换的sheet页
     * @param cell 单元格
     * @return 字体
     */
    private static org.apache.poi.ss.usermodel.Font getExcelFont(Sheet sheet, Cell cell) {
        // xls
        if (sheet instanceof HSSFSheet) {
            Workbook workbook = sheet.getWorkbook();
            return ((HSSFCell) cell).getCellStyle().getFont(workbook);
        }
        // xlsx
        return ((XSSFCell) cell).getCellStyle().getFont();
    }

    /**
     * 判断excel单元格是否有边框
     */
    private static boolean hasBorder(Cell excelCell) {
        short top = excelCell.getCellStyle().getBorderTop().getCode();
        short bottom = excelCell.getCellStyle().getBorderBottom().getCode();
        short left = excelCell.getCellStyle().getBorderLeft().getCode();
        short right = excelCell.getCellStyle().getBorderRight().getCode();
        return top + bottom + left + right > 2;
    }

    /**
     * 处理合并单元格
     *
     * @param sheet 表格
     * @param row 当前行
     * @param column 当前列
     * @param pCell pdf单元格
     */
    private static void dealMergedRegion(Sheet sheet, int row, int column, PdfPCell pCell) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (firstColumn == column && firstRow == row) {
                pCell.setRowspan(lastRow - firstRow + 1);
                pCell.setColspan(lastColumn - firstColumn + 1);
                break;
            }
        }
    }

    /**
     * 获取excel中每列宽度的占比
     */
    private static float[] getColWidth(Sheet sheet) {
        int rowNum = getMaxColRowNum(sheet);
        Row row = sheet.getRow(rowNum);
        int cellCount = row.getPhysicalNumberOfCells();
        int[] colWidths = new int[cellCount];
        int sum = 0;

        for (int i = row.getFirstCellNum(); i < cellCount; i++) {
            Cell cell = row.getCell(i);
            if (cell != null) {
                colWidths[i] = sheet.getColumnWidth(i);
                sum += sheet.getColumnWidth(i);
            }
        }

        float[] colWidthPer = new float[cellCount];
        for (int i = row.getFirstCellNum(); i < cellCount; i++) {
            colWidthPer[i] = (float) colWidths[i] / sum * 100;
        }
        return colWidthPer;
    }

    /**
     * 获取excel中列数最多的行号
     */
    private static int getMaxColRowNum(Sheet sheet) {
        int rowNum = 0;
        int maxCol = 0;
        for (int r = sheet.getFirstRowNum(); r < sheet.getPhysicalNumberOfRows(); r++) {
            Row row = sheet.getRow(r);
            if (row != null && maxCol < row.getPhysicalNumberOfCells()) {
                maxCol = row.getPhysicalNumberOfCells();
                rowNum = r;
            }
        }
        return rowNum;
    }

    /**
     * poi 根据单元格类型获取单元格内容
     *
     * @param excelCell poi单元格
     * @return 单元格内容文本
     */
    public static String getExcelCellValue(Cell excelCell) {
        if (excelCell == null) {
            return "";
        }
        // 判断数据的类型
        CellType cellType = excelCell.getCellType();

        if (cellType == CellType.STRING) {
            return excelCell.getStringCellValue();
        }
        if (cellType == CellType.BOOLEAN) {
            return String.valueOf(excelCell.getBooleanCellValue());
        }
        if (cellType == CellType.FORMULA) {
            return excelCell.getCellFormula();
        }
        if (cellType == CellType.NUMERIC) {
            //short s = excelCell.getCellStyle().getDataFormat();
            if (DateUtil.isCellDateFormatted(excelCell)) {// 处理日期格式、时间格式
                SimpleDateFormat sdf;
                // 验证short值
                if (excelCell.getCellStyle().getDataFormat() == 14) {
                    sdf = new SimpleDateFormat("yyyy/MM/dd");
                } else if (excelCell.getCellStyle().getDataFormat() == 21) {
                    sdf = new SimpleDateFormat("HH:mm:ss");
                } else if (excelCell.getCellStyle().getDataFormat() == 22) {
                    sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                } else {
                    throw new RuntimeException("日期格式错误!!!");
                }
                Date date = excelCell.getDateCellValue();
                return sdf.format(date);
            } else if (excelCell.getCellStyle().getDataFormat() == 0) {
                //处理数值格式
                DataFormatter formatter = new DataFormatter();
                return formatter.formatCellValue(excelCell);
            }
        }
        if (cellType == CellType.ERROR) {
            return "非法字符";
        }
        return "";
    }

}

Excel2PDFUtilTest 

class Excel2PDFUtilTest {

    @Test
    void excelToPdf() {
        String excelPath = "C:\\Users\\XXXX\\Desktop\\excel.xlsx";
        String pdfPath = "C:\\Users\\XXXX\\Desktop\\pdf.pdf";

        Excel2PDFUtil.excelToPdf(excelPath, pdfPath, ".xlsx");
    }
}

输出结果

excel文件:

 pdf文件:


http://www.kler.cn/a/369140.html

相关文章:

  • 想作弊❓用这个发起考试,根本没法作弊
  • 前端性能优化之SSR优化
  • 设计模式-单例模型(单件模式、Singleton)
  • linux面试题复习
  • Nodejs安装配置及创建vue项目
  • PHP const 和 define主要区别
  • 安卓自定义文本组件
  • 网络搜索引擎Shodan(3)
  • Javascript数据结构——哈希表
  • 什么是排列树?
  • 【单片机运行的原理及应用方向】
  • c#获取目录下所有文件
  • 51单片机应用开发(进阶)---外部中断(按键+数码管显示0-F)
  • 名城优企游学活动走进思腾合力:解析人工智能先行者的数字化之路
  • 记一次Esxi掉盘处理使用命令
  • [0152].第3节:IDEA中工程与模块
  • Python金色流星雨
  • 部署RocketMQ, 其实很简单 (带图, 附启动命令)
  • 视频智能分析平台LiteAIServer摄像机视频分析软件下载检测裸土
  • 易基因:Nat Commun:ATAC-seq等揭示恒河猴大脑高分辨率解剖区域的转录组和开放染色质图谱
  • 装饰器模式的适用场景示例
  • Django+Vue全栈开发项目入门(一)
  • 可以为服务器配置动态IP吗?
  • Redis 单机、主从、哨兵和集群架构详解和搭建
  • 口碑最好的开放式耳机有哪些?开放式蓝牙耳机排行榜盘点!
  • 【MySQL】视图与用户管理——MySQL