Java基于Spire实现的word文档制作

Java基于Spire实现的word文档制作(提升10倍效率)

功能概述:

定义一个word模板文件,通过Java程序对模板填充数据,生成出新的word文档。

1、创建maven项目

推荐使用idea

2、添加pom依赖配置

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>api</artifactId>
<groupId>com.xxxx.server</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>word-api</artifactId>
<packaging>pom</packaging>
<name>word-api</name>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>5.2.0</version>
</dependency>
<!--<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>5.4.2</version>
</dependency>-->
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.pdf.free</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
</project>

3、接口类开发

生成文档的接口makeWordNimble是一个固定参数的通用接口。

参数的分类为:

​ \1. 基础参数 2.文档内部文本类数据 3.文档内部图片类数据

文档内部数据使用的是Map类型字段接收前端传来的参数,程序根据Map参数的key来定位替换doc模板里的占位符。

图片数据是通过另一个图片上传接口先上传图片,然后生成文档接口里只需要传递上传到服务器上的图片名称。

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
package com.hxkj.server.controller;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.hxkj.server.common.core.result.Result;
import com.hxkj.server.common.core.utils.TddRedisUtil;
import com.hxkj.server.entity.GeneraterWordData;
import com.hxkj.server.service.GeneraterWordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* 要尊重编程
*
* @Author: 庞欢腾
* @Date: 2022/5/13
* @Description: data-server
*/
@Api(tags = "生成word文档接口")
@RestController
@RequestMapping("/generater-word")
public class GeneraterWordController {

GeneraterWordService generaterWordService;

@Autowired
public void setGeneraterWordService(GeneraterWordService generaterWordService) {
this.generaterWordService = generaterWordService;
}

@ApiOperation(value = "生成word文档接口", notes = "生成word文档接口", response = Result.class, httpMethod = "POST")
@ApiImplicitParams({
@ApiImplicitParam(name = "txt_data", value = "文本数据", paramType = "query", dataType = "Map", required = true),
@ApiImplicitParam(name = "image_data", value = "图像数据", paramType = "query", dataType = "Map", required = true),
@ApiImplicitParam(name = "inTemplatePathName", value = "输入模板地址名称", paramType = "query", dataType = "String", required = true),
@ApiImplicitParam(name = "outputPathName", value = "输出word文件地址名称", paramType = "query", dataType = "String", required = true)
})
@ApiOperationSupport(author = "庞欢腾")
@PostMapping("/generaterWord")
public Result<String> generaterWord(@RequestBody GeneraterWordData generaterWordData) {
return generaterWordService.baseGeneraterWord(generaterWordData);
}


@ApiOperation(value = "一个非常灵活随意的生成word文档接口", notes = "生成word文档接口,当使用的模板不是一个的时候,使用这个接口。" +
"模板名称参数是一个用逗号分割的任意个模板名称", response = Result.class, httpMethod = "POST")
@ApiImplicitParams({
@ApiImplicitParam(name = "txt_data", value = "文本数据", paramType = "query", dataType = "Map", required = true),
@ApiImplicitParam(name = "image_data", value = "图像数据", paramType = "query", dataType = "Map", required = true),
@ApiImplicitParam(name = "inTemplatePathName", value = "输入模板地址名称,参数是一个用逗号分割的任意个模板名称", paramType = "query", dataType = "String", required = true),
@ApiImplicitParam(name = "outputPathName", value = "输出word文件地址名称", paramType = "query", dataType = "String", required = true)
})
@ApiOperationSupport(author = "庞欢腾")
@PostMapping("/generaterWordNimble")
public Result<String> generaterWordNimble(@RequestBody GeneraterWordData generaterWordData) {
return generaterWordService.baseGeneraterWordNimble(generaterWordData);
}


@ApiOperation(value = "通用文档生成接口", notes = "2022年08月04日 生成word文档接口,当使用的模板不是一个的时候,使用这个接口。" +
"模板名称参数是一个用逗号分割的任意个模板名称", response = Result.class, httpMethod = "POST")
@ApiOperationSupport(author = "庞欢腾")
@PostMapping("/makeWordNimble")
public Result<String> makeWordNimble(@RequestBody GeneraterWordData generaterWordData) {
return generaterWordService.baseMakeWordNimble(generaterWordData);
}

@ApiOperation(value = "通用文档生成接口", notes = "2022-08-17 生成word文档接口,当使用的模板不是一个的时候,使用这个接口。" +
"模板名称参数是一个用逗号分割的任意个模板名称,(第二代接口,当图片数据不在同一个目录的时候,图片名称参数前面要指定子目录,例如:tdd配置的路径+子目录/图片名称.png)", response = Result.class, httpMethod = "POST")
@ApiOperationSupport(author = "庞欢腾")
@PostMapping("/makeWordNimblePng")
public Result<String> makeWordNimblePng(@RequestBody GeneraterWordData generaterWordData) {
return generaterWordService.baseMakeWordNimblePng(generaterWordData);
}


/**
* 测试用例
*/
/*public static void main(String[] args) {
GeneraterWord generaterWord = new GeneraterWordImpl();
String inTemplatePathName = "E:\\a工作文件\\郑州\\2022\u200E年\u200E\\精细化平台开发工作\\预警信息制作模板\\开发模板\\郑州市气象台预警模板.doc";
Map<String, String> data = new HashMap<>();
// data.put("name", "郑州");
data.put("td0table0", "31日09时t_31日10时t_31日11时t_31日12时t_31日13时t_31日14时t_31日15时t_31日16时t_31日17时t_31日18时t_31日19时t_31日20时");
data.put("td1table0", "31日09时t_31日10时t_31日11时t_31日12时t_31日13时t_31日14时t_31日15时t_31日16时t_31日17时t_31日18时t_31日19时t_31日20时");
data.put("td2table0", "31日09时t_31日10时t_31日11时t_31日12时t_31日13时t_31日14时t_31日15时t_31日16时t_31日17时t_31日18时t_31日19时t_31日20时");

//加载示例文档
Document document = new Document();
// "C:\\Users\\Administrator\\Desktop\\input.docx"
document.loadFromFile(inTemplatePathName);
// 文本
// generaterWord.replaceText(data, document);

//表格
generaterWord.replaceTable(data, document);

//保存文档
document.saveToFile("E:\\a工作文件\\郑州\\2022\u200E年\u200E\\精细化平台开发工作\\预警信息制作模板\\开发模板\\ReplaceAllMatchedText.docx", FileFormat.Docx_2013);

}*/

/**
* 测试循环生成文档功能
* @param args
*/
/*public static void main(String[] args) {
String root = "D:\\data\\word\\制作文档\\";
String out = root + "生成后的文件.docx";
Map<String, String>[] txt_data = new Map[2];
txt_data[0] = new HashMap<>();
txt_data[0].put("name", "这是第一个文本");
txt_data[1] = new HashMap<>();
txt_data[1].put("name", "这是第二个文本");

Map<String, String>[] image_data = new Map[2];
image_data[0] = new HashMap<>();
image_data[0].put("img2", root + "img1.png");
image_data[1] = new HashMap<>();
image_data[1].put("img2", root + "img3.png");

GeneraterWord generaterWord = new GeneraterWordImpl();
Document document = generaterWord.generaterWord(root + "气象信息快报_近小时降水量2.doc");
generaterWord.loopReplaceWord(txt_data, image_data, document, out);

}*/

}

核心实现类

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
/**
* 图片没用自动拼接当前日期
* @param generaterWordData
* @return
*/
private GeneraterWordData StitchingPathNoPng(GeneraterWordData generaterWordData) {
String mouth = DateUtil.getMouth();
/**
* 1.读取配置路径
*/
String area = generaterWordData.getArea();
String dataType = generaterWordData.getDataType();
TDealdataDict tdd = tddRedisUtil.getTdd(area, dataType);
if (tdd == null) {
log.info("tdd配置未找到!" + area + " " + dataType);
return null;
}
String orgPath = tdd.getOrgPath();
if (!(orgPath.endsWith("/") || orgPath.endsWith("\\"))) {
orgPath += "/";
}

/**
* 2.图片数据需要拼接前路径
*/
Map<String, String> image_data = generaterWordData.getImage_data();
for (Map.Entry<String, String> entry : image_data.entrySet()) {
StringBuilder imgname = new StringBuilder();
String value = entry.getValue();
if (value.contains(",_")) {
String[] split = value.split(",_");
for (String s : split) {
imgname.append(orgPath).append(s).append(",_");
}
value = imgname.substring(0, imgname.length() - 2);
} else {
value = orgPath + value;
}
entry.setValue(value);
}
generaterWordData.setImage_data(image_data);

/**
* 3.输出文档需要拼接前路径
*/
String outputPathName = generaterWordData.getOutputPathName();
generaterWordData.setOutputPathName(orgPath + mouth + "/" + outputPathName);

/**
* 4.模板名称需要拼接前路径
*/
String templateName = generaterWordData.getTemplateName();
// 模板数据需要拼接前路径
String[] templates = templateName.split(",|,");
StringBuilder name = new StringBuilder();
for (String template : templates) {
name.append(orgPath).append(template).append(",");
}
templateName = name.substring(0, name.length() - 1);
generaterWordData.setTemplateName(templateName);

return generaterWordData;
}

4、制作模板文件

注意:word模板文件必须是.doc为后缀的文档

新建一个doc文档,直接在文档里编写模板

①编辑模板

一、文本占位符用“#”包裹,例如:#data#

二、图片站位就是,在word里添加一张图片,图片的名称就是接口里传参的key值

例如:图片名称是img1.png

image_data: {

​ “img1”:”气象预警icon_暴雪-橙.png”

}

img

制作好doc模板文件后,将模板文件上传到服务器指定目录

在数据库里需要定义一个路径配置字典表,用来存储word文档的生成输出路径和保存模板文件路径

5、文档制作需求分类

实际需求中往往遇到的需求是很复杂的

S类文档制作是一张完整的模板文件,填充固定个数的替换符号,生成出新的文档。

SS类文档制作是多段内容根据客户选择生成出结果文档,比如客户想要文档的A、B部分,那么生成出来的文档就不包含C部分。

SSS类文档制作是文档切片后,其中一片内容可能根据数据需要循环展示,例如B分片,后台数据有3条,这三条数据需要按照模板B的格式,循环渲染出来,文档输出的结果就是ABBBC

img

6、项目应用场景

img

码字不易,有问题请联系我 vx:yce99867066