echarts通过poi导出图片到excel文件

最近在做统计报表,对比了一下echarts、flot、Highcharts,还是选择了开源的echarts,主要表现美观,而且对IE8支持好(兼容IE8什么的最讨厌了),整理了一下支持导出多个echarts图表到excel文档的方法,而且导出到excel中是按图片正常比例显示的,提交表单防跳转。
导出成品图
echarts通过poi导出图片到excel文件_第1张图片

1.首先看echarts代码,以柱状图和饼状图为例
html代码


<div class="echarts" id="useStats-bar-chart">div>

<div class="echarts" id="useStats-pie-chart">div>

javascript代码

// 柱状图
var barChart = echarts.init(document.getElementById("useStats-bar-chart"));
var baroption = {
	// 背景要设置成白色,不然导出来乌漆嘛黑的看不清
    backgroundColor: '#ffffff',
    tooltip : {
        trigger: 'axis',
        axisPointer: {            // 坐标轴指示器,坐标轴触发有效
            type: 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
        }
    },
    grid:{
        x:30,
        y:48,
        x2:40,
        y2:66
    },
    calculable : true,
    xAxis : [
        {
            type : 'category',
            data : ['乌鲁木齐市','克拉玛依市','吐鲁番地区',
                '哈密地区','昌吉回族自治州','博尔塔拉蒙古自治州',
                '巴音郭楞蒙古自治州','阿克苏地区','克孜勒苏柯尔克孜自治州',
                '喀什地区','和田地区','伊犁哈萨克自治州',
                '塔城地区','阿勒泰地区','石河子',
                '阿拉尔','图木舒克','五家渠'],
            axisLabel: {
                interval: 0,// 间隔显示数,0表示全部显示
                //坐标轴刻度标签的相关设置。
                formatter : function(params){
                    // 换行
                    return chartsLinefeed(params);
                }
            }
        }
    ],
    yAxis : [
        {
            type : 'value'
        }
    ],
    series : [
        {
            name:'xxx使用量',
            type:'bar',
            data:[300, 50, 100, 30, 50, 60, 20, 80, 70, 50, 30, 20, 70, 300, 20, 150, 45, 90],
            markPoint : {
                data : [
                    {type : 'max', name: '最大值'},
                    {type : 'min', name: '最小值'}
                ]
            },
            markLine : {
                data : [
                    {type : 'average', name: '平均值'}
                ]
            },
            itemStyle: {
                normal: {
                    color: 'rgba(28,132,198,.6)',//柱子颜色
                    // borderColor: '#1c84c6',//边框颜色
                    barBorderWidth: 3,
                    barBorderRadius: 2,
                    label: {
                        show: true,
                        position: 'insideLeft'
                    }
                }
            }
        }
    ]
};
barChart.setOption(baroption);
window.onresize = barChart.resize;
// 饼状图
var pieChart = echarts.init(document.getElementById("useStats-pie-chart"));
var pieoption = {
    backgroundColor: '#ffffff',
    tooltip : {
        trigger: 'item',
        formatter: "{a} 
{b} : {c} ({d}%)"
}, legend: { orient : 'vertical', x : 'left', data:['乌鲁木齐市','克拉玛依市','吐鲁番地区', '哈密地区','昌吉回族自治州','博尔塔拉蒙古自治州', '巴音郭楞蒙古自治州','阿克苏地区','克孜勒苏柯尔克孜自治州', '喀什地区','和田地区','伊犁哈萨克自治州', '塔城地区','阿勒泰地区','石河子', '阿拉尔','图木舒克','五家渠'] }, calculable : true, series : [ { name:'xxx使用量', type:'pie', radius : '80%', center: ['50%', '50%'], /*在series中添加itemStyle即可直观显示饼型数值*/ itemStyle:{ normal:{ label:{ show: true, formatter: '{b} : {c} ({d}%)' }, labelLine :{show:true} } }, data:[ {value:300, name:'乌鲁木齐市'}, {value:50, name:'克拉玛依市'}, {value:100, name:'吐鲁番地区'}, {value:30, name:'哈密地区'}, {value:50, name:'昌吉回族自治州'}, {value:60, name:'博尔塔拉蒙古自治州'}, {value:20, name:'巴音郭楞蒙古自治州'}, {value:80, name:'阿克苏地区'}, {value:70, name:'克孜勒苏柯尔克孜自治州'}, {value:50, name:'喀什地区'}, {value:30, name:'和田地区'}, {value:20, name:'伊犁哈萨克自治州'}, {value:70, name:'塔城地区'}, {value:300, name:'阿勒泰地区'}, {value:20, name:'石河子'}, {value:150, name:'阿拉尔'}, {value:45, name:'图木舒克'}, {value:90, name:'五家渠'} ] } ] }; pieChart.setOption(pieoption); $(window).resize(pieChart.resize);

上成品图:
echarts通过poi导出图片到excel文件_第2张图片
echarts通过poi导出图片到excel文件_第3张图片
2.导出功能
html代码:


<iframe name="none_iframe" style="display:none;">iframe>
<form method="post" id="none_form" target="none_iframe" style="display:none">form>

javascript代码

// 导出图表
function exportCharts(){
	// excel的文件名称
    var fileName = "xxx使用统计图表";
    /**
    * 柱状图的内容,base64格式数据,这里支持多个图表导出,有几个图就写几个fileContent和fileSize,只有一个的话写一个就够了
    * 图片格式data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABI4AAAEsCAYAAAClh/jbAAAgAElEQVR4XuzdB3hUVfo/8O+dSe8hCSlAaKJ0BBEQFBBQseFiwUVkURHEgtjWdV0bLPpTV10BRYodsWH5i64guIiAqKyASu8lgfTeJzNz/8 ........
    **/
    var fileContent1 = encodeURIComponent(barChart.getDataURL());
    // 饼状图内容,需要encodeURIComponent编码,防止传输过程符号丢失
    var fileContent2 = encodeURIComponent(pieChart.getDataURL());
    // 图片宽度和高度,为了计算图片比例,以便在excel中以正常比例显示,不至于拉伸
    var fileSize1 = barChart.getWidth() + ":" + barChart.getHeight();
    var fileSize2 = pieChart.getWidth() + ":" + pieChart.getHeight();
    // form表单的请求地址,ctx是你的项目地址
    $("#none_form").attr("action", ctx + "cozuxg/eeiduc");
    $("#none_form").append("");
    $("#none_form").append("");
    $("#none_form").append("");
    $("#none_form").append("");
    $("#none_form").append("");
    // 提交表单
    $("#none_form").submit();
    // 删除本次表单数据,这里要删除子元素,不然下次导出不了
    $("#none_form").empty();
}

java代码,这部分是公用的,所有导出echarts图表都调这一个接口


    /**
     * 通用导出图片到excel
     * @param fileContents base64图片内容
     * @param fileName excel文件名
     * @param fileSizes 文件尺寸,宽:高,因为在excel中是按单元格来设置图片的宽和高,所以要按图片的宽高比例算出在excel中需要多少个单元格
     * @param request 请求
     * @param response 返回
     */
    @PostMapping("/eeiduc")
    public void exportExcelForImg(String[] fileContents, String fileName, String[] fileSizes,
                             HttpServletRequest request,HttpServletResponse response) throws Exception
    {
        //创建Excel工作簿,xls格式用HSSFWorkbook,xlsx格式用SXSSFWorkbook
        HSSFWorkbook wb = new HSSFWorkbook();
        //创建sheet页
        HSSFSheet sheet = wb.createSheet(fileName);
        //创建绘图(画布),注明:一个sheet只能创建一个画布,但一个画布中可以添加多张图片
        HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
        
        String fileContent;
        String fileSize;
        // 图片宽度
        Double width;
        // 图片高度
        Double height;
        // 指定起始的单元格行索引,默认1
        int col1 = 1;
        // 指定起始的单元格列索引,row1=上一个row2+1,+1是为了两个图片之间隔开一行
        int row1;
        // 指定结束的单元格行索引,相当于宽,默认18
        int col2 = 18;
        // 指定结束的单元格列索引,相当于高,row2=row1+col2*(height/width)*3.5,乘以3.5是因为单元格的宽是高的3.5倍
        int row2 = 0;
        // 支持多个图表导入
        for(int i = 0; i < fileContents.length;i++){
            fileContent = fileContents[i];
            if(fileContent.length() > 0){
                fileSize = fileSizes[i];
                width = Double.valueOf(fileSize.split(":")[0]);
                height = Double.valueOf(fileSize.split(":")[1]);
                // 图片编码只要‘base64,’后面的部分
                fileContent = URLDecoder.decode(fileContent,"UTF-8").substring(22);
                row1 = row2 + 1;
                row2 = row1 + (int) Math.ceil(col2 * (height / width) * 3.5);
                ExcelUtil.createPictureInExcel(fileContent, patriarch, wb, (short) col1, row1, (short) col2, row2);
            }
        }
        // 重命名,文件名前面加时间,如20200805135638_xxx使用统计.xls,这部分代码按项目风格自行来定
        String timeStr = DateUtils.parseDateToStr("yyyyMMddHHmmss", DateUtils.getNowDate());
        fileName = timeStr + "_" + fileName + ".xls";
        //图片写入Excel
        OutputStream out = response.getOutputStream();
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("gb2312"), "ISO8859-1" ));
        wb.write(out);
        wb.close();
    }

ExcelUtil.createPictureInExcel代码


    /**
     * 将图片保存到excel中
     * @param dataChart  图片的BASE64格式编码
     * @param patriarch  Excel-sheet 画布
     * @param wb         Excel工作簿
     * @param col1  指定起始的单元格行索引
     * @param row1  指定起始的单元格列索引
     * @param col2  指定结束的单元格行索引
     * @param row2  指定结束的单元格列索引
     * @throws Exception
     */
    @SuppressWarnings("restriction")
    public static void createPictureInExcel(String dataChart, HSSFPatriarch patriarch, HSSFWorkbook wb,
                                     short col1, int row1, short col2, int row2) throws Exception{
        //用于将BASE64编码格式转为byte数组
        BASE64Decoder base64Decoder = new BASE64Decoder();
        ByteArrayOutputStream dataChartoutStream = new ByteArrayOutputStream();
        //将dataChartStringin作为输入流,读取图片存入image中
        ByteArrayInputStream dataChartin = new ByteArrayInputStream( base64Decoder.decodeBuffer(dataChart));
        BufferedImage dataChartbufferImg = ImageIO.read(dataChartin);
        //利用HSSFPatriarch将图片写入EXCEL
        ImageIO.write(dataChartbufferImg, "png", dataChartoutStream);
        /*
         * 指定绘图区域位置及大小
         * HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2)
         * 参数说明:
         * dx1 dy1 起始单元格中的x,y坐标.
         * dx2 dy2 结束单元格中的x,y坐标.
         * col1,row1 指定起始的单元格,下标从0开始.
         * col2,row2 指定结束的单元格 ,下标从0开始.
         */
        HSSFClientAnchor anchorCostStr = new HSSFClientAnchor(0, 0, 0, 0, col1, row1, col2, row2);
        //画图
        patriarch.createPicture(anchorCostStr, wb.addPicture(dataChartoutStream.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG));
    }

导出成品图
echarts通过poi导出图片到excel文件_第4张图片

我这里是用固定宽度18个单元格来算高度需要多少个单元格,如果有需要也可以用固定高度来算宽度,到这里就大功告成了,祝大家工作愉快!

你可能感兴趣的:(echarts,java,poi)