我想将 XWPFRun 文本更新为超链接,而不创建新的运行。如果我尝试这样做,则会收到此错误 java.lang.ArrayIndexOutOfBoundsException: 对于 XWPFRun.setText(String value,int pos) 中的参数位置来说值太大
private void updateRunsForParagraph1(XWPFParagraph p, String text, String key, Map<String, String> hyperlinkMap, Map<String, List<Boolean>> singleWordMap,SBCFormatDocument sbcFormatDocumentObj) throws IOException {
for (int i = 0; i < p.getRuns().size(); i++) {
try {
String tmpText = p.getRuns().get(i).toString();
if (tmpText != null && tmpText.equalsIgnoreCase(text)) {
//p.removeRun(i);
String[] subText = text.split(" ");
int subTextIndex = 0;
while (subTextIndex < subText.length) {
String word = subText[subTextIndex];
if (hyperlinkMap.keySet().contains(word) && tmpText.equalsIgnoreCase(text)) {
//p.createHyperlinkRun(word).setText(word, 0);
p.insertNewHyperlinkRun(subTextIndex + i, word).setText(word, i);
//p.insertNewRun(subTextIndex + i + 1).setText(" ", 0);
}
underLineAndHyperLinkWordsforParagraph(p, word, subTextIndex + i,hyperlinkMap,singleWordMap,sbcFormatDocumentObj);
subTextIndex++;
}
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我无法跟踪您对 XWPFParagraph.insertNewHyperlinkRun 的使用,尤其是
subTextIndex
的用途。为什么使用 i
(段落中文本的位置)作为 XWPFHyperlinkRun.setText
中的文本位置?
替换 Word 文档中的文本串时的主要问题是完全正确的文本串。 Microsoft Word 会出于任意原因在文本串中拆分文本。因此,只有当要替换的文本运行被明确格式化为真正属于它自己的文本运行时,这种方法才有效。只有给出了这一点,才能找到要替换的文本。
但是创建超链接不能仅通过替换找到的某些内容来完成
XWPFRun
。超链接围绕文本运行。所以前一个XWPFRun
必须被新的XWPFHyperlinkRun
包围。为此,可以在找到的 XWPFHyperlinkRun
之前的段落中插入 XWPFRun
,将找到的 XWPFRun
中的文本和主要格式复制到新的 XWPFHyperlinkRun
,然后删除找到的 XWPFRun
。
下面的完整示例就是这样做的。它用超链接包围找到的文本并替换文本。它基于 Word 文档,其中占位符“helloURL”显然被格式化为它自己的文本运行。
source.docx
:
代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import java.util.List;
import java.util.ArrayList;
public class WordXWPFRunToXWPFHyperlinkRun {
static List<XWPFParagraph> paragraphs = null;
static void findParagraphsContainigText(IBody body, String text) {
for (IBodyElement bodyElement : body.getBodyElements()) {
if (bodyElement instanceof XWPFParagraph) {
XWPFParagraph paragraph = (XWPFParagraph)bodyElement;
if (paragraph.getText().contains(text)) {
paragraphs.add(paragraph);
}
} else if (bodyElement instanceof XWPFTable) {
XWPFTable table = (XWPFTable)bodyElement;
for (XWPFTableRow tableRow : table.getRows()) {
for (ICell tableICell : tableRow.getTableICells()) {
if (tableICell instanceof XWPFTableCell) {
XWPFTableCell tableCell = (XWPFTableCell)tableICell;
findParagraphsContainigText(tableCell, text);
}
}
}
}
}
}
public static void main(String[] args) throws Exception {
try (
XWPFDocument document = new XWPFDocument(new FileInputStream("./source.docx"));
FileOutputStream out = new FileOutputStream("./result.docx") ) {
String key = "helloURL";
String replacement = "stackoverflow";
String uri = "https://stackoverflow.com";
paragraphs = new ArrayList<XWPFParagraph>();
findParagraphsContainigText(document, key);
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (int i = 0; i < runs.size(); i++ ) {
XWPFRun run = runs.get(i);
String text = run.getText(0);
if (text.contains(key)) {
text = text.replace(key, replacement);
//insert hyperlink run before run
XWPFHyperlinkRun hyperlinkRun = paragraph.insertNewHyperlinkRun(i, uri);
//set CTR of hyperlink run the same as run
hyperlinkRun.getCTHyperlink().setRArray(0, run.getCTR());
//set textrun's text
hyperlinkRun.setText(text, 0);
//set hyperlinkk formats
hyperlinkRun.setColor("0000FF");
hyperlinkRun.setUnderline(UnderlinePatterns.SINGLE);
//remove old run
paragraph.removeRun(i+1);
}
}
}
document.write(out);
}
}
}
result.docx
: