POI导出echarts统计报表到Excel

    xiaoxiao2022-07-03  120

    一、前台

    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;

    最新回复(0)