【已解决】java如何在后台生成echarts图表并将图片插入到word文档中,完整demo
- echarts
- 时间:2023-05-24 17:37
- 3403人已阅读
简介
需求:数据进行统计后,需要将统计好的数据生成对应的echarts图,并将echarts图插入到word文档中导出使用。不需要在页面(浏览器)上展示。这就导致了,无法通过浏览器对echarts数据进行渲染后,在提供对应的base64的字符串给后端进行下载。原理:通过无头浏览器调用js方法,使用服务端查出来的数据生成echars图片,此处使用了phantomjs作为无头浏览器(此开源项目目前处于终止状
🔔🔔好消息!好消息!🔔🔔
有需要的朋友👉:微信号
需求:
数据进行统计后,需要将统计好的数据生成对应的echarts图,并将echarts图插入到word文档中导出使用。不需要在页面(浏览器)上展示。这就导致了,无法通过浏览器对echarts数据进行渲染后,在提供对应的base64的字符串给后端进行下载。
原理:
通过无头浏览器调用js方法,使用服务端查出来的数据生成echars图片,此处使用了phantomjs作为无头浏览器(此开源项目目前处于终止状态,谷歌浏览器等都开发出类似功能,源码贡献者成员之一终止继续更新版本)。下附详细代码。
所需要的软件包:
链接: https://pan.baidu.com/s/1guTP-9RsZtSDFj1XFLzXqA?pwd=vgay 提取码: vgay
详细代码如下;
①:常量对象
package com.kaigejava.demo4; public class EChartWord { // ============== 这里要改成自己电脑对应的文件位置,服务器部署时可以通过环境变量等方式来动态改变它们的值 ================= /** * echart-convert包的路径 */ public static String eChartJSPath = "D:\\BaiduNetdiskDownload\\服务器生成echart图片工具包\\echarts-convert\\echarts-convert1.js"; /** * echart临时文件存储路径 */ public static String eChartTempPath = "D:\\files\\test\\"; /** * phantomjs命令路径 */ //private String phantomjsPath = "/Users/helios_fz/IdeaProjects/rbac/rbac-admin/src/main/resources/phantomjs/phantomjs-2.1.1-macosx/bin/phantomjs"; public static String phantomjsPath = "D:\\BaiduNetdiskDownload\\服务器生成echart图片工具包\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe"; }
②:工具类
package com.kaigejava; /** * @author 凯哥Java * @since 2023/5/24 14:42 */ import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.*; import java.util.UUID; import static com.kaigejava.demo4.EChartWord.phantomjsPath; public class EChartsUtil { /** * 生成EChart图 * * @param options EChart初始化json * @param tmpPath 临时文件存放处 * @param echartJsPath 第三方工具路径--也就是js的路径 * @return */ public static String generateEChartConvertFilePath(String options, String tmpPath, String echartJsPath) { return generateEChart(options, tmpPath,echartJsPath); } /** * 生成EChart图 * * @param options EChart初始化json * @param tmpPath 临时文件存放处 * @param echartJsPath 第三方工具路径--也就是js的路径 * @return */ public static InputStream generateEChartConvert(String options, String tmpPath, String echartJsPath) throws IOException { String dataPath = generateEChart(options, tmpPath,echartJsPath); return new FileInputStream(new File(dataPath)); } /** * 生成EChart图 * * @param options EChart初始化json * @param tmpPath 临时文件存放处 * @param echartJsPath 第三方工具路径--也就是js的路径 * @return */ public static BufferedImage generateEChartConvertFileToImage(String options, String tmpPath, String echartJsPath) throws IOException { // 生成Echart的初始化json文件 String dataPath = generateEChart(options, tmpPath,echartJsPath); BufferedImage image = ImageIO.read(new File(dataPath)); return image; } /** * 生成EChart图 * * @param options EChart初始化json * @param tmpPath 临时文件存放处 * @param echartJsPath 第三方工具路径--也就是js的路径 * @return */ private static String generateEChart(String options, String tmpPath, String echartJsPath) { // 生成Echart的初始化json文件 String dataPath = writeFile(options, tmpPath); // 生成随机文件名 String fileName = UUID.randomUUID().toString().substring(0, 8) + ".png"; String path = tmpPath + fileName; try { // 文件路径(路径+文件名) File file = new File(path); // 文件不存在则创建文件,先创建目录 if (!file.exists()) { File dir = new File(file.getParent()); dir.mkdirs(); file.createNewFile(); } // 这里只能写绝对路径,因为要执行系统命令行 String cmd = phantomjsPath + " " + echartJsPath + " -infile " + dataPath + " -outfile " + path; Process process = Runtime.getRuntime().exec(cmd); BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ""; while ((line = input.readLine()) != null) { System.out.println(line); } input.close(); // 删除生成的临时json文件 File jsonFile = new File(dataPath); jsonFile.delete(); return path; } catch (IOException e) { e.printStackTrace(); return path; } } /** * 保存EChart临时json * * @param options echart初始化js * @param tmpPath 临时文件保存路径 * @return 文件完整路径 */ private static String writeFile(String options, String tmpPath) { String dataPath = tmpPath + UUID.randomUUID().toString().substring(0, 8) + ".json"; try { /* 写入Txt文件 */ // 相对路径,如果没有则要建立一个新的output.txt文件 File writeName = new File(dataPath); // 文件不存在则创建文件,先创建目录 if (!writeName.exists()) { File dir = new File(writeName.getParent()); dir.mkdirs(); // 创建新文件 writeName.createNewFile(); } BufferedWriter out = new BufferedWriter(new FileWriter(writeName)); out.write(options); // 把缓存区内容压入文件 out.flush(); // 最后记得关闭文件 out.close(); } catch (IOException e) { e.printStackTrace(); } return dataPath; } }
③:测试类
package com.kaigejava.demo5; import cn.hutool.json.JSONUtil; import com.github.abel533.echarts.Option; import com.github.abel533.echarts.axis.CategoryAxis; import com.github.abel533.echarts.code.Trigger; import com.github.abel533.echarts.json.GsonOption; import com.github.abel533.echarts.series.Line; import com.kaigejava.EChartsUtil; import org.apache.poi.util.Units; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import static com.kaigejava.demo4.EChartWord.eChartJSPath; import static com.kaigejava.demo4.EChartWord.eChartTempPath; /** * @author 凯哥Java * @since 2023/5/24 17:07 */ public class Demo5 { public static void main(String[] args) throws Exception { XWPFDocument doc = new XWPFDocument(); XWPFParagraph p = doc.createParagraph(); XWPFRun r = p.createRun(); r.setText("图表展示"); r.setColor("000000"); r.setFontFamily("微软雅黑"); r.setFontSize(18); String[] categories = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"}; Option option = createEchartsOption(categories); insertImageToWord(doc,option); } // 生成Echarts Option private static Option createEchartsOption(String[] categories) { GsonOption option = new GsonOption(); option.title().text("某商场销售情况").subtext("纯属虚构"); option.tooltip().trigger(Trigger.axis); option.legend().data("最高气温", "最低气温").left("center"); option.xAxis(new CategoryAxis().data(categories)); option.yAxis(new com.github.abel533.echarts.axis.ValueAxis()); option.series(new Line().name("最高气温").data(11, 11, 15, 13, 12, 13, 10), new Line().name("最低气温").data(1, -2, 2, 5, 3, 2, 0)); return option; } public static void insertImageToWord(XWPFDocument doc,Option dataOption) throws Exception { FileOutputStream out = new FileOutputStream(eChartTempPath+"output.docx"); XWPFParagraph p = doc.createParagraph(); XWPFRun r = p.createRun(); String optionDataJson = JSONUtil.toJsonStr(dataOption); String imagePath = EChartsUtil.generateEChartConvertFilePath(optionDataJson, eChartTempPath,eChartJSPath); int format; switch (imagePath.substring(imagePath.lastIndexOf(".") + 1).toLowerCase()) { case "png": format = XWPFDocument.PICTURE_TYPE_PNG; break; case "jpg": case "jpeg": format = XWPFDocument.PICTURE_TYPE_JPEG; break; case "bmp": format = XWPFDocument.PICTURE_TYPE_BMP; break; default: throw new Exception("不支持该图片格式"); } r.addPicture(new FileInputStream(new File(imagePath)), format, imagePath, Units.toEMU(450), Units.toEMU(250)); doc.write(out); out.close(); } }
注意:需要生成Word之后,需要把生成的图片也删除掉。这里未处理
④:生成效果