开发者

Java多种方式实现Excel转Pdf的保姆级教程

开发者 https://www.devze.com 2025-08-22 10:19 出处:网络 作者: 暗武逢天
目录需求介绍itextpdf实现引入maven依赖代码实现ASPose-cell实现简介主要功能包括但不限于:特别亮点下载jar包crack使用 反编译jar包生成 aspose-cells-20.7-crack.jar测试 aspose-cells-20.7-crack.jar 使用先
目录
  • 需求介绍
  • itextpdf实现
    • 引入maven依赖
    • 代码实现
  • ASPose-cell实现
    • 简介
      • 主要功能包括但不限于:
      • 特别亮点
    • 下载jar包
      • crack使用 
        • 反编译jar包
        • 生成 aspose-cells-20.7-crack.jar
        • 测试 aspose-cells-20.7-crack.jar 使用
        • 先生成图片再转pdf
        • 直接转换

    需求介绍

    在企业级系统使用或日常使用中,我们经常使用excel表格数据进行浏览数据,但有时候我们会想要将excel转换成pdf进行预览使用,这时就需要进行程序编写实现这个需求,本篇博文以Java进行编写多种实现方式实现多sheet页excel转换一个pdf的需求

    itextpdf实现

    引入maven依赖

    引入所需依赖,下面五个是主要依赖

            <dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi</artifactId>
    			<version>4.1.0</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi-ooXML</artifactId>
    			<version>4.1.0</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi-ooxml-schemas</artifactId>
    			<version>4.1.0</version>
    		</dependency>
    		<dependency>
    			<groupId>com.itextpdf</groupId>
    			<artifactId>itextpdf</artifactId>
    			<version>5.5.13</version>
    		</dependency>
    		<dependency>
    			<groupId>com.itextpdf</groupId>
    			<artifactId>itext-asian</artifactId>
    			<version>5.2.0</version>
    		</dependency>

    具体哪几个博主忘了,如果上面依赖导入后写代码还有缺失的,可以直接把下面完整的都copy下

            <dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>4.12</version>
    		</dependency>
    		<dependency>
    			<groupId>commons-codec</groupId>
    			<artifactId>commons-codec</artifactId>
    			<version>1.10</version>
    		</dependency>
    		<dependency>
    			<groupId>commons-io</groupId>
    			<artifactId>commons-io</artifactId>
    			<version>2.4</version>
    		</dependency>
    		<dependency>
    			<groupId>dom4j</groupId>
    			<artifactId>dom4j</artifactId>
    			<version>1.6.1</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi</artifactId>
    			<version>4.1.0</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi-ooxml</artifactId>
    			<version>4.1.0</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.poi</groupId>
    			<artifactId>poi-ooxml-schemas</artifactId>
    			<version>4.1.0</version>
    		</dependency>
    		<dependency>
    			<groupId>com.itextpdf</groupId>
    			<artifactId>itextpdf</artifactId>
    			<version>5.5.13</version>
    		</dependency>
    		<dependency>
    			<groupId>com.itextpdf</groupId>
    			<artifactId>itext-asian</artifactId>
    			<version>5.2.0</version>
    		</dependency>
    
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.8.27</version>
            </dependency>
            
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.30</version>
                <scope>provided</scope>
            </dependency>

    代码实现

    由于在使用时,有时候excel里会插入图片,所以我们在转换时候需要考虑到图片的业务

    先对图片类型进行建模处理

    import java.io.Serializable;
    
    /**
     * 图片信息
     */
    public class PicturesInfo implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        /**
         * 最小行
         */
        private int minRow;
    
        /**
         * 最大行
         */
        private int maxRow;
    
        /**
         * 最小列
         */
        private int minCol;
    
        /**
         * 最大列
         */
        private int maxCol;
    
        /**
         * 扩展
         */
        private String ext;
    
        /**
         * 图片数据
         */
        private byte[] pictureData;
    
        public int getMinRow() {
            return minRow;
        }
    
        public PicturesInfo setMinRow(int minRow) {
            this.minRow = minRow;
            return this;
        }
    
        public int getMaxRow() {
            return maxRow;
        }
    
        public PicturesInfo setMaxRow(int maxRow) {
            this.maxRow = maxRow;
            return this;
        }
    
        public int getMinCol() {
            return minCol;
        }
    
        public PicturesInfo setMinCol(int minCol) {
            this.minCol = minCol;
            return this;
        }
    
      编程  public int getMaxCol() {
            return maxCol;
        }
    
        public PicturesInfo setMaxCol(int maxCol) {
            this.maxCol = maxCol;
            return this;
        }
    
        public String getExt() {
            return ext;
        }
    
        public PicturesInfo setExt(String ext) {
            this.ext = ext;
            return this;
        }
    
        public byte[] getPictureData() {
            return pictureData;
        }
    
        public PicturesInfo setPictureData(byte[] pictureData) {
            this.pictureData = pictureData;
            return this;
        }
    }
    
    

    书写转换工具类

    import com.itextpdf.text.*;
    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 org.apache.poi.hssf.usermodel.*;
    import org.apache.poi.ooxml.POIXMLDocumentPart;
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.ss.usermodel.Font;
    import org.apache.poi.ss.util.CellRangeAddress;
    import org.apache.poi.xssf.usermodel.*;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.*;
    import java.util.List;
    
    /**
     * Excel转PDF
     * @author 廖航
     * @date 2024-08-29 10:52
     */
    //@UtilityClass
    //@Slf4j
    public class ExcelToPdfUtil {
    
        /**
         * 日志输出
         */
    //    private static final log log = log.getlog(ExcelToPdfUtil.class);
    
        /**
         * 单元格队列
         */
        static Set<String> cellSet = new HashSet<>();
    
        /**
         * Excel转PDF
         *
         * @param excelPath Excel文件路径
         * @param pdfPath PDF文件路径
         * @param excelSuffix Excel文件后缀
         */
        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))) {
                ExcelToPdfUtil.excelToPdf(in, out, excelSuffix);
            } catch (Exception e) {
    
            }
        }
    
        /**
         * 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 {
    
    
            // 输入流转workbook,获取sheet  读取Excel文件
            Workbook workbook = getPoiWorkbookByFileStream(inStream, excelSuffix);
       www.devze.com     //设置pdf纸张大小 PageSize.A4 A4横向
    //        Document document = new Document(PageSize.B0);
            Document document = new Docume编程客栈nt(PageSize.A2.rotate());
    //        绑定PDF写入器到输出流
            PdfWriter.getInstance(document, outStream);
            // 设置页面四周边距
            document.setMargins(50, 50, 30, 30);
            document.open(); // 准备开始写入内容
            //设置基本字体
            BaseFont baseFont = BaseFont.createFont("C:\\Windows\\Fonts\\simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            for (int j = 0; j < workbook.getNumberOfSheets(); j++) {
                if(j != 0) {
                    document.newpage(); // 新的Sheet开始新的一页
                }
                //获取sheet
                Sheet sheet = workbook.getSheetAt(j);
    
                // 获取列宽度占比
                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)) {
                        // 插js入空对象
                        for (int i = 0; i < colCount; i++) {
                            table.addCell(createPdfPCell(null, 0, 11f, null));
                        }
                    } else {
                        // 遍历单元格
                        for (int columnIndex = 0; (columnIndex < row.getLastCellNum() || columnIndex < colCount) && columnIndex > -1; columnIndex++) {
                            PdfPCell pCell = excelCellToPdfCell(sheet, row.getCell(columnIndex), baseFont);
                            // 是否合并单元格
                            if (isMergedRegion(sheet, rowIndex, columnIndex)) {
                                int[] span = getMergedSpan(sheet, rowIndex, columnIndex);
                                //忽略合并过的单元格
                                boolean mergedCell = span[0] == 1 && span[1] == 1;
                                if (mergedCell) {
                                    continue;
                                }
                                pCell.setRowspan(span[0]);
                                pCell.setColspan(span[1]);
                            }
    
                            table.addCell(pCell);
                        }
                    }
                }
    
                document.add(table);
            }
            document.close();
    
        }
    
    
        protected static CellRangeAddress getColspanRowspanByExcel(int rowIndex, int colIndex,Sheet sheet) {
            CellRangeAddress result = null;
            int num = sheet.getNumMergedRegions();
            for (int i = 0; i < num; i++) {
                CellRangeAddress range = sheet.getMergedRegion(i);
                if (range.getFirstColumn() == colIndex && range.getFirstRow() == rowIndex) {
                    result = range;
                }
            }
            return result;
        }
    
        // 获取Workbook对象
        public static Workbook getPoiWorkbookByFileStream(InputStream inputStream, String excelSuffix) throws IOException {
            if (excelSuffix.endsWith(".xlsx")) {
                return new XSSFWorkbook(inputStream);
            } else {
                return new HSSFWorkbook(inputStream);
            }
        }
    
        /**
         * 单元格转换,poi cell 转换为 itext cell
         *
         * @param sheet     poi sheet页
         * @param excelCell poi 单元格
         * @param baseFont  基础字体
         * @return PDF单元格
         */
        private static PdfPCell excelCellToPdfCell(Sheet sheet, Cell excelCell, BaseFont baseFont) throws Exception {
            if (Objects.isNull(excelCell)) {
                return createPdfPCell(null, 0, 11f, null);
            }
            int rowIndex = excelCell.getRowIndex();
            int columnIndex = excelCell.getColumnIndex();
            // 图片信息
            List<PicturesInfo> infos = getAllPictureInfos(sheet, rowIndex, rowIndex, columnIndex, columnIndex, false);
            PdfPCell pCell;
            if (infos != null && !infos.isEmpty()) {
                Image image = Image.getInstance(infos.get(0).getPictureData());
                // 调整图片大小
                image.scaleAbsolute(527, 215);
                pCell = new PdfPCell(image);
            } else {
                Font excelFont = getExcelFont(sheet, excelCell);
                //设置单元格字体
                com.itextpdf.text.Font pdFont = new com.itextpdf.text.Font(baseFont, excelFont.getFontHeightInPoints(), excelFont.getBold() ? 1 : 0, BaseColor.BLACK);
                Integer border = hasBorder(excelCell) ? null : 0;
                String excelCellValue = getExcelCellValue(excelCell);
                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对齐方式
         *
         * @param align 对齐
         * @return 结果
         */
        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水平对齐方式
         *
         * @param align 对齐
         * @return 结果
         */
        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 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单元格是否有边框
         *
         * @param excelCell 单元格
         * @return 结果
         */
        private static boolean hasBorder(Cell excelCell) {
            CellStyle style = excelCell.getCellStyle();
    
            BorderStyle top = style.getBorderTop();
            BorderStyle bottom = style.getBorderBottom();
            BorderStyle left = style.getBorderLeft();
            BorderStyle right = style.getBorderRight();
    
            return top != BorderStyle.NONE ||
                    bottom != BorderStyle.NONE ||
                    left != BorderStyle.NONE ||
                    right != BorderStyle.NONE;
        }
    
        /**
         * 判断单元格是否是合并单元格
         *
         * @param sheet 表
         * @param row 行
         * @param column 列
         * @return 结果
         */
        private static boolean isMergedRegion(Sheet sheet, int row, int column) {
            int sheeandroidtMergeCount = 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 (row >= firstRow && row <= lastRow) {
                    if (column >= firstColumn && column <= lastColumn) {
                        return true;
                    }
                }
            }
            return false;
        }
    
    
    
        /**
         * 计算合并单元格合并的跨行跨列数
         *
         * @param sheet 表
         * @param row 行
         * @param column 列
         * @return 结果
         */
        private static int[] getMergedSpan(Sheet sheet, int row, int column) {
            int sheetMergeCount = sheet.getNumMergedRegions();
            int[] span = {1, 1};
            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) {
                    span[0] = lastRow - firstRow + 1;
                    span[1] = lastColumn - firstColumn + 1;
                    break;
                }
            }
            return span;
        }
    
        /**
         * 获取excel中每列宽度的占比
         *
         * @param sheet 表
         * @return 结果
         */
        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中列数最多的行号
         *
         * @param sheet 表
         * @return 结果
         */
        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) {
    //            // 处理日期格式、时间格式
    //            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 "";
            if (excelCell == null) {
                return "";
            }
    
            DataFormatter formatter = new DataFormatter();
            return formatter.formatCellValue(excelCell);
        }
    
    
        /**
         * 根据sheet和单元格信息获取图片
         *
         * @param sheet        sheet表
         * @param minRow       最小行
         * @param maxRow       最大行
         * @param minCol       最小列
         * @param maxCol       最大列
         * @param onlyInternal 是否内部
         * @return 图片集合
         * @throws Exception 异常
         */
        public static List<PicturesInfo> getAllPictureInfos(Sheet sheet, Integer minRow, Integer maxRow, Integer minCol,
                                                            Integer maxCol, boolean onlyInternal) throws Exception {
            if (sheet instanceof HSSFSheet) {
                return getXLSAllPictureInfos((HSSFSheet) sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
            } else if (sheet instanceof XSSFSheet) {
                return getXLSXAllPictureInfos((XSSFSheet) sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
            } else {
                throw new Exception("未处理类型,没有为该类型添加:GetAllPicturesInfos()扩展方法!");
            }
        }
    
        /**
         * 获取XLS图片信息
         *
         * @param sheet 表
         * @param minRow 最小行
         * @param maxRow 最大行
         * @param minCol 最小列
         * @param maxCol 最大列
         * @param onlyInternal 只在内部
         * @return 图片信息列表
         */
        private static List<PicturesInfo> getXLSAllPictureInfos(HSSFSheet sheet, Integer minRow, Integer maxRow,
                                                                Integer minCol, Integer maxCol, Boolean onlyInternal) {
            List<PicturesInfo> picturesInfoList = new ArrayList<>();
            HSSFShapeContainer shapeContainer = sheet.getDrawingPatriarch();
            if (shapeContainer == null) {
                return picturesInfoList;
            }
            List<HSSFShape> shapeList = shapeContainer.getChildren();
            for (HSSFShape shape : shapeList) {
                if (shape instanceof HSSFPicture && shape.getAnchor() instanceof HSSFClientAnchor) {
                    HSSFPicture picture = (HSSFPicture) shape;
                    HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
    
                    if (isInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.getRow1(), anchor.getRow2(),
                            anchor.getCol1(), anchor.getCol2(), onlyInternal)) {
    //                    String item = StrUtil.format("{},{},{},{}", anchor.getRow1(), anchor.getRow2(), anchor.getCol1(), anchor.getCol2());
                        String item = String.format("%d,%d,%d,%d",
                                anchor.getRow1(),
                                anchor.getRow2(),
                                anchor.getCol1(),
                                anchor.getCol2());
                        if (cellSet.contains(item)) {
                            continue;
                        }
                        cellSet.add(item);
                        HSSFPictureData pictureData = picture.getPictureData();
                        picturesInfoList.add(new PicturesInfo()
                                .setMinRow(anchor.getRow1())
                                .setMaxRow(anchor.getRow2())
                                .setMinCol(anchor.getCol1())
                                .setMaxCol(anchor.getCol2())
                                .setPictureData(pictureData.getData())
                                .setExt(pictureData.getMimeType()));
                    }
                }
            }
            return picturesInfoList;
        }
    
        /**
         * 获取XLSX图片信息
         *
         * @param sheet 表
         * @param minRow 最小行
         * @param maxRow 最大行
         * @param minCol 最小列
         * @param maxCol 最大列
         * @param onlyInternal 只在内部
         * @return 图片信息列表
         */
        private static List<PicturesInfo> getXLSXAllPictureInfos(XSSFSheet sheet, Integer minRow, Integer maxRow,
                                                                 Integer minCol, Integer maxCol, Boolean onlyInternal) {
            List<PicturesInfo> picturesInfoList = new ArrayList<>();
    
            List<POIXMLDocumentPart> documentPartList = sheet.getRelations();
            for (POIXMLDocumentPart documentPart : documentPartList) {
                if (documentPart instanceof XSSFDrawing) {
                    XSSFDrawing drawing = (XSSFDrawing) documentPart;
                    List<XSSFShape> shapes = drawing.getShapes();
                    for (XSSFShape shape : shapes) {
                        if (shape instanceof XSSFPicture) {
                            XSSFPicture picture = (XSSFPicture) shape;
                            XSSFClientAnchor anchor = picture.getPreferredSize();
    
                            if (isInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.getRow1(), anchor.getRow2(),
                                    anchor.getCol1(), anchor.getCol2(), onlyInternal)) {
    //                            String item = StrUtil.format("{},{},{},{}", anchor.getRow1(), anchor.getRow2(), anchor.getCol1(), anchor.getCol2());
                                String item = String.format("%d,%d,%d,%d",
                                        anchor.getRow1(),
                                        anchor.getRow2(),
                                        anchor.getCol1(),
                                        anchor.getCol2());
                                if (cellSet.contains(item)) {
                                    continue;
                                }
                                cellSet.add(item);
                                XSSFPictureData pictureData = picture.getPictureData();
                                picturesInfoList.add(new PicturesInfo()
                                        .setMinRow(anchor.getRow1())
                                        .setMaxRow(anchor.getRow2())
                                        .setMinCol(anchor.getCol1())
                                        .setMaxCol(anchor.getCol2())
                                        .setPictureData(pictureData.getData())
                                        .setExt(pictureData.getMimeType()));
                            }
                        }
                    }
                }
            }
    
            return picturesInfoList;
        }
    
        /**
         * 是内部的或相交的
         *
         * @param rangeMinRow 最小行范围
         * @param rangeMaxRow 最大行范围
         * @param rangeMinCol 最小列范围
         * @param rangeMaxCol 最大列范围
         * @param pictureMinRow 图片最小行
         * @param pictureMaxRow 图片最大行
         * @param pictureMinCol 图片最小列
         * @param pictureMaxCol 图片最大列
         * @param onlyInternal 只在内部
         * @return 结果
         */
        private static boolean isInternalOrIntersect(Integer rangeMinRow, Integer rangeMaxRow, Integer rangeMinCol,
                                                     Integer rangeMaxCol, int pictureMinRow, int pictureMaxRow, int pictureMinCol, int pictureMaxCol,
                                                     Boolean onlyInternal) {
            int _rangeMinRow = rangeMinRow == null ? pictureMinRow : rangeMinRow;
            int _rangeMaxRow = rangeMaxRow == null ? pictureMaxRow : rangeMaxRow;
            int _rangeMinCol = rangeMinCol == null ? pictureMinCol : rangeMinCol;
            int _rangeMaxCol = rangeMaxCol == null ? pictureMaxCol : rangeMaxCol;
    
            if (onlyInternal) {
                return (_rangeMinRow <= pictureMinRow && _rangeMaxRow >= pictureMaxRow && _rangeMinCol <= pictureMinCol
                        && _rangeMaxCol >= pictureMaxCol);
            } else {
                return ((Math.abs(_rangeMaxRow - _rangeMinRow) + Math.abs(pictureMaxRow - pictureMinRow) >= Math
                        .abs(_rangeMaxRow + _rangeMinRow - pictureMaxRow - pictureMinRow))
                        && (Math.abs(_rangeMaxCol - _rangeMinCol) + Math.abs(pictureMaxCol - pictureMinCol) >= Math
                        .abs(_rangeMaxCol + _rangeMinCol - pictureMaxCol - pictureMinCol)));
            }
        }
    
    
        public static void main(String[] args) {
            ExcelToPdfUtil.excelToPdf("原excel文件路径.xlsx",
                    "转换后输出pdf路径.pdf", ".xlsx");
    
        }
    }
    

    测试时直接创建一个多sheet页的excel表格,并填入一些测试数据进行测试,查看转换后的结果

    Java多种方式实现Excel转Pdf的保姆级教程

    在主方法里更改路径进行测试

    Java多种方式实现Excel转Pdf的保姆级教程

    Java多种方式实现Excel转Pdf的保姆级教程

    等待程序执行完后在导出路径查看转换后的pdf

    Java多种方式实现Excel转Pdf的保姆级教程

    点击查看

    Java多种方式实现Excel转Pdf的保姆级教程

    Java多种方式实现Excel转Pdf的保姆级教程

    可以看到转换后的效果还是不错的,表格内容宽度自动使用pdf页面的宽度,每个sheet页都另起新的页面,多个sheet页拼接在一个pdf里,后续纸张大小参数等都可以在代码里进行灵活调整

    aspose-cell实现

    简介

    Aspose.Cells for Java 是一款功能强大的 Java 库,专门用于操作 Microsoft Excel 文件而无需依赖 Microsoft Office。提供了丰富的API来创建、修改、转换和打印Excel文档。

    主要功能包括但不限于:

    • 文件格式支持:全面支持 Excel 的各种格式,如 .xls.xlsx.xlsm.xltx.xltm 等。
    • 数据处理:轻松读取、写入及修改工作表中的数据,支持复杂的数据类型与结构。
    • 格式化:灵活设置单元格、行、列的格式,包括字体、颜色、边框、背景色等,并支持条件格式化。
    • 图表与图形:创建、更新或删除图表,添加图片和其他图形元素到工作表中。
    • 公式计算:支持复杂的公式计算,确保数据准确性。
    • PDF 转换:高质量地将 Excel 文档转换为 PDF 格式,同时支持自定义页面大小、方向等属性。
    • 安全性和保护:对 Excel 文件进行加密、解密,以及设置打开或修改密码。
    • 批量处理:高效处理大量数据集,适用于大规模数据操作场景。

    特别亮点

    • 无须安装 Microsoft Office:由于其独立性,开发者可以在没有安装 MS Office 的环境中使用此库执行所有相关任务。
    • 跨平台兼容性:完全基于Java开发,可在任何支持Java的平台上运行。
    • 性能优越:优化了内存管理和处理速度,即使对于大型文件也能保持良好的性能表现。

    注意该jar包是收费的,收费版本试用时候会有水印和行数多少限制,一旦达到一定数据量可能会导致程序报错,可以进行破解使用

    下载jar包

    该jar包在国内镜像源里是拉取不到的,可以在官网直接下载jar包,后导入到本地使用

    aspose官网链接

    Java多种方式实现Excel转Pdf的保姆级教程

    在官网里找到对应版本依赖,如果是国外镜像源或者其他源库可以尝试拉取试试,如果没有也可以直接下载jar包到本地后安装到本地使用

    Java多种方式实现Excel转Pdf的保姆级教程

    点击后下载

     输入下面命令进行安装到本地

    mvn install:install-file "-Dfile=jar包所在路径\jar包名.jar" "-DgroupId=com.aspose" "-DartifactId=aspose-cells" "-Dversion=版本号" "-Dpackaging=jar"
    

    修改对应的jar包路径和包名后在idea命令行里执行安装jar包

    Java多种方式实现Excel转Pdf的保姆级教程

    没有报错说明安装成功,在pom文件里书写下对应的依赖刷新下maven即可

    Java多种方式实现Excel转Pdf的保姆级教程

    刷新下maven即可然后书写测试类尝试转换

    Java多种方式实现Excel转Pdf的保姆级教程

    执行转换 

    Java多种方式实现Excel转Pdf的保姆级教程

    可以看到导出后的效果还是不错的,但是有水印

    Java多种方式实现Excel转Pdf的保姆级教程

    crack使用 

    这里以aspose-cells-20.7 去除水印及次数限制破解作为示例

    反编译jar包

    使用 jd-gui.exe 反编译查看jar包,直接搜索 License

    Java多种方式实现Excel转Pdf的保姆级教程

    Java多种方式实现Excel转Pdf的保姆级教程

    1.修改

      public static boolean isLicenseSet() {
        return (a != null);
      }
    

     改为

      public static boolean isLicenseSet() {
        return true;
      }
    

    2.修改

      public void setLicense(InputStream stream) {
        Document document = null;
        if (stream != null)
          try {
            DocumentBuilder documentBuilder = zad.b();
            document = documentBuilder.parse(stream);
          } catch (Exception exception) {
            throw new CellsException(9, zf.a(new byte[] { 
                    -20, 93, -23, 54, -20, -49, -59, 86, -9, -86, 
                    49, 44, -59, 71, -52, -86, -90, 6, -90, -25, 
                    -86, 1, -1, -92, -91, -126, 7, 113, -66, -95, 
                    -121, 16, -122, -126, 7, 104, -40, -70, -10, -37, 
                    126, 7, -111, -121, -121 }) + exception.getMessage());
          }  
        a(document);
      }
    

    改成

      public void setLicense(InputStream paramInputStream){
        a = new License();
        zbiw.a();
      }
    

    3.修改

      private static Date k(String paramString) {
        if (paramString == null || paramString.length() < 8)
          return null; 
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(zf.a(new byte[] { 
                79, 89, 33, -52, 79, -121, -125, 33, 71, -126, 
                105, -121 }));
        try {
          return simpleDateFormat.parse(paramString);
        } catch (ParseException parseException) {
          throw new IllegalArgumentException(zf.a(new byte[] { 
                  -21, -113, -77, 13, -115, 27, Byte.MIN_VALUE, 35, 103, -52, 
                  -20, -106, 71, 95, 31, -73, -76, -38, 13, 31, 
                  -91, -97, -102, 85, -68, -33, -19, -87, -127, -14, 
                  78, -23, 6, -25, -94, 1, -97, -95, -57, -121 }));
        } 
      }
    

    改成

      private static Date k(String paramString){
        return new Date(Long.MAX_VALUE);
      }
    

    修改完后使用jdi保存所有的文件为另存

    Java多种方式实现Excel转Pdf的保姆级教程

    Java多种方式实现Excel转Pdf的保姆级教程

    生成 aspose-cells-20.7-crack.jar

    修改 class 这里使用 javassist:

    新建一个 Spring boot 项目:

    pom 文件中引用 javassist

    引入破解所需依赖

         <dependency><!--aspose的jar破解工具-->
                <groupId>org.javassist</groupId>
                <artifactId>javassist</artifactId>
                <version>3.20.0-GA</version>
            </dependency>

    指定目录生成修改后的License.class文件

        public static void crackAspose(String JarPath) throws Exception {
            // 这个是得到反编译的池
            ClassPool pool = ClassPool.getDefault();
    
            // 取得需要反编译的jar文件,设定路径
            pool.insertClassPath(JarPath);
    
            CtClass cc_License = pool.get("com.aspose.cells.License");
    
            CtMethod method_isLicenseSet = cc_License.getDeclaredMethod("isLicenseSet");
            method_isLicenseSet.setBody("return true;");
    
            CtClass cc_License2 = pool.get("com.aspose.cells.License");
            CtMethod method_setLicense = cc_License2.getDeclaredMethod("setLicense");
            method_setLicense.setBody("{    a = new com.aspose.cells.License();\n" +
                    "    com.aspose.cells.zbiw.a();}");
    
            CtMethod method_k = cc_License.getDeclaredMethod("k");
            method_k.setBody("return new java.util.Date(Long.MAX_VALUE);");
    
    
            cc_License.writeFile("输出目录路径");
        }
    

    执行该方法

    Java多种方式实现Excel转Pdf的保姆级教程

    在指定目录下可以看到生成后的编译文件

    Java多种方式实现Excel转Pdf的保姆级教程

    复制一个 aspose-cells-20.7.jar 改名为 aspose-cells-20.7-crack.zip 然后解压

    Java多种方式实现Excel转Pdf的保姆级教程

    把刚才生成的 License.class 文件 替换到解压的源代码中。

    Java多种方式实现Excel转Pdf的保姆级教程

    造一个 License xml 文件,这里文件名为 com.aspose.cells.lic_2999.xml, 位置直接放源代码解压的根目录

    Java多种方式实现Excel转Pdf的保姆级教程

    文件内容为:

    <License>
      <Data>
        <Products>
          <Product>Aspose.Cells for Java</Product>
        </Products>
        <EditionType>Enterprise</EditionType>
        <SubscriptionExpiry>29991231</SubscriptionExpiry>
        <LicenseExpiry>29991231</LicenseExpiry>
        <SerialNumber>evilrule</SerialNumber>
      </Data>
      <Signature>evilrule</Signature>
    </License>
    

    防止文件指纹校验,我们需要删除掉源代码解压包中的 META_INF 文件夹。

    最后的根目录:

    Java多种方式实现Excel转Pdf的保姆级教程

    压缩源代码(注意要是 zip 格式)

    Java多种方式实现Excel转Pdf的保姆级教程

    然后重命名后缀为:jar

    Java多种方式实现Excel转Pdf的保姆级教程

    测试 aspose-cells-20.7-crack.jar 使用

    封装一个 License 验证方法:

    public static boolean authrolizeLicense() {
        boolean result = false;
        try {
            InputStream is = com.aspose.cells.License.class.getResourceAsStream("/com.aspose.cells.lic_2999.xml");
            License asposeLicense = new License();
            asposeLicense.setLicense(is);
            is.close();
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    
    

    修改 main 方法测试使用:

        public static void main(String[] args) {
    
    
    
            // 测试破解后的 aspose-cells-20.7-crack.jar
            boolean auth = authrolizeLicense();
            if (!auth) {
                System.out.println("aspose 许可无效!");
                return;
            }
    
    
            System.out.println("aspose 已就绪!");
    
    
            try{
                Workbook wb = new Workbook("F:\\aaa123.xlsx");
                Worksheet ws = wb.getWorksheets().get(0);
    
                ImageOrPrintOptions imgOptions = new ImageOrPrintOptions();
                imgOptions.setImageFormat(ImageFormat.getPng());
                imgOptions.setCellAutoFit(true);
                imgOptions.setOnePagePerSheet(true);
                SheetRender render = new SheetRender(ws, imgOptions);
    
                render.toImage(0, "F:\\aaa\\123.png");
    
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }
    

    这里图片和excel可以随便搞一个尝试测试使用

    先生成图片再转pdf

    前面的破解工作都做好后就可以尝试测试了,aspose可以先将excel转成图片后再转成pdf

     public static void main(String[] args) {
            // 授权检查(假设你已经破解)
            boolean auth = authrolizeLicense();
            if (!auth) {
                System.out.println("aspose 许可无效!");
                return;
            }
    
            System.out.println("aspose 已就绪!");
    
            try {
                Workbook wb = new Workbook("C:\\Users\\d\\Desktop\\excelToPdf\\奥特曼.xlsx");
                ImageOrPrintOptions imgOptions = new ImageOrPrintOptions();
                imgOptions.setImageFormat(ImageFormat.getPng());
                imgOptions.setCellAutoFit(true);
                imgOptions.setOnePagePerSheet(true);
    
                String outputPdfPath = "C:\\Users\\d\\Desktop\\excelToPdf\\奥特曼Aspose导出图片版.pdf";
    
                // 创建一个无边距的文档
                Document document = new Document(PageSize.A4);  // 使用 A4 纸张尺寸
                PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPdfPath));
    
                // 设置页面无边距(非常重要)
                document.setMargins(0, 0, 0, 0);  // 左、右、上、下全部为 0
                document.open();
    
                for (int i = 0; i < wb.getWorksheets().getCount(); i++) {
                    Worksheet ws = wb.getWorksheets().get(i);
                    SheetRender render = new SheetRender(ws, imgOptions);
                    String imageFilePath = "C:\\Users\\d\\Desktop\\excelToPdf\\sheet_" + i + ".png";
                    render.toImage(0, imageFilePath);
    
                    Image img = Image.getInstance(imageFilePath);
    
                    // 自动缩放图片以适配页面宽度和高度
                    img.scaleToFit(document.getPageSize().getWidth(), document.getPageSize().getHeight());
    
                    // 居中显示(iText 默认就是居中的,但我们可以更明确地设置)
                    img.setAlignment(Image.ALIGN_CENTER);
    
                    // 新增一页
                    document.newPage();
    
                    // 插入图片到当前页面
                    document.add(img);
                }
    
                document.close();
                writer.close();
    
                System.out.println("✅ PDF 文件已生成: " + outputPdfPath);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    执行测试

    Java多种方式实现Excel转Pdf的保姆级教程

    查看生成的效果

    Java多种方式实现Excel转Pdf的保姆级教程

    Java多种方式实现Excel转Pdf的保姆级教程

    可以看到原有的水印都没了

    直接转换

    aspose也可以直接进行转换

        public static void main(String[] args) throws Exception {
    //        // 授权检查(假设你已经破解)
    //        boolean auth = authrolizeLicense();
    //        if (!auth) {
    //            System.out.println("aspose 许可无效!");
    //            return;
    //        }
    //
    //        System.out.println("aspose 已就绪!");
    //
    //        try {
    //            Workbook wb = new Workbook("C:\\Users\\d\\Desktop\\excelToPdf\\奥特曼.xlsx");
    //            ImageOrPrintOptions imgOptions = new ImageOrPrintOptions();
    //            imgOptions.setImageFormat(ImageFormat.getPng());
    //            imgOptions.setCellAutoFit(true);
    //            imgOptions.setOnePagePerSheet(true);
    //
    //            String outputPdfPath = "C:\\Users\\d\\Desktop\\excelToPdf\\奥特曼aspose导出图片版.pdf";
    //
    //            // 创建一个无边距的文档
    //            Document document = new Document(PageSize.A4);  // 使用 A4 纸张尺寸
    //            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPdfPath));
    //
    //            // 设置页面无边距(非常重要)
    //            document.setMargins(0, 0, 0, 0);  // 左、右、上、下全部为 0
    //            document.open();
    //
    //            for (int i = 0; i < wb.getWorksheets().getCount(); i++) {
    //                Worksheet ws = wb.getWorksheets().get(i);
    //                SheetRender render = new SheetRender(ws, imgOptions);
    //                String imageFilePath = "C:\\Users\\d\\Desktop\\excelToPdf\\sheet_" + i + ".png";
    //                render.toImage(0, imageFilePath);
    //
    //                Image img = Image.getInstance(imageFilePath);
    //
    //                // 自动缩放图片以适配页面宽度和高度
    //                img.scaleToFit(document.getPageSize().getWidth(), document.getPageSize().getHeight());
    //
    //                // 居中显示(iText 默认就是居中的,但我们可以更明确地设置)
    //                img.setAlignment(Image.ALIGN_CENTER);
    //
    //                // 新增一页
    //                document.newPage();
    //
    //                // 插入图片到当前页面
    //                document.add(img);
    //            }
    //
    //            document.close();
    //            writer.close();
    //
    //            System.out.println("✅ PDF 文件已生成: " + outputPdfPath);
    //        } catch (Exception e) {
    //            e.printStackTrace();
    //        }
    
    
            // 加载 Excel 文件
            Workbook workbook = new Workbook("C:\\Users\\d\\Desktop\\excelToPdf\\奥特曼.xlsx");
    
            // 设置 PDF 导出选项
            PdfSaveOptions saveOpts = new PdfSaveOptions();
    
            // 设置页面尺寸为 A2(单位是 像素 或 毫米,这里使用像素)
            // A2 尺寸:4961 x 7016 像素(分辨率为 300 DPI)
            PageSetup pageSetup = workbook.getWorksheets().get(0).getPageSetup();
            pageSetup.setPaperSize(PaperSizeType.PAPER_A_3); // 设置为 A2 纸张
            pageSetup.setOrientation(PageOrientationType.LANDSCAPE); // 设置为横向
    
            // 如果你想对所有 sheet 都生效,可以循环设置每个 sheet 的页面属性
            for (int i = 0; i < workbook.getWorksheets().getCount(); i++) {
                Worksheet sheet = workbook.getWorksheets().get(i);
                sheet.getPageSetup().setPaperSize(PaperSizeType.PAPER_A_3);
                sheet.getPageSetup().setOrientation(PageOrientationType.LANDSCAPE);
            }
    
            // 设置每张工作表输出为一页 PDF
            saveOpts.setOnePagePerSheet(true);
    
            // 导出为 PDF
            String outputPdfPath = "C:\\Users\\d\\Desktop\\excelToPdf\\奥特曼aspose导出.pdf";
            workbook.save(outputPdfPath, saveOpts);
    
            System.out.println("✅ 已成功导出 A2 横向 PDF: " + outputPdfPath);
        }

    查看效果

    Java多种方式实现Excel转Pdf的保姆级教程

    这种方式虽然可直接转换,但是还是会有水印,所以还是推荐先转图片后再转pdf的方式

    以上就是Java多种方式实现Excel转Pdf的保姆级教程的详细内容,更多关于Java Excel转Pdf的多种方式的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号