前言:项目中提出一个新需求,就将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 voidcreatedExcel(HttpServletRequest request, HttpServletResponse response){
ByteArrayOutputStream byteArrayOut=null;
HSSFWorkbook wb=null;
OutputStream os=null;
String svgCode=request.getParameter("svg");try{//加载图片
byteArrayOut= newByteArrayOutputStream();
convertToPng(svgCode,byteArrayOut);//加载图片
wb= newHSSFWorkbook();
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',
width: svg_width
},
到此该功能基本能实现出来了,别看简单,花了我两天时间,在快要崩溃的时候,出现了奇迹。