将Excel转为PDF、PDF添加图片

news/2024/7/21 3:45:08 标签: excel, pdf, java

封装在如下工具类中

java">import com.aspose.cells.SaveFormat;
import com.aspose.cells.Workbook;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;

/**
 * PDF工具类
 *
 * @author yxm
 */
@Slf4j
public abstract class PdfUtil {

    /**
     * 要去除的水印的字体
     */
    private static final String WATERMARK_FONT = "FAAADD";

    /**
     * 存放照片的PDF页的水平宽度,即左边距,右边距
     */
    private static final double SPACE_HORIZONTAL = 20;

    /**
     * 存放照片的PDF页的竖直高度,即上边距,下边距
     */
    private static final double SPACE_VERTICAL = 20;


    public static void main(String[] args) {
        try {
            long beginTime = System.currentTimeMillis();
            excelToPdf("E:\\Code\\BCCloud\\ruoyi-modules\\exin-rhaj\\src\\main\\java\\com\\exin\\rhaj\\common\\template\\巡检用户安全检查表-非居.xlsx");
            long endTime = System.currentTimeMillis();
            System.out.println("执行时间:" + ((endTime - beginTime) / 1000) + "秒");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Excel转换为PDF
     *
     * @param excelPath 需要被转换的excel源文件全路径带文件名
     * @Return void
     */
    public static void excelToPdf(String excelPath) throws Exception {
        //新建一个pdf文档
        String pdfPath = excelPath.substring(0, excelPath.lastIndexOf(".")) + ".pdf";
        File pdfFile = new File(pdfPath);
        //Excel文件数据
        Workbook wb = new Workbook(excelPath);
        FileOutputStream fileOS = new FileOutputStream(pdfFile);
        //保存为pdf文件
        wb.save(fileOS, SaveFormat.PDF);
        fileOS.close();
        // 去除水印
        removeWatermark(pdfPath);
        // 添加照片
        addImage(pdfFile, 4, 4, new String[]{"C:\\Users\\Administrator\\Pictures\\head.jpg",
                "C:\\Users\\Administrator\\Pictures\\head.jpg",
                "C:\\Users\\Administrator\\Pictures\\head.jpg",
                "C:\\Users\\Administrator\\Pictures\\admin-settings-male.png",
                "C:\\Users\\Administrator\\Pictures\\head.jpg",
                "C:\\Users\\Administrator\\Pictures\\admin-settings-male.png",
                "C:\\Users\\Administrator\\Pictures\\head.jpg",
                "C:\\Users\\Administrator\\Pictures\\admin-settings-male.png",
                "C:\\Users\\Administrator\\Pictures\\head.jpg",
                "C:\\Users\\Administrator\\Pictures\\head.jpg"});
    }

    /**
     * 移除文字水印
     *
     * @param pdfPath PDF源文件路径
     * @return
     */
    private static void removeWatermark(String pdfPath) throws IOException {
        removeWatermark(new File(pdfPath));
    }

    /**
     * 移除文字水印
     *
     * @param file PDF源文件
     * @return
     */
    private static void removeWatermark(File file) throws IOException {
        //通过文件名加载文档
        PDDocument document = Loader.loadPDF(file);
        PDPageTree pages = document.getPages();
        Iterator<PDPage> iter = pages.iterator();
        while (iter.hasNext()) {
            PDPage page = iter.next();
            PDResources resources = page.getResources();
            COSDictionary dict1 = resources.getCOSObject();
            resources.getFontNames().forEach(e -> {
                COSDictionary dict2 = dict1.getCOSDictionary(COSName.FONT);
                if (e.getName().equals(WATERMARK_FONT)) {
                    dict2.removeItem(e);
                }
                page.setResources(new PDResources(dict1));
            });
        }
        file.delete();
        document.save(file);
        document.close();
    }

    /**
     * 在pdf中添加图片
     *
     * @param pdfFile  PDF源文件
     * @param rowNum   每页显示几行照片
     * @param colNum   每页显示几列照片
     * @param imgPaths 照片路径数组
     * @throws IOException
     */
    public static void addImage(File pdfFile, int rowNum, int colNum, String[] imgPaths) throws IOException {
        // 获得PDF文件流对象
        PDDocument pdDocument = Loader.loadPDF(pdfFile);
        // 获取文档第一页配置信息
        PDRectangle commonMediaBox = pdDocument.getPage(0).getMediaBox();
        // 新页宽高
        double docWidth = commonMediaBox.getWidth();
        double docHeight = commonMediaBox.getHeight();
        // 新页内容区宽高
        double contentWidth = docWidth - SPACE_HORIZONTAL * 2;
        double contentHeight = docHeight - SPACE_VERTICAL * 2;
        // 遍历图片路径的指针、路径总数量
        int imgPathIndex = 0;
        int imgPathLength = imgPaths.length;
        // 新增的页数
        int newPageNum = (int) Math.ceil(1D * imgPathLength / (rowNum * colNum));
        // 生成页数
        for (int i = 1; i <= newPageNum; i++) {
            // 向文档中添加新页 用于放置图片
            PDPage newPage = new PDPage(commonMediaBox);
            // 创建pageStream对象
            PDPageContentStream pageStream = new PDPageContentStream(pdDocument, newPage, PDPageContentStream.AppendMode.APPEND, true, true);
            // 每个图片宽高
            double widthUnit = contentWidth / colNum;
            double HeightUnit = contentHeight / rowNum;
            // pageStream对象绘制图片位置及大小,已知PDF文件左下角为原点(0,0),图片左下角是(x,y),width、height是图片的宽和高
            for (int row = rowNum - 1; row >= 0 && imgPathIndex < imgPathLength; row--) {
                for (int col = 0; col < colNum && imgPathIndex < imgPathLength; col++) {
                    // 创建图片对象
                    PDImageXObject image = PDImageXObject.createFromFile(imgPaths[imgPathIndex], pdDocument);
                    imgPathIndex++;
                    pageStream.drawImage(image, (int) (widthUnit * col + SPACE_HORIZONTAL), (int) (HeightUnit * row + SPACE_VERTICAL), (int) widthUnit, (int) HeightUnit);
                }
            }
            pageStream.close();
            // 将新页添入文档
            pdDocument.addPage(newPage);
        }
        // 删除原pdf
        pdfFile.delete();
        // 保存PDF到指定路径
        pdDocument.save(pdfFile);
        pdDocument.close();
    }
}


http://www.niftyadmin.cn/n/5437005.html

相关文章

RabbitMQ的幂等性、优先级队列和惰性队列

文章目录 前言一、幂等性1、概念2、消息重复消费3、解决思路4、消费端的幂等性保障5、唯一 ID指纹码机制6、Redis 原子性 二、优先级队列1、使用场景2、如何添加3、实战 三、惰性队列1、使用场景2、两种模式3、内存开销对比 总结 前言 一、幂等性 1、概念 2、消息重复消费 3、…

使用Composer安装Laravel框架

使用Composer安装Laravel框架&#xff0c;不指定版本则安装当下最新版本 composer create-project laravel/laravel laravel-demo 至此&#xff0c;安装框架完成&#xff0c;这里安装的是Laravel11.0.7版本的 进入项目根目录&#xff0c;运行项目 cd laravel.11.0.7 // 进…

vue实现element-UI中table表格背景颜色设置

目前在style中设置不了&#xff0c;那么就在前面组件给设置上 :header-cell-style"{ color: #ffffff, fontSize: 14px, backgroundColor: #0E2152 }" :cell-style"{ color: #ffffff, fontSize: 14px, backgroundColor: #0E2152 }"

如何通过ETL做数据转换

在数字化时代&#xff0c;数据被誉为新时代的石油&#xff0c;而数据的价值往往隐藏在海量数据背后的信息中。然而&#xff0c;海量的原始数据并不总是直接可用的&#xff0c;这就需要一种有效的工具来对数据进行提取、转换和加载&#xff08;ETL&#xff09;&#xff0c;从而将…

从单机到分布式微服务,大文件校验上传的通用解决方案

一、先说结论 本文将结合我的工作实战经历&#xff0c;总结和提炼一种从单体架构到分布式微服务都适用的一种文件上传和校验的通用解决方案&#xff0c;形成一个完整的方法论。本文主要解决手段包括多线程、设计模式、分而治之、MapReduce等&#xff0c;虽然文中使用的编程语言…

每天学习几道面试题|Kafka架构设计类

文章目录 1. Kafka 是如何保证高可用性和容错性的&#xff1f;2. Kafka 的存储机制是怎样的&#xff1f;它是如何处理大量数据的&#xff1f;3. Kafka 如何处理消费者的消费速率低于生产者的生产速率&#xff1f;4. Kafka 集群中的 Controller 是什么&#xff1f;它的作用是什么…

python 深度学习的学习路径

一、python基础代码 1.环境安装与配置 2.变量 3.流程控制语句 4.字符串 5.列表、元组、字典 6.函数 7.面向对象&#xff1a;继承、封装、多态 8.文件处理、异常处理 二、数据处理常用包 1.numpy 2.pandas 3.matplotlib 三、常用框架 1.pytorch 四、理解经典网络 1…

小型路由器,为什么四个端口的IP在一个网段?

是的&#xff0c;路由器确实在不同网段&#xff0c;不过小型路由器&#xff08;宽带路由器&#xff09;一般都是为家用设计的&#xff0c;思路就是越简单好用越好&#xff0c;逻辑上其实它只有一个WAN口和一个LAN口&#xff0c;WAN口接公网一个地址&#xff0c;LAN口接你电脑一…