网上找过很多方法,但一直没有特别合适的直接导入方式,所以借鉴一篇博客的方法:先将echarts图表保存到本地临时文件,然后将文件添加到word摸板的对应位置,虽然比较繁琐,但摸板可调,操作更灵活。
首先测试将对应的数据新导入word摸板
新建word文档 test.docx,写好模板样式,可根据自己的需要自行添加,{{}}为你要填充的内容,固定不变文字可以提前写道模板里面
JAVA部分前期测试准备
开始写后台java代码部分,首先导入需要的依赖,因为后边会用到网页,和其他依赖这里一并导入
<!--thymeleaf web页面模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--lombok 类注释,省略getter setter方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--poi导出 导出word文档所需要的依赖-->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.0.0</version>
</dependency>
需要的java导出工具类 PoitlTest 这里是将本地存在的图片和自己构造的数据填充到模板中
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.PictureRenderData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* poi-tl库的使用示例.
*/
public class PoitlTest {
private static final Logger log = LoggerFactory.getLogger(PoitlTest.class);
/** word模板路径,这里为了方便直接采用真实路径 */
private static final String DOC_PATH = "D:\\test\\test.docx";
/** 要插入word的图片路径. 同上*/
private static final String PIC_PATH = "D:\\test\\demo1.jpg";
private static final String PIC_PATH1 = "D:\\test\\demo2.jpg";
/** 输出文件及路径. */
private static final String OUTPUT_PATH = "D:\\test\\poitl_out_word.docx";
/**
* 构造要填充的数据
* Map或者是对象都可以(map的key为模板里面的填充标签,对象的属性名为模板里面的填充标签
* @return map
*/
private static Map<String,Object> buildBeanData() {
Map<String,Object> map= new HashMap<>();
map.put("title","导出word文档");
map.put("smallTitle","数据图表信息");
map.put("content1","图1");
map.put("pic1",new PictureRenderData(600, 400, PIC_PATH));
map.put("content2","图2");
map.put("pic2",new PictureRenderData(600, 400, PIC_PATH1));
return map;
}
/**
*
* 导出方法
*/
public static void export() throws IOException {
XWPFTemplate template = XWPFTemplate.compile(DOC_PATH).render(buildBeanData());
FileOutputStream out = new FileOutputStream(OUTPUT_PATH);
template.write(out);
out.flush();
out.close();
template.close();
log.info("通过'poi-tl'导出word成功!");
}
}
直接运行 export 方法测试输出word文档成功,效果展示如下
接下来使用echarts生成图表,并将生成的图表保存到word
我们思路是echarts图片再页面显示,点击导出后先将图片存到本地,然后放入模板,因为我用到是thymeleaf引擎,需要在配置文件添加thymeleaf配置内容
spring.thymeleaf.prefix= classpath:/templates/ #页面所在位置
spring.thymeleaf.suffix= .html #后缀
index.html页面内容为
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试的ECharts数据统计图</title>
</head>
<body>
<!-- 导出按钮 -->
<button id="button">button</button><br/><br/>
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM 因为我们是两张图,所以准备了两个DOM-->
<div id="main1" style="width:560px; height:270px;"></div><br/>
<div id="main2" style="width:560px; height:270px;"></div><br/>
<!-- 引入用到的js文件 两文件存放在resources/static目录下 -->
<script type="text/javascript" src="jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="echarts.js"></script>
<script type="text/javascript">
//暂时使用的静态数据
// 基于准备好的dom,初始化echarts实例
var myChart1 = echarts.init(document.getElementById('main1'));
// 指定图表的配置项和数据
var option1 = {
title: {
text: 'ECharts 入门示例1'
},
animation: false, // 关闭动画效果
tooltip: {},
legend: {
data:['销量']
},
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart1.setOption(option1);
var myChart2 = echarts.init(document.getElementById('main2'));
var option2 = {
title: {
text: 'ECharts 入门示例2'
},
animation: false, // 关闭动画效果
tooltip: {},
legend: {
data:['销量']
},
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
};
myChart2.setOption(option2);
//点击按钮方法触发请求
$("#button").click(postImage());
/**
* ajax传输图片信息到后台保存
*/
function postImage() {
// 向后台发起请求保存图片到指定目录.
$.ajax({
type: 'POST',
url: '/saveImage',
data: {picInfo1: myChart1.getDataURL(),picInfo2:myChart2.getDataURL()},
success: function() {
console.log('通过post请求传输数据成功!');
}
});
}
</script>
</body>
</html>
后台请求的controller方法内容为,在方法中导出word文档时应该动态传入你设置保存图片的路径,此处只为演示所以没改,各位看客可以根据自己的需要更改一下,未修改记得将导出类的图片路径修改为你导出图片的路径
import com.example.practice.word.PoitlTest;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@CrossOrigin
@RestController
public class AdminController {
private static final Logger log = LoggerFactory.getLogger(AdminController.class);
@PostMapping("saveImage")
public void getAdmin(HttpServletRequest request) {
// 获取图片信息.其实是图片解析为base64的编码
String picInfo1 = request.getParameter("picInfo1");
String picInfo2 = request.getParameter("picInfo2");
if (StringUtils.isBlank(picInfo1) || StringUtils.isBlank(picInfo2)) {
log.error("picInfo为空,未从前台获取到base64图片信息!");
return;
}
//存放图片的位置
getAndsaveImage(picInfo1, "D:\\test\\image1.png");
getAndsaveImage(picInfo2, "D:\\test\\image2.png");
//生成word文档
try {
//此处应该改为将图片地址动态的传入,博主未改,各位看客见谅
PoitlTest.export();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("导出成功");
}
/**
* 获取并保存图片到本地.
*
* @param picInfo 图片信息
* @param imagePath 图片保存的路径
*/
private void getAndsaveImage(String picInfo, String imagePath) {
// 传递过程中 "+" 变为了 " ".
String newPicInfo = picInfo.replaceAll(" ", "+");
String picPath = decodeBase64(newPicInfo, imagePath);
log.warn("从echarts中生成图片的的路径为:{}", picPath);
}
/**
* 解析Base64位信息并输出到某个目录下面.
*
* @param base64Info base64串
* @param picPath 生成的文件路径
* @return 文件地址
*/
private String decodeBase64(String base64Info, String picPath) {
if (StringUtils.isEmpty(base64Info)) {
return null;
}
// 数据中:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABI4AAAEsCAYAAAClh/jbAAA ... 在"base64,"之后的才是图片信息
String[] arr = base64Info.split("base64,");
// 将图片输出到系统某目录.
OutputStream out = null;
try {
// 使用了Apache commons codec的包来解析Base64
byte[] buffer = Base64.decodeBase64(arr[1]);
out = new FileOutputStream(picPath);
out.write(buffer);
} catch (IOException e) {
log.error("解析Base64图片信息并保存到某目录下出错!", e);
} finally {
IOUtils.closeQuietly(out);
}
return picPath;
}
}
验证效果:在浏览器输入localhost:8080
点击button,导出到word,查看word内容