使用poi向word中插入文字或图片

参考自

https://blog.csdn.net/weixin_50638065/article/details/133958393

依赖包

最下面的两个包肯定需要的,其他的有几个不需要的,自己试着删一下,用不了这么多

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>4.1.2</version>
</dependency>
<!--poi-tl-->
<dependency>
    <groupId>com.deepoove</groupId>
    <artifactId>poi-tl</artifactId>
    <version>1.12.1</version>
</dependency>
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.20</version>
</dependency>
<dependency>
    <groupId>com.aspose.words</groupId>
    <artifactId>aspose-words-jdk16</artifactId>
    <version>15.8.0.0</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>3.15</version>
</dependency>

word文档格式

  • 我用的是docx格式,文字替换使用的替换符为 美元符号+大括号,中间是传入的参数名;例:

    ${year}年${month}月${day}日 
    
  • 图片的替换方式为使用“word的标签格式‘;操作步骤为:

    • 先鼠标点击想要插入图片的位置;
    • 菜单栏点击--插入--书签--输入书签名--点击添加;OK了,书签名就是图片的替换文本,也就是代码中map的key;

这里使用apache-aspose去除pdf的水印

在resources目录下加入License.xml配置文件

<!--报表打印,去水印-->
<License>
    <Data>
        <Products>
            <Product>Aspose.Total for Java</Product>
            <Product>Aspose.Words for Java</Product>
        </Products>
        <EditionType>Enterprise</EditionType>
        <SubscriptionExpiry>20991231</SubscriptionExpiry>
        <LicenseExpiry>20991231</LicenseExpiry>
        <SerialNumber><!-- 自己百度找吧 --></SerialNumber>
    </Data>
    <Signature>
     <!-- 自己百度找吧 -->
    </Signature>
</License>

word插入文字、图片、转换成pdf的base64

import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.List;
import java.util.Map;




/**
     * 获取原文件,并将其生成pdf的base64
     * @param map 需要插入的文本  {"text1":"asdf","text2":"233"}  text1和text2就是插入的文本,在word中用 ${text1};
     * @param map1 需要插入的图片 {"pic1":"base64"}  pic1就是插入word中的标签,值是图片的base64
     * @param base64 原docx文件的base64
     * @return
     */
    public static String searchAndReplace(Map<String, Object> map, Map<String, Object> map1, String base64) {
        // 获取原docx文件
        byte[] decodedBytes = Base64.getDecoder().decode(base64.replaceAll("[^A-Za-z0-9+/=]", ""));
        try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decodedBytes)){
            XWPFDocument document = new XWPFDocument(byteArrayInputStream);
            // 替换文字与图片标签
            replaceInPara1(document, map, map1);
            // 生成pdf的base64
            return docxConvertPdf(document);
//            ByteArrayOutputStream out = new ByteArrayOutputStream();
//            document.write(out);
//            byte[] bytes = out.toByteArray();
//            out.close();
//            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception e) {
            // XXXXXXX
        }
        return null;

    }
   
   
     /**
     * 替换段落里面的变量
     * @param doc 要替换的文档
     * @param params 参数
     */
    public static void replaceInPara1(XWPFDocument doc, Map<String, Object> params, Map<String, Object> params1) {
        for (XWPFParagraph para : doc.getParagraphs()) {
            replaceInPara(para, params);
        }
        for (XWPFParagraph para : doc.getParagraphs()) {
            replaceInBook(para, params1);
        }
    }
    
    
    
    
    
    /**
     * 替换段落里面的文字
     *
     * @param paragraph   要替换的段落
     * @param params 参数
     */
    private static void replaceInPara(XWPFParagraph paragraph, Map<String, Object> params) {
        List<XWPFRun> runs = paragraph.getRuns();
        for (int i = 0; i < runs.size(); i++) {
            //获取字符
            String text0 = runs.get(i).getText(runs.get(i).getTextPosition());
            if (text0 != null && text0.contains("$")) {
                //包含占位符的字符缓存
                StringBuilder cache = new StringBuilder(text0);
                int endIndex = 0;
                boolean contains = text0.contains("}");
                //同一个run中是否包含占位符
                if (!contains) {
                    int j = i + 1;
                    for (; j < runs.size(); j++) {
                        String text1 = runs.get(j).getText(runs.get(j).getTextPosition());
                        if (text1 == null) {
                            continue;
                        }
                        cache.append(text1);
                        if (text1.contains("}")) {
                            endIndex = j;
                            break;
                        }
                    }
                }
                if (contains || endIndex != 0) {
                    //处理替换
                    String s = cache.toString();
                    for (Map.Entry<String, Object> entry : params.entrySet()) {
                        String k = entry.getKey();
                        String v = entry.getValue().toString();
                        if (s.contains("${" + k + "}")) {
                            String replace = s.replace("${" + k + "}", v);
                            runs.get(i).setText(replace, 0);
                            for (int j = endIndex; j > i; j--) {
                                runs.get(j).setText("", 0);
                            }
                            break;
                        }
                    }
                }
            }
        }
    }




 /**
     * 替换段落里面的图片标签
     *
     * @param paragraph   要替换的段落
     * @param params 参数
     */
    private static void replaceInBook(XWPFParagraph paragraph, Map<String, Object> params) {
        CTP ctp = paragraph.getCTP();
        for (int dwI = 0; dwI < ctp.sizeOfBookmarkStartArray(); dwI++) {
            CTBookmark bookmark = ctp.getBookmarkStartArray(dwI);
            if (!params.containsKey(bookmark.getName())) continue;
            try (InputStream ins = (InputStream) params.get(bookmark.getName())){
                XWPFRun run = paragraph.createRun();
                //bus.png为鼠标在word里选择图片时,图片显示的名字,100,100则为像素单元,根据实际需要的大小进行调整即可。
                run.addPicture(ins, XWPFDocument.PICTURE_TYPE_PNG, "tutu.png,", Units.toEMU(56), Units.toEMU(35));
            } catch (InvalidFormatException | IOException e) {
                // XXXXXX
            }

        }
    }
    
    
    /**
     * docx转换pdf
     */
    public static String docxConvertPdf(XWPFDocument doc){
        // 写入文档到输出流
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();
             ByteArrayOutputStream outPdf = new ByteArrayOutputStream()){
            doc.write(out);
            // 将输出流转换为字节数组
            byte[] docBytes = out.toByteArray();
            // 将字节数组转换为输入流
            try(InputStream inputStream = new ByteArrayInputStream(docBytes)){
                if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
                    log.error("向docx文件中插入图片时失败");
                    BusiExcUtil.dataIsTrueEx(true, "验证License失败!");
                }
                com.aspose.words.Document document = new com.aspose.words.Document(inputStream);
                document.save(outPdf, SaveFormat.PDF);
                byte[] byteArray = outPdf.toByteArray();
                return Base64.getEncoder().encodeToString(byteArray);
            } catch (Exception e) {
                log.error("docx转换pdf时失败", e);
                BusiExcUtil.dataIsTrueEx(true, "docx转换pdf时失败!");
            }
        } catch (IOException e) {
            log.error("docx转换pdf时失败", e);
            BusiExcUtil.dataIsTrueEx(true, "docx转换pdf时失败!");
        }
        return null;
    }


    /**
     * 验证且去除pdf水印
     * @return
     */
    public static boolean getLicense() {
        try (InputStream is = DocxToPdf.class.getClassLoader().getResourceAsStream("License.xml")){
            License license = new License();
            license.setLicense(is);
            return true;
        } catch (Exception e) {
            log.error("验证且去除pdf水印失败", e);
        }
        return false;
    }
   
posted @ 2024-05-22 11:04  窃窃私语QAQ  阅读(27)  评论(0编辑  收藏  举报