Apache poi bullets and numbering

2019-03-04 12:57发布

问题:

I am using apache POI for converting a word document into pdf. I am filling the table rows with dynamic data. Everything is working fine, but i want to do some enhancement that is i want to add a bullet before each row data. Here is a for loop i am using to fill the row data in the table:

  for (String string : documentList) {
        XWPFTableRow lnewRow = ltable.createRow();
        XWPFTableCell lnewCell = lnewRow.getCell(0);
        XWPFParagraph lnewPara =lnewCell.getParagraphs().get(0);
        XWPFRun lnewRun = lnewPara.createRun();
        lnewRun.setText(string); 
  }

Can anyone please tell me how can i add a bullet before each row data?

回答1:

There are multiple examples for creating XWPFNumbering already. Most of them are unnecessary complex in my opinion. So let's have a simplest solution:

import java.io.File;
import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLvl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STNumberFormat;

import java.util.ArrayList;
import java.util.Arrays;

import java.math.BigInteger;

public class CreateWordTableWithBulletList {
 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument();

  XWPFParagraph paragraph = document.createParagraph();
  XWPFRun run=paragraph.createRun();  
  run.setText("The table:");

  XWPFTable ltable = document.createTable(1,1);

  ltable.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(5000));
  CTTblWidth tblWidth = ltable.getRow(0).getCell(0).getCTTc().addNewTcPr().addNewTcW();
  tblWidth.setW(BigInteger.valueOf(5000));
  tblWidth.setType(STTblWidth.DXA);

  ltable.getRow(0).getCell(0).getParagraphs().get(0).createRun().setText("The list:");

  ArrayList<String> documentList = new ArrayList<String>(
   Arrays.asList(
    new String[] {
     "documentList item 1",
     "documentList item 2",
     "documentList item 3"
    }));


//your code with supplements

  CTAbstractNum cTAbstractNum = CTAbstractNum.Factory.newInstance();
  //Next we set the AbstractNumId. This requires care. 
  //Since we are in a new document we can start numbering from 0. 
  //But if we have an existing document, we must determine the next free number first.
  cTAbstractNum.setAbstractNumId(BigInteger.valueOf(0));

///* Bullet list
  CTLvl cTLvl = cTAbstractNum.addNewLvl();
  cTLvl.addNewNumFmt().setVal(STNumberFormat.BULLET);
  cTLvl.addNewLvlText().setVal("•");
//*/

/* Decimal list
  CTLvl cTLvl = cTAbstractNum.addNewLvl();
  cTLvl.addNewNumFmt().setVal(STNumberFormat.DECIMAL);
  cTLvl.addNewLvlText().setVal("%1.");
  cTLvl.addNewStart().setVal(BigInteger.valueOf(1));
*/

  XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum);

  XWPFNumbering numbering = document.createNumbering();

  BigInteger abstractNumID = numbering.addAbstractNum(abstractNum);

  BigInteger numID = numbering.addNum(abstractNumID);

  for (String string : documentList) {
        XWPFTableRow lnewRow = ltable.createRow();
        XWPFTableCell lnewCell = lnewRow.getCell(0);
        XWPFParagraph lnewPara =lnewCell.getParagraphs().get(0);
        lnewPara.setNumID(numID);
        XWPFRun lnewRun = lnewPara.createRun();
        lnewRun.setText(string); 
  }

//your code end

  paragraph = document.createParagraph();

  FileOutputStream out = new FileOutputStream("CreateWordTableWithBulletList.docx");    
  document.write(out);

  System.out.println("CreateWordTableWithBulletList written successully");
 }
}

My examples are always complete examples. I have marked the part with your code and my supplements to it.



回答2:

Maybe little late but I applied the solution that Axel is proposing and it works nicely.

Just had a little problem with class CTLvlText, returned object from method cTLvl.addNewLvlText(), had no way to find it out in apache-poi jars.

I handled it by not introducing a next level, but setting NumId to the Paragraph everytime it is created new.

private void generateVarios(XWPFDocument doc1, List<VariosDTO> varios) {
    CTAbstractNum cTAbstractNum = CTAbstractNum.Factory.newInstance();
    cTAbstractNum.setAbstractNumId(BigInteger.valueOf(0));
    CTLvl cTLvl = cTAbstractNum.addNewLvl();
    cTLvl.addNewNumFmt().setVal(STNumberFormat.BULLET);
    //CTLevelText a = cTLvl.addNewLvlText();

    XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum);
    XWPFNumbering numbering = doc1.createNumbering();
    BigInteger abstractNumID = numbering.addAbstractNum(abstractNum);
    BigInteger numID = numbering.addNum(abstractNumID);

    for (VariosDTO item : varios){
        XWPFParagraph bulletedPara = doc1.createParagraph();
        XWPFRun run = bulletedPara.createRun();
        run.setFontFamily(ARIAL);
        run.setFontSize(10);
        run.setText(item.getComentario());
        bulletedPara.setNumID(numID);
    }
}

Hope can be useful to someone!