POI导出echarts统计报表到Excel

一、前台

1.创建echarts统计图相关

//基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('taskTotal'));//项目统计

//项目统计指定图表的配置项和数据
var initOption = {
    title: {
        text: '月度计划项目统计图',
        x:'center',
        y:'top',//标题位置
        textAlign:'center'
    },
    tooltip: {
        trigger: 'axis'//鼠标移上图标触发轴
    },
    legend: {//图例;
        data:['计划完成值','实际完成值'],
        x:'center',
        y:'bottom'//图例位置
    },
    grid: {
        left: '3%',
        right: '4%',
        bottom: '3%',
        containLabel: true//坐标轴标签不会溢出容器
    },
    toolbox: {
        feature: {
            saveAsImage: {}
        }
    },
    xAxis: {
        type: 'category',
        boundaryGap: false,//左右无留白;
        name:'月份',//横轴名称
        data: []
    },
    yAxis: {
        type: 'value',
        name:'数量'//纵轴名称
    },
    series: [
        {	
        	name:'计划完成值',
            type:'line',
            stack: '总量2',
            symbol: 'circle',     //设定为实心点
            symbolSize: 10,   //设定实心点的大小
            itemStyle : {  
                normal : { 
                    color:'#0099ff' ,//折线点颜色
                    lineStyle:{  
                        color:'#0099ff' ,//折线条颜色
                        width:2,
                        type:'dashed'  //'dotted'虚线 'solid'实线 
                    }  
                }
            },
            data:[]
        },
        {
        	name:'实际完成值',
            type:'line',
            stack: '总量1',
            symbol: 'circle',     //设定为实心点
            symbolSize: 10,   //设定实心点的大小
            itemStyle : {  
                normal : {  
                    lineStyle:{  
                        color:'red',
                        width:2 
                    }  
                }
            },
            data:[]
        }
    ]
};

以上的taskTotal是一个预先准备好id=“taskTotal”的dom,即一个有明确宽高的div区域。

2.给统计图赋值

//项目统计
function taskTotal(unitNames,startDate,endDate){
	$.ajax({
		url :webCfg.servePath +"/reportForm/showTotalForm",
		type: "POST",
		dataType : "JSON",
		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
		data: {"unitNames":encodeURI(unitNames),"startDate":startDate,"endDate":endDate},
		cache : false,
		beforeSend : function(XHR) {
        },
		success : function(result) {
			//请求成功时处理
			var data =result;
			if (typeof(data.xAxis) == "undefined"||typeof(data.series) == "undefined"){
				initOption.xAxis.data = [];//x轴
				initOption.series[0].data = [];
				initOption.series[1].data = [];
			}else{
				//initOption.legend.data = data.legend;
				initOption.xAxis.data = data.xAxis;//x轴
				var serieslist = data.series;
				for (var i = 0; i < serieslist.length; i++) {//循环放入数据
					initOption.series[i].data = serieslist[i];
				}
			}
			myChart.setOption(initOption, true);
			var common=$("#taskTotal").parent();//该表单的父节点
			//页面表单回显
			common.find("input[name='startTime']").val(data.echoes.startTime);
			common.find("input[name='endTime']").val(data.echoes.endTime);
			common.find("input[name='unitNames']").val(data.echoes.unitNames);
			//给报表表格添加内容;
			var html ="";
			if(data.xAxis!= null && typeof data.xAxis !== "undefined" && data.xAxis.length>0){
				for(var i=0;i<data.xAxis.length;i++){
                    html+="<tr>";
                    html+="<td width='6%'>"+(i+1)+"</td>";
                    html+="<td>"+data.xAxis[i]+"</td>";
                    html+="<td>"+data.xAxis[i]+"</td>";
                    html+="<td>"+(data.series[0])[i]+"</td>";
                    html+="<td>"+(data.series[1])[i]+"</td>";
                    html+="</tr>";
                }
			}else{
  			    html ="<tr><td colspan='99' style='text-align:center'>查询数据为空</td></tr>";
  			}
			common.find("tbody").empty();
			common.find("tbody").append(html);
		},
		complete : function() {
		//请求完成的处理
		},
		error : function(e) {
			//请求出错处理
			alert(e);
		}
	});
}

赋值数据通过请求后台得到,这里省略(按需要补充)。

3.js以post方式提交统计报表数据

//点击导出按钮获取到导出Excel的相关数据
function btnExcel() {
	var picBaseCode=myChart.getDataURL();
	//获取报表上存在的条件
	var unitNames=nodeCommon.find("input[name='unitNames']").val();
	var	startDate=nodeCommon.find("input[name='startTime']").val();
	var	endDate=nodeCommon.find("input[name='endTime']").val();
	var	status=nodeCommon.find("input[name='status']").val();
	var	delayNum=nodeCommon.find("input[name='delayNum']").val();
	//调用方法请求后台;
	reportExcel(index+1,picBaseCode,unitNames,startDate,endDate,status,delayNum);
}

//封装待导出Excel的参数
function reportExcel(reportType,picBaseCode,unitNames,startDate,endDate,status,delayNum){
	var url=webCfg.servePath +"/reportForm/reportExcel";
    var params = {
    	"reportType":reportType,
    	"picBaseCode":picBaseCode,
    	"unitNames":encodeURI(unitNames),
    	"startDate":startDate,
    	"endDate":endDate,
    	"status":encodeURI(status),
    	"delayNum":encodeURI(delayNum)        
    };

    httpPost(url, params);
}

//发送POST请求跳转到指定页面
function httpPost(URL, PARAMS) {
    var temp = document.createElement("form");
    temp.action = URL;
    temp.method = "post";
    temp.style.display = "none";

    for (var x in PARAMS) {
        var opt = document.createElement("textarea");
        opt.name = x;
        opt.value = PARAMS[x];
        temp.appendChild(opt);
    }

    document.body.appendChild(temp);
    temp.submit();

    return temp;
}

二、后台

    /**
     * 导出报表
     *
     * @return
     */
    @RequestMapping(value = "/reportExcel", method = RequestMethod.POST)
    public Object getReportExcel(HttpServletRequest request, HttpServletResponse             response) throws Exception {
        fileName = "项目统计表.xlsx";
        OutputStream os=response.getOutputStream();
        setFileName(request, response, fileName);//设置导出文件标题及编码
        // 第一步,创建一个HSSFWorkbook,对应一个Excel文件
        // 创建Excel工作薄
        Workbook book = null;
        try {
            book = new XSSFWorkbook();//excell2007
        } catch (Exception ex) {
            book = new HSSFWorkbook();//excell2003
        }

        // 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
        Sheet sheet = book.createSheet(fileName);

        //调用方法获取统计报表内的表格数据(此处省略,需自行补充,同前台echarts统计图数据源)
        @SuppressWarnings("unchecked")
        Map<String, Object> result = (Map<String, Object>) taskTotalForm(request);
        String[] xAxis = (String[]) result.get("xAxis");
        @SuppressWarnings("unchecked")
        List<Integer[]> series = (List<Integer[]>) result.get("series");

        // 第三步,设置标题和表头;
        Row row = sheet.createRow(0);// 创建第一行,设置表的标题;
        row.setHeightInPoints(36);//设置行的高度是34个点
        Cell cell = row.createCell(0);
        cell.setCellValue(headTitle);
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, cols - 1));//第一行跨表所有列;
        // 第二行为表头行
        String title = "";
        Row row1 = sheet.createRow(1);// 创建第2行
        row1.setHeightInPoints(22);//设置表头行的高度是20个点
        for (int i = 0; i < 4; i++) {
            Cell cell = row1.createCell(i);
            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
            if (i == 0) {
                title = "月份";
            }
            if (i == 1) {
                title = "时间节点";
            }
            if (i == 2) {
                title = "计划完成项";
            }
            if (i == 3) {
                title = "实际完成项";
            }
            cell.setCellValue(title);
        }
        int start = 2;
        //根据各一级任务的分解任务数循环向单元格填充数据;
        for (int i = 0; i < xAxis.length; i++) {
            Row row = sheet.createRow(start + i);
            Cell cell0 = row.createCell(0);
            Cell cell1 = row.createCell(1);
            Cell cell2 = row.createCell(2);
            Cell cell3 = row.createCell(3);
            cell0.setCellValue(xAxis[i]);
            cell1.setCellValue(xAxis[i]);
            cell2.setCellValue(series.get(0)[i]);
            cell3.setCellValue(series.get(1)[i]);
        }
        //生成统计图图片
        String imgUrl = request.getParameter("picBaseCode");
        if (!imgUrl.isEmpty()) {
            String[] imgUrlArr = imgUrl.split("base64,");//拆分base64编码后部分
            byte[] buffer = new BASE64Decoder().decodeBuffer(imgUrlArr[1]);
            //获取项目运行目录的路径:以下是request.getRealPath()的代替方法
            String picPath = request.getSession().getServletContext().getRealPath(
                    "static/app/appkmbgszh/images" + fileName + ".png");
            File file = new File(picPath);//图片文件
            try {
                //生成图片
                OutputStream out = new FileOutputStream(file);//图片输出流
                out.write(buffer);
                out.flush();//清空流
                out.close();//关闭流
                // 将图片写入流中
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                BufferedImage bufferImg = ImageIO.read(file);
                ImageIO.write(bufferImg, "PNG", outStream);
                // 利用HSSFPatriarch或XSSFDrawing将图片写入EXCEL
                Drawing patri = sheet.createDrawingPatriarch();
                //偏移量  这个有点恶心, 这个单位直接以万 计, 10000以下 基本设了等于没设。原因不明 ,操作2003 的 HSSF 是正常的比例  
                ClientAnchor anchor = new XSSFClientAnchor(30 * 10000, 0, 100, 100, 5, 1, 18, 22);
                patri.createPicture(anchor, book.addPicture(outStream.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG));

                // 写入数据 把相应的Excel 工作簿存盘
                book.write(os);
                book.close();
                os.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            if (file.exists()) {
                file.delete();//删除图片
            }
        }
    }


    /**
     * 设置导出文件名,并处理编码问题;
     * @param request
     * @param response
     * @param name
     * @throws UnsupportedEncodingException
     */
    public void setFileName(HttpServletRequest request, HttpServletResponse response, String name)
            throws UnsupportedEncodingException {
        String agent = request.getHeader("USER-AGENT");
        if (null != agent && -1 != agent.indexOf("MSIE") || null != agent && -1 != agent.indexOf("Trident")) {// IE
            name = java.net.URLEncoder.encode(name, "UTF8");

        } else if (null != agent && -1 != agent.indexOf("Mozilla")) {// 火狐,chrome等
            name = new String(name.getBytes("UTF-8"), "iso-8859-1");
        }
        response.setHeader("Content-disposition", "attachment; filename=" + name);
    }

三、说明

关于HSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2)的参数,有必要在这里说明一下:
    dx1:起始单元格的x偏移量,如例子中的255表示直线起始位置距A1单元格左侧的距离;
    dy1:起始单元格的y偏移量,如例子中的125表示直线起始位置距A1单元格上侧的距离;
    dx2:终止单元格的x偏移量,如例子中的1023表示直线起始位置距C3单元格左侧的距离;
    dy2:终止单元格的y偏移量,如例子中的150表示直线起始位置距C3单元格上侧的距离;
    col1:起始单元格列序号,从0开始计算;
    row1:起始单元格行序号,从0开始计算,如例子中col1=0,row1=0就表示起始单元格为A1;
    col2:终止单元格列序号,从0开始计算;
    row2:终止单元格行序号,从0开始计算,如例子中col2=2,row2=2就表示起始单元格为C3;

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值