0

Apache POI XWPF ライブラリを使用して、Word docx ファイルでレポートを作成しようとしています。

私のアプローチは、既存の 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 つしかありません (ドキュメント内に存在するリスト項目の数は 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

したがって、基本的には、私が持っているスタイルを使用する方法を理解しようとしていますが、ドキュメント内のさまざまな場所でページ番号を付け直しています. 誰かがこれがどのように機能するかのサンプルを提供できますか?

4

2 に答える 2

0

keilの助けを借りて。私は解決策を考え出しました。ここに完全な動作サンプルを投稿しました: https://github.com/jimklo/apache-poi-sample

秘訣は、番号付けを再開する新しい Num を作成するときに、ドキュメントで定義されている番号付けスタイルの 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);
    }

}

Style から 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();

}

繰り返しますが、全体として、キールが提供したポインターがなければ、これを理解できなかったでしょ

于 2016-11-03T01:58:53.273 に答える