Работа с флажками в файле docx с помощью Apache POI - PullRequest
1 голос
/ 06 ноября 2019

не могли бы вы мне помочь? Мне нужно заполнить флажки в моем шаблоне MS Word docx через Apache POI. Флажки были вставлены вкладкой Разработчик-> Элементы управления-> Флажок и расположены внутри абзаца -> тег «w: sdt» (не внутри абзаца -> run).

Я пробовал paragraph.getCTP().getFldSimpleList(), но возвращает0 полей.

Так есть ли другой способ получить доступ к флажкам?

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>

1 Ответ

1 голос
/ 07 ноября 2019

Это не поддерживается apache poi до сих пор. И поскольку он использует расширенное пространство имен XML из w14, даже базовые классы ooxml-schema не поддерживают это. Эти классы схем были сгенерированы из XML схем Office Open XML, которые были опубликованы в 2007 году. Расширенное XML из w14 пространства имен позже и не является частью Office Open XML.

Так что есликто-то хочет поддержать это, тогда ему нужно работать на очень низком уровне XML. Но для такой простой вещи, как флажок, это может быть показано здесь в качестве примера.

Следующий код содержит рабочий проект класса W14Checkbox. Это обеспечивает статический метод для проверки того, содержит ли данный CTSdtRun w14:checkbox. Если это так, то из этого CTSdtRun может быть создан объект W14Checkbox. Затем этот объект предоставляет методы getChecked и setChecked.

Обратите внимание, что в setChecked необходимо установить не только логическое значение w14:checkbox/w14:checked, но и соответствующее текстовое значение CTSdtContentRunбыть установленным. Это может быть либо символ Unicode 'BALLOT BOX' (U + 2610) для не отмеченных, либо символ Unicode 'BALLOT BOX WITH CHECK' (U + 2612) для проверенных.

Complete Пример:

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;
  }
 }
}

Примечание. Это только рабочий проект, который необходимо доработать, чтобы он был готов к продуктивному использованию.

...