如何在Apache POI XWPF文档中创建项目符号列表



我想用Java在docx word文档中创建一个项目符号/编号列表。我使用的是Apache POI 3.10库。如果我理解正确,步骤如下:

  1. 创建编号numbering = doc.createNumbering
  2. 将AbstractNum添加到编号中,并获得相应的abstractNumId
  3. 使用AbstractNumId numId = numbering.addNum(abstractNumId)添加数字
  4. 现在我可以使用para.setNumID(numId)将numId添加到段落中

然而,我被困在了第二步。如何创建可以添加到编号中的AbstractNum对象?

我试图做一些类似的事情,但我的头碰到了它,直到它开始工作。

以下是我将AbstractNum添加到文档编号对象中的方法。调用addAbstractNum((在我使用的版本(3.10-FINAL(中发现了一个null错误。因此,为了解决这个问题,您需要用XML生成AbstractNum,解析它,手动为它分配一个id,并将它添加到文档的编号对象中。

我就是这样做的:

protected XWPFDocument doc;     
private BigInteger addListStyle(String style)
{
    try
    {
        XWPFNumbering numbering = doc.getNumbering();
        // generate numbering style from XML
        CTAbstractNum abstractNum = CTAbstractNum.Factory.parse(style);
        XWPFAbstractNum abs = new XWPFAbstractNum(abstractNum, numbering);
        // find available id in document
        BigInteger id = BigInteger.valueOf(0);
        boolean found = false;
        while (!found)
        {
            Object o = numbering.getAbstractNum(id);
            found = (o == null);
            if (!found) id = id.add(BigInteger.ONE);
        }
        // assign id
        abs.getAbstractNum().setAbstractNumId(id);
        // add to numbering, should get back same id
        id = numbering.addAbstractNum(abs);
        // add to num list, result is numid
        return doc.getNumbering().addNum(id);           
    }
    catch (Exception e)
    {
        e.printStackTrace();
        return null;
    }
}

传递给方法的"style"字符串的格式需要XWPF文档的知识——我对此一无所知。因此,我创建了一个具有我想要的编号样式的word文档。将其保存到".docx"文件中。解压缩".docx"文件,并从"numbering.XML"复制XML片段。它看起来像这样:

<xml-fragment xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14"><w:nsid w:val="1656060D" /><w:multiLevelType w:val="hybridMultilevel" /><w:tmpl w:val="99FCFC1A" /><w:lvl w:ilvl="0" w:tplc="0409000F"><w:start w:val="1" /><w:numFmt w:val="decimal" /><w:lvlText w:val="%1." /><w:lvlJc w:val="left" /><w:pPr><w:ind w:left="720" w:hanging="360" /></w:pPr></w:lvl><w:lvl w:ilvl="1" w:tplc="04090019" w:tentative="1"><w:start w:val="1" /><w:numFmt w:val="lowerLetter" /><w:lvlText w:val="%2." /><w:lvlJc w:val="left" /><w:pPr><w:ind w:left="1440" w:hanging="360" /></w:pPr></w:lvl><w:lvl w:ilvl="2" w:tplc="0409001B" w:tentative="1"><w:start w:val="1" /><w:numFmt w:val="lowerRoman" /><w:lvlText w:val="%3." /><w:lvlJc w:val="right" /><w:pPr><w:ind w:left="2160" w:hanging="180" /></w:pPr></w:lvl><w:lvl w:ilvl="3" w:tplc="0409000F" w:tentative="1"><w:start w:val="1" /><w:numFmt w:val="decimal" /><w:lvlText w:val="%4." /><w:lvlJc w:val="left" /><w:pPr><w:ind w:left="2880" w:hanging="360" /></w:pPr></w:lvl><w:lvl w:ilvl="4" w:tplc="04090019" w:tentative="1"><w:start w:val="1" /><w:numFmt w:val="lowerLetter" /><w:lvlText w:val="%5." /><w:lvlJc w:val="left" /><w:pPr><w:ind w:left="3600" w:hanging="360" /></w:pPr></w:lvl><w:lvl w:ilvl="5" w:tplc="0409001B" w:tentative="1"><w:start w:val="1" /><w:numFmt w:val="lowerRoman" /><w:lvlText w:val="%6." /><w:lvlJc w:val="right" /><w:pPr><w:ind w:left="4320" w:hanging="180" /></w:pPr></w:lvl><w:lvl w:ilvl="6" w:tplc="0409000F" w:tentative="1"><w:start w:val="1" /><w:numFmt w:val="decimal" /><w:lvlText w:val="%7." /><w:lvlJc w:val="left" /><w:pPr><w:ind w:left="5040" w:hanging="360" /></w:pPr></w:lvl><w:lvl w:ilvl="7" w:tplc="04090019" w:tentative="1"><w:start w:val="1" /><w:numFmt w:val="lowerLetter" /><w:lvlText w:val="%8." /><w:lvlJc w:val="left" /><w:pPr><w:ind w:left="5760" w:hanging="360" /></w:pPr></w:lvl><w:lvl w:ilvl="8" w:tplc="0409001B" w:tentative="1"><w:start w:val="1" /><w:numFmt w:val="lowerRoman" /><w:lvlText w:val="%9." /><w:lvlJc w:val="right" /><w:pPr><w:ind w:left="6480" w:hanging="180" /></w:pPr></w:lvl></xml-fragment>

取该字符串,将其传递给上面的方法。现在你有了一个numID,你可以用它列出列表。

XWPFParagraph para = doc.createParagraph();
para.setStyle("ListParagraph");
para.setNumID(listType);
para.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(level));

祝你好运。

我也使用了您提到的相同步骤,对于第二步,我使用了以下语句。

BigInteger abstractNumId = BigInteger.valueOf(0);

有了这个,我可以创建项目符号列表。然而,我仍然没有找到创建编号列表的方法。

我发现最简单的方法是从具有所需样式的Word文档中提取numbering.xml,然后使用Java从xml树中手动重新创建重要标记。这听起来有点痛苦,但它比试图解析MS Word创建的东西要精确得多。CT函数是以它们所影响的XML节点命名的,所以一旦你有了这个想法,它就相当直观了。

例如,在我的情况下(这将为项目符号或编号的单层列表返回正确的CTAbstractNum(:

private static CTAbstractNum getAbstractNumber(STNumberFormat.Enum numFmt) {
    CTAbstractNum ctAbsNum = CTAbstractNum.Factory.newInstance();
    CTLvl lvl = ctAbsNum.addNewLvl(); //Add a level
    CTDecimalNumber start = lvl.addNewStart(); //Set the starting number
    start.setVal(BigInteger.ONE);
    CTNumFmt fmt = lvl.addNewNumFmt(); //Set the number format
    fmt.setVal(numFmt);
    //Add the text that's used for the bullet point 
    CTLevelText lt = lvl.addNewLvlText(); 
    if (numFmt == STNumberFormat.BULLET) {
        lt.setVal("");     
        lvl.addNewRPr(); //Set the Symbol font
        CTFonts f = lvl.getRPr().addNewRFonts();
        f.setAscii("Symbol");
        f.setHAnsi("Symbol");
    }
    else { //Decimal
        lt.setVal("%1.");
    }
    lvl.addNewPPr(); 
    CTInd ind = lvl.getPPr().addNewInd(); //Set the indent
    ind.setHanging(BigInteger.valueOf(360));
    ind.setLeft(BigInteger.valueOf(720));           
    System.out.println(ctAbsNum);
    return ctAbsNum;
}
static void addCustomHeadingStyle(XWPFDocument docxDocument, XWPFStyles styles, String strStyleId, int headingLevel, int pointSize, String hexColor) {
        CTStyle ctStyle = CTStyle.Factory.newInstance();
        ctStyle.setStyleId(strStyleId);
        CTString styleName = CTString.Factory.newInstance();
        styleName.setVal(strStyleId);
        ctStyle.setName(styleName);
        CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
        indentNumber.setVal(BigInteger.valueOf(headingLevel));
        // lower number > style is more prominent in the formats bar
        ctStyle.setUiPriority(indentNumber);
        CTOnOff onoffnull = CTOnOff.Factory.newInstance();
        ctStyle.setUnhideWhenUsed(onoffnull);
        // style shows up in the formats bar
        ctStyle.setQFormat(onoffnull);
        // style defines a heading of the given level
        CTPPr ppr = CTPPr.Factory.newInstance();
        ppr.setOutlineLvl(indentNumber);
        ppr.addNewNumPr().addNewNumId().setVal(BigInteger.ONE);
        ctStyle.setPPr(ppr);
        XWPFStyle style = new XWPFStyle(ctStyle);
        CTHpsMeasure size = CTHpsMeasure.Factory.newInstance();
        size.setVal(new BigInteger(String.valueOf(pointSize)));
        CTHpsMeasure size2 = CTHpsMeasure.Factory.newInstance();
        size2.setVal(new BigInteger("24"));
        CTFonts fonts = CTFonts.Factory.newInstance();
        fonts.setAscii("Calibri Light");
        CTRPr rpr = CTRPr.Factory.newInstance();
        rpr.setRFonts(fonts);
        rpr.setSz(size);
        rpr.setSzCs(size2);
        style.setType(STStyleType.PARAGRAPH);
        styles.addStyle(style);
    }
}

可以添加自定义样式,用于创建标题和索引,这个答案不是我的,只是添加数字

的一些更改

打开文档从文档中获取XWPFNumbering对象。从文档中获取XWPF段落列表。逐步浏览段落列表,当你得到每个段落时,试着从中获取数字ID。如果返回null,则该段落不在列表中。如果它不返回null,则可以使用BigInteger从XWPFNumbering对象检索应用于段落的编号/项目符号方案的详细信息。

我从这个网站

最新更新