java 导出word 包含echarts图表

打印 上一主题 下一主题

主题 909|帖子 909|积分 2727

需求是导出word,里面有数据统计图表。
要从后端直接导出图表的话,思路是这样的:
  先通过echarts生成图片,通过phantomjs 截图,将图片暂存在本地,再将图片转换成base64,然后放入word。
 
phantomjs 是一个基于js的webkit内核无头浏览器 也就是没有显示界面的浏览器。
 
一、准备word模板,转换成xml,需要填入数据的地方用${字段},需要天出图片的地方可以先随便一张用图片替代,方便之后找到图片插入位置。这里就不多说了
 
二、准备环境、依赖
 1、准备js,需要用到的,放在同一个文件夹下面。自己更改echarts-convert.js的路径
  
 
 
   echarts.min.js 和jquery.js 去官网下载
  echarts-convert.js的内容如下:
  
  1. (function () {
  2.     var system = require('system');
  3.     var fs = require('fs');
  4.     var config = {
  5.         // define the location of js files
  6.         //这样写要求这三个js在同一个文件夹下
  7.         JQUERY: 'jquery-3.5.1.min.js',
  8.         //ESL: 'esl.js',
  9.         ECHARTS: 'echarts.min.js',
  10.         // default container width and height
  11.         DEFAULT_WIDTH: '400',
  12.         DEFAULT_HEIGHT: '600'
  13.     }, parseParams, render, pick, usage;
  14.     usage = function () {
  15.         console.log("\nUsage: phantomjs echarts-convert.js -options options -outfile filename -width width -height height"
  16.             + "OR"
  17.             + "Usage: phantomjs echarts-convert.js -infile URL -outfile filename -width width -height height\n");
  18.     };
  19.     pick = function () {
  20.         var args = arguments, i, arg, length = args.length;
  21.         for (i = 0; i < length; i += 1) {
  22.             arg = args[i];
  23.             if (arg !== undefined && arg !== null && arg !== 'null' && arg != '0') {
  24.                 return arg;
  25.             }
  26.         }
  27.     };
  28.     parseParams = function () {
  29.         var map = {}, i, key;
  30.         if (system.args.length < 2) {
  31.             usage();
  32.             phantom.exit();
  33.         }
  34.         for (i = 0; i < system.args.length; i += 1) {
  35.             if (system.args[i].charAt(0) === '-') {
  36.                 key = system.args[i].substr(1, i.length);
  37.                 if (key === 'infile') {
  38.                     // get string from file
  39.                     // force translate the key from infile to options.
  40.                     key = 'options';
  41.                     try {
  42.                         map[key] = fs.read(system.args[i + 1]).replace(/^\s+/, '');
  43.                     } catch (e) {
  44.                         console.log('Error: cannot find file, ' + system.args[i + 1]);
  45.                         phantom.exit();
  46.                     }
  47.                 } else {
  48.                     map[key] = system.args[i + 1].replace(/^\s+/, '');
  49.                 }
  50.             }
  51.         }
  52.         return map;
  53.     };
  54.     render = function (params) {
  55.         var page = require('webpage').create(), createChart;
  56.         var bodyMale = config.SVG_MALE;
  57.         page.onConsoleMessage = function (msg) {
  58.             console.log(msg);
  59.         };
  60.         page.onAlert = function (msg) {
  61.             console.log(msg);
  62.         };
  63.         createChart = function (inputOption, width, height,config) {
  64.             var counter = 0;
  65.             function decrementImgCounter() {
  66.                 counter -= 1;
  67.                 if (counter < 1) {
  68.                     console.log(messages.imagesLoaded);
  69.                 }
  70.             }
  71.             function loadScript(varStr, codeStr) {
  72.                 var script = $('<script>').attr('type', 'text/javascript');
  73.                 script.html('var ' + varStr + ' = ' + codeStr);
  74.                 document.getElementsByTagName("head")[0].appendChild(script[0]);
  75.                 if (window[varStr] !== undefined) {
  76.                     console.log('Echarts.' + varStr + ' has been parsed');
  77.                 }
  78.             }
  79.             function loadImages() {
  80.                 var images = $('image'), i, img;
  81.                 if (images.length > 0) {
  82.                     counter = images.length;
  83.                     for (i = 0; i < images.length; i += 1) {
  84.                         img = new Image();
  85.                         img.onload = img.onerror = decrementImgCounter;
  86.                         img.src = images[i].getAttribute('href');
  87.                     }
  88.                 } else {
  89.                     console.log('The images have been loaded');
  90.                 }
  91.             }
  92.             // load opitons
  93.             if (inputOption != 'undefined') {
  94.                 // parse the options
  95.                 loadScript('options', inputOption);
  96.                 // disable the animation
  97.                 options.animation = false;
  98.             }
  99.             // we render the image, so we need set background to white.
  100.             $(document.body).css('backgroundColor', 'white');
  101.             var container = $("").appendTo(document.body);
  102.             container.attr('id', 'container');
  103.             container.css({
  104.                 width: width,
  105.                 height: height
  106.             });
  107.             // render the chart
  108.             var myChart = echarts.init(container[0]);
  109.             myChart.setOption(options);
  110.             // load images
  111.             loadImages();
  112.             return myChart.getDataURL();
  113.         };
  114.         // parse the params
  115.         page.open("about:blank", function (status) {
  116.             // inject the dependency js
  117.             page.injectJs(config.ESL);
  118.             page.injectJs(config.JQUERY);
  119.             page.injectJs(config.ECHARTS);
  120.             var width = pick(params.width, config.DEFAULT_WIDTH);
  121.             var height = pick(params.height, config.DEFAULT_HEIGHT);
  122.             // create the chart
  123.             var base64 = page.evaluate(createChart, params.options, width, height,config);
  124.             fs.write("base64.txt",base64);
  125.             // define the clip-rectangle
  126.             page.clipRect = {
  127.                 top: 0,
  128.                 left: 0,
  129.                 width: width,
  130.                 height: height
  131.             };
  132.             // render the image
  133.             page.render(params.outfile);
  134.             console.log('render complete:' + params.outfile);
  135.             // exit
  136.             phantom.exit();
  137.         });
  138.     };
  139. // get the args
  140.     var params = parseParams();
  141. // validate the params
  142.     if (params.options === undefined || params.options.length === 0) {
  143.         console.log("ERROR: No options or infile found.");
  144.         usage();
  145.         phantom.exit();
  146.     }
  147. // set the default out file
  148.     if (params.outfile === undefined) {
  149.         var tmpDir = fs.workingDirectory + '/tmp';
  150.         // exists tmpDir and is it writable?
  151.         if (!fs.exists(tmpDir)) {
  152.             try {
  153.                 fs.makeDirectory(tmpDir);
  154.             } catch (e) {
  155.                 console.log('ERROR: Cannot make tmp directory');
  156.             }
  157.         }
  158.         params.outfile = tmpDir + "/" + new Date().getTime() + ".png";
  159.     }
  160. // render the image
  161.     render(params);
  162. }());
复制代码
 
  2、安装phantomjs
    网站:https://phantomjs.org/download.html
    选择合适的版本,我下载的是windows的,下载解压
    
 
 
     配置环境变量:
 
 
 
 
     
 
 
   
    然后测试是否安装成功,在命令行 输入:phantomjs -- version
    
 
 
     出现版本就表示安装成功了。
  
  3、构建echarts数据,就是option
    可以看原文档:https://gitee.com/free/ECharts#https://gitee.com/link?target=http%3A%2F%2Fblog.csdn.net%2Fisea533%2Farticle%2Fdetails%2F43225717
    
  1. <dependency>
  2.      <groupId>com.github.abel533</groupId>
  3.      <artifactId>ECharts</artifactId>
  4.      <version>3.0.0.6</version>
  5. </dependency>               
复制代码
 
三、生成echarts图表
  1、构建echarts 的数据option
   
  1.     /**
  2.      * 构建柱状图
  3.      * @param cate x轴数据
  4.      * @param enterpriseCnt 数据
  5.      * @return
  6.      */
  7.     private static String getOption(List<String> cate, List<Integer> enterpriseCnt){
  8.         GsonOption option = new GsonOption();
  9.         option.title().setText("测试点位数图片"); // 标题
  10.         // 设置图例
  11.         option.legend().data("点位数").x("center");
  12.         Bar bar = new Bar();
  13.         // x轴
  14.         CategoryAxis category = new CategoryAxis();
  15.         category.data(cate.toArray());
  16.         //y 轴
  17.         ValueAxis valueAxis = new ValueAxis();
  18.         bar.data().addAll(enterpriseCnt); // 数据
  19.         option.xAxis(category);  //x轴
  20.         option.yAxis(valueAxis);  //y轴
  21.         option.series(bar);// 多条柱子放多个bar就行
  22.         String optionStr = option.toString().replace(" ", "");
  23.         log.info(optionStr);
  24.         return optionStr;
  25.     }
复制代码
  2、生成echarts图片
  
  1.     public static String generateEChart(String option, String filepath, String fileName) {
  2.         String dataPath = writeOptionToFile(option, filepath); // 将option 数据写磁盘上用文件保存
  3.         String path = filepath + fileName+".png"; //生成图片路径
  4.         try {
  5.             String JSpath = "D:\\data\\tmp\\echarts-convert.js";
  6.             String cmd = "phantomjs " + JSpath + " -infile " + dataPath + " -outfile " + path;
  7.             log.info(cmd);
  8.             Process process = Runtime.getRuntime().exec(cmd);
  9.             BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
  10.             String line = "";
  11.             while ((line = input.readLine()) != null) {
  12.                 log.info(line);
  13.             }
  14.             input.close();
  15.             // 删除json数据
  16.             File jsonFile = new File(dataPath);
  17.             jsonFile.delete();
  18.         } catch (IOException e) {
  19.             e.printStackTrace();
  20.         }
  21.         return path;
  22.     }
复制代码
  
  1.     public static String writeOptionToFile(String options, String filepath) {
  2.         String dataPath = filepath +"echart.json";
  3.         try {
  4.             File writename = new File(dataPath);
  5.             if (!writename.getParentFile().exists()) {   //文件目录不存在,则先创建,不然会报错
  6.                 writename.getParentFile().mkdirs();
  7.             }
  8.             BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(writename), "UTF-8"));
  9.             out.write(options);
  10.             out.flush();
  11.             out.close();
  12.         } catch (IOException e) {
  13.             e.printStackTrace();
  14.         }
  15.         return dataPath;
  16.     }
复制代码
 
  先测试一哈:
   
  这个时候在文件夹下可以看到图片啦:
  
 
 
 
四、导出word
  准备好数据,图片需要base64编码的,将之前生成的echart图片读入转base64
  
  1.     public static String imageToBase64(String imgPath) {
  2.         InputStream in = null;
  3.         byte[] data = null;
  4.         try {
  5.             in = new FileInputStream(imgPath);
  6.             data = new byte[in.available()];
  7.             in.read(data);
  8.             in.close();
  9.         } catch(Exception ex) {
  10.             ex.printStackTrace();
  11.         }
  12.         Base64Encoder encoder = new Base64Encoder();
  13.         return encoder.encode(data);
  14.     }
复制代码
  
  然后就是正常word的导出了
  
 
   
  

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

吴旭华

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表