前言:项目中提出一个新需求,就将Highcharts中的图片读取到Excel中。并在前台做下载,当听到这功能,第一想法是需要由后台编写程序,将数据写道图片中。
虽然没做过但是也没觉得太难,毕竟前辈们肯定也做过类似的功能。但是后来发现Highcharts本身就可以导出图片,也能导出不同格式图片。
我突然觉得将Highcharts的图片流传到后台,在输出到Excel中不就可以了吗?于是开始了.....
第一步:首先要获取Highcharts中SVG对象,信息保存到 form表单中。
第二步:将SVG 转换成PNG格式
别问我为什么,因为报错!报错!报错... 不能直接解析SVG
所需要jar包
batik-all-1.7.jar
batik-transcoder-1.7.jar
xml-apis-ext-1.3.04.jar
链接: https://pan.baidu.com/s/1FkLvC7dnXdLla5FASpjEKw 提取码: 71aq 复制这段内容后打开百度网盘手机App,操作更方便哦
下面这段代码在网上找的,我能用,也就贴出来了
/** * @Description: 将svgCode转换成png文件,直接输出到流中 * @Author:saiSQ * @Since: 2013-11-4下午01:37:56 * @param svgCode * svg代码 * @param outputStream * 输出流 * 异常 * @throws IOException * io异常 */ public static void convertToPng(String svgCode, OutputStream outputStream){ try { byte[] bytes = svgCode.getBytes("UTF-8"); PNGTranscoder t = new PNGTranscoder(); t.addTranscodingHint(PNGTranscoder.KEY_WIDTH, new Float(1024));//只要指定宽度即可,高度自动调整。 TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(bytes)); TranscoderOutput output = new TranscoderOutput(outputStream); t.transcode(input, output); outputStream.flush(); }catch (Exception e){ e.printStackTrace(); }finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
第三步:将文件写入response 中,做页面下载(以上是我写的代码,安全起见,我复制下来时,删掉了部分代码,如果没有运行成功,下方留言,按照你的情况再做解答,这里只说个思路。勿怪,勿怪)
/** * 生成Excel 文档 */ @RequestMapping(value = "/downExcel",produces = "application/json;charset=UTF-8") public void createdExcel(HttpServletRequest request, HttpServletResponse response){ ByteArrayOutputStream byteArrayOut=null; HSSFWorkbook wb=null; OutputStream os=null; String svgCode=request.getParameter("svg"); try { //加载图片 byteArrayOut= new ByteArrayOutputStream(); convertToPng(svgCode,byteArrayOut); //加载图片 wb= new HSSFWorkbook(); HSSFSheet sheet1 = wb.createSheet("sheet1"); HSSFPatriarch patriarch = sheet1.createDrawingPatriarch(); /** dx1 - the x coordinate within the first cell.//定义了图片在第一个cell内的偏移x坐标,既左上角所在cell的偏移x坐标,一般可设0 dy1 - the y coordinate within the first cell.//定义了图片在第一个cell的偏移y坐标,既左上角所在cell的偏移y坐标,一般可设0 dx2 - the x coordinate within the second cell.//定义了图片在第二个cell的偏移x坐标,既右下角所在cell的偏移x坐标,一般可设0 dy2 - the y coordinate within the second cell.//定义了图片在第二个cell的偏移y坐标,既右下角所在cell的偏移y坐标,一般可设0 col1 - the column (0 based) of the first cell.//第一个cell所在列,既图片左上角所在列 row1 - the row (0 based) of the first cell.//图片左上角所在行 col2 - the column (0 based) of the second cell.//图片右下角所在列 row2 - the row (0 based) of the second cell.//图片右下角所在行 */ int line=23;//列 int row=12;//行exportProjectExcel HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0,(short) 0, 0, (short) row, line); //插入图片 patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG)); //再图片下插入内容 HSSFRow hssfRow=null; HSSFCell hssfCell=null; String fileName = "xxxx名称.xls";// 文件名 setResponseHeader(response,fileName); os=response.getOutputStream(); // 输出文件 wb.write(os); } catch (Exception e) { e.printStackTrace(); }finally { try{ if(byteArrayOut!=null){ byteArrayOut.close(); } if(byteArrayOut!=null){ byteArrayOut.close(); } if(wb!=null){ wb.close(); } if(os!=null){ os.close(); } }catch (Exception e){ e.printStackTrace(); } } }
第四步:测试效果
浏览器
Excel
五:特别注意: Highcharts 导出来的图片有可能因为比例问题,会导致数据出现问题,需要修改一下 Highcharts 宽度即可
这是前端大佬写的,我也不太懂,大概意思就是初始化 Highcharts表的时候 修改他的宽度, (svg_width 这里设置成了全量,获取的是浏览器上显示Highcharts那一快区域的宽度。主要是不能设置成百分比,写死了又不好)
Highcharts.chart('container', {
chart: {
type: 'column',
svg_width
},
到此该功能基本能实现出来了,别看简单,花了我两天时间,在快要崩溃的时候,出现了奇迹。