I\'m currently trying to work on the code mentioned on a previous post called Replacing a text in Apache POI XWPF.
I have tried the below and it works but I don\'t k
This method replace search Strings in paragraphs and is able to work with Strings spanning over more than one Run.
private long replaceInParagraphs(Map<String, String> replacements, List<XWPFParagraph> xwpfParagraphs) {
long count = 0;
for (XWPFParagraph paragraph : xwpfParagraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (Map.Entry<String, String> replPair : replacements.entrySet()) {
String find = replPair.getKey();
String repl = replPair.getValue();
TextSegement found = paragraph.searchText(find, new PositionInParagraph());
if ( found != null ) {
count++;
if ( found.getBeginRun() == found.getEndRun() ) {
// whole search string is in one Run
XWPFRun run = runs.get(found.getBeginRun());
String runText = run.getText(run.getTextPosition());
String replaced = runText.replace(find, repl);
run.setText(replaced, 0);
} else {
// The search string spans over more than one Run
// Put the Strings together
StringBuilder b = new StringBuilder();
for (int runPos = found.getBeginRun(); runPos <= found.getEndRun(); runPos++) {
XWPFRun run = runs.get(runPos);
b.append(run.getText(run.getTextPosition()));
}
String connectedRuns = b.toString();
String replaced = connectedRuns.replace(find, repl);
// The first Run receives the replaced String of all connected Runs
XWPFRun partOne = runs.get(found.getBeginRun());
partOne.setText(replaced, 0);
// Removing the text in the other Runs.
for (int runPos = found.getBeginRun()+1; runPos <= found.getEndRun(); runPos++) {
XWPFRun partNext = runs.get(runPos);
partNext.setText("", 0);
}
}
}
}
}
return count;
}
Your logic is not quite right. You need to collate all the text in the runs first and then do the replace. You also need to remove all runs for the paragraph and add a new single run if a match on "test" is found.
Try this instead:
public class testPOI {
public static void main(String[] args) throws Exception{
String filepath = "F:\\MASTER_DOC.docx";
String outpath = "F:\\Test.docx";
XWPFDocument doc = new XWPFDocument(new FileInputStream(filepath));
for (XWPFParagraph p : doc.getParagraphs()){
int numberOfRuns = p.getRuns().size();
// Collate text of all runs
StringBuilder sb = new StringBuilder();
for (XWPFRun r : p.getRuns()){
int pos = r.getTextPosition();
if(r.getText(pos) != null) {
sb.append(r.getText(pos));
}
}
// Continue if there is text and contains "test"
if(sb.length() > 0 && sb.toString().contains("test")) {
// Remove all existing runs
for(int i = 0; i < numberOfRuns; i++) {
p.removeRun(i);
}
String text = sb.toString().replace("test", "DOG");
// Add new run with updated text
XWPFRun run = p.createRun();
run.setText(text);
p.addRun(run);
}
}
doc.write(new FileOutputStream(outpath));
}
}
Don't waste your time when you can keep things simple:
//download from http://www.independentsoft.de/jword/evaluation.html
import com.independentsoft.office.word.WordDocument;
public class JWORD {
public static void main(String[] args) {
String filepath = "C:\\Users\\setrivayne\\Downloads\\TEST.docx";
String outpath = "C:\\Users\\setrivayne\\Downloads\\TEST.docx";
try {
WordDocument doc = new WordDocument(filepath);
doc.replace("FIRST NAME", "first name");
doc.replace("MIDDLE NAME", "middle name");
doc.replace("LAST NAME", "last name");
doc.save(outpath, true);
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
just change text for every run in your paragraph, and then save the file. this code worked for mi
XWPFDocument doc = new XWPFDocument(new FileInputStream(filepath));
for (XWPFParagraph p : doc.getParagraphs()) {
StringBuilder sb = new StringBuilder();
for (XWPFRun r : p.getRuns()) {
String text = r.getText(0);
if (text != null && text.contains("variable1")) {
text = text.replace("variable1", "valeur1");
r.setText(text, 0);
}
if (text != null && text.contains("variable2")) {
text = text.replace("variable2", "valeur2");
r.setText(text, 0);
}
if (text != null && text.contains("variable3")) {
text = text.replace("variable3", "valeur3");
r.setText(text, 0);
}
}
}
doc.write(new FileOutputStream(outpath));
Worth noticing that, run.getPosition()
returns -1 most of the cases. But it does not effect when there is only one text postion per a run. But, technically it can have any number of textPositions
and I've experienced such cases. So, the best way is to getCTR ()
for run and terate through each the run for count of textPositions
. Number of textPositions
are equal to ctrRun.sizeOfTArray()
A sample code
for (XWPFRun run : p.getRuns()){
CTR ctrRun = run.getCTR();
int sizeOfCtr = ctrRun.sizeOfTArray();
for(int textPosition=0; textPosition<sizeOfCtr){
String text = run.getText(textPosition);
if(text.contains("test")) {
text = text.replace("test", "DOG");
r.setText(text,textPosition);
}
}
}