当前位置:
文档之家› JAVA操作WORD可操作书签
JAVA操作WORD可操作书签
// 书签处值结束 if (entry.getKey().equals(bookMarkName)) {
Element node = (Element)
oldBookStart.getNextSibling();// 获取兄弟节点w:r
// 如果书签处无文字,则在书签处添加需要替换的内
容,如果书签处存在描述文字,则替换内容,用w:r NodeList wtList =
TransformerException, TransformerConfigurationException {
// 使用java.util打开文件
File file=new File("D:test.docx"); boolean exist=file.exists(); boolean read=file.canRead(); boolean write=file.canWrite(); System.out.println(exist); System.out.println(read); System.out.println(write); ZipFile docxFile = new ZipFile(file);
现在新建一个 word,在请输入用户名处添加书签 userName,请输入年龄处添加书签 age
Word2007 版本其实就是 zip 格式,将新建 word 后缀名改.zip,解压会发现,里面全是文 件夹,打开 word 文件夹会有一个 document.xml 文件,在 word 所有内容,都在这 xml 文件中,
node.getElementsByTagName("w:t");// 获取w:r标签下的显示书签处
内容标签w:t
if (wtList.getLength() == 0) { // 如果不存
在,即,书签处本来就无内容,则添加需要替换的内容 oldBookStart.appendChild(wr);
Document doc = dbf.newDocumentBuilder().parse(documentXMLIS);
// linkMan tel proCode companyName fundName fundCode sysProCode
Map<String, String> bookMarkMap = new HashMap<String, String>();
docxOutFile.write(data, 0, readCount); docxOutFile.closeEntry(); } } docxOutFile.cl入的map集合比较 for (Map.Entry<String, String> entry : bookMarkMap.entrySet()) {
// 书签处值开始 Node wr = doc.createElement("w:r"); Node wt = doc.createElement("w:t"); Node wt_text = doc.createTextNode(entry.getValue()); wt.appendChild(wt_text); wr.appendChild(wt);
最近有个需求,在 word 模板文档上设置书签,然后从数据库中查询数据,填充到 word 文档书签位置,刚拿到需求时,使劲在网上找资料。幻想第三方 jar 包,帮我实现。有 Apatch 的 POI,java2word,jcob 等,一直让我无法实现。POI 操作 word 只能获取 word 中的书签,并 不能进行操作.java2word 可以实现,但是除了 java2word.jar 包以外,还要一个 dll 文件放在 system32 文件夹下,环境部署在 linux 服务器上,谁允许你放这样的文件,结果死心了.下面新 建一个 word2007 文件告诉大家不用第三方技术怎么一一实现。
//此处设定值需慎重,如果设置小了,会破坏word文档,至于为什么会破坏,
自己去思考 byte[] data = new byte[1024 * 512];
int readCount = incoming.read(data, 0, (int) entry.getSize());
docxOutFile.putNextEntry(new ZipEntry(entry.getName()));
分析 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 模板而论.
<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 了。
} else { // 如果书签处有内容,则直接替换内容
wtList.item(0);
Element wtNode = (Element)
wtNode.setTextContent(entry.getValue()); }
} }
} }
Transformer t = TransformerFactory.newInstance().newTransformer();
这样的思路是可以实现了,但是该怎么用 java 搞定呢,下面贴出代码
public static void modifyDocumentAndSave() throws IOException,
ZipException, SAXException, ParserConfigurationException,
//如果是document.xml则修改,别的文件直接拷贝,不改变word
的样式 if (entry.getName().equals("word/document.xml")) { byte[] data = baos.toByteArray(); docxOutFile.putNextEntry(new
// 返回ZipEntry应用程序接口
ZipEntry documentXML = docxFile.getEntry("word/document.xml");
InputStream documentXMLIS = docxFile.getInputStream(documentXML);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
ZipEntry(entry.getName())); docxOutFile.write(data, 0, data.length); docxOutFile.closeEntry();
} else { InputStream incoming =
docxFile.getInputStream(entry);
bookMarkMap.put("userName", "张三");
bookMarkMap.put("password", "888888");
/**
* 书签列表 */ NodeList this_book_list = doc.getElementsByTagName("w:bookmarkStart"); if (this_book_list.getLength() != 0) {
"D:\\response.docx")); Enumeration entriesIter = docxFile.entries(); while (entriesIter.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entriesIter.nextElement();
<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>