Replacing variables in a word document template with java

前端 未结 3 1630
深忆病人
深忆病人 2020-12-12 22:53

I want to load a template word document to add content to and save as new document. I\'m working on .doc file.

After a long research I only found solutions for docx

相关标签:
3条回答
  • 2020-12-12 23:38

    Recently I had to solve the same problem but with a .docx document. And trying the approach above resulted as the following error (As reported in this post):

    org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)

    Finally, I had to change the code as follow (in my case the .docx file is inside the resource folder):

    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.URISyntaxException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    
    public class XWPFTest {
    
        public static void main(String[] args) throws URISyntaxException, IOException {
            String resourcePath = "template.docx";
            Path templatePath = Paths.get(XWPFTest.class.getClassLoader().getResource(resourcePath).toURI());
            XWPFDocument doc =  new XWPFDocument(Files.newInputStream(templatePath));
            doc = replaceTextFor(doc, "UNIQUE_VAR", "MyValue1");
            saveWord("C:\\document.docx", doc);
        }
    
        private static XWPFDocument replaceTextFor(XWPFDocument doc, String findText, String replaceText){
            doc.getParagraphs().forEach(p ->{
                p.getRuns().forEach(run -> {
                    String text = run.text();
                    if(text.contains(findText)) {
                        run.setText(text.replace(findText, replaceText), 0);
                    } 
                });
            });
    
            return doc;
        }
    
        private static void saveWord(String filePath, XWPFDocument doc) throws FileNotFoundException, IOException{
            FileOutputStream out = null;
            try{
                out = new FileOutputStream(filePath);
                doc.write(out);
            }
            catch(Exception e) {
                e.printStackTrace();
            }
            finally{
                out.close();
            }
        }
    
    }
    

    P.S. I had to remove the $ because in .docx are managed are separate runs so I had to opt for the approach of a unique var name. I needed the following Apache POI dependencies:

    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.17</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.17</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-scratchpad</artifactId>
        <version>3.17</version>
    </dependency>
    
    0 讨论(0)
  • Vikrant,

    The code Snippet is given above and in order to work, we need jar mentioned above. Along with that Jar, use/download poi-3.5-FINAL.jar as well.

    Hope this will answer your question.

    0 讨论(0)
  • 2020-12-12 23:48

    Yes, you can do it using Apache-POI. Your variable names must be unique. See the following code

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import org.apache.poi.hwpf.HWPFDocument;
    import org.apache.poi.hwpf.usermodel.CharacterRun;
    import org.apache.poi.hwpf.usermodel.Paragraph;
    import org.apache.poi.hwpf.usermodel.Range;
    import org.apache.poi.hwpf.usermodel.Section;
    import org.apache.poi.poifs.filesystem.POIFSFileSystem;
    
    public class HWPFTest {
        public static void main(String[] args){
            String filePath = "F:\\Sample.doc";
            POIFSFileSystem fs = null;        
            try {            
                fs = new POIFSFileSystem(new FileInputStream(filePath));            
                HWPFDocument doc = new HWPFDocument(fs);
                doc = replaceText(doc, "$VAR", "MyValue1");
                saveWord(filePath, doc);
            }
            catch(FileNotFoundException e){
                e.printStackTrace();
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }
    
        private static HWPFDocument replaceText(HWPFDocument doc, String findText, String replaceText){
            Range r1 = doc.getRange(); 
    
            for (int i = 0; i < r1.numSections(); ++i ) { 
                Section s = r1.getSection(i); 
                for (int x = 0; x < s.numParagraphs(); x++) { 
                    Paragraph p = s.getParagraph(x); 
                    for (int z = 0; z < p.numCharacterRuns(); z++) { 
                        CharacterRun run = p.getCharacterRun(z); 
                        String text = run.text();
                        if(text.contains(findText)) {
                            run.replaceText(findText, replaceText);
                        } 
                    }
                }
            } 
            return doc;
        }
    
        private static void saveWord(String filePath, HWPFDocument doc) throws FileNotFoundException, IOException{
            FileOutputStream out = null;
            try{
                out = new FileOutputStream(filePath);
                doc.write(out);
            }
            finally{
                out.close();
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题