一个复杂的poi处理 合并单元格及其样式对齐问题

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java. text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFPrintSetup;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.PrintSetup;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellUtil;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.tshn.hydrology.base.BaseUtil;
import com.tshn.hydrology.base.Consts;
import com.tshn.hydrology.entity.system.Organization;
import com.tshn.hydrology.service.modules.StPptnRService;


@Controller
@RequestMapping("stPptnR")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class StPptnRDetailsExcelExport {
     @Inject
     private StPptnRService stPptnRservice;
     private  final int ZONE_NAME_CELL_STYLE = 1;
     private  final int COMMON_CEELL_STYLE = 2;
     private  final int AVG_RAIN_CELL_STYLE = 3;
     private  final int NUMBERIC_CELL_STYLE = 4;
     private  String decimalFormatPattern = "0.0"; //
     private  String rainDetailExcelName = "雨晴表year.第xx期.xls"; //excel名称
     private  DateFormat  dateFormat = new SimpleDateFormat("yyyy-MM-dd HH");
     private  DateFormat  chineseDateFormat = new SimpleDateFormat("yyyy年MM月dd日HH时");
     private  DateFormat  chineseDateFormatNoYear = new SimpleDateFormat("MM月dd日HH时");
     private  Calendar cal = Calendar.getInstance();
     private  int[] queryDatePosition = {3,5}; //excel模版放置查询时间段的位置(3行5列)
     private String templatePath = BaseUtil.getDefultAttPrefixPath()+Consts.STANDARD_REPORT_TEMPLATE; //excel模版位置
     private int rowZoneNum =3; //每行存放的县区个数
     private String[][] allAreaRainStatistics =
             new String[][]{{"平均","parentAvg","AVERAGE"},{"最大","parentMax","MAX"},{"最小","parentMin","MIN"}}; //全区统计
     
     @RequestMapping("exportRegularRainDetailsExcel")
      public void  exportRegularRainDetailsExcel(HttpServletRequest request,HttpServletResponse response,Model model){
        String startTime = request.getParameter("startTime"); //开始查询时间
        String endTime = request.getParameter("endTime"); //结束查询时间
        try {
            Date startDate = dateFormat.parse(startTime);
            Date endDate = dateFormat.parse(endTime);
            rainDetailExcelName = rainDetailExcelName.replaceAll("year", getQueryYear(startDate)); //根据查询日期重新设置excel表格名称
            String queryDateSection = chineseDateFormat.format(startDate)+"~"+chineseDateFormatNoYear.format(endDate); //设置查询时间段
            stPptnRservice.getStPptnRDetails(model,request); 
            Map<String, Object>  data = model.asMap(); //降雨量信息
            Workbook excelBook = getWrittenExcelbook(queryDateSection,data); //写excel
            
            response.setContentType("application/x-msdownload"); // 通知客户文件的MIME类型:
             try {
                response.setHeader("Content-disposition", "attachment;filename="+new String(rainDetailExcelName.getBytes(),"ISO-8859-1"));
                excelBook.write(response.getOutputStream());
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
      }
     
     /**
      * 计算起始查询日期的年份
      * @param startDate 
      * @return
      */
     private String getQueryYear(Date startDate){
        cal.setTime(startDate);
        return String.valueOf(cal.get(Calendar.YEAR));
     }
     
     
 
     
     
     @SuppressWarnings("unchecked")
    private Workbook getWrittenExcelbook(String queryDateSection,Map<String, Object>  data){
         int startWirteRowNum = 5;//开始行数
         StringBuffer calculateArea = new  StringBuffer();
         Workbook workbook = null;
        try {
            workbook = new HSSFWorkbook(new FileInputStream(templatePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
         Sheet sheet = workbook.getSheetAt(0);
         sheet.setColumnWidth(1, 2180);
         sheet.setColumnWidth(4, 2180);
         sheet.setColumnWidth(7, 2180);
         //在queryDatePosition 指定的位置写入查询时间
         sheet.getRow(queryDatePosition[0]).getCell(queryDatePosition[1]).setCellValue(queryDateSection);
         
         List<Map<String,Object>> stpps  = (List<Map<String,Object>>)data.get("stpps");
         
         int[] currentRowNums = new int[rowZoneNum];  
         for(int m=0;m<currentRowNums.length;m++){
             currentRowNums[m]=startWirteRowNum;
         }
         for(int i=0;i<stpps.size();i++){
               Map<String,Object> sttp  = stpps.get(i);
               String mainOrgName = String.valueOf(sttp.get("orgName"));
               
               List<Organization> childOrgs = (List<Organization>)sttp.get("child");
               int rowNum = childOrgs.size()+1; //各乡镇降雨量+县区平均降雨量
               int columnZoneIndex = i%rowZoneNum;
               int startRowNum = currentRowNums[columnZoneIndex];
               int endRowNum = currentRowNums[columnZoneIndex]+rowNum-1;
               int startAndEndColumnNum = i%rowZoneNum*rowZoneNum;
            
               //合并县区名称单元格
               CellRangeAddress cellRangeAddress = new CellRangeAddress(startRowNum, endRowNum, startAndEndColumnNum, startAndEndColumnNum);
               sheet.addMergedRegion(cellRangeAddress);
           
               
               Row currentRow = null;
               Cell startCalCell = null;
               Cell endCalCell = null;
               for(int j=0;j<rowNum;j++){
           
                   if( sheet.getRow(currentRowNums[columnZoneIndex]) == null){
                       currentRow =  sheet.createRow(startWirteRowNum++);
                       currentRowNums[columnZoneIndex] = startWirteRowNum;
                   }else{
                       currentRow = sheet.getRow(currentRowNums[i%rowZoneNum]);
                       currentRowNums[columnZoneIndex] = currentRowNums[columnZoneIndex]+1;
                   }
                   
                   Cell orgNameCell = currentRow.createCell(startAndEndColumnNum+1);//存放站名单元格
                  
                   Cell rainCell = currentRow.createCell(startAndEndColumnNum+2);//存放降雨雨量
                   rainCell.setCellType(Cell.CELL_TYPE_NUMERIC);
                rainCell.setCellStyle(this.getCustomedCellStyle(workbook, NUMBERIC_CELL_STYLE));
                  if(rowNum-1>j){
                       Organization org =  childOrgs.get(j);
                       orgNameCell.setCellStyle(this.getCustomedCellStyle(workbook, COMMON_CEELL_STYLE));
                       orgNameCell.setCellValue(org.getOrganizationName()); //设置站名
                       if(j == 0){
                          if(!mainOrgName.equals("开发区")){    
                              orgNameCell.setCellValue("城区");
                          }   
                           startCalCell = rainCell;
                       }else if(j==rowNum-2){
                           endCalCell = rainCell;
                       }
                       rainCell.setCellValue(org.getAvgOfStpptnR()); //设置降雨量
                  }else{//设置县区平均降雨量
                      orgNameCell.setCellStyle(this.getCustomedCellStyle(workbook, AVG_RAIN_CELL_STYLE));
                      orgNameCell.setCellValue(mainOrgName.substring(mainOrgName.length()-1)+"平均");
                      rainCell.setCellValue(Double.parseDouble(String.valueOf(sttp.get("avg"))));
                      String excelArea = this.tranlateExcelArea(startCalCell, endCalCell); //获取excel区域
                      calculateArea.append(excelArea).append(",");
                      this.setFormula(rainCell,"AVERAGE",excelArea); //给平均雨量单元格设置公式
                  }
                 
               }
               
            for (int m = cellRangeAddress.getFirstRow(); m <=  cellRangeAddress.getLastRow(); m ++) {//设置表头单元格样式
                CellUtil.getCell(sheet.getRow(m), startAndEndColumnNum).setCellStyle(this.getCustomedCellStyle(workbook, ZONE_NAME_CELL_STYLE));
            }
             Cell areaCell = CellUtil.getCell(sheet.getRow( cellRangeAddress.getFirstRow()), startAndEndColumnNum);
             
             areaCell.setCellValue(getStringWithEnter(mainOrgName));
             
               
             
         }
         
         int minArrayValueIndex = 2;
         int currentRowNum = currentRowNums[minArrayValueIndex] ;
         int lastRowColumnIndex = minArrayValueIndex*3 ;
         //合并竖行单元格
         CellRangeAddress cellRangeAddress = new CellRangeAddress(currentRowNum, currentRowNum+2, lastRowColumnIndex, lastRowColumnIndex);
         sheet.addMergedRegion(cellRangeAddress);
         
         calculateArea.deleteCharAt(calculateArea.length()-1);//删除最后一个逗号
         for(int k=0;k<3;k++){
             if(sheet.getRow(k+currentRowNum)==null){
                 sheet.createRow(k+currentRowNum);
             }
             Row tempRow = sheet.getRow(k+currentRowNum);
             Cell  dataNameCell  =  tempRow.createCell(lastRowColumnIndex+1); //数据名称
             dataNameCell.setCellStyle(this.getCustomedCellStyle(workbook, ZONE_NAME_CELL_STYLE));
             dataNameCell.setCellValue(allAreaRainStatistics[k][0]);
             Cell  dataContentCell  =  tempRow.createCell(lastRowColumnIndex+2); //数据内容
             dataContentCell.setCellType(Cell.CELL_TYPE_NUMERIC);//设置单元格类型
             dataContentCell.setCellStyle(this.getCustomedCellStyle(workbook,NUMBERIC_CELL_STYLE));
             dataContentCell.setCellValue(Double.parseDouble(String.valueOf(data.get(allAreaRainStatistics[k][1]))));
             this.setFormula(dataContentCell, allAreaRainStatistics[k][2], calculateArea.toString());
         } 
         currentRowNums[minArrayValueIndex] =   currentRowNums[minArrayValueIndex] + 3;
         for (int m = cellRangeAddress.getFirstRow(); m <=  cellRangeAddress.getLastRow(); m ++) {//设置表头单元格样式
             CellUtil.getCell(sheet.getRow(m), lastRowColumnIndex).setCellStyle(this.getCustomedCellStyle(workbook, ZONE_NAME_CELL_STYLE));
         }
         Cell areaCell = CellUtil.getCell(sheet.getRow( cellRangeAddress.getFirstRow()), lastRowColumnIndex);
         
         areaCell.setCellValue("全市\r\n统计");
         
         //动态补齐单元格
         int maxArrayValueIndex =  getMaxArrayValueIndex(currentRowNums);
         int maxArrayValue = currentRowNums[maxArrayValueIndex];
         for(int i=0;i<currentRowNums.length;i++){
             if(i!=maxArrayValueIndex && maxArrayValue>currentRowNums[i]){ //如果该列单元格的行数 小于 最多行的单元格,那么动态补齐该列单元格
                  int startMergedRegionRow = currentRowNums[i]-1; //开始行数
                  int endMergedRegionRow = maxArrayValue-1; //结束行数
                  for(int m=0;m<3;m++){
                      CellRangeAddress cellRange =   new CellRangeAddress(startMergedRegionRow, endMergedRegionRow, i*rowZoneNum+m,  i*rowZoneNum+m);
                      sheet.addMergedRegion(cellRange);
                      for (int x = startMergedRegionRow; x <= endMergedRegionRow; x++) {
                          CellUtil.getCell(sheet.getRow(x),  i*rowZoneNum+m).setCellStyle(
                                  getCustomedCellStyle(workbook,i*rowZoneNum+m==0 ? ZONE_NAME_CELL_STYLE : (i*rowZoneNum+m==1 ? AVG_RAIN_CELL_STYLE : NUMBERIC_CELL_STYLE ))
                            );
                      }
                  }  
                  
                  
             }
         }
         
         /*--打印设置--*/
        PrintSetup   printSetUp = sheet.getPrintSetup();
        sheet.setAutobreaks(true);
        printSetUp.setFitHeight((short)1); //一页打印
        printSetUp.setPaperSize(PrintSetup.A4_PAPERSIZE);//设置
        sheet.setHorizontallyCenter(true);//设置打印页面为水平居中  
        sheet.setVerticallyCenter(true);//设置打印页面为垂直居中  
         
         return workbook;
         
     }
     
     
     /**
      * 根据开始单元格和结束单元格,获取两个单元格之间的Excel区域
      * @param startCalCell
      * @param endCalCell
      * @return
      */
     private String tranlateExcelArea(Cell startCalCell,Cell endCalCell){
         int startCellColumnIndex = startCalCell.getColumnIndex();//获取单元格列索引
         int startCellRowIndex = startCalCell.getRowIndex(); //获取单元格行索引
         
         int endCellColumnIndex = endCalCell.getColumnIndex();//获取单元格列索引
         int endCellRowIndex = endCalCell.getRowIndex(); //获取单元格行索引
         
         String startCellStr = BaseUtil.transformArabNoToEnglishNo(startCellColumnIndex, true)
                                 + (startCellRowIndex+1);
         String endCellStr = BaseUtil.transformArabNoToEnglishNo(endCellColumnIndex, true)
                 + (endCellRowIndex+1);
         return startCellStr+":"+endCellStr; 
     }
     
     private void setFormula(Cell cell,String formulaName,String calculateArea){
         cell.setCellFormula(formulaName+"("+calculateArea+")");
     }
     
     
     /**
      * 在每个字符后追加回车符
      * @param inputStr
      * @return
      */
     private String getStringWithEnter(String inputStr){
          String[] mainOrgNames = inputStr.split("");
          String finalMainOrgName = "";//实现县区竖排效果
          for(int x=0;x<mainOrgNames.length;x++ ){ 
              finalMainOrgName += mainOrgNames[x] +"\r\n";
          }
          return finalMainOrgName;
     }
     
     private CellStyle getCustomedCellStyle(Workbook workbook,int cellStyleType){
         CellStyle newCellStyle =   workbook.createCellStyle();
         Font font = workbook.createFont();
         font.setFontName("仿宋_GB2312");
         
         if(cellStyleType == ZONE_NAME_CELL_STYLE){
             font.setFontName("黑体");
             font.setFontHeightInPoints((short) 12);
             font.setBoldweight(Font.BOLDWEIGHT_BOLD);
             newCellStyle.setFont(font);
             newCellStyle.setWrapText(true);
             //newCellStyle.setRotation((short)-90); //字体旋转90度
         }else if(cellStyleType==AVG_RAIN_CELL_STYLE){
             font.setFontHeightInPoints((short) 12);
             font.setBoldweight(Font.BOLDWEIGHT_BOLD);
             font.setColor(HSSFColor.ROYAL_BLUE.index);
             newCellStyle.setFont(font);
             newCellStyle.setFillBackgroundColor(HSSFColor.GREY_80_PERCENT.index);
         }else if(cellStyleType  == NUMBERIC_CELL_STYLE){
            DataFormat format =  workbook.createDataFormat();
            newCellStyle.setDataFormat(format.getFormat(decimalFormatPattern));
         }else{
             font.setFontHeightInPoints((short) 12);
             font.setBoldweight(Font.BOLDWEIGHT_NORMAL);
             newCellStyle.setFont(font);
         }
         
         newCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //垂直居中
         newCellStyle.setAlignment(CellStyle.ALIGN_CENTER); //水平居中
         this.setBorder(newCellStyle, CellStyle.BORDER_THIN);   //设置单元格边框
         
         return newCellStyle;
     }
     
     /**
      * 获取数组中最小元素对应的数组索引
      * @param array
      * @return
      */
     private int getMaxArrayValueIndex(int[] array){
         int maxValue = array[0];
         int maxValueIndex = 0;
         for(int i=0;i<array.length;i++){
             if(maxValue<array[i]){
                 maxValue = array[i];
                 maxValueIndex = i;
             }
         }
         
         return maxValueIndex;
         
     }
     
     /**
         * 设置单元格边框宽度
         * @param cellStyle
         * @param borderWidth
         */
        private void setBorder(CellStyle cellStyle,short borderWidth){
            cellStyle.setBorderTop(borderWidth);
            cellStyle.setBorderBottom(borderWidth);
            cellStyle.setBorderLeft(borderWidth);
            cellStyle.setBorderRight(borderWidth);
        }
        
         
     
        
         
}
原文地址:https://www.cnblogs.com/lcuzhanglei/p/2875288.html