4

I use apache-poi to highlight a sentence in a docx. I wrote the code underneath, that works if there is no XWPFFieldRun in (or before) the sentence I have to highlight. A XWPFFieldRun can be something like chapter references, or something like that.

private void highlightSentence(XWPFParagraph p, String sentence, HighlighterColor color, XWPFDefaultRunStyle defaultRunStyle) {
    List<XWPFRun> oldRuns = new ArrayList<>(p.getRuns());
    PositionInParagraph pos = new PositionInParagraph();
    TextSegement searchText = p.searchText(sentence, pos);
    while (searchText != null) {
        int beginPosIndex = searchText.getBeginPos().getRun();
        int endPosIndex = searchText.getEndPos().getRun();
        int offsetRuns = highlightInvolvedRuns(beginPosIndex, endPosIndex, oldRuns, sentence, p, color, defaultRunStyle);
        searchText = p.searchText(sentence, new PositionInParagraph(endPosIndex + offsetRuns + 1, 0, 0));
    }
}

If a XWPFFieldRun is among the runs containing the sentence, the searchText method does't find the sentence in the text. If a XWPFFieldRun is among the runs before the sentence, the method returns results that are shifted by one, like there is a run less. It seems like XWPFFieldRuns are not considered like real text-runs, so I re-implemented the searchText method looking just at the text.

The new method finds the text and the corresponding runs containing my sentence, but when all is said and done, the highlighted docx has the content of the XWPFFieldRun at the start of the paragraph.

INPUT: This is normal text and ****Here is the chapter reference****

OUTPUT: ****Here is the chapter reference**** This is normal text and

The reason of this shift I think is due to the fact that I remove/add runs in the process. Here the subfunction that does the work:

private int highlightSubsentence(String sentence, XWPFParagraph p, int i, String hexColor, XWPFDefaultRunStyle defaultRunStyle) {
    XWPFRun currentRun = p.getRuns().get(i);
    Style currentStyle = new Style(currentRun, defaultRunStyle);
    String currentRunText = currentRun.text();
    int sentenceLength = sentence.length();
    int sentenceBeginIndex = currentRunText.indexOf(sentence);
    int offsetRuns = 0;
    p.removeRun(i);
    if (sentenceBeginIndex > 0) {
        XWPFRun before = p.insertNewRun(i);
        before.setText(currentRunText.substring(0, sentenceBeginIndex));
        currentStyle.copyStyle(before);
        offsetRuns++;
    }

    XWPFRun sentenceRun = p.insertNewRun(i + offsetRuns);
    sentenceRun.setText(currentRunText.substring(sentenceBeginIndex, sentenceBeginIndex + sentenceLength));
    currentStyle.copyStyle(sentenceRun);
    Style.addShading(sentenceRun, hexColor);

    if (sentenceBeginIndex + sentenceLength != currentRunText.length()) {
        XWPFRun after = p.insertNewRun(i + offsetRuns + 1);
        after.setText(currentRunText.substring(sentenceBeginIndex + sentenceLength));
        currentStyle.copyStyle(after);
        //addedRuns++; this run can be searched again
    }
    return offsetRuns;
}

When I ask for the paragraph runs, after all the add and removal is done, I see them in the right order.

After the writefile is done and I open the file, the runs are like I described before. How can I make the XWPFFieldRun perceive the shift instead of being put at the start of the paragraph? Thanks

Ale
  • 946
  • 4
  • 17
  • 28

0 Answers0