aspose-words转换成word时生成的文字型窗体域问题

325 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情


使用aspose-words将html转换成word文档时,

如果html中包含input控件,那么在转换的word中,则会生成对应的文字型窗体域,并且不能编辑;

本文讲解怎么去除input造成的文字型窗体域问题。

demo代码地址


image.png

测试页面很简单,姓名、年龄后面是两个input输入框;

只是加了两行css,隐藏了边框,和给文字加了下划线;

html源码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    .inputClass {
        border: none;
        text-decoration: underline;
    }
</style>
<body>
<div class="Section1">
    <p style="margin-top: 0; margin-bottom: 0; text-align: center; font-size: 21pt; ">
        <span style="font-family: 微软雅黑,serif; color: #003399;">测试文档</span>
    </p>
    <p style="margin-top: 14pt; margin-bottom: 15pt; text-indent: 24pt; font-size: 12pt; ">
        <span style="font-family: 微软雅黑,serif;">姓名:
            <label>
                <input class="inputClass" type="text" value="张三"/>
            </label>
        </span>
    </p>
    <p style="margin-top: 14pt; margin-bottom: 15pt; text-indent: 24pt; font-size: 12pt;">
        <span style="font-family: 微软雅黑,serif;">年龄:
            <label>
                <input class="inputClass" type="text" value="20"/>
            </label>
        </span>
    </p>
</div>
</body>
</html>

我这里使用的 aspose-words 版本是 19.1

使用 aspose-words ,两行代码搞定 html 转 word 的操作,so easy

public static void main(String[] args) throws Exception {
    String inPath = "C:\Users\xxxx\Desktop\index.html";
    String outPath = "C:\Users\xxxx\Desktop\index.docx";
    htmlToWord(inPath, outPath);
}

public static void htmlToWord(String inPath, String outPath) throws Exception {
    Document wordDoc = new Document(inPath);
    wordDoc.save(outPath, SaveFormat.DOCX);
}

来看下生成的结果,上面是网页的显示效果,下面是word文档的

image.png

可以看到,对于 input 输入框,生成的word文件中,是有一块灰色背景的,并且鼠标点上去是不可编辑的

双击灰色背景块,会弹出一个文字型窗体域选项

image.png

这个很影响使用啊...

首先想到是到 aspose 官网找文档,找到了这么一篇

Working with Ranges

(虽然是 .net 的代码,但是调用的方法名是一样的)

可以看到这一段,可以获取到文档中的内容

image.png

试一下

image.png

好像获取到的只是最后一段内容;

先注意下,这里在 年龄 和 20 中间有一个 FORMTEXT
这个 FORMTEXT 后面需要用到;

那要获取全部的呢,再看下文档下面

image.png

这里好像是个数组

再试一下

image.png

好像没什么卵用。。。

但是 range 这里我发现了一个新玩法

image.png

可以替换里面指定的内容

比如 key 可以是你要替换的字段,value 是你从数据库查询出来的值,这时候,就可以在这里对文档内容进行替换

可以参考这篇文章 world模板参数替换导出pdf


回到正题,怎么替换掉生成的这个文字型窗体域

把生成的 index.docx 文档解压出来,然后把 word 文件夹下的 document.xml 拷贝到 idea 里面,格式化一下方便查看

image.png

然后再打开 index.docx 这个 word 文档,鼠标选中其中一个灰色背景框,用快捷键去除掉文字型窗体域

ctrl+shift+F9

如果有fn键,还需要加上fn
ctrl+shift+fn+F9

这是去除后,可以看到正常了,也能进行输入了

image.png

这个时候,我们也把刚刚去除掉文字型窗体域的word文档解压;

同样的,把解压出来的 document.xml 拷贝到 idea 里面,注意别覆盖了,重新命名一下

对比一下两个文件的不同

image.png

可以看到,在 姓名和李四 之间

去除掉文字型窗体域和没去除的,中间差了一大段代码

这一段代码中间,就有前面提到的 FORMTEXT


那这个 FORMTEXT 是什么呢?

在网上找解决方法时,看到了这种写法

image.png

出于好奇,打印一下看下是这个fieldCode是什么东西

image.png

有点眼熟;

到 aspose 官网的文档里,找到了这个field操作

Updating and Removing a Field

image.png

我们再打印看一下这个 field 里面还有什么

image.png

fieldCode 是 FORMTEXT,对应的 result 就是我们要的值

这个时候如果对 field 做 remove 操作,会把原先有的内容也给去掉了

image.png

我们既然可以通过 field.getResult() 获取到对应的内容,

那么我们就能在 remove 之前,再重新设置值即可

image.png

DocumentBuilder内部维护了一个游标Cursor,它允许你指向任何你想指向的地方

moveToField 这个方法,官方文档的解释

Class DocumentBuilder

image.png

那上面for循环内那段代码的意思就是,

先把光标移动到 field 结尾;

重新把值写一份;

然后再把前面的 field 删掉;

如果你把 remove() 方法注释掉

image.png