javadocx⽂档解析_带有docx4j的JavaWord(.docx)⽂档java docx⽂档解析
⼏个⽉前,我需要创建⼀个包含许多表和段落的动态Word⽂档。 过去,我曾使⽤POI来实现此⽬的,但是我发现它很难使⽤,并且在创建更复杂的⽂档时对我来说效果不佳。 因此,对于这个项⽬,经过⼀番搜索,我决定使⽤ 。 Docx4j,根据他们的⽹站是:
“ docx4j是⼀个Java库,⽤于创建和处理Microsoft Open XML(Word docx,Powerpoint pptx和Excel xlsx)⽂件。
它类似于Microsoft的OpenXML SDK,但适⽤于Java。”
在本⽂中,我将向您展⽰⼏个⽰例,您可以使⽤这些⽰例来⽣成Word⽂档的内容。 更具体地说,我们将看以下两个⽰例:
加载模板Word⽂档以添加内容并另存为新⽂档
将段落添加到此模板⽂档
将表添加到此模板⽂档
这⾥的⼀般⽅法是⾸先创建⼀个Word⽂档,其中包含最终⽂档的布局和主要样式。 在本⽂档中,您将需要添加占位符(简单字符串),我们将使⽤这些占位符来搜索并替换为真实内容。
例如,⼀个⾮常基本的模板如下所⽰:
在本⽂中,我们将向您展⽰如何填充此内容,以便获得此信息:
加载模板Word⽂档以添加内容并另存为新⽂档
⾸先是第⼀件事。 让我们创建⼀个简单的Word⽂档,将其⽤作模板。 为此,只需打开Word,创建⼀个新⽂档并将其另存为
template.docx。 这是我们⽤来向其添加内容的单词模板。 我们需要做的第⼀件事是⽤docx4j加载该⽂档。 您可以使⽤以下⼀段Java代码:
private WordprocessingMLPackage getTemplate(String name) throws Docx4JException, FileNotFoundException {
WordprocessingMLPackage template = WordprocessingMLPackage.load(new FileInputStream(new File(name)));
return template;
}
这将返回⼀个Java对象,该对象表⽰完整的(此时)空⽂档。 现在,我们可以使⽤Docx4J API在此Word⽂档中添加,删除和修改内容。Docx4J有许多帮助程序类,可⽤于遍历此⽂档。 我确实写了⼀些帮助程序,尽管它们确实使查特定的占位符并⽤实际内容替换它们⾮常容易。 让我们看看其中之⼀。 此操作是⼏个JAXB操作的包装,使您可以搜索特定元素及其所有⼦元素来查某个类。 例如,您可以使⽤它来获取⽂档中的所有表,表中的所有⾏等等。
private static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
List<Object> result = new ArrayList<Object>();
if (obj instanceof JAXBElement) obj = ((JAXBElement<?>) obj).getValue();
if (Class().equals(toSearch))
result.add(obj);
else if (obj instanceof ContentAccessor) {
List<?> children = ((ContentAccessor) obj).getContent();
for (Object child : children) {
result.addAll(getAllElementFromObject(child, toSearch));
}
}
return result;
}
没什么复杂的,但真的很有帮助。 让我们看看如何使⽤此操作。 在此⽰例中,我们仅将简单的⽂本占位符替换为其他值。 例如,这是您⽤来动态设置⽂档标题的内容。 不过,⾸先,在您创建的Word模板中添加⼀个⾃定义占位符。 我将为此使⽤SJ_EX1。 我们将⽤我们的名字替换这个值。 docx4j中的基本⽂本元素由org.docx4j.wml.Text类表⽰。 要替换此简单的占位符,我们要做的就是调⽤此⽅法:
private void replacePlaceholder(WordprocessingMLPackage template, String name, String placeholder ) {
List<Object> texts = MainDocumentPart(), Text.class);
for (Object text : texts) {
Text textElement = (Text) text;
if (Value().equals(placeholder)) {
textElement.setValue(name);
}
}
}
这将查⽂档中的所有Text元素,并将匹配的元素替换为我们指定的值。 现在,我们要做的就是将⽂档写回到⽂件中。
private void writeDocxToStream(WordprocessingMLPackage template, String target) throws IOException, Docx4JException {
File f = new File(target);
template.save(f);
}
如您所见,并不难。
通过此设置,我们还可以将更复杂的内容添加到Word⽂档中。 确定如何添加特定内容的最简单⽅法是查看word⽂档的XML源代码。 这将告诉您需要哪些包装器以及Word如何编组XML。 对于下⼀个⽰例,我们将研究如何添加完整的段落。
将段落添加到此模板⽂档
您可能想知道为什么我们需要添加段落? 我们已经可以添加⽂本了,⼀个段落不只是⼀⼤段⽂本吗? 好吧,是的,不是。 ⼀段确实看起来像是⼀段很⼤的⽂字,但是您需要考虑的是换⾏符。 如果您像以前⼀样添加Text元素,并在⽂本中添加换⾏符,则它们不会显⽰。 如果需要换⾏,则需要创建⼀个新段落。 幸运的是,使⽤Docx4j也很容易做到这⼀点。
我们将通过以下步骤进⾏操作:
1. 从模板中到要替换的段落
2. 将输⼊⽂本分成单独的⾏
3. 对于每⼀⾏,根据模板中的段落创建⼀个新段落
4. 删除原始段落
java replace方法我们应该已经拥有的辅助⽅法不应该太难了。
private void replaceParagraph(String placeholder, String textToAdd, WordprocessingMLPackage template, ContentAccessor addTo) {
// 1. get the paragraph
List<Object> paragraphs = MainDocumentPart(), P.class);
P toReplace = null;
for (Object p : paragraphs) {
List<Object> texts = getAllElementFromObject(p, Text.class);
for (Object t : texts) {
Text content = (Text) t;
if (Value().equals(placeholder)) {
toReplace = (P) p;
break;
}
}
}
// we now have the paragraph that contains our placeholder: toReplace
// 2. split into seperate lines
String as[] = StringUtils.splitPreserveAllTokens(textToAdd, '\n');
for (int i = 0; i < as.length; i++) {
String ptext = as[i];
// 3. copy the found paragraph to keep styling correct
P copy = (P) XmlUtils.deepCopy(toReplace);
// replace the text elements from the copy
List texts = getAllElementFromObject(copy, Text.class);
if (texts.size() > 0) {
Text textToReplace = (Text) (0);
textToReplace.setValue(ptext);
}
// add the paragraph to the document
}
// 4. remove the original one
((Parent()).getContent().remove(toReplace);
}
在此⽅法中,我们⽤提供的⽂本替换段落的内容,然后将新段落替换为⽤addTo指定的参数。
String placeholder = "SJ_EX1";
String toAdd = "jos\ndirksen";
replaceParagraph(placeholder, toAdd, template, MainDocumentPart());
如果您在Word模板中使⽤更多内容来运⾏此程序,则会注意到这些段落将出现在⽂档的底部。 原因是将段落添加回了主⽂档。 如果您希望将段落添加到⽂档中的特定位置(通常需要这样做),则可以将其包装在1×1⽆边界表格中。 该表被视为段落的⽗级,可以在此处添加新段落。
将表添加到此模板⽂档
我想展⽰的最后⼀个⽰例是如何向单词模板添加表格。 实际上,更好的描述是如何在Word模板中填充预定义的表格。 就像我们对简单的⽂本和段落所做的⼀样,我们将替换占位符。 对于此⽰例,向您的Word⽂档中添加⼀个简单的表格(您可以随意设置样式)。 向此表添加1个哑⾏,⽤作内容模板。 在代码中,我们将查该⾏,将其复制,并将内容替换为来⾃Java代码的新⾏,如下所⽰:
1. 查包含我们的关键字之⼀的表
2. 复制⽤作⾏模板的⾏
3. 对于每⾏数据,根据⾏模板向表中添加⼀⾏
4. 删除原始模板⾏
与我们在段落中显⽰的⽅法相同。 ⾸先,让我们看⼀下如何提供替换数据。 对于此⽰例,我仅提供了⼀组哈希图,其中包含要替换的占位符的名称和要替换为其的值。 我还提供了可以在表格⾏中到的替换令牌。
Map<String,String> repl1 = new HashMap<String, String>();
repl1.put("SJ_FUNCTION", "function1");
repl1.put("SJ_DESC", "desc1");
repl1.put("SJ_PERIOD", "period1");
Map<String,String> repl2 = new HashMap<String,String>();
repl2.put("SJ_FUNCTION", "function2");
repl2.put("SJ_DESC", "desc2");
repl2.put("SJ_PERIOD", "period2");
Map<String,String> repl3 = new HashMap<String,String>();
repl3.put("SJ_FUNCTION", "function3");
repl3.put("SJ_DESC", "desc3");
repl3.put("SJ_PERIOD", "period3");
replaceTable(new String[]{"SJ_FUNCTION","SJ_DESC","SJ_PERIOD"}, Arrays.asList(repl1,repl2,repl3), template);
现在,这个replaceTable⽅法是什么样的。
private void replaceTable(String[] placeholders, List<Map<String, String>> textToAdd,
WordprocessingMLPackage template) throws Docx4JException, JAXBException {
List<Object> tables = MainDocumentPart(), Tbl.class);
// 1. find the table
Tbl tempTable = getTemplateTable(tables, placeholders[0]);
List<Object> rows = getAllElementFromObject(tempTable, Tr.class);
// first row is header, second row is content
if (rows.size() == 2) {
// this is our template row
Tr templateRow = (Tr) (1);
for (Map<String, String> replacements : textToAdd) {
// 2 and 3 are done in this method
addRowToTable(tempTable, templateRow, replacements);
}
// 4. remove the template row
}
}
该⽅法查表,获取第⼀⾏,并为每个提供的映射向表添加新⾏。 返回之前,它将删除模板⾏。 此⽅法使⽤两个帮助器:addRowToTable和getTemplateTable。 我们⾸先来看最后⼀个:
private Tbl getTemplateTable(List<Object> tables, String templateKey) throws Docx4JException, JAXBException {
for (Iterator<Object> iterator = tables.iterator(); iterator.hasNext();) {
Object tbl = ();
List<?> textElements = getAllElementFromObject(tbl, Text.class);
for (Object text : textElements) {
Text textElement = (Text) text;
if (Value() != null && Value().equals(templateKey))
return (Tbl) tbl;
}
}
return null;
}
此函数只是查看表是否包含我们的占位符之⼀。 如果是这样,则返回该表。 addRowToTable操作也⾮常简单。
private static void addRowToTable(Tbl reviewtable, Tr templateRow, Map<String, String> replacements) {
Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow);
List textElements = getAllElementFromObject(workingRow, Text.class);
for (Object object : textElements) {
Text text = (Text) object;
String replacementValue = (String) (Value());
if (replacementValue != null)
text.setValue(replacementValue);
}
}
此⽅法复制我们的模板,并使⽤提供的值替换此模板⾏中的占位符。 该副本将添加到表中。 就是这样。 通过这段代码,我们可以在Word ⽂档中填写套利表,同时保留表的布局和样式。
⾄此为⽌。 使⽤段落和表,您可以创建许多不同类型的⽂档,这与最常⽣成的⽂档类型⾮常匹配。 但是,也可以使⽤这种相同的⽅法将其他类型的内容添加到Word⽂档中。
参考:来⾃博客的 Jos Dirksen 。
java docx⽂档解析
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论