【问题标题】:How can I add List in poi word, ordered number or other symbol for list symbol?如何在 poi 字、有序数字或其他符号中添加列表作为列表符号?
【发布时间】:2022-01-06 22:18:33
【问题描述】:

大家! 首先,我想在我的 poi 字(XWPF)中添加列表, 其次,我想使用黑色立方体作为列表符号,如下图所示。 第三,如果订购数字而不是黑色立方体符号我该怎么办。有人可以给我一些建议吗?非常感谢!

【问题讨论】:

    标签: apache-poi


    【解决方案1】:

    由于要在XWPFNumbering 中添加新的AbstractNum,所以需要XWPFAbstractNum,并且直到现在不使用底层底层对象才能创建,至少需要org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum

    CTAbstractNum 中有用于在其中创建单个子对象的方法。但是生成的代码将是非常小的部分代码,并且需要很多代码行。所以我认为最好的方法是解析XML 来创建AbstractNum。要获得这个XML,可以创建一个简单的带有编号的Worddocument,然后解压缩*.docx 文件并查看/word/numbering.xml。在那里你会找到类似的东西:

    <w:numbering>
     <w:abstractNum w:abstractNumId="0">
      <w:multiLevelType w:val="hybridMultilevel"/>
      <w:lvl w:ilvl="0">
       <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:hanging="360" w:left="720"/>
       </w:pPr>
      </w:lvl>
      <w:lvl w:ilvl="1" w:tentative="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:hanging="360" w:left="1440"/>
       </w:pPr>
      </w:lvl>
      <w:lvl w:ilvl="2" w:tentative="1">
       <w:start w:val="1"/><w:numFmt w:val="decimal"/><w:lvlText w:val="%1.%2.%3"/><w:lvlJc w:val="left"/>
       <w:pPr>
        <w:ind w:hanging="360" w:left="2160"/>
       </w:pPr>
      </w:lvl>
     </w:abstractNum>
    ...
    </w:numbering>
    

    以 3 级十进制编号为例。

    我认为这个XML 是自我解释的。每个编号级别都有一个lvl 定义,定义了它的外观和缩进。

    对于项目符号编号,XML 将类似,但使用的项目符号字符的字形将使用 Font 定义进行额外定义。例如,“黑色立方体”是字体 Wingdings 的字形。

    ...
    <w:lvl w:ilvl="0">
     <w:start w:val="1"/><w:numFmt w:val="bullet"/><w:lvlText w:val=" "/><w:lvlJc w:val="left"/>
     <w:pPr>
      <w:ind w:hanging="360" w:left="720"/>
     </w:pPr>
     <w:rPr>
      <w:rFonts w:ascii="Wingdings" w:hAnsi="Wingdings" w:hint="default"/>
     </w:rPr>
    </w:lvl>
    ...
    

    w:val=" " 中的空格是 unicode 代码点 F06E 的默认字体字形表示。这是因为 ASCII 码点 6E 在 Wingdings 中显示字形“黑色立方体”,但在普通字体中显示字形 n。如果字体 Wingdings 不可用,这可能会导致恼火。这就是为什么使用 unicode F06E 而不是 ASCII 6E

    知道了这一点我们就可以编码了:

    import java.io.File;
    import java.io.FileOutputStream;
    
    import org.apache.poi.xwpf.usermodel.*;
    
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumbering;
    
    import java.math.BigInteger;
    
    public class CreateWordBulletOrDecimalList {
    
     static String cTAbstractNumBulletXML = 
      "<w:abstractNum xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" w:abstractNumId=\"0\">"
    + "<w:multiLevelType w:val=\"hybridMultilevel\"/>"
    + "<w:lvl w:ilvl=\"0\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"\uF06E\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"720\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Wingdings\" w:hAnsi=\"Wingdings\" w:hint=\"default\"/></w:rPr></w:lvl>"
    + "<w:lvl w:ilvl=\"1\" w:tentative=\"1\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"\u2013\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"1440\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Courier New\" w:hAnsi=\"Courier New\" w:cs=\"Courier New\" w:hint=\"default\"/></w:rPr></w:lvl>"
    + "<w:lvl w:ilvl=\"2\" w:tentative=\"1\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"\u26Ac\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"2160\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Courier New\" w:hAnsi=\"Courier New\" w:hint=\"default\"/></w:rPr></w:lvl>"
    + "</w:abstractNum>";
    
     static String cTAbstractNumDecimalXML = 
      "<w:abstractNum xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" w:abstractNumId=\"0\">"
    + "<w:multiLevelType w:val=\"hybridMultilevel\"/>"
    + "<w:lvl w:ilvl=\"0\"><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:tentative=\"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=\"1440\" w:hanging=\"360\"/></w:pPr></w:lvl>"
    + "<w:lvl w:ilvl=\"2\" w:tentative=\"1\"><w:start w:val=\"1\"/><w:numFmt w:val=\"decimal\"/><w:lvlText w:val=\"%1.%2.%3\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"2160\" w:hanging=\"360\"/></w:pPr></w:lvl>"
    + "</w:abstractNum>";
    
     public static void main(String[] args) throws Exception {
    
      XWPFDocument document = new XWPFDocument();
    
      XWPFParagraph paragraph = document.createParagraph();
      XWPFRun run=paragraph.createRun();  
      run.setText("The List:");
    
      CTNumbering cTNumbering = CTNumbering.Factory.parse(cTAbstractNumBulletXML);
      //CTNumbering cTNumbering = CTNumbering.Factory.parse(cTAbstractNumDecimalXML);
    
      CTAbstractNum cTAbstractNum = cTNumbering.getAbstractNumArray(0);
    
      XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum);
    
      XWPFNumbering numbering = document.createNumbering();
    
      BigInteger abstractNumID = numbering.addAbstractNum(abstractNum);
    
      BigInteger numID = numbering.addNum(abstractNumID);
    
      for (int i = 0; i < 5; i++) {
       paragraph = document.createParagraph();
       paragraph.setNumID(numID);
       run = paragraph.createRun();
       run.setText("List item " + (i+1)); 
       if (i < 4) paragraph.setSpacingAfter(0);
       if (i == 0) {
        for (int j = 0; j < 2; j++) {
         paragraph = document.createParagraph();
         paragraph.setNumID(numID);
         paragraph.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(1));
         run = paragraph.createRun();
         run.setText("Sub list item " + (i+1) + " " + (char)(97+j));
         paragraph.setSpacingAfter(0);
        }
       }
       if (i == 1 || i == 3) {
        paragraph = document.createParagraph();
        paragraph.setNumID(numID);
        paragraph.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(1));
        run = paragraph.createRun();
        run.setText("Sub list item " + (i+1) + " a");
        paragraph.setSpacingAfter(0); 
       }
      }
    
      paragraph = document.createParagraph();
      run=paragraph.createRun();  
      run.setText("Paragraph after the list.");
    
      FileOutputStream out = new FileOutputStream("CreateWordBulletOrDecimalList.docx");    
      document.write(out);
      out.close();
      document.close();
    
      System.out.println("CreateWordBulletOrDecimalList written successully");
     }
    }
    

    在一个文档中使用两种列表的代码:

    import java.io.File;
    import java.io.FileOutputStream;
    
    import org.apache.poi.xwpf.usermodel.*;
    
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumbering;
    
    import java.math.BigInteger;
    
    public class CreateWordBulletAndDecimalList {
    
     static String cTAbstractNumBulletXML = 
      "<w:abstractNum xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" w:abstractNumId=\"0\">"
    + "<w:multiLevelType w:val=\"hybridMultilevel\"/>"
    + "<w:lvl w:ilvl=\"0\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"\uF06E\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"720\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Wingdings\" w:hAnsi=\"Wingdings\" w:hint=\"default\"/></w:rPr></w:lvl>"
    + "<w:lvl w:ilvl=\"1\" w:tentative=\"1\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"\u2013\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"1440\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Courier New\" w:hAnsi=\"Courier New\" w:cs=\"Courier New\" w:hint=\"default\"/></w:rPr></w:lvl>"
    + "<w:lvl w:ilvl=\"2\" w:tentative=\"1\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"\u26Ac\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"2160\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Courier New\" w:hAnsi=\"Courier New\" w:hint=\"default\"/></w:rPr></w:lvl>"
    + "</w:abstractNum>";
    
     static String cTAbstractNumDecimalXML = 
      "<w:abstractNum xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" w:abstractNumId=\"1\">"
    + "<w:multiLevelType w:val=\"hybridMultilevel\"/>"
    + "<w:lvl w:ilvl=\"0\"><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:tentative=\"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=\"1440\" w:hanging=\"360\"/></w:pPr></w:lvl>"
    + "<w:lvl w:ilvl=\"2\" w:tentative=\"1\"><w:start w:val=\"1\"/><w:numFmt w:val=\"decimal\"/><w:lvlText w:val=\"%1.%2.%3\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"2160\" w:hanging=\"360\"/></w:pPr></w:lvl>"
    + "</w:abstractNum>";
    
     public static void main(String[] args) throws Exception {
    
      XWPFDocument document = new XWPFDocument();
    
      CTNumbering cTNumbering = CTNumbering.Factory.parse(cTAbstractNumBulletXML);
      CTAbstractNum cTAbstractNum = cTNumbering.getAbstractNumArray(0);
      XWPFAbstractNum abstractNum1 = new XWPFAbstractNum(cTAbstractNum);
    
    
      cTNumbering = CTNumbering.Factory.parse(cTAbstractNumDecimalXML);
      cTAbstractNum = cTNumbering.getAbstractNumArray(0);
      XWPFAbstractNum abstractNum2 = new XWPFAbstractNum(cTAbstractNum);
    
      XWPFNumbering numbering = document.createNumbering();
    
      BigInteger abstractNumID1 = numbering.addAbstractNum(abstractNum1);
      BigInteger numID1 = numbering.addNum(abstractNumID1);
    
      BigInteger abstractNumID2 = numbering.addAbstractNum(abstractNum2);
      BigInteger numID2 = numbering.addNum(abstractNumID2);
    
      XWPFParagraph paragraph = document.createParagraph();
      XWPFRun run=paragraph.createRun();  
      run.setText("The lists:");
      paragraph = document.createParagraph();
    
      paragraph = document.createParagraph();
      run=paragraph.createRun();  
      run.setText("The bullet list:");
    
      for (int i = 0; i < 5; i++) {
       paragraph = document.createParagraph();
       paragraph.setNumID(numID1);
       run = paragraph.createRun();
       run.setText("List item " + (i+1)); 
       if (i < 4) paragraph.setSpacingAfter(0);
       if (i == 0) {
        for (int j = 0; j < 2; j++) {
         paragraph = document.createParagraph();
         paragraph.setNumID(numID1);
         paragraph.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(1));
         run = paragraph.createRun();
         run.setText("Sub list item " + (i+1) + " " + (char)(97+j));
         paragraph.setSpacingAfter(0);
        }
       }
       if (i == 1 || i == 3) {
        paragraph = document.createParagraph();
        paragraph.setNumID(numID1);
        paragraph.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(1));
        run = paragraph.createRun();
        run.setText("Sub list item " + (i+1) + " a");
        paragraph.setSpacingAfter(0); 
       }
      }
    
      paragraph = document.createParagraph();
      paragraph = document.createParagraph();
      run=paragraph.createRun();  
      run.setText("The decimal list:");
    
      for (int i = 0; i < 5; i++) {
       paragraph = document.createParagraph();
       paragraph.setNumID(numID2);
       run = paragraph.createRun();
       run.setText("List item " + (i+1)); 
       if (i < 4) paragraph.setSpacingAfter(0);
       if (i == 0) {
        for (int j = 0; j < 2; j++) {
         paragraph = document.createParagraph();
         paragraph.setNumID(numID2);
         paragraph.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(1));
         run = paragraph.createRun();
         run.setText("Sub list item " + (i+1) + " " + (char)(97+j));
         paragraph.setSpacingAfter(0);
        }
       }
       if (i == 1 || i == 3) {
        paragraph = document.createParagraph();
        paragraph.setNumID(numID2);
        paragraph.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(1));
        run = paragraph.createRun();
        run.setText("Sub list item " + (i+1) + " a");
        paragraph.setSpacingAfter(0); 
       }
      }
    
      paragraph = document.createParagraph();
      paragraph = document.createParagraph();
      run=paragraph.createRun();  
      run.setText("Paragraph after the lists.");
    
      FileOutputStream out = new FileOutputStream("CreateWordBulletAndDecimalList.docx");    
      document.write(out);
      out.close();
      document.close();
    
      System.out.println("CreateWordBulletAndDecimalList written successully");
     }
    }
    

    【讨论】:

    • 如果我同时使用 cTAbstractNumBulletXML 和 cTAbstractNumDecimalXML ,我发现后者将代替之前。有两个方法getList1(),getList2(),分别用cTAbstractNumBulletXML和cTAbstractNumDecimalXML,但是getList1()会变成getList2()的样式,有什么问题?
    • 我的示例代码是或者,对于 either 使用 cTAbstractNumBulletXML 使用 cTAbstractNumDecimalXML。如果两者都需要,您将需要两个不同的XWPFAbstractNum abstractNum1abstractNum2 都添加到XWPFNumbering numbering 导致两个不同的BigInteger abstractNumID1abstractNumID2 以及两个不同的BigInteger @987654356 @和numID2paragraph.setNumID 中使用的不同 numID 将为段落设置不同类型的编号。
    • 忘了一件事:w:abstractNumId="0" 不能同时是 0XML。其中之一必须不同。我现在提供了使用这两种列表的示例代码。
    • 非常感谢。您的回答很有价值。
    • 你对my questions..有什么想法吗?也许我应该复制style.xml,但我不知道连接document.xml和styles.xml的关系,以及如何在document.xml中设置样式id来连接具体的文本部分和具体的样式。我应该付出巨大的努力来做到这一点。你有什么想法吗?
    猜你喜欢
    • 2022-01-23
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    相关资源
    最近更新 更多