liujie
2026-05-16 539fa09b48cfe03c573284381cfba4ba092e8007
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.estate.expert.admin.stat.report.render;
 
import com.deepoove.poi.XWPFTemplate;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumPr;
 
import java.math.BigInteger;
 
/**
 * 修复模板中缺失层级的编号段落,避免 POI 转换时读取 ilvl 空指针。
 */
public final class WordNumberingSanitizer {
 
    private WordNumberingSanitizer() {
    }
 
    public static XWPFTemplate sanitize(XWPFTemplate template) {
        if (template == null) {
            return null;
        }
 
        sanitizeDocument(template.getXWPFDocument());
        return template;
    }
 
    private static void sanitizeDocument(XWPFDocument document) {
        if (document == null) {
            return;
        }
 
        document.getParagraphs().forEach(WordNumberingSanitizer::sanitizeParagraph);
        document.getTables().forEach(table -> table.getRows().forEach(row ->
                row.getTableCells().forEach(WordNumberingSanitizer::sanitizeCell)));
        document.getHeaderList().forEach(header -> header.getParagraphs().forEach(WordNumberingSanitizer::sanitizeParagraph));
        document.getFooterList().forEach(footer -> footer.getParagraphs().forEach(WordNumberingSanitizer::sanitizeParagraph));
    }
 
    private static void sanitizeCell(XWPFTableCell cell) {
        if (cell == null) {
            return;
        }
        cell.getParagraphs().forEach(WordNumberingSanitizer::sanitizeParagraph);
        cell.getTables().forEach(table -> table.getRows().forEach(row ->
                row.getTableCells().forEach(WordNumberingSanitizer::sanitizeCell)));
    }
 
    private static void sanitizeParagraph(XWPFParagraph paragraph) {
        if (paragraph == null || !paragraph.getCTP().isSetPPr()) {
            return;
        }
 
        var paragraphProperties = paragraph.getCTP().getPPr();
        if (!paragraphProperties.isSetNumPr()) {
            return;
        }
 
        CTNumPr numPr = paragraphProperties.getNumPr();
        if (numPr.getNumId() != null && numPr.getIlvl() == null) {
            CTDecimalNumber ilvl = numPr.addNewIlvl();
            ilvl.setVal(BigInteger.ZERO);
        }
    }
}