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段的单词? 编号项是默认样式的列表项。它可以出现在报告文档的任何章节中。
答案 0 :(得分:0)
回答这个问题:
如何使用Word
在apache 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;
}
}
}