web-dev-qa-db-fra.com

Remplacement des variables dans un modèle de document Word par java

Je souhaite charger un modèle de document Word pour y ajouter du contenu et l'enregistrer en tant que nouveau document. Je travaille sur un fichier .doc.

Après une longue recherche, je n'ai trouvé que des solutions pour docx:

http://www.smartjava.org/content/create-complex-Word-docx-documents-programately-docx4j

http://www.sambhashanam.com/mail-merge-in-Java-for-Microsoft-Word-document-part-i/

Je veux donc remplacer toute variable écrite dans ce format: $VAR par sa valeur. Puis-je le faire avec vélocité ou Apache-poi, quelle est la meilleure solution pour cela. Toute aide serait appréciée.

15
Amira

Oui, vous pouvez le faire en utilisant Apache-POI. Vos noms de variables doivent être uniques. Voir le code suivant

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

Récemment, j'ai dû résoudre le même problème mais avec un document . Docx . Et essayer l'approche ci-dessus a entraîné l'erreur suivante (comme indiqué dans ce post ):

org.Apache.poi.poifs.filesystem.OfficeXmlFileException: les données fournies semblent être au format XML Office 2007+. Vous appelez la partie du POI qui traite des documents Office OLE2. Vous devez appeler une autre partie du POI pour traiter ces données (par exemple XSSF au lieu de HSSF)

Enfin, j'ai dû changer le code comme suit (dans mon cas, le fichier .docx est à l'intérieur du dossier de ressources):

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. J'ai dû supprimer le $ car dans .docx sont gérés des runs séparés donc j'ai dû opter pour l'approche d'un nom var unique. J'avais besoin des dépendances Apache POI suivantes:

<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
Valerio Emanuele