Java使用POI替换Word模板并输出

需求分析:将平台上已录入的数据导出Word格式并提供下载。思路:先在Word中做好文件模板,留对应格式的文字直接替换为需要展示的数据即可

一、导入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-excelant -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>3.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-examples -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-examples</artifactId>
<version>3.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.xmlbeans/xmlbeans -->
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.6.0</version>
</dependency>

二、导入WordUtil工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import org.apache.poi.xwpf.usermodel.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author : MrMao14
* @version : 1.0
* @program : web
* @description : 该工具类用于将Word中的文字进行指定替换
* @create : 2021/12/16 11:08
**/
public class WordUtil {
/**
* 替换所有段落中的标记
*
* @param xwpfParagraphList
* @param params
*/
public static void replaceInAllParagraphs(List<XWPFParagraph> xwpfParagraphList, Map<String, String> params) {
for (XWPFParagraph paragraph : xwpfParagraphList) {
if (paragraph.getText() == null paragraph.getText().equals("")) {
continue;
}
for (String key : params.keySet()) {
if (paragraph.getText().contains(key)) {
replaceInParagraph(paragraph, key, params.get(key));
}
}
}
}

/**
* 替换段落中的字符串
*
* @param xwpfParagraph
* @param oldString
* @param newString
*/
public static void replaceInParagraph(XWPFParagraph xwpfParagraph, String oldString, String newString) {
Map<String, Integer> pos_map = findSubRunPosInParagraph(xwpfParagraph, oldString);
if (pos_map != null) {
List<XWPFRun> runs = xwpfParagraph.getRuns();
XWPFRun modelRun = runs.get(pos_map.get("end_pos"));
XWPFRun xwpfRun = xwpfParagraph.insertNewRun(pos_map.get("end_pos") + 1);
xwpfRun.setText(newString);
if (modelRun.getFontSize() != -1)
//默认值是五号字体,但五号字体getFontSize()时,返回-1
{
xwpfRun.setFontSize(modelRun.getFontSize());
}
xwpfRun.setFontFamily(modelRun.getFontFamily());
for (int i = pos_map.get("end_pos"); i >= pos_map.get("start_pos"); i--) {
xwpfParagraph.removeRun(i);
}
}
}

/**
* 找到段落中子串的起始XWPFRun下标和终止XWPFRun的下标
*
* @param xwpfParagraph
* @param substring
* @return
*/
public static Map<String, Integer> findSubRunPosInParagraph(XWPFParagraph xwpfParagraph, String substring) {
List<XWPFRun> runs = xwpfParagraph.getRuns();
int start_pos = 0;
int end_pos = 0;
String subtemp = "";
for (int i = 0; i < runs.size(); i++) {
subtemp = "";
start_pos = i;
for (int j = i; j < runs.size(); j++) {
if (runs.get(j).getText(runs.get(j).getTextPosition()) == null) {
continue;
}
subtemp += runs.get(j).getText(runs.get(j).getTextPosition());
if (subtemp.equals(substring)) {
end_pos = j;
Map<String, Integer> map = new HashMap<>();
map.put("start_pos", start_pos);
map.put("end_pos", end_pos);
return map;
}
}
}
return null;
}

/**
* 替换所有的表格
*
* @param xwpfTableList
* @param params
*/
public static void replaceInTables(List<XWPFTable> xwpfTableList, Map<String, String> params) {
for (XWPFTable table : xwpfTableList) {
replaceInTable(table, params);
}
}

/**
* 替换一个表格中的所有行
*
* @param xwpfTable
* @param params
*/
public static void replaceInTable(XWPFTable xwpfTable, Map<String, String> params) {
List<XWPFTableRow> rows = xwpfTable.getRows();
replaceInRows(rows, params);
}

/**
* 替换表格中的一行
*
* @param rows
* @param params
*/
public static void replaceInRows(List<XWPFTableRow> rows, Map<String, String> params) {
for (int i = 0; i < rows.size(); i++) {
XWPFTableRow row = rows.get(i);
replaceInCells(row.getTableCells(), params);
}
}

/**
* 替换一行中所有的单元格
*
* @param xwpfTableCellList
* @param params
*/
public static void replaceInCells(List<XWPFTableCell> xwpfTableCellList, Map<String, String> params) {
for (XWPFTableCell cell : xwpfTableCellList) {
replaceInCell(cell, params);

}
}

/**
* 替换表格中每一行中的每一个单元格中的所有段落
*
* @param cell
* @param params
*/
public static void replaceInCell(XWPFTableCell cell, Map<String, String> params) {
List<XWPFParagraph> cellParagraphs = cell.getParagraphs();
replaceInAllParagraphs(cellParagraphs, params);
}
}

三、功能测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import com.mrmao.modules.utils.WordUtil;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFTable;

import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* @author : MrMao14
* @version : 1.0
* @program : web
* @description : WordUtils方法测试类
* @create : 2021/12/16 11:12
**/
public class TestMethod1 {
public static void main(String[] args) {
Map<String, String> params = new HashMap<>(50);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
params.put("${name}", "MrMao14");
params.put("${age}", "18");
params.put("${nowDate}", simpleDateFormat.format(new Date()));
String filepath = "C:\\test.docx";
String destpath = "C:\\test1.docx";
try {
//读取模板文件
OPCPackage pack = POIXMLDocument.openPackage(filepath);
//创建word文件并将模板导入
XWPFDocument document = new XWPFDocument(pack);
//对段落中的标记进行替换
List<XWPFParagraph> parasList = document.getParagraphs();
WordUtil.replaceInAllParagraphs(parasList, params);
//表格标记替换
List<XWPFTable> tables = document.getTables();
WordUtil.replaceInTables(tables, params);
FileOutputStream outStream = new FileOutputStream(destpath);
document.write(outStream);
outStream.flush();
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}