Как заменить закладки в ".docx", используя POI без потери формата? - PullRequest
2 голосов
/ 09 мая 2019

Я пытаюсь заменить закладку значениями.

private FileInputStream fis = new FileInputStream(new File("D:\\test.docx"));
private XWPFDocument document = new XWPFDocument(fis);
List<XWPFParagraph> paraList = this.document.getParagraphs();

private final void procParaList(List<XWPFParagraph> paraList, String bookmarkName, String bookmarkValue) {
    Iterator<XWPFParagraph> paraIter = null;
    XWPFParagraph para = null;
    List<CTBookmark> bookmarkList = null;
    Iterator<CTBookmark> bookmarkIter = null;
    CTBookmark bookmark = null;
    XWPFRun run = null;
    Node nextNode = null;

    paraIter = paraList.iterator();
    while (paraIter.hasNext()) {
        para = paraIter.next();
        bookmarkList = para.getCTP().getBookmarkStartList();
        bookmarkIter = bookmarkList.iterator();

        while (bookmarkIter.hasNext()) {
            bookmark = bookmarkIter.next();
            if (bookmark.getName().equals(bookmarkName)) {
                run = para.createRun();
                run.setText(bookmarkValue);
                nextNode = bookmark.getDomNode().getNextSibling();
                while (!(nextNode.getNodeName().contains("bookmarkEnd"))) {
                    para.getCTP().getDomNode().removeChild(nextNode);
                    nextNode = bookmark.getDomNode().getNextSibling();
                }
                para.getCTP().getDomNode().insertBefore(run.getCTR().getDomNode(), nextNode);
            }
        }
    }
}

Я могу заменить закладку на значение, но она не поддерживает тот же формат (семейство шрифтов, размер шрифта, цвет и т. Д.), Что и у текста закладки.

Может ли кто-нибудь предоставитьнесколько советов.

1 Ответ

0 голосов
/ 09 мая 2019

Как обсуждалось ранее, я считаю, что это именно тот случай использования, официальная ссылка на архив help Пожалуйста, обратите внимание на использование Node styleNode для копирования информации о стиле.

    /**
     * Replace the text - if any - contained between the bookmarkStart and
it's
     * matching bookmarkEnd tag with the text specified. The technique used
will
     * resemble that employed when inserting text after the bookmark. In
short,
     * the code will iterate along the nodes until it encounters a matching
     * bookmarkEnd tag. Each node encountered will be deleted unless it is
the
     * final node before the bookmarkEnd tag is encountered and it is a
     * character run. If this is the case, then it can simply be updated to
     * contain the text the users wishes to see inserted into the document.
If
     * the last node is not a character run, then it will be deleted, a new
run
     * will be created and inserted into the paragraph between the
bookmarkStart
     * and bookmarkEnd tags.
     *
     * @param run An instance of the XWPFRun class that encapsulates the
text
     * that is to be inserted into the document following the bookmark.
     */
    private void replaceBookmark(XWPFRun run) {
        Node nextNode = null;
        Node styleNode = null;
        Node lastRunNode = null;
        Node toDelete = null;
        NodeList childNodes = null;
        Stack<Node> nodeStack = null;
        boolean textNodeFound = false;
        boolean foundNested = true;
        int bookmarkStartID = 0;
        int bookmarkEndID = -1;
        int numChildNodes = 0;

        nodeStack = new Stack<Node>();
        bookmarkStartID = this._ctBookmark.getId().intValue();
        nextNode = this._ctBookmark.getDomNode();
        nodeStack.push(nextNode);

        // Loop through the nodes looking for a matching bookmarkEnd tag
        while (bookmarkStartID != bookmarkEndID) {
            nextNode = nextNode.getNextSibling();
            nodeStack.push(nextNode);

            // If an end tag is found, does it match the start tag? If so,
end
            // the while loop.
            if (nextNode.getNodeName().contains(Bookmark.BOOKMARK_END_TAG))
{
                try {
                    bookmarkEndID = Integer.parseInt(
                            nextNode.getAttributes().getNamedItem(
                            Bookmark.BOOKMARK_ID_ATTR_NAME).getNodeValue());
                } catch (NumberFormatException nfe) {
                    bookmarkEndID = bookmarkStartID;
                }
            }
            //else {
                // Place a reference to the node on the nodeStack
            //    nodeStack.push(nextNode);
            //}
        }

        // If the stack of nodes found between the bookmark tags is not
empty
        // then they have to be removed.
        if (!nodeStack.isEmpty()) {

            // Check the node at the top of the stack. If it is a run, get
it's
            // style - if any - and apply to the run that will be replacing
it.
            //lastRunNode = nodeStack.pop();
            lastRunNode = nodeStack.peek();
            if ((lastRunNode.getNodeName().equals(Bookmark.RUN_NODE_NAME)))
{
                styleNode = this.getStyleNode(lastRunNode);
                if (styleNode != null) {
                    run.getCTR().getDomNode().insertBefore(
                            styleNode.cloneNode(true),
run.getCTR().getDomNode().getFirstChild());
                }
            }
...