准备工作:
创建一个需要替换的docx文件,放到某个项目路径下,确保程序可以拿到这个文件
引入pom文件
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<!--word工具类-->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.9.1</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
<!--html渲染插件-->
<dependency>
<groupId>io.github.draco1023</groupId>
<artifactId>poi-tl-ext</artifactId>
<version>0.3.3</version>
<exclusions>
<exclusion>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--样式依赖-->
<dependency>
<groupId>org.w3c.css</groupId>
<artifactId>sac</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>net.sourceforge.cssparser</groupId>
<artifactId>cssparser</artifactId>
<version>0.9.29</version>
</dependency>
工具类
public class ReplaceUtils {
public static String replace(String templatePath, String outputPath, Map<String, String> replacements) throws IOException {
// 读取模板文件
FileInputStream fis = new FileInputStream(templatePath);
XWPFDocument document = new XWPFDocument(fis);
fis.close();
// 替换文本
for (XWPFParagraph paragraph : document.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
String text = run.getText(0);
if (text != null) {
for (Map.Entry<String, String> entry : replacements.entrySet()) {
String placeholder = "${" + entry.getKey() + "}";
if (text.contains(placeholder)) {
text = text.replace(placeholder, entry.getValue());
run.setText(text, 0);
}
}
}
}
}
// 导出新文件
FileOutputStream fos = new FileOutputStream(outputPath);
document.write(fos);
fos.close();
return outputPath;
}
}
使用事例
// 定义要替换的文本
Map<String, String> replacements = new HashMap<>();
replacements.put("documentTitle", 测试");
replacements.put("documentSymbol", "测试");
replacements.put("year", "2023");
replacements.put("serialNumber", "666");
replacements.put("contentTitle", "测试");
replacements.put("mainText", "测试");
replacements.put("inscription", "测试");
replacements.put("time", "2023年8月29日");
// 替换文本并输出到新文件
String templatePath = "/path/to/template.docx";
String outputPath = "/path/to/output.docx";
ReplaceUtils.replace(templatePath, outputPath, replacements);
大致思路,创建一个实体类,实体类字段对应文件中需要替换的文本去占位,然后只需要拿着实体类参数调用工具类就可以了
续:
这样实际会出现一个问题,当${mainText}为富文本时,则会出现导出文件内容带有富文本标签例如<p></p><br></br>此问题可以做一个处理,最终代码:
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.sdecloud.documentManagement.entity.TDocumentContent;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.ddr.poi.html.HtmlRenderPolicy;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
public class ReplaceUtils {
public static String doc(TDocumentContent a) throws IOException {
// 读取模板文件
String projectPath = System.getProperty("user.dir");
File file = new File(projectPath + "/docTest.docx");
FileInputStream fis = new FileInputStream(file);
XWPFDocument document = new XWPFDocument(fis);
fis.close();
// 替换文本
for (XWPFParagraph paragraph : document.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
String text = run.getText(0);
if (text != null) {
if (text.contains("${documentTitle}")) {
text = text.replace("${documentTitle}", a.getDocumentTitle());
run.setText(text, 0);
}
if (text.contains("${documentSymbol}")) {
text = text.replace("${documentSymbol}", a.getDocumentSymbol());
run.setText(text, 0);
}
if (text.contains("${year}")) {
text = text.replace("${year}", a.getYear().toString());
run.setText(text, 0);
}
if (text.contains("${serialNumber}")) {
text = text.replace("${serialNumber}", a.getSerialNumber().toString());
run.setText(text, 0);
}
if (text.contains("${contentTitle}")) {
text = text.replace("${contentTitle}", a.getContentTitle());
run.setText(text, 0);
}
// if (text.contains("${mainText}")) {
// text = text.replace("${mainText}", a.getMainText());
// run.setText(text, 0);
// }
if (text.contains("${inscription}")) {
text = text.replace("${inscription}", a.getInscription());
run.setText(text, 0);
}
if (text.contains("${time}")) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
String dateString = sdf.format(a.getTime());
text = text.replace("${time}", dateString);
run.setText(text, 0);
}
}
}
}
// 导出新文件
//生成uuid作为文件名称
String docNameTemp = a.getDocumentTitle()+"_temp" + ".docx";
String outputPathTemp = projectPath +"/files/temp/"+ docNameTemp;
FileOutputStream fos = new FileOutputStream(outputPathTemp);
document.write(fos);
fos.close();
return dealRichText(a,outputPathTemp);
}
/**
* @Description: 处理富文本数据
*/
private static String dealRichText(TDocumentContent a,String outputPathTemp){
StringBuffer sbf = new StringBuffer();
sbf.append("<html><body>");
sbf.append(a.getMainText());
sbf.append("</body></html");
Map map = new HashMap<>(1);
map.put("mainText",sbf.toString());
// html渲染插件
HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
// 第一个案例
Configure configure = Configure.builder()
.bind("mainText", htmlRenderPolicy)
.build();
XWPFTemplate template = XWPFTemplate.compile(outputPathTemp, configure).render(map);
// 读取模板文件
String projectPath = System.getProperty("user.dir");
String docName = a.getDocumentTitle() + ".docx";
String outputPath = projectPath +"/files/temp/"+ docName;
try {
template.writeToFile(outputPath);
template.close();
} catch (IOException e) {
e.printStackTrace();
}
return docName;
}
}