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

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

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

但是我陷入了第二步。 如何创建可以添加到编号的AbstractNum对象?

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

这是我将AbstractNum添加到文档的编号对象的方法。 调用’addAbstractNum()’结果在我使用的版本(3.10-FINAL)中有一个空错误。 因此,为了解决这个问题,您需要在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片段。 它看起来像这样:

  

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

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

祝好运。

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

我在这个网站上提到过

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

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