Replacing a text in Apache POI XWPF not working

后端 未结 5 1813
Happy的楠姐
Happy的楠姐 2020-12-11 09:20

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

相关标签:
5条回答
  • 2020-12-11 09:53

    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;
      }
    
    0 讨论(0)
  • 2020-12-11 10:00

    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));
        }
    }
    
    0 讨论(0)
  • 2020-12-11 10:00

    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();
             }
        }
    }
    
    0 讨论(0)
  • 2020-12-11 10:04

    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));
    
    0 讨论(0)
  • 2020-12-11 10:16

    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);
                }
         }
    
     }
    
    0 讨论(0)
提交回复
热议问题