5

I've read many blogs and forums related to my requirement, but till now I was able to generate bullet or numbering for first level with all the help I got. Can anyone guide me how to create a multilevel numbering using apache poi.

Wondering whether Apache POI XWPFDocument support such feature?

Below is what my requirement

  1. First Level
    • Second Level
    • Second Level
  2. First Level

Edit 1 :

Here is my sample code which works for single level numbering

    public class TestNumbering {
        String fileName=""; 
        InputStream in = null;
        CTAbstractNum abstractNum = null;
        public TestNumbering() {
            try {
                in = CreateWordDocument.class.getClassLoader().getResourceAsStream("numbering.xml");
                abstractNum = CTAbstractNum.Factory.parse(in);
            } catch (XmlException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public String createDocument(String fileName, String content) {
            this.fileName=fileName;
            XWPFDocument doc = new XWPFDocument();

            doc.createNumbering();
            XWPFNumbering numbering=null;
            numbering=doc.createNumbering();
            for(String value: content.split("@")) {
                XWPFParagraph para = doc.createParagraph();
                para.setVerticalAlignment(TextAlignment.CENTER);
                para.setNumID(addListStyle(abstractNum, doc, numbering));
                XWPFRun run=para.createRun();
                run.setText(value);
            }
            try {
                FileOutputStream out = new FileOutputStream(fileName);
                doc.write(out);
                out.close();
                in.close();
            } catch(Exception e) {}
            return null;
        }
        private BigInteger addListStyle(CTAbstractNum abstractNum, XWPFDocument doc, XWPFNumbering numbering) {
            try {

                XWPFAbstractNum abs = new XWPFAbstractNum(abstractNum, numbering);
                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);
                }
                abs.getAbstractNum().setAbstractNumId(id);
                id = numbering.addAbstractNum(abs);
                return doc.getNumbering().addNum(id);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        public static void main(String[] args) throws Exception {
            String fileName="Test.docx";
            new TestNumbering().createDocument(fileName, "First Level@@Second Level@@Second Level@@First Level");
        }
    }

Also find below the numbering.xml

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <w:numbering xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mo="http://schemas.microsoft.com/office/mac/office/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" 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:abstractNum w:abstractNumId="0">
    <w:nsid w:val="3A6A237F"/>
    <w:multiLevelType w:val="hybridMultilevel"/>
    <w:tmpl w:val="5C9890C4"/>
    <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>
    </w:abstractNum>

    <w:abstractNum w:abstractNumId="1">
    <w:nsid w:val="5E7736F6"/>
    <w:multiLevelType w:val="hybridMultilevel"/>
    <w:tmpl w:val="F602653C"/>
    <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="04090001"><w:start w:val="1"/><w:numFmt w:val="bullet"/><w:lvlText w:val=""/><w:lvlJc w:val="left"/><w:pPr><w:ind w:left="1440" w:hanging="360"/></w:pPr><w:rPr><w:rFonts w:ascii="Symbol" w:hAnsi="Symbol" w:hint="default"/></w:rPr></w:lvl>
    <w:lvl w:ilvl="2" w:tplc="04090003"><w:start w:val="1"/><w:numFmt w:val="bullet"/><w:lvlText w:val="o"/><w:lvlJc w:val="left"/><w:pPr><w:ind w:left="2340" 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: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>
    </w:abstractNum>

    <w:num w:numId="1"><w:abstractNumId w:val="1"/></w:num>
    <w:num w:numId="2"><w:abstractNumId w:val="0"/></w:num>

    </w:numbering>
user2009750
  • 3,169
  • 5
  • 35
  • 58
Athiappan
  • 53
  • 1
  • 6
  • 1
    please post part of your code where you are creating list, i might be able to help – user2009750 Jul 09 '15 at 08:01
  • @ɢʜʘʂʈ ʀɛɔʘɴ - thanks for your time, were you able to check the code, any luck... – Athiappan Jul 09 '15 at 13:48
  • @Athiappan The class CreateWordDocument can not be found in my project. Did you made it by yourself or it is from some special library. It does not inside of apache POI library. – MJBZA Feb 13 '16 at 13:45
  • Ok my problem solved by changing the line "in = CreateWordDocument.class.getClassLoader().getResourceAsStream("numbering.xml");" to "in = new FileInputStream("numbering.xml");" – MJBZA Feb 13 '16 at 14:24

1 Answers1

4

You are right Apache POI has the worst kind of documentation or you can say no documentation at all. So there is nothing much you can find except a few blogs.

Replace your for loop with:

for (String value : content.split("@")) {
            XWPFParagraph para = doc.createParagraph();
            para.setVerticalAlignment(TextAlignment.CENTER);
            para.setNumID(addListStyle(abstractNum, doc, numbering));
            if (value.contains("Second")) {
                para.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(1));
            }
            XWPFRun run = para.createRun();
            run.setText(value);
        }

Create a multi hierarchy bullited list in MS-Word .docx manually and inspect its XML structure by renaming its extension to .zip, inside this zip you'll find word/document.xml, by inspecting it you'll find that its <w:ilvl w:val="0"/>, "ilvl" Indent Level that is responsible for you indentation so using above code you can create you multi level lists.

Here is how you set indent level:

para.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(1));

Just increase indent level by BigInteger.valueOf((int)IndentLevel)

user2009750
  • 3,169
  • 5
  • 35
  • 58
  • Thanks again for your time and effort. It worked :-) – Athiappan Jul 10 '15 at 05:29
  • 1
    Now I understand little bit about open office xml. I was wondering why there is getNumIlvl method in XWPFParagraph but not setter method, when I see the xml, seriously there is more hierarchy. – Athiappan Jul 10 '15 at 05:34