简体   繁体   English

替换 Apache POI XWPF 中的文本不起作用

[英]Replacing a text in Apache POI XWPF not working

I'm currently trying to work on the code mentioned on a previous post called Replacing a text in Apache POI XWPF .我目前正在尝试处理上一篇名为Replacing a text in Apache POI XWPF 的帖子中提到的代码。

I have tried the below and it works but I don't know if I am missing anything.我已经尝试了下面的方法并且它有效,但我不知道我是否遗漏了什么。 When I run the code the text is not replaced but added onto the end of what was searched.当我运行代码时,文本不会被替换,而是添加到搜索内容的末尾。 For example I have created a basic word document and entered the text "test".例如,我创建了一个基本的 word 文档并输入了文本“test”。 In the below code when I run it I eventually get the new document with the text "testDOG".在下面的代码中,当我运行它时,我最终得到了带有文本“testDOG”的新文档。

I have had to change the original code from String text = r.getText(0) to String text = r.toString() because I kept getting a NullError while running the code.我不得不将原始代码从 String text = r.getText(0) 更改为 String text = r.toString() 因为我在运行代码时不断收到 NullError 。

import java.io.*;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;


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(OPCPackage.open(filepath));
    for (XWPFParagraph p : doc.getParagraphs()){
        for (XWPFRun r : p.getRuns()){
            String text = r.toString();
            if(text.contains("test")) {
                text = text.replace("test", "DOG");
                r.setText(text);
            }
        }
    }
   doc.write(new FileOutputStream(outpath));
}

EDIT: Thanks for your help everyone.编辑:感谢大家的帮助。 I browsed around and found a solution on Replace table column value in Apache POI我浏览了一下,找到了一个关于在 Apache POI 中替换表列值的解决方案

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));
    }
}

just change text for every run in your paragraph, and then save the file.只需更改段落中每次运行的文本,然后保存文件。 this code worked for mi此代码适用于 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));

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();
         }
    }
}

Worth noticing that, run.getPosition() returns -1 most of the cases.值得注意的是, run.getPosition()在大多数情况下返回 -1。 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.但是,从技术上讲,它可以有任意数量的textPositions ,我也遇到过这种情况。 So, the best way is to getCTR () for run and terate through each the run for count of textPositions .因此,最好的方法是getCTR ()进行 run 并遍历每个 run 以获取textPositions计数。 Number of textPositions are equal to ctrRun.sizeOfTArray() textPositions数量等于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);
            }
     }

 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM