当前位置:文档之家› java操作word可操作书签

java操作word可操作书签

最近有个需求,在word模板文档上设置书签,然后从数据库中查询数据,填充到word 文档书签位置,刚拿到需求时,使劲在网上找资料。

幻想第三方jar包,帮我实现。

有Apatch 的POI,java2word,jcob等,一直让我无法实现。

POI操作word只能获取word中的书签,并不能进行操作.java2word可以实现,但是除了包以外,还要一个dll文件放在system32文件夹下,环境部署在linux服务器上,谁允许你放这样的文件,结果死心了.下面新建一个word2007文件告诉大家不用第三方技术怎么一一实现。

现在新建一个word,在请输入用户名处添加书签userName,请输入年龄处添加书签age
Word2007版本其实就是zip格式,将新建word后缀名改.zip,解压会发现,里面全是文件夹,打开word文件夹会有一个文件,在word所有内容,都在这xml文件中, <w:bookmarkStart w:id="0" w:name="userName"/>
<w:r>
<w:rPr><w:rFonts w:hint="eastAsia"/></w:rPr>
<w:t>请输入用户名</w:t>
</w:r>
<w:bookmarkEnd w:id="0"/>
这是新建书签处的内容,细心的会发现,书签处内容在<w:bookmarkStart/> <w:bookmarkEnd w:id="0"/>标签之间,<w:bookmarkStart>标签中的w:id跟w:name 标识书签的唯一,中间是书签处的内容,会不会可以这样呢,找到用dom或者sax解析这个xml文档找到<w:bookmarkStart/>标签,然后找到<w:r>标签,再找到<w:r>标签里面的<w:t>标签内容,替换就Ok了呢。

一开始我就这样想的。

但是你会发现,<w:bookmarkStart></w:bookmarkStart>不是这样配套的,如果是这样配套的,那按照前面的说的直接解析找到<w:bookmarkStart>标签就OK了。

分析xml文件你会发现,其实<w:bookmarkStart w:id="0" w:name="userName"/>标签跟<w:r>标签是同级的,只是结束方式不同而已,所以算是兄弟节点,可以不可以找到<w:bookmarkStart>的兄弟节点,也就是<w:r>标签,然后找到<w:t>标签,替换其文本。

其实w3c中Element对象中提供了获取兄弟节点的方法,getNextSibling()获取下一个兄弟节点。

按照分析的思路是可以实现的。

但是会不会有疑问,如果<w:bookmarkStar>的下一个兄弟节点会不会不是<w:r>标签呢,是的,如果书签处无内容,就会是这样的<w:bookmarkStart w:id="0" w:name="userName"/>
<w:bookmarkEnd w:id="0"/>
这样可以直接在<w:bookmarkStart>后面直接添加<w:r>标签
你多试几个文档你会发现,无论多复杂,只要节操还在。

都会是这个样子。

除非那种非常恶心的word。

这个还得看你的word模板而论.
这样的思路是可以实现了,但是该怎么用java搞定呢,下面贴出代码
public static void modifyDocumentAndSave() throws IOException,
ZipException, SAXException, ParserConfigurationException,
TransformerException, TransformerConfigurationException { arse(documentXMLIS);
quals(bookMarkName)) {
Element node = (Element) ();ewTransformer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
(new DOMSource(doc), new StreamResult(baos));
ZipOutputStream docxOutFile = new ZipOutputStream(new FileOutputStream(
"D:\\"));
Enumeration entriesIter = ();
while ()) {
ZipEntry entry = (ZipEntry) ();
quals("word/")) {
byte[] data = ();
(new ZipEntry()));
(data, 0, ;
();
} else {
InputStream incoming = (entry);
//此处设定值需慎重,如果设置小了,会破坏word文档,至于为什么会破坏,自己去思考
byte[] data = new byte[1024 * 512]; int readCount = (data, 0, (int) ());
(new ZipEntry()));
(data, 0, readCount);
();
}
}
();
}。

相关主题