如何在word文件中指定文本添加批注

比如我想在这个文本中的这两个字添加批注,
image.png (4.8 KB)

@humanhuman, 这是一个如何做到这一点的例子:

Document doc = new Document("in.docx");

FindReplaceOptions options = new FindReplaceOptions();
options.setReplacingCallback(new FindReplaceHandler());
doc.getRange().replace("股份", "", options);

doc.stopTrackRevisions();

doc.save("out.docx");



static class FindReplaceHandler implements IReplacingCallback {
    public int replacing(ReplacingArgs e) throws Exception {

        Node currentNode = e.getMatchNode();

        // The first (and may be the only) run can contain text before the match,
        // in this case it is necessary to split the run.
        if (e.getMatchOffset() > 0)
            currentNode = SplitRun((Run)currentNode, e.getMatchOffset());

        // This array is used to store all nodes of the match for further removing.
        ArrayList runs = new ArrayList();

        // Find all runs that contain parts of the match string.
        int remainingLength = e.getMatch().group().length();
        while ((remainingLength > 0) &&
                   (currentNode != null) &&
                   (currentNode.getText().length() <= remainingLength))
        {
            runs.add(currentNode);
            remainingLength = remainingLength - currentNode.getText().length();

            // Select the next Run node.
            // Have to loop because there could be other nodes such as BookmarkStart etc.
            do
            {
                currentNode = currentNode.getNextSibling();
            }
            while ((currentNode != null) && (currentNode.getNodeType() != NodeType.RUN));
        }

        // Split the last run that contains the match if there is any text left.
        if ((currentNode != null) && (remainingLength > 0))
        {
            SplitRun((Run)currentNode, remainingLength);
            runs.add(currentNode);
        }

        Document doc =(Document) e.getMatchNode().getDocument();

        Run startRun = (Run)runs.get(0);
        Run endRun = (Run)runs.get(runs.size() - 1);

        Comment comment = new Comment(doc, "My Name", "MN", new Date());
        comment.getParagraphs().add(new Paragraph(doc));
        comment.getFirstParagraph().getRuns().add(new Run(doc, "Comment text."));

        CommentRangeStart commentRangeStart = new CommentRangeStart(doc, comment.getId());
        CommentRangeEnd commentRangeEnd = new CommentRangeEnd(doc, comment.getId());

        startRun.getParentNode().insertBefore(commentRangeStart, currentNode);
        endRun.getParentNode().insertAfter(commentRangeEnd, currentNode);
        commentRangeEnd.getParentNode().insertAfter(comment, commentRangeEnd);

        //Signal to the replace engine to stop after the first replacement.
        return ReplaceAction.STOP;
    }

    private static Run SplitRun(Run run, int position)
    {
        ((Document)run.getDocument()).stopTrackRevisions();
        Run afterRun = (Run)run.deepClone(true);
        afterRun.setText(run.getText().substring(position));
        run.setText(run.getText().substring((0), (0) + (position)));
        run.getParentNode().insertAfter(afterRun, run);
        ((Document)run.getDocument()).startTrackRevisions("My Name");
        return afterRun;
    }
}

in.docx (12.2 KB)

请查看我们的文档以获取更多详细信息:

如果指定的文本是分布在多个段落中,好像会失效,比如我想要这种
image.png (18.7 KB)

@humanhuman, 您可以使用正则表达式查找不同段落中的文本。 请检查更新后的代码:

Document doc = new Document("in.docx");

FindReplaceOptions options = new FindReplaceOptions();
options.setReplacingCallback(new FindReplaceHandler());

String stringPattern = "股份";
doc.getRange().replace(stringPattern, "", options);

String regex = "过[^开]+开";
Pattern p = Pattern.compile(regex);
doc.getRange().replace(p, "", options);

doc.stopTrackRevisions();

doc.save("out.docx");


static class FindReplaceHandler implements IReplacingCallback {
    public int replacing(ReplacingArgs e) throws Exception {

        Node currentNode = e.getMatchNode();

        // The first (and may be the only) run can contain text before the match,
        // in this case it is necessary to split the run.
        if (e.getMatchOffset() > 0)
            currentNode = SplitRun((Run)currentNode, e.getMatchOffset());

        // This array is used to store all nodes of the match for further removing.
        ArrayList runs = new ArrayList();


        // Find the length of the found text.
        char[] chars = e.getMatch().group().toCharArray();
        int remainingLength = 0;
        for (char c: chars) {
            if (c != '\uE00D') {
                remainingLength++;
            }
        }

        // Find all runs that contain parts of the match string.
        while (
                (remainingLength > 0) &&
                        (currentNode != null) &&
                        (currentNode.getText().length() <= remainingLength))
        {
            runs.add(currentNode);
            remainingLength = remainingLength - currentNode.getText().length();

            // Select the next Run node.
            // Have to loop because there could be other nodes such as BookmarkStart etc.
            do
            {
                Node prevNode = currentNode;
                currentNode = currentNode.getNextSibling();

                if (currentNode == null) {
                    Paragraph curParagraph = (Paragraph)prevNode.getParentNode();
                    // If the current node is the last in the paragraph, get the first run of the next paragraph.
                    if (curParagraph.getLastChild() == prevNode) {
                        Paragraph nextParagraph = (Paragraph)curParagraph.getNextSibling();
                        currentNode = nextParagraph.getFirstChild();
                    }
                }
            }
            while ((currentNode != null) && (currentNode.getNodeType() != NodeType.RUN));
        }

        // Split the last run that contains the match if there is any text left.
        if ((currentNode != null) && (remainingLength > 0))
        {
            SplitRun((Run)currentNode, remainingLength);
            runs.add(currentNode);
        }

        Document doc =(Document) e.getMatchNode().getDocument();

        Run startRun = (Run)runs.get(0);
        Run endRun = (Run)runs.get(runs.size() - 1);

        Comment comment = new Comment(doc, "My Name", "MN", new Date());
        comment.getParagraphs().add(new Paragraph(doc));
        comment.getFirstParagraph().getRuns().add(new Run(doc, "Comment text."));

        CommentRangeStart commentRangeStart = new CommentRangeStart(doc, comment.getId());
        CommentRangeEnd commentRangeEnd = new CommentRangeEnd(doc, comment.getId());

        startRun.getParentNode().insertBefore(commentRangeStart, startRun);
        endRun.getParentNode().insertAfter(commentRangeEnd, endRun);

        commentRangeEnd.getParentNode().insertAfter(comment, commentRangeEnd);

        //Signal to the replace engine to do nothing because we have already done all what we wanted.
        return ReplaceAction.STOP;
    }

    private static Run SplitRun(Run run, int position)
    {
        ((Document)run.getDocument()).stopTrackRevisions();
        Run afterRun = (Run)run.deepClone(true);
        afterRun.setText(run.getText().substring(position));
        run.setText(run.getText().substring((0), (0) + (position)));
        run.getParentNode().insertAfter(afterRun, run);
        ((Document)run.getDocument()).startTrackRevisions("My Name");
        return afterRun;
    }
}

out.docx (11.4 KB)