POI動態合併行和列

效果圖

主要代碼

package cn.com.gtmc.glaf2.framework.utils;

import org.apache.poi.hssf.usermodel.;
import org.apache.poi.ss.usermodel.
;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**

  • Copyright (C), 2015-2017, its

  • FileName: PoiExportAutoMergeRowAndColumn

  • Author: hdk

  • Date: 2020-10-28 0:00

  • Description: 基於poi動態導出合併頭,合併列工具類,

  •          mergeRow 合併行
    
  •          genMergeCellByContent 合併頭
    
  • History:

  • 作者姓名 修改時間 版本號 描述
    */
    public class PoiExportAutoMergeRowAndColumn {
    private static final Logger logger = LoggerFactory.getLogger(PoiExportAutoMergeRowAndColumn.class);

    public static void exportTest(String excelName, List list, LinkedHashMap<String, Object> fieldMap) {

     // 設置默認文件名爲當前時間:年月日時分秒
     if (excelName == null || excelName == "") {
         excelName = new SimpleDateFormat("yyyyMMddhhmmss").format(
                 new Date()).toString();
     }
    
    
     try {
         //創建一個WorkBook,對應一個Excel文件
         HSSFWorkbook wb = new HSSFWorkbook();
         //在Workbook中,創建一個sheet,對應Excel中的工作薄(sheet)
         HSSFSheet sheet = wb.createSheet(excelName);
         //創建單元格,並設置值表頭 設置表頭居中
         HSSFCellStyle style = wb.createCellStyle();
         //創建一個居中格式
         //style.setAlignment(ALIGN_CENTER);
         style.setAlignment(HorizontalAlignment.CENTER);
         // 填充工作表
         fillSheet(sheet, list, fieldMap, style);
    
    
         FileOutputStream dd = new FileOutputStream("c://test.xls");
    
         //將文件輸出
         OutputStream ouputStream = dd;
         wb.write(ouputStream);
         ouputStream.flush();
         ouputStream.close();
     } catch (Exception e) {
         logger.info("導出Excel失敗!");
         logger.error(e.getMessage());
     }
    

    }

    /**

    • 根據字段名獲取字段對象

    • @param fieldName 字段名

    • @param clazz 包含該字段的類

    • @return 字段
      */
      public static Field getFieldByName(String fieldName, Class<?> clazz) {
      // logger.info("根據字段名獲取字段對象:getFieldByName()");
      // 拿到本類的所有字段
      Field[] selfFields = clazz.getDeclaredFields();

      // 如果本類中存在該字段,則返回
      for (Field field : selfFields) {
      //如果本類中存在該字段,則返回
      if (field.getName().equals(fieldName)) {
      return field;
      }
      }

      // 否則,查看父類中是否存在此字段,如果有則返回
      Class<?> superClazz = clazz.getSuperclass();
      if (superClazz != null && superClazz != Object.class) {
      //遞歸
      return getFieldByName(fieldName, superClazz);
      }

      // 如果本類和父類都沒有,則返回空
      return null;
      }

    /**

    • 根據字段名獲取字段值

    • @param fieldName 字段名

    • @param o 對象

    • @return 字段值

    • @throws Exception 異常
      */
      public static Object getFieldValueByName(String fieldName, Object o)
      throws Exception {

      if (o instanceof HashMap) {
      return ((HashMap) o).get(fieldName);
      }

      // logger.info("根據字段名獲取字段值:getFieldValueByName()");
      Object value = null;
      //根據字段名得到字段對象
      Field field = getFieldByName(fieldName, o.getClass());

      //如果該字段存在,則取出該字段的值
      if (field != null) {
      field.setAccessible(true);//類中的成員變量爲private,在類外邊使用屬性值,故必須進行此操作
      value = field.get(o);//獲取當前對象中當前Field的value
      } else {
      throw new Exception(o.getClass().getSimpleName() + "類不存在字段名 "
      + fieldName);
      }

      return value;
      }

    /**

    • 根據帶路徑或不帶路徑的屬性名獲取屬性值,即接受簡單屬性名,

    • 如userName等,又接受帶路徑的屬性名,如student.department.name等

    • @param fieldNameSequence 帶路徑的屬性名或簡單屬性名

    • @param o 對象

    • @return 屬性值

    • @throws Exception 異常
      */
      public static Object getFieldValueByNameSequence(String fieldNameSequence,
      Object o) throws Exception {
      // logger.info("根據帶路徑或不帶路徑的屬性名獲取屬性值,即接受簡單屬性名:getFieldValueByNameSequence()");
      Object value = null;

      // 將fieldNameSequence進行拆分
      String[] attributes = fieldNameSequence.split("\.");
      if (attributes.length == 1) {
      value = getFieldValueByName(fieldNameSequence, o);
      } else {
      // 根據數組中第一個連接屬性名獲取連接屬性對象,如student.department.name
      Object fieldObj = getFieldValueByName(attributes[0], o);
      //截取除第一個屬性名之後的路徑
      String subFieldNameSequence = fieldNameSequence
      .substring(fieldNameSequence.indexOf(".") + 1);
      //遞歸得到最終的屬性對象的值
      value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);
      }
      return value;

    }

    /**

    • 向工作表中填充數據

    • @param sheet excel的工作表名稱

    • @param list 數據源

    • @param fieldMap 中英文字段對應關係的Map

    • @param style 表格中的格式

    • @throws Exception 異常
      */
      public static void fillSheet(HSSFSheet sheet, List list,
      LinkedHashMap<String, Object> fieldMap, HSSFCellStyle style) throws Exception {
      // logger.info("向工作表中填充數據:fillSheet()");
      // 定義存放英文字段名和中文字段名的數組
      String[] enFields = new String[fieldMap.size()];
      String[] cnFields = new String[fieldMap.size()];

      // 填充數組
      int count = 0;
      for (Map.Entry<String, Object> entry : fieldMap.entrySet()) {
      enFields[count] = entry.getKey();
      cnFields[count] = entry.getValue().toString();
      count++;
      }
      int firstRow = 0;
      int lastRow = 3;
      int firstCol = 0;
      int lastCol = 0;

      //在sheet中添加表頭第0行,注意老版本poi對Excel的行數列數有限制short
      HSSFRow row = sheet.createRow((int) 0);
      // 填充表頭
      for (int i = 0; i < cnFields.length; i++) {
      String val = cnFields[i];
      HSSFCell cell = null;
      String[] split = val.split("-");
      if (split.length == 4) {
      genMergeHeader(split, sheet, i, style);//生成合並列
      continue;
      }

       cell = row.createCell(i);
       cell.setCellValue(val);
      
       if (split.length != 4) {
           firstCol = i;
           lastCol = i;
           CellRangeAddress cellRangeAddress = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
           sheet.addMergedRegion(cellRangeAddress);
           RegionUtil.setBorderBottom(BorderStyle.THIN, cellRangeAddress, sheet);
           RegionUtil.setBorderBottom(BorderStyle.THIN, cellRangeAddress, sheet);
           RegionUtil.setBorderLeft(BorderStyle.THIN, cellRangeAddress, sheet);
           RegionUtil.setBorderRight(BorderStyle.THIN, cellRangeAddress, sheet);
           RegionUtil.setBorderTop(BorderStyle.THIN, cellRangeAddress, sheet);
      
       }
      
       HSSFFont font = sheet.getWorkbook().createFont();
       style.setAlignment(HorizontalAlignment.CENTER);
       font.setFontName("宋體");
       font.setFontHeightInPoints((short) 12);// 設置字體大小
       //font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
       style.setFont(font);
       style.setWrapText(true);
       style.setVerticalAlignment(VerticalAlignment.CENTER);
      
       style.setBorderBottom(BorderStyle.THIN); //下邊框
       style.setBorderLeft(BorderStyle.THIN);//左邊框
       style.setBorderTop(BorderStyle.THIN);//上邊框
       style.setBorderRight(BorderStyle.THIN);//右邊框
      
       style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
       style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
      
       cell.setCellStyle(style);
      
       sheet.setColumnWidth(i, val.length() * 1000);
      
       sheet.autoSizeColumn(i);
      

      }

      //todo合併單元格列頭
      genMergeCellByContent(0, 2, 6, 56, sheet);
      // 填充內容
      String[] arrayList = new String[enFields.length];
      HashMap hashMap = new HashMap();

      for (int index = 0; index < list.size(); index++) {
      row = sheet.createRow(index + 4);

       // 獲取單個對象
       T item = list.get(index);
       for (int i = 0; i < enFields.length; i++) {
           Object objValue = getFieldValueByNameSequence(enFields[i], item);
           String fieldValue = objValue == null ? "" : objValue.toString();
           row.createCell(i).setCellValue(fieldValue);
      
       }
      

      }

      for (Object o : hashMap.keySet()) {
      Integer i = (Integer) o;
      List o1 = (ArrayList) hashMap.get(o);
      CellRangeAddress cellRangeAddress = new CellRangeAddress((Integer) o1.get(0) + 3, (Integer) o1.get(o1.size() - 1) + 4, i, i);
      sheet.addMergedRegionUnsafe(cellRangeAddress);
      }

    }

    /**

    • 根據內容合併單元格

    • @param firstRow

    • @param lastRow

    • @param firstCol

    • @param lastCol

    • @param sheet
      */
      private static void genMergeCellByContent(int firstRow, int lastRow, int firstCol, int lastCol, HSSFSheet sheet) {

      class Range {
      public String vlaue;
      public int rowIndex;
      public int firstCol;
      public int lastCol;
      }
      String valueTemp = "";
      int firstColTemp = 0;
      int lastColTemp = 0;

      List list = new ArrayList();

      for (int i = firstRow; i <= lastRow; i++) {
      Row row = sheet.getRow(i);
      valueTemp = "";
      for (int j = firstCol; j <= lastCol; j++) {
      String stringCellValue = row.getCell(j).getStringCellValue();
      if (valueTemp.equals(stringCellValue)) {
      lastColTemp = j;
      if (j == lastCol) {
      Range range = new Range();
      range.rowIndex = i;
      range.vlaue = valueTemp;
      range.firstCol = firstColTemp;
      range.lastCol = lastColTemp;
      list.add(range);
      }
      } else {
      //找到合併單元信息。 存到list中
      if (!valueTemp.equals("")) {
      Range range = new Range();
      range.rowIndex = i;
      range.vlaue = valueTemp;
      range.firstCol = firstColTemp;
      range.lastCol = lastColTemp;
      list.add(range);
      }

               valueTemp = stringCellValue;
               firstColTemp = j;
           }
      
       }
      

      }

      for (Range range : list) {
      sheet.addMergedRegion(new CellRangeAddress(range.rowIndex, range.rowIndex, range.firstCol, range.lastCol));
      }

    }

    /**

    • 合併單元格

    • @param split
      */
      private static void genMergeHeader(String[] split, HSSFSheet sheet, int columnIndex, HSSFCellStyle style) {
      for (int i = 0; i < split.length; i++) {

       HSSFRow row = null;
      
       row = sheet.getRow(i);
       if (row == null) {
           row = sheet.createRow(i);
       }
      
       HSSFCell cell = row.createCell(columnIndex);
       String s = split[i];
       cell.setCellValue(s);
      
       HSSFFont font = sheet.getWorkbook().createFont();
       style.setAlignment(HorizontalAlignment.CENTER);
       font.setFontName("宋體");
       font.setFontHeightInPoints((short) 12);// 設置字體大小
       font.setBold(true);
       style.setFont(font);
       style.setWrapText(true);
       style.setVerticalAlignment(VerticalAlignment.CENTER);
       cell.setCellStyle(style);
       sheet.setColumnWidth(columnIndex, s.length() * 700);
      
       //  sheet.autoSizeColumn(columnIndex);
      

      }
      }

    public static void exportHeader(String excelName, List list, LinkedHashMap<String, Object> fieldMap) {

     // 設置默認文件名爲當前時間:年月日時分秒
     if (excelName == null || excelName == "") {
         excelName = new SimpleDateFormat("yyyyMMddhhmmss").format(
                 new Date()).toString();
     }
    
    
     try {
         //創建一個WorkBook,對應一個Excel文件
         HSSFWorkbook wb = new HSSFWorkbook();
         //在Workbook中,創建一個sheet,對應Excel中的工作薄(sheet)
         HSSFSheet sheet = wb.createSheet(excelName);
         //創建單元格,並設置值表頭 設置表頭居中
         HSSFCellStyle style = wb.createCellStyle();
         //創建一個居中格式
         style.setAlignment(HorizontalAlignment.CENTER);
         // 填充工作表
         fillSheet(sheet, list, fieldMap, style);
    
         //合併行
         mergeRow(sheet, (List<HashMap>)list);
    
         FileOutputStream dd = new FileOutputStream("D://out//test.xls");
    
         //將文件輸出
         OutputStream ouputStream = dd;
         wb.write(ouputStream);
         ouputStream.flush();
         ouputStream.close();
     } catch (Exception e) {
         System.out.println(e.getMessage());
     }
    

    }

    /**

    • 合併行

    • @param sheet

    • @param list
      */
      private static void mergeRow(HSSFSheet sheet,List list){
      //獲取待合併單元格下標
      List<MergeRowBuilder.ItemLink> genindexList = new MergeRowBuilder().BuidIndex(list);
      //遍歷集合進行合併,每個相鄰單元格的信息都存儲在一個鏈表裏
      for (MergeRowBuilder.ItemLink itemList : genindexList) {
      for (MergeRowBuilder.Item o : itemList.listItem) {
      Integer[] tempArr = new Integer[2];
      MergeRowBuilder.getIndex(o, tempArr);//獲取要和並的起始行和最後一行的下標
      CellRangeAddress cellRangeAddress = new CellRangeAddress(tempArr[0]+4, tempArr[1]+4, o.getY(), o.getY());
      sheet.addMergedRegionUnsafe(cellRangeAddress);

       }
      

      }
      }

    public static void main(String[] args) {

     LinkedHashMap<String, Object> headerHashMap = new LinkedHashMap<String, Object>();
     LinkedHashMap<String, Object> hashMapSecond = new LinkedHashMap<String, Object>();
     LinkedHashMap<String, Object> hashMapThird = new LinkedHashMap<String, Object>();
     LinkedHashMap<String, Object> hashMapLeaf = new LinkedHashMap<String, Object>();
    
     headerHashMap.put("序號", "序號");
     headerHashMap.put("單位名稱", "單位名稱");
     headerHashMap.put("單位類別", "單位類別");
     headerHashMap.put("指標評分", "指標評分");
     headerHashMap.put("百分制得分", "百分制得分");
     headerHashMap.put("信息系統名稱", "信息系統名稱");
    
    
     hashMapLeaf.put("防火(4)", "");
     hashMapLeaf.put("問題", "");
     hashMapLeaf.put("防雷(4)", "防火(4)");
     hashMapLeaf.put("問題", "");
     hashMapLeaf.put("場地(4)", "防火(4)");
     hashMapLeaf.put("問題", "");
     hashMapLeaf.put("濾空(4)", "防火(4)");
     hashMapLeaf.put("問題", "");
     hashMapLeaf.put("訪問控制(4)", "防火(4)");
     hashMapLeaf.put("問題", "");
    
     hashMapThird.put("機房綜合安全(20)", hashMapLeaf);
    
     hashMapSecond.put("信息安全建設(40)", hashMapThird);
    
     headerHashMap.put("檢查評分細項", hashMapSecond);
    
    
     LinkedHashMap<String, Object> fieldMap = new LinkedHashMap<String, Object>();
     fieldMap.put("a", "序號");
     fieldMap.put("b", "單位名稱");
     fieldMap.put("c", "單位類別");
     fieldMap.put("d", "指標評分");
     fieldMap.put("e", "百分制得分");
     fieldMap.put("f", "信息系統名稱");
    
     fieldMap.put("g6", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-防火(4)");
     fieldMap.put("g7", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-問題");
     fieldMap.put("g8", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-防雷(4)");
     fieldMap.put("g9", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-問題");
     fieldMap.put("g10", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-場地(4)");
     fieldMap.put("g11", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-問題");
     fieldMap.put("g12", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-濾空(4)");
     fieldMap.put("g13", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-問題");
     fieldMap.put("g14", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-訪問控制(4)");
     fieldMap.put("g15", "檢查評分細項-信息安全建設(40)-機房綜合安全(20)-問題");
    
    
     fieldMap.put("g16", "檢查評分細項-信息安全建設(40)-基礎架構設施(15)-硬件設施(5)");
     fieldMap.put("g17", "檢查評分細項-信息安全建設(40)-基礎架構設施(15)-問題");
     fieldMap.put("g18", "檢查評分細項-信息安全建設(40)-基礎架構設施(15)-網絡架構(5)");
     fieldMap.put("g19", "檢查評分細項-信息安全建設(40)-基礎架構設施(15)-問題");
     fieldMap.put("g20", "檢查評分細項-信息安全建設(40)-基礎架構設施(15)-安全保障(5)");
     fieldMap.put("g21", "檢查評分細項-信息安全建設(40)-基礎架構設施(15)-問題");
    
    
     fieldMap.put("g22", "檢查評分細項-信息安全管理(20)-組織與工作(10)-信息安全主管領導(5)");
     fieldMap.put("g23", "檢查評分細項-信息安全管理(20)-組織與工作(10)-問題");
     fieldMap.put("g24", "檢查評分細項-信息安全管理(20)-組織與工作(10)-信息安全員(5)");
     fieldMap.put("g25", "檢查評分細項-信息安全管理(20)-組織與工作(10)-問題");
     fieldMap.put("g26", "檢查評分細項-信息安全管理(20)-安全與制度(10)-信息安全制度管理(5)");
     fieldMap.put("g27", "檢查評分細項-信息安全管理(20)-安全與制度(10)-問題");
     fieldMap.put("g28", "檢查評分細項-信息安全管理(20)-安全與制度(10)-崗位信息安全責任制度(5)");
     fieldMap.put("g29", "檢查評分細項-信息安全管理(20)-安全與制度(10)-問題");
    
    
     fieldMap.put("g30", "檢查評分細項-信息安全防護(40)-安全保護管理(15)-漏洞評測(15)");
     fieldMap.put("g31", "檢查評分細項-信息安全防護(40)-安全保護管理(15)-問題");
     fieldMap.put("g32", "檢查評分細項-信息安全防護(40)-信息安全應急(8)-信息安全應急預案(4)");
     fieldMap.put("g33", "檢查評分細項-信息安全防護(40)-信息安全應急(8)-問題");
     fieldMap.put("g34", "檢查評分細項-信息安全防護(40)-信息安全應急(8)-信息安全應急演練(4)");
     fieldMap.put("g35", "檢查評分細項-信息安全防護(40)-信息安全應急(8)-問題");
     fieldMap.put("g36", "檢查評分細項-信息安全防護(40)-Web應用系統(10)-身份驗證(3)");
     fieldMap.put("g37", "檢查評分細項-信息安全防護(40)-Web應用系統(10)-問題");
     fieldMap.put("g38", "檢查評分細項-信息安全防護(40)-Web應用系統(10)-上傳安全(3)");
     fieldMap.put("g39", "檢查評分細項-信息安全防護(40)-Web應用系統(10)-問題");
     fieldMap.put("g40", "檢查評分細項-信息安全防護(40)-Web應用系統(10)-抗拒絕服務(4)");
     fieldMap.put("g41", "檢查評分細項-信息安全防護(40)-Web應用系統(10)-問題");
     fieldMap.put("g42", "檢查評分細項-信息安全防護(40)-服務器操作系統(12)-Windows(6)");
     fieldMap.put("g43", "檢查評分細項-信息安全防護(40)-服務器操作系統(12)-問題");
     fieldMap.put("g44", "檢查評分細項-信息安全防護(40)-服務器操作系統(12)-Linux(6)");
     fieldMap.put("g45", "檢查評分細項-信息安全防護(40)-服務器操作系統(12)-問題");
    
     fieldMap.put("g46", "檢查評分細項-扣分指標- -安全事件(最多扣20分)");
     fieldMap.put("g47", "檢查評分細項-扣分指標- -問題");
     fieldMap.put("g48", "檢查評分細項-扣分指標- -媒體曝光(最多扣10分)");
     fieldMap.put("g49", "檢查評分細項-扣分指標- -問題");
     fieldMap.put("g50", "檢查評分細項-扣分指標- -材料報送效率(最多扣10分)");
     fieldMap.put("g51", "檢查評分細項-扣分指標- -問題");
     fieldMap.put("g52", "檢查評分細項-扣分指標- -開展信息安全等級保護工作(最多扣10分)");
     fieldMap.put("g53", "檢查評分細項-扣分指標- -問題");
    
     fieldMap.put("g54", " -加分指標-  -等保建設");
     fieldMap.put("g55", " -加分指標-  -流量分析");
     fieldMap.put("g56", " -加分指標-  -日誌分析");
    
     List<HashMap> list = new ArrayList<HashMap>();
     HashMap hm = new HashMap();
     hm.put("a", "#1");
     hm.put("b", "專");
     hm.put("c", "低積載");
     hm.put("d", "4");
     hm.put("e", "5");
     hm.put("f", "6");
     hm.put("g", "7");
     hm.put("g1", "8");
    
     HashMap hm11 = new HashMap();
     hm11.put("a", "#1");
     hm11.put("b", "專");
     hm11.put("c", "高積載");
     hm11.put("d", "4");
     hm11.put("e", "5");
     hm11.put("f", "6");
     hm11.put("g", "7");
     hm11.put("g1", "8");
    
    
     HashMap hm1 = new HashMap();
     hm1.put("a", "#1");
     hm1.put("b", "共同");
     hm1.put("c", "32");
     hm1.put("d", "43");
     hm1.put("e", "54");
     hm1.put("f", "65");
     hm1.put("g", "74");
     hm1.put("g1", "83");
    
     HashMap hm2 = new HashMap();
     hm2.put("a", "#2");
     hm2.put("b", "專");
     hm2.put("c", "322");
     hm2.put("d", "43a");
     hm2.put("e", "54a");
     hm2.put("f", "65a");
     hm2.put("g", "74a");
     hm2.put("g1", "83a");
    
    
     HashMap hm3 = new HashMap();
     hm3.put("a", "#2");
     hm3.put("b", "共同");
     hm3.put("c", "322");
     hm3.put("d", "43a");
     hm3.put("e", "54a");
     hm3.put("f", "65a");
     hm3.put("g", "74a");
     hm3.put("g1", "83a");
    
     HashMap hm4 = new HashMap();
     hm4.put("a", "5");
     hm4.put("b", "5");
     hm4.put("c", "322");
     hm4.put("d", "43a");
     hm4.put("e", "54a");
     hm4.put("f", "65a");
     hm4.put("g", "74a");
     hm4.put("g1", "83a");
    
     list.add(hm);
     list.add(hm11);
     list.add(hm1);
    
    
     list.add(hm2);
     list.add(hm3);
     list.add(hm4);
    
    
     exportHeader("test", list, fieldMap);
    

    }

}

代碼下載

https://download.csdn.net/download/wolf12/13066217

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