我使用apache-poi在docx中突出显示一个句子。我在下面编写了代码,如果必须突出显示的句子中(或之前)没有XWPFFieldRun
,该代码将起作用。 XWPFFieldRun
可以是章节引用之类的东西。
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));
}
}
如果XWPFFieldRun
在包含句子的游程中,则searchText
方法不会在文本中找到该句子。如果XWPFFieldRun
在句子前的游程中,则该方法返回的结果将移位1,就像游程较少一样。似乎XWPFFieldRun
被认为不是真正的 text-runs ,所以我重新实现了searchText
方法,仅查看文本。
新方法找到包含我的句子的文本和相应的行,但是当全部说完之后,突出显示的docx在段落的开头具有XWPFFieldRun
的内容。
输入:这是普通文本,****这里是章节参考****
输出:****这里是章节参考****这是普通文字,并且
我认为这一转变的原因是由于我在流程中删除/添加了运行。子函数在这里起作用:
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;
}
当我要求段落运行时,在完成所有添加和删除之后,我会以正确的顺序看到它们。
写完文件并打开文件后,运行就像我之前描述的那样。
如何使XWPFFieldRun
感知到变化,而不是放在段落的开头?
谢谢