用java替换word文档模板中的变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22615594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Replacing variables in a word document template with java
提问by Amira
I want to load a template word document to add content to and save as new document. I'm working on .doc file.
我想加载一个模板 word 文档来添加内容并另存为新文档。我正在处理 .doc 文件。
After a long research I only found solutions for docx :
经过长时间的研究,我只找到了 docx 的解决方案:
http://www.smartjava.org/content/create-complex-word-docx-documents-programatically-docx4j
http://www.smartjava.org/content/create-complex-word-docx-documents-programatically-docx4j
http://www.sambhashanam.com/mail-merge-in-java-for-microsoft-word-document-part-i/
http://www.sambhashanam.com/mail-merge-in-java-for-microsoft-word-document-part-i/
So I want to replace any variable written in this format: $VAR
by its value.
Can I do it with velocity or Apache-poi, what is the best solution for it.
Any help will be appreciated.
所以我想替换以这种格式编写的任何变量:$VAR
通过它的值。我可以用速度或 Apache-poi 来做,什么是最好的解决方案。任何帮助将不胜感激。
采纳答案by Liquidpie
Yes, you can do it using Apache-POI. Your variable names must be unique. See the following code
是的,您可以使用 Apache-POI 来完成。您的变量名称必须是唯一的。看下面的代码
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();
}
}
}
回答by SandeepManda
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.
上面给出了代码片段,为了工作,我们需要上面提到的 jar。与该 Jar 一起使用/下载 poi-3.5-FINAL.jar。
Hope this will answer your question.
希望这能回答你的问题。
回答by Valerio Emanuele
Recently I had to solve the same problem but with a .docxdocument. And trying the approach above resulted as the following error (As reported in this post):
最近我不得不用.docx文档解决同样的问题。并试图上述结果如下面的错误方式(如该报道后):
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)
org.apache.poi.poifs.filesystem.OfficeXmlFileException:提供的数据似乎在 Office 2007+ XML 中。您正在调用处理 OLE2 Office 文档的 POI 部分。您需要调用 POI 的不同部分来处理此数据(例如 XSSF 而不是 HSSF)
Finally, I had to change the code as follow (in my case the .docx file is inside the resource folder):
最后,我不得不按如下方式更改代码(在我的情况下,.docx 文件位于资源文件夹中):
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:
PS 我不得不删除 $ 因为在 .docx 中管理是单独的运行,所以我不得不选择唯一 var 名称的方法。我需要以下 Apache POI 依赖项:
<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>