粘貼一段自己寫的,但都看不懂了代碼吧,紀念那幾個夜深人靜的夜,poi導出多級表頭

package com.cf.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.cf.service.AirInputService;
import com.cf.service.ElectricInputService;
import com.cf.service.WaterInputService;

@Controller
public class ExportData {
	@Autowired
	private ElectricInputService electricInputService;
	@Autowired
	private WaterInputService waterInputService;
	@Autowired
	private AirInputService airInputService;
	@RequestMapping("/exportData")
	public void exportData(@RequestParam Map<String,Object> params,HttpServletResponse response){
		ServletOutputStream outputStream = null;
		try {
			response.setContentType("application/force-download;charset=utf-8");
			response.setHeader("Content-Disposition", "attachment;fileName="+URLEncoder.encode(params.get("fileName").toString()+"數據導出", "utf-8")+".xlsx");
			outputStream = response.getOutputStream();
			
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		String starttime = params.get("starttime").toString();
		String starttomonth = starttime.substring(0,7);
		String endtime = params.get("endtime").toString();
		String endtomonth = endtime.substring(0,7);
		SimpleDateFormat dayformat = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat monthformat = new SimpleDateFormat("yyyy-MM");
		List<String> sheetList = new LinkedList<>();
		List<List<String>> dayList = new LinkedList<>();
		try {
			Calendar startca = Calendar.getInstance();
			startca.setTime(monthformat.parse(starttomonth));//開始時間如2019-01
			Calendar endca = Calendar.getInstance();
			endca.setTime(monthformat.parse(endtomonth));//開始時間如2019-01
			while(true) {
				String sheetstr = startca.get(Calendar.YEAR)+"年"+(startca.get(Calendar.MONTH)+1)+"月";
				sheetList.add(sheetstr);
				List<String> lis = new LinkedList<>();//添加日期的list,空集合
				dayList.add(lis);
				if(startca.equals(endca)) {
					break;
				}
				startca.add(Calendar.MONTH, 1);
			}
			Calendar startdayca = Calendar.getInstance();
			startdayca.setTime(dayformat.parse(starttime));//開始時間如2019-01-01
			Calendar enddayca = Calendar.getInstance();
			enddayca.setTime(dayformat.parse(endtime));
			while(true) {
				String indexStr = startdayca.get(Calendar.YEAR)+"年"+(startdayca.get(Calendar.MONTH)+1)+"月";
				List<String> list = dayList.get(sheetList.indexOf(indexStr));
				list.add(startdayca.get(Calendar.YEAR)+"年"+(startdayca.get(Calendar.MONTH)+1)+"月"+startdayca.get(Calendar.DAY_OF_MONTH)+"日");
				if(startdayca.equals(enddayca)) {
					break;
				}
				startdayca.add(Calendar.DAY_OF_MONTH, 1);
			}
			//創建表格
			XSSFWorkbook workbook = new XSSFWorkbook();
	    	//表頭樣式
	        CellStyle titleStyle = workbook.createCellStyle();
	        titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
	        Font titleFont = workbook.createFont();
	        titleFont.setFontHeightInPoints((short) 20);
	        titleFont.setBoldweight((short) 700);
	        titleStyle.setFont(titleFont);
	        // 列頭樣式
	        CellStyle headerStyle = workbook.createCellStyle();
	        headerStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
	        headerStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
	        headerStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
	        headerStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
	        headerStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
	        headerStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
	        Font headerFont = workbook.createFont();
	        headerFont.setFontHeightInPoints((short) 12);
	        headerFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
	        headerStyle.setFont(headerFont);
	        
	        // 單元格樣式
	        CellStyle cellStyle = workbook.createCellStyle();
	        cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
	        cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
	        cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
	        cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
	        cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
	        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
	        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
	        cellStyle.setFillForegroundColor(HSSFColor.WHITE.index);
	        cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
	        Font cellFont = workbook.createFont();
	        cellFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
	        cellStyle.setFont(cellFont);
	        
	    	String[][] dianOpt = {{"表號","倍率","表字","用量","產量","單張能耗"},{"表字","水量"},{"表字","氣量"}};
	    	String[][] dianProxyOpt = {{"eno","erate","edata","eval","eoutput","eenergy"},{"wdata","wval"},{"adata","aval"}};
	    	String[] selectOpt = {"電錶","水錶","氣表"};
	    	String selectOption = params.get("selectOption").toString();
			String[] split = selectOption.split(",");
			int[] checkOpt = new int[split.length];
			//0電錶,1水錶,2氣表
			List<String> selectedOpt = new LinkedList<>();
			for(int i = 0;i < split.length;i++) {
				int val = Integer.parseInt(split[i]);
				checkOpt[i] = val;
				selectedOpt.addAll(Arrays.asList(dianProxyOpt[Integer.parseInt(split[i])]));
			}
	    	int firstHe = 0;//第一級合併的寬度
	    	int leftStartSum = 1;
	    	for (int i : checkOpt) {//算出第三級的寬度,即第一級的合併寬度
				firstHe += dianOpt[i].length;
			}
	    	for(String sheetStr :sheetList) {
	    		// 生成一個(帶標題)表格
		        XSSFSheet sheet = workbook.createSheet(sheetStr);
		        //設置列寬
		        XSSFRow row = sheet.createRow(0);//第一行顯示日期
		        row.setHeight((short)400);
		        //創建車間表頭
		        XSSFCell workCell = row.createCell(0);
		        workCell.setCellStyle(cellStyle);
		        workCell.setCellValue("車間");
		        sheet.setColumnWidth(0, 3000);
		        sheet.addMergedRegion(new CellRangeAddress(0, 2, 0, 0));
		        int dateLength = dayList.get(sheetList.indexOf(sheetStr)).size();
		        for(int i = leftStartSum;i < leftStartSum+firstHe*dateLength;i++){
		        	XSSFCell cell = row.createCell(i);
		        	cell.setCellStyle(cellStyle);
		        	if(i % firstHe == leftStartSum){
		        		try {
							cell.setCellValue(dayList.get(sheetList.indexOf(sheetStr)).get(i/firstHe));
						} catch (Exception e) {
							e.printStackTrace();
						}
		        		sheet.addMergedRegion(new CellRangeAddress(0, 0, i, i+firstHe-1));
		        	}
		        }
		        row = sheet.createRow(1);//第二行顯示監測選項
		        row.setHeight((short)400);
		        for(int i = leftStartSum;i < leftStartSum+firstHe*dateLength;i++){
		        	XSSFCell cell = row.createCell(i);
		        	cell.setCellStyle(cellStyle);
		        }
		        int sum = leftStartSum;
		        for(int i = leftStartSum;i < leftStartSum+firstHe*dateLength;i+=firstHe){
		        	for(int j = 0;j < checkOpt.length;j++){
		        		XSSFCell cell = row.getCell(sum);
		        		cell.setCellValue(selectOpt[checkOpt[j]]);
		        		sheet.addMergedRegion(new CellRangeAddress(1, 1, sum, sum+dianOpt[checkOpt[j]].length-1));
		        		sum += dianOpt[checkOpt[j]].length;
		        	}
		        }
		        row = sheet.createRow(2);//第三行顯示監測選項
		        XSSFCell createCell = row.createCell(0);
		        createCell.setCellStyle(cellStyle);//補上車間下面的邊框
		        row.setHeight((short)400);
		        for(int i = leftStartSum;i < leftStartSum+firstHe*dateLength;i++){
		        	XSSFCell cell = row.createCell(i);
		        	cell.setCellStyle(cellStyle);
		        }
		        int optCount = leftStartSum;
		        for(int i = leftStartSum;i < leftStartSum+firstHe*dateLength;i+=firstHe){
		        	for(int j = 0;j < checkOpt.length;j++){
		        		for(int s = 0;s < dianOpt[checkOpt[j]].length;s++){
		        			XSSFCell cell = row.getCell(optCount);
		        			cell.setCellValue(dianOpt[checkOpt[j]][s]);
		        			optCount++;
		        		}
		        	}
		        }
	    	}
			//創建表格
			//0電錶,1水錶,2氣表
	    	int startRow = 3;
	    	String endtimeaddone = params.get("endtime").toString();
	    	Date parse = dayformat.parse(endtimeaddone);
	    	Calendar instance = Calendar.getInstance();
	    	instance.setTime(parse);
	    	instance.add(Calendar.DAY_OF_MONTH, 1);
	    	params.put("endtime", instance.get(Calendar.YEAR)+"-"+(instance.get(Calendar.MONTH)+1)+"-"+instance.get(Calendar.DAY_OF_MONTH));
			for(int i = 0;i < checkOpt.length;i++) {
				int val = checkOpt[i];
				if(val == 0) {//調用查詢電錶 
					List<Map<String, Object>> queryData = electricInputService.getExportData(params);
					for (Map<String, Object> map : queryData) {
						String createtime = map.get("createtime").toString();
						Calendar dataca = Calendar.getInstance();
						dataca.setTime(dayformat.parse(createtime));
						String yearMonth = dataca.get(Calendar.YEAR)+"年"+(dataca.get(Calendar.MONTH)+1)+"月";
						String yearMonthDay = yearMonth+dataca.get(Calendar.DAY_OF_MONTH)+"日";
						XSSFSheet sheet = workbook.getSheet(yearMonth);
						String workname = map.get("workname").toString();
						XSSFRow row = null;
						XSSFCell cell = null;
						XSSFCell workcell = null;
						//填充電錶號
						String eno = map.get("no").toString();
						int indexOfCheckOpt = selectedOpt.indexOf("eno");//屬於每組日期的第幾個
						List<String> list = dayList.get(sheetList.indexOf(yearMonth));
						int indexOfDate = list.indexOf(yearMonthDay);//屬於第幾組日期
						boolean flag = false;
						int lastRowNum = startRow;
						//確定數據插入第幾行,首先遍歷全部的行,尋找和車間名所匹配的行(可能會匹配多行),然後查詢要插入數據的列存不存在數據,如果不存在,則插入,如果存在,則新建一行,再在此列插入
						int lastRowNum2 = sheet.getLastRowNum();
						for(int s = startRow;s <= lastRowNum2;s++) {//確定數據插入第幾行
							row = sheet.getRow(s);
							if(row != null) {
								workcell = row.getCell(0);
								String cellWorkName = workcell.getStringCellValue();
								if(cellWorkName.equals(workname)) {
									cell = row.getCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
									if(cell != null) {
										lastRowNum = s + 1;
										flag = true;
									}else{
										break;
									}
								}else {
									row = null;
								}
							}
						}
						if(flag) {
							row = sheet.createRow(lastRowNum);
						}
						if(row == null) {
							row = sheet.createRow(sheet.getLastRowNum()+1);
						}
						workcell = row.getCell(0);
						workname = map.get("workname").toString();
						if(workcell == null) {
							workcell = row.createCell(0);
							workcell.setCellStyle(cellStyle);
							workcell.setCellValue(workname);
						}
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(eno);
						//填充電錶倍率
						String erate = map.get("rate").toString();
						indexOfCheckOpt = selectedOpt.indexOf("erate");
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(erate);
						//填充表字
						String edata = map.get("data").toString();
						indexOfCheckOpt = selectedOpt.indexOf("edata");
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(edata);
						//填充表用量
						String eval = map.get("useval").toString();
						indexOfCheckOpt = selectedOpt.indexOf("eval");
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(eval);
						//填充表產量
						Object eoutput = map.get("output");
						indexOfCheckOpt = selectedOpt.indexOf("eoutput");
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(eoutput == null ? "" : eoutput.toString());
						//填充單行能耗
						Object eenergy = map.get("energy");
						indexOfCheckOpt = selectedOpt.indexOf("eenergy");
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(eenergy == null ? "" : eenergy.toString());
					}
				}
				if(val == 1) {//調用查詢水錶 
					List<Map<String, Object>> queryData = waterInputService.getExportData(params);
					for (Map<String, Object> map : queryData) {
						String createtime = map.get("createtime").toString();
						Calendar dataca = Calendar.getInstance();
						dataca.setTime(dayformat.parse(createtime));
						String yearMonth = dataca.get(Calendar.YEAR)+"年"+(dataca.get(Calendar.MONTH)+1)+"月";
						String yearMonthDay = yearMonth+dataca.get(Calendar.DAY_OF_MONTH)+"日";
						XSSFSheet sheet = workbook.getSheet(yearMonth);
						String workname = map.get("workname").toString();
						XSSFRow row = null;
						XSSFCell cell = null;
						XSSFCell workcell = null;
						//填充電錶號
						String eno = map.get("data").toString();
						int indexOfCheckOpt = selectedOpt.indexOf("wdata");//屬於每組日期的第幾個
						List<String> list = dayList.get(sheetList.indexOf(yearMonth));
						int indexOfDate = list.indexOf(yearMonthDay);//屬於第幾組日期
						boolean flag = false;
						int lastRowNum = startRow;
						//確定數據插入第幾行,首先遍歷全部的行,尋找和車間名所匹配的行(可能會匹配多行),然後查詢要插入數據的列存不存在數據,如果不存在,則插入,如果存在,則新建一行,再在此列插入
						int lastRowNum2 = sheet.getLastRowNum();
						for(int s = startRow;s <= lastRowNum2;s++) {//確定數據插入第幾行
							row = sheet.getRow(s);
							if(row != null) {
								workcell = row.getCell(0);
								String cellWorkName = workcell.getStringCellValue();
								if(cellWorkName.equals(workname)) {
									cell = row.getCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
									if(cell != null) {//如果在循環中找到了車間名稱,則記錄此row的下一行,並標記需要插入
										lastRowNum = s + 1;
										flag = true;
									}else{//如果此行的車間等於要插入的車間號,並且cell是個空的,則這個row就是需要插入數據的row,所以break;
										flag = false;
										break;
									}
								}else {//如果循環走完了,找不到車間號對應的,則加在最後
									row = null;
								}
							}
						}
						if(flag) {
							try {
								if(row == null){
									sheet.shiftRows(lastRowNum, sheet.getLastRowNum(), 1,true,true);
								}
							} catch (Exception e) {
								System.out.println("移動失敗:"+lastRowNum+","+sheet.getLastRowNum());
							}
							row = sheet.createRow(lastRowNum);
						}
						if(row == null) {
							row = sheet.createRow(sheet.getLastRowNum()+1);
						}
						workcell = row.getCell(0);
						workname = map.get("workname").toString();
						if(workcell == null) {
							workcell = row.createCell(0);
							workcell.setCellStyle(cellStyle);
							workcell.setCellValue(workname);
						}
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(eno);
						//填充電錶倍率
						String erate = map.get("useval").toString();
						indexOfCheckOpt = selectedOpt.indexOf("wval");
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(erate);
					}
				}
				if(val == 2) {//調用查詢氣表 
					List<Map<String, Object>> queryData = airInputService.getExportData(params);
					for (Map<String, Object> map : queryData) {
						String createtime = map.get("createtime").toString();
						Calendar dataca = Calendar.getInstance();
						dataca.setTime(dayformat.parse(createtime));
						String yearMonth = dataca.get(Calendar.YEAR)+"年"+(dataca.get(Calendar.MONTH)+1)+"月";
						String yearMonthDay = yearMonth+dataca.get(Calendar.DAY_OF_MONTH)+"日";
						XSSFSheet sheet = workbook.getSheet(yearMonth);
						String workname = map.get("workname").toString();
						XSSFRow row = null;
						XSSFCell cell = null;
						XSSFCell workcell = null;
						//填充電錶號
						String eno = map.get("data").toString();
						int indexOfCheckOpt = selectedOpt.indexOf("adata");//屬於每組日期的第幾個
						List<String> list = dayList.get(sheetList.indexOf(yearMonth));
						int indexOfDate = list.indexOf(yearMonthDay);//屬於第幾組日期
						boolean flag = false;
						int lastRowNum = startRow;
						//確定數據插入第幾行,首先遍歷全部的行,尋找和車間名所匹配的行(可能會匹配多行),然後查詢要插入數據的列存不存在數據,如果不存在,則插入,如果存在,則新建一行,再在此列插入
						int lastRowNum2 = sheet.getLastRowNum();
						for(int s = startRow;s <= lastRowNum2;s++) {//確定數據插入第幾行
							row = sheet.getRow(s);
							if(row != null) {
								workcell = row.getCell(0);
								String cellWorkName = workcell.getStringCellValue();
								if(cellWorkName.equals(workname)) {
									cell = row.getCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
									if(cell != null) {//如果在循環中找到了車間名稱,則記錄此row的下一行,並標記需要插入
										lastRowNum = s + 1;
										flag = true;
									}else{//如果此行的車間等於要插入的車間號,並且cell是個空的,則這個row就是需要插入數據的row,所以break;
										flag = false;
										break;
									}
								}else {//如果循環走完了,找不到車間號對應的,則加在最後
									row = null;
								}
							}
						}
						if(flag) {
							try {
								if(row == null){
									sheet.shiftRows(lastRowNum, sheet.getLastRowNum(), 1,true,true);
								}
							} catch (Exception e) {
								System.out.println("移動失敗:"+lastRowNum+","+sheet.getLastRowNum());
							}
							row = sheet.createRow(lastRowNum);
						}
						if(row == null) {
							row = sheet.createRow(sheet.getLastRowNum()+1);
						}
						workcell = row.getCell(0);
						workname = map.get("workname").toString();
						if(workcell == null) {
							workcell = row.createCell(0);
							workcell.setCellStyle(cellStyle);
							workcell.setCellValue(workname);
						}
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(eno);
						//填充電錶倍率
						String erate = map.get("useval").toString();
						indexOfCheckOpt = selectedOpt.indexOf("aval");
						cell = row.createCell(indexOfDate*selectedOpt.size()+indexOfCheckOpt+leftStartSum);
						cell.setCellStyle(cellStyle);
						cell.setCellValue(erate);
					}
				}
			}
			//數據添加完成之後,循環sheet合併車間
			for(String sheetName : sheetList){
				XSSFSheet sheet = workbook.getSheet(sheetName);
				int startNum = 3;
				int endNum = 3;
				String workName = "";
				for(int i = 3;i <= sheet.getLastRowNum();i++){
					XSSFRow row = sheet.getRow(i);
					XSSFCell cell = row.getCell(0);
					String cellValue = cell.getStringCellValue();
					if(!cellValue.equals(workName)){
						if(workName.equals("")){
							startNum = i;
						}else{
							endNum = i - 1;
							sheet.addMergedRegion(new CellRangeAddress(startNum, endNum, 0, 0));
							startNum = i;
						}
						workName = cellValue;
					}
				}
				if(startNum != sheet.getLastRowNum()+1){
					sheet.addMergedRegion(new CellRangeAddress(startNum, sheet.getLastRowNum(), 0, 0));
				}
			}
			workbook.write(outputStream);
			workbook.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章