一、前言
最近项目遇到个需求,在模板中填充数据,刚开始是用smartBi报表进行填充,输出参数都是必录,无法满足需求。在网上查了很多资料,有些需要把文档转成xml格式修改里面内容,IDEA里面修改要替换的占位符的位置等方式,都不满足需求。
二、JAR包
因为项目要做兼容,我这使用的是3.15的版本,不需要兼容可以选择4.0+版本
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.15</version>
</dependency>
三、实现代码
package com.fortunes.javamg.common.utils.poi;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @version V1.0
* @Description:Word模板数据填充
* @Date: 2022/11/16 17:47
*/
public class ReplaceWord {
/***
* @Description :替换段落文本
* @param document docx解析对象
* @param textMap 需要替换的信息集合
* @return void
* @Date 2022/11/17 17:22
*/
public static void changeText(XWPFDocument document, Map<String, Object> textMap) {
// 获取段落集合
Iterator<XWPFParagraph> iterator = document.getParagraphsIterator();
XWPFParagraph paragraph = null;
while (iterator.hasNext()) {
paragraph = iterator.next();
// 判断此段落是否需要替换
if (checkText(paragraph.getText())) {
replaceValue(paragraph, textMap);
}
}
}
/***
* @Description :检查文本中是否包含指定的字符(此处为“$”)
* @param text
* @return boolean
* @Date 2022/11/17 17:22
*/
public static boolean checkText(String text) {
boolean check = false;
if (text.contains("$")) {
check = true;
}
return check;
}
/**
* 替换图片
*
* @param document
* @param picData
* @throws Exception
*/
public static void changePic(XWPFDocument document, Map<String, Object> picData) throws Exception {
// 获取段落集合
Iterator<XWPFParagraph> iterator = document.getParagraphsIterator();
XWPFParagraph paragraph;
while (iterator.hasNext()) {
paragraph = iterator.next();
// 判断此段落是否需要替换
String text = paragraph.getText();
if (checkText(text)) {
replacePicValue(paragraph, picData);
}
}
}
/***
* @Description :替换表格内的文字
* @param document
* @param data
* @return void
* @Date 2022/11/18 11:29
*/
public static void changeTableText(XWPFDocument document, Map<String, Object> data) {
// 获取文件的表格
Iterator<XWPFTable> tableList = document.getTablesIterator();
XWPFTable table;
List<XWPFTableRow> rows;
List<XWPFTableCell> cells;
// 循环所有需要进行替换的文本,进行替换
while (tableList.hasNext()) {
table = tableList.next();
if (checkText(table.getText())) {
rows = table.getRows();
// 遍历表格,并替换模板
for (XWPFTableRow row : rows) {
cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
// 判断单元格是否需要替换
if (checkText(cell.getText())) {
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
replaceValue(paragraph, data);
}
}
}
}
}
}
}
/***
* @Description :替换表格内图片
* @param document
* @param picData
* @return void
* @Date 2022/11/18 11:29
*/
public static void changeTablePic(XWPFDocument document, Map<String, Object> picData) throws Exception {
// 获取文件的表格
Iterator<XWPFTable> tableList = document.getTablesIterator();
XWPFTable table;
List<XWPFTableRow> rows;
List<XWPFTableCell> cells;
// 循环所有需要进行替换的文本,进行替换
while (tableList.hasNext()) {
table = tableList.next();
if (checkText(table.getText())) {
rows = table.getRows();
// 遍历表格,并替换模板
for (XWPFTableRow row : rows) {
cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
// 判断单元格是否需要替换
if (checkText(cell.getText())) {
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
replacePicValue(paragraph, picData);
}
}
}
}
}
}
}
/***
* @Description :替换内容
* @param paragraph
* @param textMap
* @return void
* @Date 2022/11/18 11:33
*/
public static void replaceValue(XWPFParagraph paragraph, Map<String, Object> textMap) {
XWPFRun run, nextRun;
String runsText;
List<XWPFRun> runs = paragraph.getRuns();
for (int i = 0; i < runs.size(); i++) {
run = runs.get(i);
runsText = run.getText(0);
if (runsText.contains("${") || (runsText.contains("$") && runs.get(i + 1).getText(0).substring(0, 1).equals("{"))) {
while (!runsText.contains("}")) {
nextRun = runs.get(i + 1);
runsText = runsText + nextRun.getText(0);
//删除该节点下的数据
paragraph.removeRun(i + 1);
}
Object value = changeValue(runsText, textMap);
//判断key在Map中是否存在
if (textMap.containsKey(runsText)) {
run.setText(value.toString(), 0);
} else {
//如果匹配不到,则不修改
run.setText(runsText, 0);
}
}
}
}
/***
* @Description :替换图片内容
* @param paragraph
* @param picData
* @return void
* @Date 2022/11/18 11:33
*/
public static void replacePicValue(XWPFParagraph paragraph, Map<String, Object> picData) throws Exception {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
Object value = changeValue(run.toString(), picData);
if (picData.containsKey(run.toString())) {
//清空内容
run.setText("", 0);
FileInputStream is = new FileInputStream((String) value);
//图片宽度、高度
int width = Units.toEMU(100), height = Units.toEMU(100);
//添加图片信息,段落高度需要在模板中自行调整
run.addPicture(is, XWPFDocument.PICTURE_TYPE_PNG, (String) value, width, height);
}
}
}
/***
* @Description :匹配参数
* @param value
* @param textMap
* @return java.lang.Object
* @Date 2022/11/18 11:33
*/
public static Object changeValue(String value, Map<String, Object> textMap) {
Object valu = "";
for (Map.Entry<String, Object> textSet : textMap.entrySet()) {
// 匹配模板与替换值 格式${key}
String key = textSet.getKey();
if (value.contains(key)) {
valu = textSet.getValue();
}
}
return valu;
}
}
四、测试代码
public static void main(String[] args) throws Exception {
Map<String, Object> data = new HashMap<>();
Map<String, Object> picData = new HashMap<>();
data.put("${aab999}", "123456789");
data.put("${aac003}", "刘毅");
data.put("${aac147}", "43102119001212109X");
data.put("${aae004}", "刘毅");
data.put("${aae005}", "13800000000");
data.put("${aae013}", "");
data.put("${aae123}", "刘毅");
data.put("${aae123_1}", "");
data.put("${aae123_2}", "");
data.put("${aae124}", "刘小毅");
data.put("${aae124_1}", "");
data.put("${aae124_2}", "");
picData.put("${aac013}", "C:\\Users\\Liu\\Pictures\\26ed64f74a659d46d6db0fd979bc0142.jpeg");
operateWord(data, picData);
}
public static void operateWord(Map<String, Object> data, Map<String, Object> picData){
try {
FileInputStream is = new FileInputStream("D:\\test.docx");
XWPFDocument document = new XWPFDocument(is);
if (data.size() > 0) {
// 替换掉表格之外的文本(仅限文本)
ReplaceWord.changeText(document, data);
// 替换表格内的文本对象
ReplaceWord.changeTableText(document, data);
}
if (picData.size() > 0) {
// 替换内容图片
ReplaceWord.changePic(document, picData);
// 替换表格内的图片对象
ReplaceWord.changeTablePic(document, picData);
}
FileOutputStream out = new FileOutputStream("D:\\test2" + ".docx");
document.write(out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}