Java操作Word文档

2年前 (2022) 程序员胖胖胖虎阿
230 0 0


title: Java操作Word文档
description: 使用 Spire.Doc for Java操作Word文档;替换Word模板中的占位符,然后生成新的Word文档
tags: [工具]
categories:

  • 其他

Java 生成 Word 的几种方案

参考

​ 主要有这么一些工具可以使用 Jacob、Apache POI、Java2word、iText,还有一种方法是使用XML作为模板。

​ 使用 XML 的思路:先用 office 编辑好word的样式,然后另存为xml,将xml翻译为FreeMarker模板,最后用java来解析 FreeMarker模板 并输出 Word 文档。经测试这样方式生成的word文档完全符合 office 标准,样式、内容控制非常便利,打印也不会变形,生成的文档和office中编辑文档完全一样。 ===> 参考

Java操作Word文档

  • Jacob 和 Java2word需要服务器端支持 office,相对麻烦。
  • Apache POI 功能较少。===> 参考

​ 这里推荐一个刚刚发现的产品,由成都冰蓝科技开发的产品 Spire,可以用于操作各种文档,目前我只体验过 Spire.Doc for Java,个人认为使用简单,功能强大,对样式的支持非常好(虽然Spire主要面向企业提供产品,但是也提供了免费使用的产品)。最大的缺点是,免费版,没有 Api 文档且Jar包不能完美反编译,只有使用文档,有些代码只能依靠名称推断作用,所以很难深入的挖掘 Spire 的用法。

使用 Spire.Doc 替换 Word 模板中占位符

这里使用 Maven 下载 Spire.Doc 也可以直接下载 jar 包 ==> 参考

1️⃣:首先引入 Maven 依赖

​ 在 Maven 的官方仓库或者阿里云镜像仓库中是没有 Spire 依赖的,所以需要配置 Spire 自己的一个仓库源。

<repositories>
	<repository>
        <id>com.e-iceblue</id>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
	</repository>
</repositories>

​ 以下就是 Spire.Doc for Java 的依赖

<!--spire.doc 操作word文档-->
<dependency>
    <groupId>e-iceblue</groupId>
    <artifactId>spire.doc.free</artifactId>
    <version>3.9.0</version>
</dependency>

2️⃣:设计一个Word模板,此文档中存在占位符

Java操作Word文档

3️⃣:编码

public class TestSpireWord {

    @Test
    public void generateAndReplaceText() {
        Document doc = new Document();
        doc.loadFromFile("F:\\yourlocation\\template.docx", FileFormat.Docx);

        Map<String, String> map = new HashMap<>();
        map.put("${name}", "张山");
        map.put("${birthday}", "2021-10-18");
        map.put("${result}", "成功");
        map.put("${col}", "第一列");
        map.put("${col1}", "第二列");
        map.put("${col2}", "第三列");
        replaceSpecialWord(doc, map);
        // 保存为文件
        doc.saveToFile("F:\\yourlocation\\result.docx",FileFormat.Docx);
        // 或者保存至输出流中
        //ByteArrayOutputStream os = new ByteArrayOutputStream();
        //doc.saveToStream(os, FileFormat.Docx);
    }

    /**
     * 替换Word文件中 ${} 标识的特殊字符
     * <br>
     * <strong>注意:如果存在部分特殊表示无法替换,请尝试将 ${} 的整个字符串复制到word中,有可能word没有将${}识别为一个整体</strong>
     * @param doc: Sprire Document
     * @param map: 占位符${} 与 需要替换的为字符串的对应关系
     */
    public void replaceSpecialWord(Document doc, Map<String, String> map) {
        // 正则表达式,匹配所有的占位符 ${}
        Pattern pattern = Pattern.compile("\\$\\{.*?}");
        // 根据正则表达式获取所有文本
        TextSelection[] allPattern = doc.findAllPattern(pattern);
        // 逐个替换占位符
        for (TextSelection textSelection : allPattern) {
            String tmp = map.get(textSelection.getSelectedText());
            System.out.print(textSelection.getSelectedText());
            int res = doc.replace(textSelection.getSelectedText(), tmp, true, true);
            System.out.println(": " + res);
        }
    }
}

最终结果:

// 控制台输出
${name}: 1
${birthday}: 1
${result}: 1
${col}: 1
${col1}: 1
${col2}: 1

Java操作Word文档

​ 可以看到使用 Spire.Doc for Java 替换占位符十分简单,并且不会破坏模板的原有样 式。

​ 如果需要了解 Spire.Doc for Java 的更多操作,参考 ===> 官方文档

使用Spire.Doc 将Word文档中占位符替换为图片

1️⃣:编写一个测试文档

Java操作Word文档

2️⃣:了解Sprie.Doc 是如何插入一张图片

参考—官方文档

Spire.Doc for Java中的 Paragraph类 提供了appendPicture ()方法用于给Word段落添加图片。

public class InsertImage {
    public static void main(String[] args){
        //创建Document对象
        Document doc = new Document();
        //添加节
        Section section = doc.addSection();

        //添加第一个段落
        Paragraph paragraph = section.addParagraph();
        //添加图片到段落
        DocPicture picture = paragraph.appendPicture("C:\\Users\\Administrator\\Desktop\\Hydrangeas.jpg");
        //设置图片宽度
        picture.setWidth(300f);
        //设置图片高度
        picture.setHeight(250f);

        //给段落设置水平居中对齐方式
        paragraph.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
        
        //保存
        doc.saveToFile("InsertImage.docx", FileFormat.Docx_2013);
    }
}

第二种方式: ===> 参考

​ 通过获取 Spire.Doc 中的 TextRange 对象,可以用这个对象插入图片。

Document doc = new Document();
doc.loadFromFile("F:\\yourlocation\\template.docx", FileFormat.Docx);	// 或者可以加载流loadFromStream(.,.)
// 0. 使用 Spire.Doc 的 DocPicture类 加载一张图片,并且可以设置图片的宽高
DocPicture pic = new DocPicture(doc);
pic.loadImage(imgList.get(count));
// 1. 获取 TextSelection
TextSelection selection = doc.findString("matchString", true, true);	// 第一个参数是需要的匹配字符串即占位符,后面两个参数的意思为:是否大小写敏感、是否匹配整个单词
// 2. 根据 selection 获取 TextRange
TextRange range = selection.getAsOneRange();
// 3. 通过 TextRange 找到 占位符在一个段落中的位置
int index = range.getOwnerParagraph().getChildObjects().indexOf(range);
// 4. 通过获取到的 index 位置,插入一张图片
range.getOwnerParagraph().getChildObjects().insert(index, pic);
range.getOwnerParagraph().getChildObjects().remove(range);	// 这个remove 操作具体作用不太清楚,但是没有这一步图片是无法正确插入的

3️⃣:开始编码​

// 测试方法
@Test
public void imageTest() {
        Document doc = new Document();
        doc.loadFromFile("F:\\yourlocation\\template.docx", FileFormat.Docx);
        File file = new File("F:\\yourlocation\\orange.jpg");
        File file1 = new File("F:\\yourlocation\\orange.jpg");
        try {
            InputStream in = new FileInputStream(file);
            InputStream in1 = new FileInputStream(file1);
            List<InputStream> imgList = new ArrayList<>();
            imgList.add(in);
            imgList.add(in1);
            String matchString = "${images}";
            replaceTextToImage(doc, matchString, imgList);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        doc.saveToFile("F:\\yourlocation\\result.docx",FileFormat.Docx);
    }

/**
     * 替换Word文档中的同一占位符,为多张不同的图片,每一个占位符对应一张图片,
     * 如果占位符比图片数量多则该占位符会被写为空字符串
     * @param doc: Spire Document
     * @param matchString: 占位符
     * @param imgList: 图片输入流集合
     * @date 2021/10/22 20:09
     */
public void replaceTextToImage(Document doc, String matchString, List<InputStream> imgList) {
    TextSelection[] selections = doc.findAllString(matchString, true, true);
    int total = imgList.size();
    int count = 0;
    for (TextSelection selection : selections) {
        if (count < total && imgList.get(count) != null) {
            DocPicture pic = new DocPicture(doc);
            pic.loadImage(imgList.get(count));
            pic.setWidth(100f);		// 设置图片宽高
            pic.setHeight(100f);
            TextRange range = selection.getAsOneRange();
            int index = range.getOwnerParagraph().getChildObjects().indexOf(range);
            range.getOwnerParagraph().getChildObjects().insert(index, pic);
            range.getOwnerParagraph().getChildObjects().remove(range);
            count++;
        } else {
            // 如果已近没有了图片则将所有占位符替换为空
            doc.replace(selection.getSelectedText(), "", true, true);
            break;
        }
    }
}



	/**
     * 按照横纵比缩放图片
     * @param pic: Spire 图片对象
     * @param rate: 缩放比例 0.1<= rate <=10,
     * @author He Peng
     * @date 2021/10/23 9:28
     */
public static void zoomImage(DocPicture pic, float rate) {
    if (rate < 0.1 || rate > 10) {
        throw new IllegalArgumentException("缩放比例参数的数值范围为:0.1<= rate <=10,不能超过此范围");
    }
    float originalWidth = pic.getWidth();
    float originalHeight = pic.getHeight();
    pic.setWidth(originalWidth * rate);
    pic.setHeight(originalHeight * rate);
}

最终结果:

Java操作Word文档

📘 参考资料

个人博客同步发布

POI操作word模板并生成新的word–jianshu
Spire.doc for Java—官方文档
Spire.Doc for Java 资源—csdn
通过 Maven 仓库安装 Spire 系列 Java 产品—官方文档
Spire.Doc 系列教程

版权声明:程序员胖胖胖虎阿 发表于 2022年11月9日 上午3:48。
转载请注明:Java操作Word文档 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...