java+thymeleaf+echartys实现图表导入到word

mac2025-03-31  2

网上找过很多方法,但一直没有特别合适的直接导入方式,所以借鉴一篇博客的方法:先将echarts图表保存到本地临时文件,然后将文件添加到word摸板的对应位置,虽然比较繁琐,但摸板可调,操作更灵活。

参考博客连接:https://blinkfox.github.io/2018/10/01/hou-duan/java/shi-yong-java-diao-yong-phantomjs-dong-tai-dao-chu-echarts-tu-pian-dao-word-wen-jian-zhong/

首先测试将对应的数据新导入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内容

最新回复(0)