在特定书签中使用 docx4j 在 word 文档中创建 table:
Create table in word doc using docx4j in specific bookmark:
我在特定的书签位置创建了一个table(意味着它在word文档中显示为table),但是在将word转换为PDF后它无法在其中显示table PDF因为书签在w:p
!!
里面
<w:p w:rsidR="00800BD9" w:rsidRDefault="00800BD9">
<w:bookmarkStart w:id="0" w:name="abc"/>
<w:bookmarkEnd w:id="0"/>
</w:p>
现在我想找到段落(使用书签),然后将段落替换为 table。
有人有什么建议吗?
这是我的代码:
private void replaceBookmarkContents(List<Object> paragraphs, Map<DataFieldName, String> data) throws Exception {
Tbl table = TblFactory.createTable(3,3,9600);
RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
new TraversalUtil(paragraphs, rt);
for (CTBookmark bm : rt.getStarts()) {
// do we have data for this one?
if (bm.getName()==null) continue;
String value = data.get(new DataFieldName(bm.getName()));
if (value==null) continue;
try {
// Can't just remove the object from the parent,
// since in the parent, it may be wrapped in a JAXBElement
List<Object> theList = null;
if (bm.getParent() instanceof P) {
System.out.println("OK!");
theList = ((ContentAccessor)(bm.getParent())).getContent();
} else {
continue;
}
int rangeStart = -1;
int rangeEnd=-1;
int i = 0;
for (Object ox : theList) {
Object listEntry = XmlUtils.unwrap(ox);
if (listEntry.equals(bm)) {
if (DELETE_BOOKMARK) {
rangeStart=i;
} else {
rangeStart=i+1;
}
} else if (listEntry instanceof CTMarkupRange) {
if ( ((CTMarkupRange)listEntry).getId().equals(bm.getId())) {
if (DELETE_BOOKMARK) {
rangeEnd=i;
} else {
rangeEnd=i-1;
}
break;
}
}
i++;
}
if (rangeStart>0) {
// Delete the bookmark range
for (int j=rangeStart; j>0; j--) {
theList.remove(j);
}
// now add a run
org.docx4j.wml.R run = factory.createR();
run.getContent().add(table);
theList.add(rangeStart, run);
}
} catch (ClassCastException cce) {
log.error(cce.getMessage(), cce);
}
}
}
用 table 盲目替换段落内的书签的问题在于,您最终会得到 w:p/w:tbl(或您的代码 w:p/w:r/w:tbl!) 文件格式不允许。
为避免此问题,您可以将书签设为段落的同级,或者您可以更改代码,以便在段落中找到书签后,如果您将其替换为 table,您替换父 p。
请注意,书签 find/replace 是文档生成的脆弱基础。如果您的要求不高,最好改用内容控件。
我在特定的书签位置创建了一个table(意味着它在word文档中显示为table),但是在将word转换为PDF后它无法在其中显示table PDF因为书签在w:p
!!
<w:p w:rsidR="00800BD9" w:rsidRDefault="00800BD9">
<w:bookmarkStart w:id="0" w:name="abc"/>
<w:bookmarkEnd w:id="0"/>
</w:p>
现在我想找到段落(使用书签),然后将段落替换为 table。
有人有什么建议吗?
这是我的代码:
private void replaceBookmarkContents(List<Object> paragraphs, Map<DataFieldName, String> data) throws Exception {
Tbl table = TblFactory.createTable(3,3,9600);
RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
new TraversalUtil(paragraphs, rt);
for (CTBookmark bm : rt.getStarts()) {
// do we have data for this one?
if (bm.getName()==null) continue;
String value = data.get(new DataFieldName(bm.getName()));
if (value==null) continue;
try {
// Can't just remove the object from the parent,
// since in the parent, it may be wrapped in a JAXBElement
List<Object> theList = null;
if (bm.getParent() instanceof P) {
System.out.println("OK!");
theList = ((ContentAccessor)(bm.getParent())).getContent();
} else {
continue;
}
int rangeStart = -1;
int rangeEnd=-1;
int i = 0;
for (Object ox : theList) {
Object listEntry = XmlUtils.unwrap(ox);
if (listEntry.equals(bm)) {
if (DELETE_BOOKMARK) {
rangeStart=i;
} else {
rangeStart=i+1;
}
} else if (listEntry instanceof CTMarkupRange) {
if ( ((CTMarkupRange)listEntry).getId().equals(bm.getId())) {
if (DELETE_BOOKMARK) {
rangeEnd=i;
} else {
rangeEnd=i-1;
}
break;
}
}
i++;
}
if (rangeStart>0) {
// Delete the bookmark range
for (int j=rangeStart; j>0; j--) {
theList.remove(j);
}
// now add a run
org.docx4j.wml.R run = factory.createR();
run.getContent().add(table);
theList.add(rangeStart, run);
}
} catch (ClassCastException cce) {
log.error(cce.getMessage(), cce);
}
}
}
用 table 盲目替换段落内的书签的问题在于,您最终会得到 w:p/w:tbl(或您的代码 w:p/w:r/w:tbl!) 文件格式不允许。
为避免此问题,您可以将书签设为段落的同级,或者您可以更改代码,以便在段落中找到书签后,如果您将其替换为 table,您替换父 p。
请注意,书签 find/replace 是文档生成的脆弱基础。如果您的要求不高,最好改用内容控件。