【已解决】java如何在后台生成echarts图表并将图片插入到word文档中,完整demo
- echarts
- 时间:2023-05-24 17:37
- 3588人已阅读
简介
需求:数据进行统计后,需要将统计好的数据生成对应的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之后,需要把生成的图片也删除掉。这里未处理
④:生成效果

