问题描述
能请你帮我吗?我需要通过Apache POI填写MS Word docx 模板中的复选框.复选框已通过开发人员"选项卡->控件"->复选框"插入,并位于段落->"w:sdt"标记内(不在段落->运行内).
could you please help me?I need to fill checkboxes in my MS Word docx template via Apache POI. Checkboxes has been inserted by Developer tab->Controls->Checkbox and located inside paragraph -> "w:sdt" tag (not inside paragraph -> run).
我已经尝试过 paragraph.getCTP().getFldSimpleList()
,但它返回0个字段.
I've tried paragraph.getCTP().getFldSimpleList()
but it returns 0 fields.
那么还有另一种获取复选框访问权限的方法吗?
So is there another way to get access for checkboxes?
XML部分:
<w:p w:rsidR="00C81ACC" w:rsidRDefault="00C81ACC" w:rsidP="004658AE">
<w:pPr>
<w:spacing w:line="276" w:lineRule="auto"/>
<w:ind w:left="383" w:hanging="383"/>
<w:rPr>
<w:rFonts w:ascii="Arial" w:hAnsi="Arial" w:cs="Arial"/>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
</w:rPr>
</w:pPr>
<w:sdt>
<w:sdtPr>
<w:rPr>
<w:rFonts w:ascii="Arial" w:hAnsi="Arial" w:cs="Arial"/>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
</w:rPr>
<w:id w:val="615721754"/>
<w14:checkbox>
<w14:checked w14:val="0"/>
<w14:checkedState w14:val="2612" w14:font="MS Gothic"/>
<w14:uncheckedState w14:val="2610" w14:font="MS Gothic"/>
</w14:checkbox>
</w:sdtPr>
<w:sdtContent>
<w:r>
<w:rPr>
<w:rFonts w:ascii="MS Gothic" w:eastAsia="MS Gothic" w:hAnsi="MS Gothic" w:cs="Arial" w:hint="eastAsia"/>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
</w:rPr>
<w:t>☐</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
<w:r>
<w:rPr>
<w:rFonts w:ascii="Arial" w:hAnsi="Arial" w:cs="Arial"/>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
</w:rPr>
<w:t xml:space="preserve"> Pass</w:t>
</w:r>
</w:p>
推荐答案
到目前为止, apache poi
不支持此功能.而且由于它使用了来自 w14
命名空间的扩展的 XML
,甚至底层的 ooxml-schema
类也不支持此功能.这些架构类是根据2007年发布的 Office Open XML
的 XML
架构生成的.扩展了 w14 的
XML
code>名称空间是更高版本,而不是 Office Open XML
的一部分.
This is not supported by apache poi
until now. And since it uses the extended XML
from w14
name space not even the underlying ooxml-schema
classes supports this. Those schema classes were generated from the XML
schemas of Office Open XML
which was published in 2007. The extended XML
from w14
name space is later and not part of Office Open XML
.
因此,如果要支持该功能,则需要在非常低的 XML
级别上工作.但是对于复选框这样简单的事情,可以在此处作为示例显示.
So if one wants supporting that then one needs working on very low level XML
level. But for such a simple thing as a checkbox this can be shown here as an example.
以下代码包含类 W14Checkbox
的工作草案.这提供了一种静态方法来检查给定的 CTSdtRun
是否包含 w14:checkbox
.如果是这种情况,则可以从该 CTSdtRun
创建一个 W14Checkbox
对象.然后,此对象提供 getChecked
和 setChecked
方法.
The following code contains a working draft of a class W14Checkbox
. This provides a static method to check whether a given CTSdtRun
contains a w14:checkbox
. If that is the case, then a W14Checkbox
object can be created from that CTSdtRun
. This object then provides getChecked
and setChecked
methods.
请注意,在 setChecked
中,不仅需要设置布尔值 w14:checkbox/w14:checked
,而且还需要设置 CTSdtContentRun
需要设置.可以是未选中的Unicode字符"BALLOT BOX"(U + 2610),也可以是选中的Unicode字符"BALLOT BOX WITH CHECK"(U + 2612).
Note that in setChecked
not only the boolean value w14:checkbox/w14:checked
needs to be set but also the corresponding text value of the CTSdtContentRun
needs to be set. This can be either Unicode Character 'BALLOT BOX' (U+2610) for not checked or Unicode Character 'BALLOT BOX WITH CHECK' (U+2612) for checked.
完整示例:
import java.io.*;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.apache.xmlbeans.*;
import javax.xml.namespace.QName;
public class WordFillCheckBox {
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("source.docx"));
for (XWPFParagraph paragraph : document.getParagraphs()) { //go through all paragraphs
for (CTSdtRun sdtRun : paragraph.getCTP().getSdtList()) {
if (W14Checkbox.isW14Checkbox(sdtRun)) {
W14Checkbox w14Checkbox = new W14Checkbox(sdtRun);
System.out.println(w14Checkbox.getChecked());
if (w14Checkbox.getChecked()) w14Checkbox.setChecked(false); else w14Checkbox.setChecked(true);
System.out.println(w14Checkbox.getChecked());
}
}
}
FileOutputStream out = new FileOutputStream("result.docx");
document.write(out);
out.close();
document.close();
}
static class W14Checkbox {
CTSdtRun sdtRun = null;
CTSdtContentRun sdtContentRun = null;
XmlObject w14CheckboxChecked = null;
W14Checkbox(CTSdtRun sdtRun) {
this.sdtRun = sdtRun;
this.sdtContentRun = sdtRun.getSdtContent();
String declareNameSpaces = "declare namespace w14='http://schemas.microsoft.com/office/word/2010/wordml'";
XmlObject[] selectedObjects = sdtRun.getSdtPr().selectPath(declareNameSpaces + ".//w14:checkbox/w14:checked");
if (selectedObjects.length > 0) {
this.w14CheckboxChecked = selectedObjects[0];
}
}
CTSdtContentRun getContent() {
return this.sdtContentRun;
}
XmlObject getW14CheckboxChecked() {
return this.w14CheckboxChecked;
}
boolean getChecked() {
XmlCursor cursor = this.w14CheckboxChecked.newCursor();
String val = cursor.getAttributeText(new QName("http://schemas.microsoft.com/office/word/2010/wordml", "val", "w14"));
return "1".equals(val) || "true".equals(val);
}
void setChecked(boolean checked) {
XmlCursor cursor = this.w14CheckboxChecked.newCursor();
String val = (checked)?"1":"0";
cursor.setAttributeText(new QName("http://schemas.microsoft.com/office/word/2010/wordml", "val", "w14"), val);
cursor.dispose();
CTText t = this.sdtContentRun.getRArray(0).getTArray(0);
String content = (checked)?"\u2612":"\u2610";
t.setStringValue(content);
}
static boolean isW14Checkbox(CTSdtRun sdtRun) {
CTSdtPr sdtPr = sdtRun.getSdtPr();
String declareNameSpaces = "declare namespace w14='http://schemas.microsoft.com/office/word/2010/wordml'";
XmlObject[] selectedObjects = sdtPr.selectPath(declareNameSpaces + ".//w14:checkbox");
if (selectedObjects.length > 0) return true;
return false;
}
}
}
注意:这只是一个工作草案,需要进行进一步开发才能投入生产.
Note: This is a working draft only and needs to be further developed to be ready for productive usage.
这篇关于使用Apache POI处理docx文件中的复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!