Java 使用 poi 和 aspose 实现 word 模板数据写入并转换 pdf 增加水印

本项目所有源码和依赖资源都在文章顶部链接,有需要可以下载使用

1. 需求描述


  1. 从指定位置读取一个 word 模板
  2. 获取业务数据并写入该 word 模板,生成新的 word 文档
  3. 将新生成的 word 文档转换为 pdf 格式
  4. 对 pdf 文档添加水印

2. 效果预览


  1. word 模板
    在这里插入图片描述
  2. 带水印的 pdf 文档
    在这里插入图片描述

3. 实现思路


  • word 模板数据写入:使用 poi-tl 库实现
  • word 转 pdf 格式:aspose-words 库实现
  • pdf 增加水印:aspose-pdf 库实现

4. 实现过程


4.1 依赖库准备

poi-tl 可以使用 maven 直接从中央仓库下载,但是 aspose 无法下载,需要从网上下载 jar 包并导入本地仓库

  • poi-tl

        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.1</version>
        </dependency>
    
  • aspose-word
    将 jar 包导入本地仓库

        mvn install:install-file \
          -DgroupId="com.aspose" \
          -DartifactId="aspose-words" \
          -Dversion="15.8.0" \
          -Dpackaging="jar" \
          -Dfile="aspose-words-15.8.0-jdk16.jar"
    

    项目中添加依赖

        <dependency>
            <groupId>com.aspose</groupId>
            <artifactId>aspose-words</artifactId>
            <version>15.8.0</version>
        </dependency>
    
  • aspose-pdf
    将 jar 包导入本地仓库

        mvn install:install-file \
          -DgroupId="com.aspose" \
          -DartifactId="aspose-pdf" \
          -Dversion="17.8" \
          -Dpackaging="jar" \
          -Dfile="aspose.pdf-17.8.jar"
    

    项目中添加依赖

        <dependency>
            <groupId>com.aspose</groupId>
            <artifactId>aspose-pdf</artifactId>
            <version>17.8</version>
        </dependency>
    
  • license.xml
    由于 aspose 库分为免费版和收费版,免费版导出的文档带有试用水印,所以需要添加 license.xml,版权关系不在文章中写出,有需要的可以下载文章顶部链接的完整源码包。

4.2 核心实现方法
@SpringBootApplication
public class Word2PDFApplication {

    public static void main(String[] args) {

        SpringApplication.run(Word2PDFApplication.class, args);

        // word 模板
        String wordTemplatePath = "src/main/resources/templates/简历模板.docx";
        // 写入数据后的 word
        String wordOutputPath = "src/main/resources/templates/简历模板-output.docx";
        // word 转换为 pdf
        String pdfOutputPath = "src/main/resources/templates/简历模板.pdf";
        // pdf 增加水印
        String pdfWithMarkerOutputPath = "src/main/resources/templates/简历模板-marker.pdf";

        // step 1: 封装模板数据
        Map<String, Object> dataMap = getPersonDataMap();

        // step 2: 将数据写入 word 模板
        writeDataToWord(dataMap, wordTemplatePath, wordOutputPath);

        // step 3: 将 word 转换为 pdf
        convertWordToPdf(wordOutputPath, pdfOutputPath);

        // step 4: 将 pdf 增加水印
        addMarkerToPdf(pdfOutputPath, pdfWithMarkerOutputPath);
    }

	// 封装业务数据,用于填入模板对应占位符中
    private static Map<String, Object> getPersonDataMap() {
        Map<String, Object> personDataMap = new HashMap<>();
        personDataMap.put("name", "张三");
        personDataMap.put("sex", "男");
        personDataMap.put("birthDate", "1998-12-02");
        personDataMap.put("id", "420202199812020011");
        personDataMap.put("phone", "18819297766");
        personDataMap.put("skills", "java Spring MySQL ...");
        return personDataMap;
    }

	// 将业务数据写入 word 模板,并生成新的 word 文件
    private static void writeDataToWord(Map<String, Object> dataMap, String wordTemplatePath, String wordOutputPath) {

        XWPFTemplate render = XWPFTemplate.compile(wordTemplatePath).render(dataMap);
        File dest = new File(wordOutputPath);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            render.writeToFile(wordOutputPath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

	// 将新生成的带有业务数据的 word 文档转换为 pdf 格式
    private static void convertWordToPdf(String wordOutputPath, String pdfOutputPath) {
        // 验证 License 若不验证则转化出的 pdf 文档带有水印
        if (!getAsposeWordLicense()) {
            return;
        }
        FileOutputStream os = null;
        try {
            long old = System.currentTimeMillis();
            File file = new File(pdfOutputPath);
            os = new FileOutputStream(file);
            Document doc = new Document(wordOutputPath);
            doc.save(os, SaveFormat.PDF);
            long now = System.currentTimeMillis();
            System.out.println("pdf转换成功,共耗时:" + ((now - old) / 1000.0) + "秒");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.flush();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

	// 对转换后的 pdf 文档添加水印效果
    private static void addMarkerToPdf(String pdfOutputPath, String pdfWithMarkerOutputPath) {
        // 验证 License 若不验证则增加水印后的 pdf 文档带有试用水印
        boolean asposePdfLicense = getAsposePdfLicense();
        if (!asposePdfLicense) {
            return;
        }

        com.aspose.pdf.Document pdfDocument = new com.aspose.pdf.Document(pdfOutputPath);

        TextStamp textStamp = new TextStamp("水印文本");
        textStamp.getTextState().setFontSize(14.0F);
        textStamp.getTextState().setFontStyle(FontStyles.Bold);
        textStamp.setRotateAngle(45);
        textStamp.setOpacity(0.2);

        // 设置水印间距
        float xOffset = 100;
        float yOffset = 100;

        // 添加水印到每一页
        for (Page page : pdfDocument.getPages()) {
            float xPosition = 0;
            float yPosition = 0;

            // 在页面上添加水印直到页面被覆盖
            while (yPosition < page.getRect().getHeight()) {
                textStamp.setXIndent(xPosition);
                textStamp.setYIndent(yPosition);
                page.addStamp(textStamp);

                xPosition += xOffset;

                // 如果水印超过页面宽度,移到下一行
                if (xPosition + textStamp.getWidth() > page.getRect().getWidth()) {
                    xPosition = 0;
                    yPosition += yOffset;
                }
            }
        }
        // 保存修改后的文档
        pdfDocument.save(pdfWithMarkerOutputPath);
    }

	// 验证 license,否则有试用水印
    private static boolean getAsposeWordLicense() {
        boolean result = false;
        InputStream is = null;
        try {
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            org.springframework.core.io.Resource[] resources = resolver.getResources("classpath:license.xml");
            is = resources[0].getInputStream();
            License asposeLic = new License();
            asposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

	// 验证 license,否则有试用水印
    private static boolean getAsposePdfLicense() {
        boolean result = false;
        InputStream is = null;
        try {
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            org.springframework.core.io.Resource[] resources = resolver.getResources("classpath:license.xml");
            is = resources[0].getInputStream();
            com.aspose.pdf.License asposeLic = new com.aspose.pdf.License();
            asposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用POI将Excel模板写入数据并保存本地的工具类示例: ```java import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; public class ExcelWriter { private File file; private Workbook workbook; public ExcelWriter(String filePath) throws IOException { file = new File(filePath); workbook = WorkbookFactory.create(new FileInputStream(file)); } public void writeData(String[] sheetNames, Map<String, Object[][]> data) throws IOException { for (String sheetName : sheetNames) { Sheet sheet = workbook.getSheet(sheetName); Object[][] sheetData = data.get(sheetName); if (sheetData != null) { int rowIndex = 0; for (Object[] rowData : sheetData) { Row row = sheet.getRow(rowIndex); if (row == null) { row = sheet.createRow(rowIndex); } int columnIndex = 0; for (Object cellData : rowData) { Cell cell = row.getCell(columnIndex); if (cell == null) { cell = row.createCell(columnIndex); } if (cellData != null) { if (cellData instanceof Number) { cell.setCellValue(((Number) cellData).doubleValue()); } else if (cellData instanceof String) { cell.setCellValue((String) cellData); } else if (cellData instanceof Boolean) { cell.setCellValue((Boolean) cellData); } else { cell.setCellValue(cellData.toString()); } } columnIndex++; } rowIndex++; } } } } public void save() throws IOException { workbook.write(new FileOutputStream(file)); workbook.close(); } public static void main(String[] args) throws IOException { ExcelWriter writer = new ExcelWriter("template.xlsx"); Map<String, Object[][]> data = new HashMap<String, Object[][]>(); data.put("Sheet1", new Object[][] { { "A1", "B1", "C1" }, { "A2", "B2", "C2" } }); data.put("Sheet2", new Object[][] { { "X1", "Y1", "Z1" }, { "X2", "Y2", "Z2" } }); writer.writeData(new String[] { "Sheet1", "Sheet2" }, data); writer.save(); } } ``` 使用示例: 1. 创建Excel文件"template.xlsx",在Sheet1和Sheet2中分别添加3列数据; 2. 在Java使用ExcelWriter类读取"template.xlsx"文件; 3. 调用writeData方法向Sheet1和Sheet2中写入数据; 4. 调用save方法保存更新后的Excel文件。 注意:ExcelWriter类中的写入数据方法是覆盖式写入,即会清空原有数据,再写入数据。如果需要追加数据,需要修改方法实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值