java导出为excel

导出时候遇到的问题:

  • poi导出excel不下载:不可以使用ajax提交(jp.post/jp.get);否则会无法出现文件自动下载的那个框,后台也不会报错,执行完就完了,没有任何反应;(使用的是window.location.href=url;参数也拼接在url路径中了);
  • 不在方法上指定提交方式,就会既允许get,又允许post;所以就不指定了;
  • 如果合并单元格的话,注意合并单元格前为每个格子都设置对应的样式,否则若设置边框的话,只有第一个格子有边框,其他的都没有;
  • 想要导出到同一个excel中的多个sheet使用 workbook.createSheet();

前端js:

//导出
function reportExport(){
	var ids = getIdSelections();
	if(ids==''){
		jp.error("请先选择要导出的报表!");
	}else{
		jp.confirm('确认要导出选中报表的数据吗?',function(){
			var url = "${ctx}/pri/select/priReportExport/export?ids=" + ids;
			window.location.href=url;
		});
	}
}

后台代码:

	/**
	 * 导出选中的报表到excel文件
	 */
	@ResponseBody
	@RequestMapping(value = "export")
	public AjaxJson export(HttpServletRequest request, HttpServletResponse response,RedirectAttributes redirectAttributes) {
		AjaxJson json = new AjaxJson();
		//处理导出——begin
		String p = "项目路径";
		String name = "userfiles/exportMoudle/export.xlsx";//模板的路径
		File newFile = FileUtils.createNewFile(p+"/"+name, p);
		FileInputStream is = null;
		XSSFWorkbook workbook = null;
		XSSFSheet sheet = null;
		try {
			is = new FileInputStream(newFile);// 将excel文件转为输入流
			workbook = new XSSFWorkbook(is);// 创建个workbook
			XSSFCellStyle cellStyle = workbook.createCellStyle();
			cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER); // 居中 
			//cellStyle.setWrapText(true); //设置换行	
            //获得第一个sheet
 			sheet = workbook.getSheetAt(0);
            
			//创建表头--begin
			XSSFRow titleRow = sheet.createRow(0);
			XSSFCell titleCell = titleRow.createCell(0);
			titleCell.setCellValue("xx监测表");//还需要设置具体的样式
            //需要合并的单元格--起始行,结束行,起始列,结束列
			CellRangeAddress cellRangeAddress = new CellRangeAddress(0,3,0,1);
			sheet.addMergedRegion(cellRangeAddress);
			//创建表头--end
			
			//导出内容--begin
			//从第二行开始
			int rowNum = 4;
			for(int i = 0; i < 1; i++){
				//创建一行
			    XSSFRow row = sheet.createRow((rowNum + i));
			    XSSFCell cell = row.createCell(0);
			    cell.setCellValue(i);
			    cell.setCellStyle(cellStyle);
    		
			    cell = row.createCell(1);
			    cell.setCellValue(i+1);
			    cell.setCellStyle(cellStyle);
			        		
			    cell = row.createCell(2);
			    cell.setCellValue(i+2);
			    cell.setCellStyle(cellStyle);
			        		
			    cell = row.createCell(3);
			    cell.setCellValue(i+3);
			    cell.setCellStyle(cellStyle);
			}
			//导出内容--end
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		if (sheet != null) {
			try {
				//写数据
				FileOutputStream fos = new FileOutputStream(newFile);
				workbook.write(fos);
				fos.flush();
				fos.close();
				//下载
				InputStream fis = new BufferedInputStream(new FileInputStream(newFile));
				byte[] buffer = new byte[fis.available()];
				fis.read(buffer);
				fis.close();
				response.reset();
				response.setContentType("text/html;charset=UTF-8");
				OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
				response.setContentType("application/x-msdownload");
				//定义名字
				SimpleDateFormat formt = new SimpleDateFormat("yyyy-MM-dd");
				String newName = "价格报送_" + formt.format(new Date()) + ".xlsx";
				newName = URLEncoder.encode(newName, "UTF-8");
				response.addHeader("Content-Disposition","attachment;filename=\"" + newName + "\"");
				response.addHeader("Content-Length", "" + newFile.length());
				toClient.write(buffer);
				toClient.flush();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					if (null != is) {
						is.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		//删除创建的新文件
		FileUtils.deleteFile(newFile);
		//处理导出 ——end
		return json;
	}

工具类:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;

public class FileUtils {
	
	 /**
     * 读取excel模板,并复制到新文件中供写入和下载
     * @param tempPath  模板路径+名称
     * @param rPath	新路径
     * @return
     */
    public static File createNewFile(String tempPath, String rPath) {
        // 读取模板,并赋值到新文件************************************************************
        // 文件模板路径
        File file = new File(tempPath);
        // 保存文件的路径
        String realPath = rPath;
        // 新的文件名
        String newFileName = System.currentTimeMillis() + ".xlsx";
        // 判断路径是否存在
        File dir = new File(realPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        // 写入到新的excel
        File newFile = new File(realPath, newFileName);
        try {
            newFile.createNewFile();
            // 复制模板到新文件
            fileChannelCopy(file, newFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return newFile;
    }
    
    /**
     * 复制文件
     * 
     * @param s
     *            源文件
     * @param t
     *            复制到的新文件
     */

    public static void fileChannelCopy(File s, File t) {
        try {
            InputStream in = null;
            OutputStream out = null;
            try {
                in = new BufferedInputStream(new FileInputStream(s), 1024);
                out = new BufferedOutputStream(new FileOutputStream(t), 1024);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = in.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }
            } finally {
                if (null != in) {
                    in.close();
                }
                if (null != out) {
                    out.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    
    /**
    * 下载成功后删除
    * 
    * @param files
    */
    public static void deleteFile(File... files) {
       for (File file : files) {
           if (file.exists()) {
               file.delete();
           }
       }
   }
    
    /**
     * 读取任意模板,并复制到新文件中供写入和下载
     * @param file  源文件
     * @param rPath	新路径
     * @param newFileName  新文件名称
     * @return
     */
    public static File createNewFile(File file, String rPath, String newFileName) {
        // 读取模板,并赋值到新文件************************************************************
        // 保存文件的路径
        String realPath = rPath;
        // 判断路径是否存在
        File dir = new File(realPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        // 写入到新的excel
        File newFile = new File(realPath, newFileName);
        try {
            newFile.createNewFile();
            // 复制模板到新文件
            fileChannelCopy(file, newFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return newFile;
    }
    /**
     * 计算文件大小
     * @param bytes
     * @return
     */
    public static String bytesTrans(long bytes) {  
        BigDecimal filesize = new BigDecimal(bytes);  
        BigDecimal megabyte = new BigDecimal(1024 * 1024);
        
        float returnValue = filesize.divide(megabyte, 2, BigDecimal.ROUND_UP).floatValue();  
        if (returnValue > 1)
            return (returnValue + "MB");  
        BigDecimal kilobyte = new BigDecimal(1024); 
        returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();  
        return (returnValue + "KB");  
    }    
    
}

后台所有代码如下:

	/**
	 * 导出选中的报表到excel文件
	 */
	@ResponseBody
	@RequestMapping(value = "export")
	public AjaxJson export(String start,String ids, HttpServletRequest request, HttpServletResponse response,RedirectAttributes redirectAttributes) {
		AjaxJson json = new AjaxJson();
		String[] idArr = ids.split(",");
		
		//处理导出  —— begin  
		//这里是获得导出的路径,配置在properties文件中
		String p = request.getSession().getServletContext().getRealPath(Global.getConfig(Constant.EXPORT_MOULD));
		String name = Constant.PRI_REPORT_EXPORT;
		File newFile = FileUtils.createNewFile(p+"/"+name, p);
		FileInputStream is = null;
		XSSFWorkbook workbook = null;
		XSSFSheet sheet = null;
		try {
			is = new FileInputStream(newFile);// 将excel文件转为输入流
			workbook = new XSSFWorkbook(is);// 创建个workbook
			
			//表体的样式
			XSSFCellStyle cellStyle = workbook.createCellStyle();
			cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER); //居中 
			cellStyle.setBorderTop(CellStyle.BORDER_THIN);//设置边框
			cellStyle.setBorderRight(CellStyle.BORDER_THIN);
			cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
			cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
            //表头的样式
			XSSFCellStyle titleCellStyle = workbook.createCellStyle();
			titleCellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER); //居中 
	        Font font = workbook.createFont();//设置字体
	        font.setFontHeightInPoints((short) 20);//字体高度
	        font.setFontName(" 黑体 "); //字体
	        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//字体加粗
	        titleCellStyle.setFont(font);
	        
			for(int x=0;x<idArr.length;x++){//ids中有几个id,就有几个sheet,所以应该循环
				//获得报表实体
				PriReportTemplate priReportTemplate = priReportTemplateService.get(idArr[x]);
				//获取指定报表的周期规则
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				PriReportTemplatePeriod weekPeriod = priReportTemplateService.getTemplatePeriodById(priReportTemplate.getPeriodId());
				int firstDayOfWeek = Integer.parseInt(weekPeriod.getPeriod().substring(0, 1))+1;
				int week = WeekUtils.getWeekOfYear(sdf.parse(start), firstDayOfWeek);//页面传递的日期所处周期
				String reportName = start.substring(0,4)+"年第"+week+"周";
				PriReportPeriod priReportPeriod = priReportPeriodService.findPeriodByName(reportName,priReportTemplate.getId());
				
				//创建sheet
				if(x==0){//workbook本身自己有一个sheet---int f = workbook.getNumberOfSheets();//结果为1
					sheet = workbook.getSheetAt(0);
					workbook.setSheetName(x,priReportTemplate.getName());
				}else{
					sheet = workbook.createSheet(priReportTemplate.getName());
				}
				
				//创建标题---标题的内容是动态读取的,标题合并几个单元格也是动态读取的,需要根据下面的数据动态设置
				//创建标题--begin
				XSSFRow titleRow = sheet.createRow(0);
				XSSFCell titleCell = titleRow.createCell(0);
				titleCell.setCellValue(priReportTemplate.getName());
				titleCell.setCellStyle(titleCellStyle);//还需要设置具体的样式
				int colNum = 0;
				//创建标题--end

				
				//查询表头第一列的数据
		        List<PriReportTemplateDetail> priReportTemplateDetailList = priReportTemplateDetailDao.findList(new PriReportTemplateDetail(priReportTemplate));
				List<String> listName = new ArrayList<>();
		        for(PriReportTemplateDetail detail : priReportTemplateDetailList){
		        	listName.add(detail.getName());
				}
		        String[] headers = listName.toArray(new String[0]); 
				//表头数据
				//拿到指定模板主表所拥有的表头信息
				PriReportTemplateMid priReportTemplateMid = new PriReportTemplateMid();
				priReportTemplateMid.setPeriodId(priReportPeriod.getId());
				priReportTemplateMid.setTemplateId(priReportTemplate.getId());
				String treeData = priReportTemplateService.getDataFromMid(priReportTemplateMid);//根据报表期id以及报表id获得json串,如果没有的话,从header表中查询出来插入进去,然后重新查询
				if(treeData==null){//判断中间表中是否有该期、该模板对应的表头json串,没有的话新增
					List<PriReportHeaderJson> priReportHeaderListAll = priReportHeaderService.getAllData(priReportTemplate.getId());
			        List<PriReportHeaderJson> treeList = PriReportHeaderService.listToTree(priReportHeaderListAll);//生成树形结构的List集合
			        String headerData = JSON.toJSONString(treeList);//把集合转换成json字符串存入中间表中
			        priReportTemplateMid.setHeaderData(headerData);
					priReportTemplateService.saveDataToMid(priReportTemplateMid);//保存到中间表
					treeData = priReportTemplateService.getDataFromMid(priReportTemplateMid);//重新查询
				}
		        //把从中间表中查询出来的json字符串转换成json数组对象
		        JSONArray jsonArray = JSON.parseArray(treeData);
		        //每一层中每一个格子需要合并的单元格数目,都取决于他的children的最大的个数
		        listMap = new ArrayList<HashMap>();//每次重新放数据之前都要清空里面的数据
		        for(int j=0;j<jsonArray.size();j++){
		        	getLength(jsonArray.getJSONObject(j),0);
		        }
				
				//导出表头内容--begin
				int rowNum = 3;//从第二行开始
				for(int i = 0; i <= headers.length; i++){//创建几行,循环几次,先创建表头的几行数据
				    XSSFRow row = sheet.createRow((rowNum + i));//创建一行
				    XSSFCell cell = null;//创建一个格子
				    //第一列
				    if(i<headers.length){
					    cell = row.createCell(0);
					    cell.setCellValue(headers[i]);
					    cell.setCellStyle(cellStyle);
				    }else{
					    cell = row.createCell(0);
					    cell.setCellValue("监测点名称");
					    cell.setCellStyle(cellStyle);
				    }
				    //后面的几列
				    List<HashMap> list = getListByIndex(i);//这里拿到的是同一层的数据
				    int col = 0;
				    for(int j=0;j<list.size();j++){
					    cell = row.createCell(col+1);
					    cell.setCellValue(list.get(j).get("subject")+"");
					    cell.setCellStyle(cellStyle);
					    int endCol = col+Integer.parseInt(list.get(j).get("length")+"");
					    //********防止有的格子没有边框的操作
					    for(int s=col+2;s<=endCol;s++){//为每个单元格都设置一下边框,否则合并单元格后只有第一个格子有对应的样式
					    	cell = row.createCell(s);
					    	cell.setCellValue("");
					    	cell.setCellStyle(cellStyle);
					    }
					    CellRangeAddress cellRange = new CellRangeAddress(rowNum + i,rowNum + i,col+1,endCol);//起始行,结束行,起始列,结束列
					    sheet.addMergedRegion(cellRange);
					    col += Integer.parseInt(list.get(j).get("length")+"");
					    if(i==0){
					    	colNum+=Integer.parseInt(list.get(j).get("length")+"");
					    }
				    }
				}
				//合并标题的单元格
				CellRangeAddress cellRangeAddress = new CellRangeAddress(0,1,0,colNum);//起始行,结束行,起始列,结束列
				sheet.addMergedRegion(cellRangeAddress);
				//导出表头内容--end
				
				//报表期以及填报单位
				XSSFRow subRow = sheet.createRow(2);
				XSSFCell periodCell = subRow.createCell(0);
				periodCell.setCellValue(reportName);
				XSSFCell unitCell = subRow.createCell(colNum);//把单位放到最后一列
				unitCell.setCellValue(priReportTemplate.getCount());
				
				//查询列表数据
				List<HashMap> listAll = new ArrayList<HashMap>();
				String officeId = UserUtils.getUser().getCompany().getId();
				//寻找上一周未停止报送的情况
				PriReportPeriod period = new PriReportPeriod();
				while(true){
					if(week-1!=0){
						week--;
					}else{//否则是上一年的最后一周  TODO
						
					}
					String periodName = start.substring(0,4)+"年第"+week+"周";
					period = priReportPeriodService.findPeriodByName(periodName,priReportTemplate.getId());
					if(period.getStatus().equals("10")){//找到了正常报送的上一周的数据
						break;
					}
				}
				//从填报主表寻找上一期的数据
				List<HashMap> fill = priReportFillService.getAverageData(priReportTemplate.getId(),period.getId(),officeId);
				List<HashMap> averageDetailList = new ArrayList<HashMap>();
				if(fill.size() != 0){//获得填报子表的数据
					averageDetailList = priReportFillService.getConvertList((String)fill.get(0).get("id"));
				}
				
				//判断是走哪个查询数据的逻辑
				if(priReportTemplate.getName().equals("省级重点购销企业原粮市场监测表")||priReportTemplate.getName().equals("省级重点批发市场价格监测表")||priReportTemplate.getName().equals("省级重点超市价格监测表")||priReportTemplate.getName().equals("市级物流节点原粮价格监测表")){
			        //2查询列表数据
			        //先查询审核通过的所有数据
			        List<HashMap> priReportFillList = priReportFillService.getSelectDataList(priReportTemplate.getId(),priReportPeriod.getId());//2.1查询所有状态为已审核的主表数据---根据模板主表id、报表期id,获得当期的填报数据
			        //把审核通过的数据是当前用户所管理的所有监测点的数据拿过来
			        PriReportOffice priOffice = priReportOfficeService.getPriOffice(officeId,priReportTemplate.getId());
			        List<Office> currentPointList = priReportOfficeService.getAllPointList(priOffice.getCode(),priReportTemplate.getId());//当前登录用户下的所有监测点
			        List<HashMap> currentFillList = new ArrayList<HashMap>();
			        for(int i=0;i<currentPointList.size();i++){
			    		Office office = currentPointList.get(i);
			    		for(int j=0;j<priReportFillList.size();j++){
			    			HashMap hashMap = priReportFillList.get(j);
			    			String psId = (String)hashMap.get("pointId");
			    			if(office.getId().equals(psId)){//从所有的列表数据中获得当前登录用户下的监测点
			    				currentFillList.add(hashMap);
			    			}
			    		}
			        }
			        if(currentFillList.size()!=0){//当有审核通过的数据的时候才会有列表数据
				        int detailLength = priReportFillService.getDetailList((String)currentFillList.get(0).get("id")).size();//获得格子的个数
				        float[] sumArray = new float[detailLength];//定义一个数组存放纵向看报表格子的数值的和(初始化为默认值,int型为0)
				        float[] sumNum = new float[detailLength];//存放求和数据的个数--对几个求和了就以几为基数求平均值
				        boolean[] isAverage = new boolean[detailLength];//标识是否计算平均值了
				        for(int i=0;i<currentFillList.size();i++){
				            //遍历获得填报子表中的数据---是从单位换算后的表中查询的数据
				            List<HashMap> fillDetailList = priReportFillService.getConvertList((String)currentFillList.get(i).get("id"));
				            for(int j =0;j<fillDetailList.size();j++){//对一行数据进行遍历,挨个拿出来code,判断是否计算平均值
				            	PriReportHeader priReportHeader = priReportHeaderService.getHeaderData(priReportTemplate.getId(),(String)fillDetailList.get(j).get("code"));
				            	if(null != priReportHeader.getAverage() && null!=fillDetailList.get(j).get("value") && priReportHeader.getAverage().equals("10")){
				            		isAverage[j]=true;
				            		sumNum[j]++;
				            		sumArray[j] = sumArray[j]+Float.parseFloat((String)fillDetailList.get(j).get("value"));
				            	}
				            }
				            //把数据按照格式放到map中(监测点数据直接封装到List<HashMap>,然后对这个进行遍历,对应着挨个放进自己的detail的list(也是存好成hashMap了---注意排序->根据code排序)!)
				            currentFillList.get(i).put("data", fillDetailList);
				        }
				        //计算平均值以及与上期的比
				        List<HashMap> listAverage = new ArrayList<HashMap>();//平均值
				        List<HashMap> listCompare = new ArrayList<HashMap>();//与上期比
				        for(int i=0;i<sumArray.length;i++){
							HashMap average = new HashMap();
							HashMap compare = new HashMap();
							float averageValue=0;
							if(sumNum[i]!=0){
								averageValue = sumArray[i]/sumNum[i];
								average.put("value",String.format("%.2f",averageValue));//固定写保留两位小数
							}
							//查询上期平均值(注意不应该是直接上期,因为如果直接上期停止报送的话,比值就是错误的)
							//用当期平均值减去上期平均值
							/*float compareValue = averageValue-0;//TODO
							if(isAverage[i]==true){//只有计算平均价的才显示与上期的数据比值
								compare.put("value",String.format("%.2f",compareValue));//固定写保留两位小数
							}*/
							float compareValue = 0;
							if(averageDetailList.size() != 0 && averageDetailList.get(i).get("value")!=null){//按顺序减去上期的比
								compareValue = averageValue-Float.parseFloat((String)averageDetailList.get(i).get("value"));
							}else{
								compareValue = averageValue-0;
							}
							if(isAverage[i]==true){
								compare.put("value",String.format("%.2f",compareValue));//固定写保留两位小数
							}
							listAverage.add(average);
							listCompare.add(compare);
				        }
				        //拼接平均值、与上期比以及监测点的list集合
						HashMap hash1 = new HashMap();
						hash1.put("officeName", "全省平均价");
						hash1.put("data",listAverage);//平均值的list集合
						listAll.add(hash1);
						HashMap hash2 = new HashMap();
						hash2.put("officeName", "与上期比");
						hash2.put("data",listCompare);//与上期比的list集合
						listAll.add(hash2);
						listAll.addAll(currentFillList);
			        }
				}else{
					//2查询列表数据
			        //先查询审核通过的所有数据
					String reportId = priReportTemplate.getId();
			        List<HashMap> priReportFillList = priReportFillService.getSelectDataList(reportId,priReportPeriod.getId());//2.1查询所有状态为已审核的主表数据---根据模板主表id、报表期id,获得当期的填报数据
			        //list存放所有的监测点的list
			        List<List<HashMap>> listCityData = new ArrayList<List<HashMap>>();
			        //把审核通过的数据是当前用户所管理的所有监测点的数据拿过来
			        PriReportOffice priOffice = priReportOfficeService.getPriOffice(officeId,reportId);
			        List<Office> currentPointList = priReportOfficeService.getAllPointList(priOffice.getCode(),reportId);//当前登录用户下的所有监测点
			        //这个code是这个报表组织机构的code,所以新集挂在了河北省下的话,就会有他的数据
			        String[] codes = priReportOfficeService.getCodes(priOffice.getCode(),reportId);//获取当前登录用户下所有的市级的code
			        for(int i=0;i<codes.length;i++){//一个市的数据
			        	List<HashMap> cityFillList = new ArrayList<HashMap>();
			        	List<Office> cityList = new ArrayList<Office>();//每个市的监测点分别放到不同的list集合中
			        	for(int j=0;j<currentPointList.size();j++){//这里可以拿到当前登录用户下的监测点当前市的监测点,同时获得对应的审核通过的数据
			        		Office office = currentPointList.get(j);
			        		if(office.getCode().substring(0, 6).equals(codes[i])){//说明是当前市下的监测点,把组织机构都放在一起,同一个list中的组织机构对应的监测点的数据一起求平均值
			        			cityList.add(office);
			            		for(int f=0;f<priReportFillList.size();f++){
			            			HashMap hashMap = priReportFillList.get(f);
			            			String psId = (String)hashMap.get("pointId");
			            			if(office.getId().equals(psId)){//从所有的列表数据中获得当前登录用户下的监测点(如果当前拿到的监测点--即是当前登录用户下的,又通过审核了)
			            	            cityFillList.add(hashMap);//那么就拿到这条数据,把这条数据放到???一个list中,这个list还要和这个市进行拼接
			            			}
			            		}
			        		}
			        	}
			        	if(cityFillList.size()>0){//如果当前市下有数据,那么就给他放到大的list中
			        		listCityData.add(cityFillList);//当前登录用户,且当前市下,有哪些通过审核的数据都在这里了!
			        	}
			        }
			        //listCityData这个是所有市级的list集合
			        if(listCityData.size()>0){//这个是想求全省平均值的分母,即有几个市就除以几,否则都是0?或者就直接没有全省平均价以及与上期比这两行
						HashMap hash1 = new HashMap();
						hash1.put("officeName", "全省平均价");//因为先判断了是否有市级的数据,才进来的,所以是可以的,没有数据的时候根本执行不到这里
						listAll.add(hash1);
						HashMap hash2 = new HashMap();
						hash2.put("officeName", "与上期比");
						listAll.add(hash2);
						int detailLength = priReportFillService.getDetailList((String)listCityData.get(0).get(0).get("id")).size();//获得格子的个数
						float[] sumCityArray = new float[detailLength];//这个数组用来放市级的平均值
						float[] sumCityNum = new float[detailLength];//存放求和数据的个数--对几个求和了就以几为基数求平均值
						boolean[] isAverage = new boolean[detailLength];//标识是否计算平均值了
						for(int s=0;s<listCityData.size();s++){
			        		List<HashMap> currentFillList = listCityData.get(s);//获得第x个市下的数据----怎么知道是哪个市呢??
			     	        float[] sumArray = new float[detailLength];//定义一个数组存放纵向看报表格子的数值的和(初始化为默认值,int型为0)
			     	        float[] sumNum = new float[detailLength];//存放求和数据的个数--对几个求和了就以几为基数求平均值
							for(int i=0;i<currentFillList.size();i++){
			     	            //遍历获得填报子表中的数据---是从单位换算后的表中查询的数据
			     	            List<HashMap> fillDetailList = priReportFillService.getConvertList((String)currentFillList.get(i).get("id"));
			     	            for(int j =0;j<fillDetailList.size();j++){
			     	            	PriReportHeader priReportHeader = priReportHeaderService.getHeaderData(priReportTemplate.getId(),(String)fillDetailList.get(j).get("code"));
			     	            	if(null != priReportHeader.getAverage() && null!=fillDetailList.get(j).get("value") && priReportHeader.getAverage().equals("10")){
			    	            		isAverage[j]=true;
			     	            	}
			     	            	if(null!=fillDetailList.get(j).get("value")){//这样写的话,就是市级的平均值计算所有的格子,如果不需要,则放到上面的方法里
			     	            		sumNum[j]++;
			     	            		sumArray[j] = sumArray[j]+Float.parseFloat((String)fillDetailList.get(j).get("value"));
			     	            	}
			     	            }
			     	            //把数据按照格式放到map中(监测点数据直接封装到List<HashMap>,然后对这个进行遍历,对应着挨个放进自己的detail的list(也是存好成hashMap了---注意排序->根据code排序)!)
			     	            currentFillList.get(i).put("data", fillDetailList);//第x个市中的第i个监测点设置对应的填报值
			     	        }
			     	        List<HashMap> listAverage = new ArrayList<HashMap>();//平均值
			     	        for(int i=0;i<sumArray.length;i++){
			     				HashMap average = new HashMap();
			     				float averageValue=0;
			     				if(sumNum[i]!=0){
			     					averageValue = sumArray[i]/sumNum[i];
			     					average.put("value",String.format("%.2f",averageValue));//固定写保留两位小数
									sumCityArray[i] = sumCityArray[i]+averageValue;
									sumCityNum[i]++;
			     				}
			     				listAverage.add(average);//这个list是一个市对应的所有平均值的list
			     	        }
			     	        //获得当前的数据所属的市的名称----根据code获得
			     	        PriReportOffice reportOffice = priReportOfficeService.getPriOffice((String)currentFillList.get(0).get("pointId"),reportId);
			     	        Office priReportOffice = priReportOfficeService.getNameByCode(reportOffice.getCode().substring(0, 6),reportId);
			     	        //拼接平均值、与上期比以及监测点的list集合
			     			List<HashMap> listCity = new ArrayList<HashMap>();
			     			HashMap hash3 = new HashMap();//这个hash存放市级计算出的平均值
			     			hash3.put("officeName", priReportOffice.getName());
			     			hash3.put("data",listAverage);//平均值的list集合-----和本行数据的第一列封装到一个hashmap中
			     			hash3.put("flag", 1);//标记是市级的平均值,样式调整一下
			     			listCity.add(hash3);//平均值放在最上面的一行
			     			listCity.addAll(currentFillList);
			     			listAll.addAll(listCity);
			        	}
						//计算最上面的平均值以及与上期的比
				        List<HashMap> listCityAverage = new ArrayList<HashMap>();//平均值
				        List<HashMap> listCompare = new ArrayList<HashMap>();//与上期比
				        for(int i=0;i<detailLength;i++){//listCityData.size()
							HashMap cityAverage = new HashMap();
							HashMap compare = new HashMap();
							float averageCityValue=0;
							if(sumCityNum[i]!=0){
								averageCityValue = sumCityArray[i]/sumCityNum[i];//有几个市就除以几=======好像不是,因为有的市没有数据的话,也不可以除以啊  TODO
								if(isAverage[i]==true){
									cityAverage.put("value",String.format("%.2f",averageCityValue));//固定写保留两位小数
								}
							}
							//查询上期平均值(注意不应该是直接上期,因为如果直接上期停止报送的话,比值就是错误的)
							float compareValue = 0;
							if(averageDetailList.size() != 0 && averageDetailList.get(i).get("value")!=null){//按顺序减去上期的比
								compareValue = averageCityValue-Float.parseFloat((String)averageDetailList.get(i).get("value"));
							}else{
								compareValue = averageCityValue-0;
							}
							if(isAverage[i]==true){
								compare.put("value",String.format("%.2f",compareValue));//固定写保留两位小数
							}
							listCityAverage.add(cityAverage);//这个list是一个市对应的所有平均值的list
							listCompare.add(compare);
				        }
			        	//把所有的市都循环判断完了的话,更新一下listAll集合中的前两个hashmap
			        	listAll.get(0).put("data", listCityAverage);//所有市的平均值计算后的均值的list集合
			        	listAll.get(1).put("data", listCompare);//与上期比
			        }
				}
		        
				//导出表体数据--begin
		        int rowDataNum = 3+headers.length+1;//从第几行开始?
				for(int i=0;i<listAll.size();i++){//listAll中决定了有多少行数据
					 XSSFRow row = sheet.createRow((rowDataNum + i));//创建一行
					 XSSFCell cell = null;//创建一个格子
					 
					 HashMap hash1 = listAll.get(i);
					 //第一列
					 cell = row.createCell(0);
					 cell.setCellValue(hash1.get("officeName")+"");
					 cell.setCellStyle(cellStyle);
					 //其余列
					 List<HashMap> dataList = (List) hash1.get("data");//把hash中存放的list转化回list
					 for(int j=0;j<dataList.size();j++){
						cell = row.createCell(j+1);
						if(dataList.get(j).get("value")!=null){
							cell.setCellValue(dataList.get(j).get("value")+"");
						}else{
							cell.setCellValue("");
						}
						cell.setCellStyle(cellStyle);
					 }
				}
				//导出表体数据--end
				
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		if (sheet != null) {
			try {
				//写数据
				FileOutputStream fos = new FileOutputStream(newFile);
				workbook.write(fos);
				fos.flush();
				fos.close();
				//下载
				InputStream fis = new BufferedInputStream(new FileInputStream(newFile));
				byte[] buffer = new byte[fis.available()];
				fis.read(buffer);
				fis.close();
				response.reset();
				response.setContentType("text/html;charset=UTF-8");
				OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
				response.setContentType("application/x-msdownload");
				//定义名字
				SimpleDateFormat formt = new SimpleDateFormat("yyyy-MM-dd");
				String newName = "价格报送_" + formt.format(new Date()) + ".xlsx";
				newName = URLEncoder.encode(newName, "UTF-8");
				response.addHeader("Content-Disposition","attachment;filename=\"" + newName + "\"");
				response.addHeader("Content-Length", "" + newFile.length());
				toClient.write(buffer);
				toClient.flush();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					if (null != is) {
						is.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		//删除创建的新文件
		FileUtils.deleteFile(newFile);
		//处理导出 ——end
		return json;
	}

猜你喜欢

转载自blog.csdn.net/zh1ang23/article/details/88920063