导出时候遇到的问题:
- 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;
}