2016-10-24 7 views
0

Apache POI XWPFライブラリを使用して、Wordのdocxファイルでレポートを作成しようとしています。Apache POI:ワードドキュメントの番号付きリストの番号付けを再開するにはどうすればよいですか?

私のアプローチは、既存のWord文書をスタイルテンプレートとして使用することです。テンプレートの中で私は "SRINumberList"という名前のスタイルを定義しました。

ので、テンプレートをロードして、ヘッダーまたはフッターにないすべて削除するには:今、私の文書内の番号付きリストが含まれているいくつかの異なるセクションがある

protected void createDocFromTemplate() { 
    try { 
     document = new XWPFDocument(this.getClass().getResourceAsStream(styleTemplate)); 


     int pos = document.getBodyElements().size()-1; 

     while (pos >= 0) { 
      IBodyElement element = document.getBodyElements().get(pos); 
      if (!EnumSet.of(BodyType.HEADER, BodyType.FOOTER).contains(element.getPartType())) { 
       boolean success = document.removeBodyElement(pos); 
       logger.log(Level.INFO, "Removed body element "+pos+": "+success); 
      } 
      pos--; 
     } 

    } catch (IOException e) { 
     logger.log(Level.WARNING, "Not able to load style template", e); 
     document = new XWPFDocument(); 
    } 

} 

を。それぞれ1からこの付番再起動する必要があり、私はこれをやっている典型的な方法である:

if (itemStem.getItems().size() > 0) { 
     p = document.createParagraph(); 
     p.setStyle(ParaStyle.StemAndItemTitle.styleId); 
     final BigInteger bulletNum = newBulletNumber(); 

     run = p.createRun(); 
     run.setText("Sub Items"); 

     itemStem.getItems().stream().forEach(item -> { 
      XWPFParagraph p2 = document.createParagraph(); 
      p2.setStyle(ParaStyle.NumberList.styleId); 

      XWPFRun run2 = p2.createRun(); 
      run2.setText(item.getSubItemText()); 
     }); 
     p = document.createParagraph(); 
     p.createRun(); 
} 

だから、これは正しく番号形式が含まれているスタイルを適用されますが、単一の配列のみ(1があります...ただし、多くのリスト項目は文書内で終了します)。たとえば、次のように

Heading 1 
1. item a 
2. item b 
3. item c 

Heading 2 
4. item a 
5. item d 
6. item g 

しかし、私が欲しいのさ。だから、基本的に私は私が持っているスタイルが、文書内のさまざまなスポットに番号を再起動ページを使用する方法を把握しようとしている

Heading 1 
1. item a 
2. item b 
3. item c 

Heading 2 
1. item a 
2. item d 
3. item g 

。誰かがこれがどのように機能するかのサンプルを提供できますか?

答えて

0

keilからの助けを借りて。私は解決策を考え出した。 https://github.com/jimklo/apache-poi-sample

ナンバリングを再開する新しいNumを作成するときに、ドキュメントで定義されているNumberingスタイルのAbstractNumを参照する必要があるということがあります。

ここにハイライトがありますが、キーはドキュメント内のスタイルのためにAbstractNum IDが何であるかを判断する必要がありました。残念なことですが、これは単なるXML文書であり、既存のNumとAbstractNumを列挙する方法はありません。もしそうなら、私はそれをする方法を知りたいです。

/** 
* first discover all the numbering styles defined in the template. 
* a bit brute force since I can't find a way to just enumerate all the 
* abstractNum's inside the numbering.xml 
*/ 
protected void initNumberingStyles() { 
    numbering = document.getNumbering(); 

    BigInteger curIdx = BigInteger.ONE; 
    XWPFAbstractNum abstractNum; 

    while ((abstractNum = numbering.getAbstractNum(curIdx)) != null) { 
     if (abstractNum != null) { 
      CTString pStyle = abstractNum.getCTAbstractNum().getLvlArray(0).getPStyle(); 
      if (pStyle != null) { 
       numberStyles.put(pStyle.getVal(), abstractNum); 
      } 
     } 
     curIdx = curIdx.add(BigInteger.ONE); 
    } 

} 

今、私たちはAbstractNumまでのスタイルからのマッピングを持っていることを、我々はLvlOverrideとStartOverrideを経由して再起動し、新規のNumを作成することができます。

/** 
* This creates a new num based upon the specified numberStyle 
* @param numberStyle 
* @return 
*/ 
private XWPFNum restartNumbering(String numberStyle) { 
    XWPFAbstractNum abstractNum = numberStyles.get(numberStyle); 
    BigInteger numId = numbering.addNum(abstractNum.getAbstractNum().getAbstractNumId()); 
    XWPFNum num = numbering.getNum(numId); 
    CTNumLvl lvlOverride = num.getCTNum().addNewLvlOverride(); 
    lvlOverride.setIlvl(BigInteger.ZERO); 
    CTDecimalNumber number = lvlOverride.addNewStartOverride(); 
    number.setVal(BigInteger.ONE); 
    return num; 
} 

これで、作成しているリストにNumIDを適用できます。再び

/** 
* This creates a five item list with a simple heading, using the specified style.. 
* @param index 
* @param styleName 
*/ 
protected void createStyledNumberList(int index, String styleName) { 
    XWPFParagraph p = document.createParagraph(); 
    XWPFRun run = p.createRun(); 
    run.setText(String.format("List %d: - %s", index, styleName)); 

    // restart numbering 
    XWPFNum num = restartNumbering(styleName); 

    for (int i=1; i<=5; i++) { 
     XWPFParagraph p2 = document.createParagraph(); 

     // set the style for this paragraph 
     p2.setStyle(styleName); 

     // set numbering for paragraph 
     p2.setNumID(num.getCTNum().getNumId()); 
     CTNumPr numProp = p2.getCTP().getPPr().getNumPr(); 
     numProp.addNewIlvl().setVal(BigInteger.ZERO); 

     // set the text 
     XWPFRun run2 = p2.createRun(); 
     run2.setText(String.format("Item #%d using '%s' style.", i, styleName)); 
    } 

    // some whitespace 
    p = document.createParagraph(); 
    p.createRun(); 

} 

、全体的に私はkeilが提供するポインタせずにこれを考え出していないだろう。

0

私が見つけた唯一の方法は、CTNumのレベルを上書きすることです。もう1つの方法は、新しい抽象的な番号/スタイルをたくさん作成することですが、文書を開くときにスタイルエントリがたくさんかかることになります。

ArrayList<String> list = new ArrayList<String>(); 
list.add("SubItem 1"); 
list.add("SubItem 2"); 
list.add("SubItem 3"); 

XWPFNumbering numbering = document.getNumbering(); 
XWPFAbstractNum numAbstract = numbering.getAbstractNum(BigInteger.ONE); 

for (Integer nx = 1; nx < 3; nx++) { 
    XWPFParagraph p = document.createParagraph(); 
    XWPFRun run = p.createRun(); 
    run.setText("Items " + nx.toString()); 
    //leveloverride (start the new numbering) 
    BigInteger numId = numbering.addNum(numAbstract.getAbstractNum().getAbstractNumId()); 
    XWPFNum num = numbering.getNum(numId); 
    CTNumLvl lvloverride = num.getCTNum().addNewLvlOverride(); 
    lvloverride.setIlvl(BigInteger.ZERO); 
    CTDecimalNumber number = lvloverride.addNewStartOverride(); 
    number.setVal(BigInteger.ONE); 

    for (String item : list) { 
     XWPFParagraph p2 = document.createParagraph(); 
     p2.setNumID(num.getCTNum().getNumId()); 
     CTNumPr numProp = p2.getCTP().getPPr().getNumPr(); 
     numProp.addNewIlvl().setVal(BigInteger.ZERO); 

     XWPFRun run2 = p2.createRun(); 
     run2.setText(item); 
    } 
} 
+0

これは近いです...確かに数字を再起動しますが、何らかのリストを再起動しません。つまり、アルファリストがある場合は、「a」で再起動します。 – Jim

関連する問題