使用Apache POI处理docx文件中的复选框 [英] Work with checkboxes in docx file with Apache POI

查看:279
本文介绍了使用Apache POI处理docx文件中的复选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

能请你帮我吗?我需要通过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文件中的复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆