使用指定位置的apache POI将表从应用程序UI导出到word文档

时间:2017-01-19 06:13:04

标签: apache-poi

1.  Sdfhsh
2.  Dhfsh
   2.1. Sfasd
   2.2. Asdfdfs
   2.3. F
   2.4. Asf
     2.4.1. Acv
      2.4.1.1.  Asc
       2.4.1.1.1.   casc

我的文档由上面的编号项目符号组成。我想在2.1段之后插入表。如何使用Apache POI搜索​​2.1段的单词? 编号项是默认样式的列表项。它可以出现在报告文档的任何章节中。

1 个答案:

答案 0 :(得分:0)

回答这个问题:

如何使用Wordapache poi中搜索使用“2.1”编号的段落?

我提供的代码能够阅读Word并考虑直接在段落中格式化的编号。它不会考虑以特殊样式存储的编号,例如标题。

对代码进行了评论,以便更好地理解。

一般情况下,由于*.docx个文件只是包含ZIP个文件的XML个档案,因此可以解压缩*.docx个文件并查看XML个文件。在编号的情况下,例如可以找到:

<w:p>
 <w:pPr>
  <w:numPr>
   <w:ilvl w:val="1"/>
   <w:numId w:val="1"/>
  </w:numPr>
 </w:pPr>
 <w:r><w:t>Sfasd</w:t></w:r>
</w:p>
/word/document.xml中的

numID引用了/word/numbering.xml中的编号ID,而ilvl是缩进级别。

/word/numbering.xml中,您会找到:

<w:num w:numId="1"><w:abstractNumId w:val="1"/></w:num>

引用abstractNumId 1,其中包含:

<w:lvl w:ilvl="1">
 <w:start w:val="1"/>
 <w:numFmt w:val="decimal"/>
 <w:lvlText w:val="%1.%2."/>
 <w:lvlJc w:val="left"/>
 <w:pPr><w:ind w:left="792" w:hanging="432"/></w:pPr>
</w:lvl>

定义缩进级别格式。

示例:

import java.io.*;
import org.apache.poi.xwpf.usermodel.*;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

import java.math.BigInteger;

public class WordReaderExtended {

 private XWPFDocument document;

 private List<Numberinglevel> numberingLevels = new ArrayList<Numberinglevel>();
 //a List to store the numberings and their known indent levels and counts

 private Map<BigInteger, BigInteger> numIDMaxIlvls = new HashMap<BigInteger, BigInteger>();
 //a Map to store the numberings and their actual max indent levels

 public WordReaderExtended(String fileName) {
  try {
   this.document = new XWPFDocument(new FileInputStream(fileName));
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }

 public String getNumber(BigInteger numID, BigInteger ilvl, String lvlText) {
  //a method to get the numbering number
  String number = lvlText; //"%1.%2.%3.%4..." see listParagraphs
  boolean found = false;

  for (Numberinglevel numberinglevel : numberingLevels) {
   //loop over all actual stored numbering levels
   if (numID.compareTo(numberinglevel.numID) == 0) {
    //this stored numbering is the requested
    if (ilvl.compareTo(numberinglevel.ilvl) == -1) {
     //if the requested indent level is less than a stored one, then the stored one's count must be resetted
     numberinglevel.reset();
    } else if (ilvl.compareTo(numberinglevel.ilvl) == 1) {
     //if the requested indent level is greater than a stored one, then the stored lesser one must be considered
     if (numberinglevel.counter == 0) numberinglevel.countUp(); //if the counter was reset to 0, then count up before using it
     number = number.replace("%"+(numberinglevel.ilvl.intValue()+1), ""+numberinglevel.counter);
    } else if (ilvl.compareTo(numberinglevel.ilvl) == 0) {
     //if the requested indent level is equal a stored one, then the stored one must be counted up and considered
     numberinglevel.countUp();
     number = number.replace("%"+(numberinglevel.ilvl.intValue()+1), ""+numberinglevel.counter);
     found = true; //we have found the requested indent level as actual stored
    }
   }
  }
  if (!found) {
   //if we have not found the requested indent level as actual stored, then it must be created and stored
   //all lesser indent levels which are not actual stored also must be created and stored

   BigInteger maxIlvl = numIDMaxIlvls.get(numID);
   if (maxIlvl == null) maxIlvl = BigInteger.valueOf(-1);
   //maxIlvl is now the biggest stored indent level or -1 if none was stored

   do { //create and store all indent levels between the actual maxIlvl and the requested one
    Numberinglevel numberinglevel = new Numberinglevel(numID, ilvl);
    numberinglevel.countUp();
    number = number.replace("%"+(numberinglevel.ilvl.intValue()+1), ""+numberinglevel.counter);
    numberingLevels.add(numberinglevel);
    ilvl = ilvl.subtract(BigInteger.valueOf(1));
   } while (ilvl.compareTo(maxIlvl) == 1);

   numIDMaxIlvls.put(numID, ilvl); //put in new maxIlvl for this numID

  }
  return number;
 }

 public void listParagraphs() {
  for (XWPFParagraph paragraph : this.document.getParagraphs()) {
   String number = "";

   if (paragraph.getNumID() != null) {
    //if we have a numID, then this paragraph is numbered
    BigInteger numID = paragraph.getNumID();
    String numFmt = paragraph.getNumFmt(); //the numFmt type, "decimal" in this case
    BigInteger ilvl = paragraph.getNumIlvl(); //the indent level of this numbering: 0 = %1., 1 = %1.%2., 2= %1.%2.%3., ...
    String lvlText = paragraph.getNumLevelText(); //the indent level text format: "%1.", "%1.%2.", "%1.%2.%3.", ...
    if ("decimal".equalsIgnoreCase(numFmt)) {
     number = getNumber(numID, ilvl, lvlText);
    }
   }

   System.out.println(number + paragraph.getText());

  }
 }

 public static void main(String[] args) {
   WordReaderExtended wordReaderExtended = new WordReaderExtended("XWPFwithNumbering.docx");
   wordReaderExtended.listParagraphs();
 }

 private class Numberinglevel {
  //a class to store a numbering level and its counter
  private BigInteger numID; //the numID of the numbering
  private BigInteger ilvl; //the indent level
  private int counter; //the counter

  private Numberinglevel(BigInteger numID, BigInteger ilvl) {
   this.numID = numID;
   this.ilvl = ilvl;
   this.counter = 0;
  }

  private void countUp() {
   this.counter++;
  }
  private void reset() {
   this.counter = 0;
  }
 }
}