zoukankan      html  css  js  c++  java
  • 一个复杂的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);
            }
            
             
         
            
             
    }
  • 相关阅读:
    Working with macro signatures
    Reset and Clear Recent Items and Frequent Places in Windows 10
    git分支演示
    The current .NET SDK does not support targeting .NET Core 2.1. Either target .NET Core 2.0 or lower, or use a version of the .NET SDK that supports .NET Core 2.1.
    Build website project by roslyn through devenv.com
    Configure environment variables for different tools in jenkins
    NUnit Console Command Line
    Code Coverage and Unit Test in SonarQube
    头脑王者 物理化学生物
    头脑王者 常识,饮食
  • 原文地址:https://www.cnblogs.com/lcuzhanglei/p/2875288.html
Copyright © 2011-2022 走看看