Excel單元格

package com.kuangcp.mythpoi.excel;

import com.kuangcp.mythpoi.excel.base.ExcelTransform;
import com.kuangcp.mythpoi.excel.base.MainConfig;
import com.kuangcp.mythpoi.excel.type.BooleanHandler;
import com.kuangcp.mythpoi.excel.type.DateHandler;
import com.kuangcp.mythpoi.excel.type.DoubleHandler;
import com.kuangcp.mythpoi.excel.type.FloatHandler;
import com.kuangcp.mythpoi.excel.type.IntegerHandler;
import com.kuangcp.mythpoi.excel.type.LoadCellValue;
import com.kuangcp.mythpoi.excel.type.LongHandler;
import com.kuangcp.mythpoi.excel.type.StringHandler;
import com.kuangcp.mythpoi.utils.base.ReadAnnotationUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;

/**
 * Created by https://github.com/kuangcp on 18-2-21  下午12:47
 * Excel導出工具類
 * TODO 異常的合理處理
 * 目前單元格的類型尚不支持公式和錯誤
 * Boolean 缺省爲false,
 * 字符串缺省爲空串, 數值類型爲空則是0
 *
 * @author kuangcp
 */
@Slf4j
public class ExcelExport {

  private static MainConfig mainConfig = MainConfig.getInstance();
  private static HSSFWorkbook workbook = new HSSFWorkbook();
  private static Map<String, LoadCellValue> handlerMap = new HashMap<>(7);

  // 字典結合策略模式簡化代碼
  static {
    handlerMap.put("String", new StringHandler());
    handlerMap.put("Date", new DateHandler());
    handlerMap.put("Boolean", new BooleanHandler());
    handlerMap.put("Long", new LongHandler());
    handlerMap.put("Integer", new IntegerHandler());
    handlerMap.put("Double", new DoubleHandler());
    handlerMap.put("Float", new FloatHandler());
  }

  /**
   * @param filePath 文件的絕對路徑
   * @param originData 主要數據
   */
  public static boolean exportExcel(String filePath, List<? extends ExcelTransform> originData) {
    if (Objects.isNull(originData) || originData.isEmpty()) {
      log.warn("export data is empty");
      return false;
    }
    try {
      File file = new File(filePath);
      OutputStream out = new FileOutputStream(file);
      return exportExcel(out, originData);
    } catch (FileNotFoundException e) {
      log.error("file not found", e);
      return false;
    }
  }

  /**
   * @param outputStream 輸出流
   * @param originData 原始對象集合 不爲空
   */
  public static boolean exportExcel(OutputStream outputStream,
      List<? extends ExcelTransform> originData) {

    try {
      Class<? extends ExcelTransform> target = originData.get(0).getClass();
      String sheetTitle = ReadAnnotationUtil.getSheetExportTitle(target);
      List<Object[]> dataList = ReadAnnotationUtil.getContentByList(target, originData);

      if (Objects.isNull(dataList)) {
        log.error("{} 中沒有已註解的字段, 導出失敗", target.getSimpleName());
        return false;
      }

      HSSFSheet sheet = workbook.createSheet(sheetTitle);
      HSSFCellStyle columnTitleStyle = getColumnTitleCellStyle(workbook);

      setSheetTitle(sheet, dataList, sheetTitle, columnTitleStyle);
      setColumnTitle(dataList, sheet, target, columnTitleStyle);
      setContent(dataList, sheet);
      workbook.write(outputStream);
    } catch (Exception e) {
      log.error("export error ", e);
      return false;
    }
    return true;
  }

  /**
   * 設置sheet的列頭
   */
  private static void setColumnTitle(List<Object[]> dataList, HSSFSheet sheet, Class target,
      HSSFCellStyle columnTopStyle) {
    List<ExcelCellMeta> metaList = ReadAnnotationUtil.getCellMetaData(target);
    HSSFRow row = sheet.createRow(mainConfig.getTitleLastRowNum());
    int columnNum = dataList.get(0).length;
    for (int n = 0; n < columnNum; n++) {
      //創建列頭對應個數的單元格
      HSSFCell cellRowName = row.createCell(n);
      //設置列頭單元格的數據類型

      cellRowName.setCellType(CellType.STRING);
      HSSFRichTextString text = new HSSFRichTextString(metaList.get(n).getTitle());
      cellRowName.setCellValue(text);
      cellRowName.setCellStyle(columnTopStyle);
    }
  }

  /**
   * 根據List來創造出一行的cell, 使用策略模式是因爲要從多種的對象類型轉換成Excel的特定類型
   */
  private static void createRowCell(Object[] obj, int index, HSSFRow row) {
    HSSFCellStyle style = getContentCellStyle(workbook);
    Object temp = obj[index];
    HSSFCell cell = handlerMap.get(temp.getClass().getSimpleName()).loadValue(row, index, temp);

    if (!Objects.isNull(cell)) {
      cell.setCellStyle(style);
    }
  }

  /**
   * cell分爲: 空格 布爾類型(TRUE FALSE) 字符串 數值 | 錯誤 公式
   * 填充sheet內容
   */
  private static void setContent(List<Object[]> dataList, HSSFSheet sheet) {
    for (int m = 0; m < dataList.size(); m++) {
      Object[] obj = dataList.get(m);
      HSSFRow row = sheet.createRow(m + mainConfig.getContentStartNum());
      for (int j = 0; j < obj.length; j++) {
        createRowCell(obj, j, row);
      }
    }
  }

  /**
   * 設置表格標題行 合併單元格 並 居中
   */
  private static void setSheetTitle(HSSFSheet sheet, List<Object[]> dataList, String sheetTitle,
      HSSFCellStyle columnTitleStyle) {

    HSSFRow row = sheet.createRow(mainConfig.getStartRowNum());
    HSSFCell cellTitle = row.createCell(mainConfig.getStartColNum());

    int lastColNum = dataList.get(0).length - 1;
    log.debug("title cell range : firstRow={} lastRow={} firstCol={} lastCol={}",
        mainConfig.getStartRowNum(),
        mainConfig.getTitleLastRowNum() - 1,
        mainConfig.getStartColNum(),
        lastColNum);

    sheet.addMergedRegion(new CellRangeAddress(
        mainConfig.getStartRowNum(),
        mainConfig.getTitleLastRowNum() - 1,
        mainConfig.getStartColNum(),
        lastColNum));

    log.debug("title value position: cell ={}", cellTitle.getAddress().toString());
    cellTitle.setCellStyle(columnTitleStyle);
    cellTitle.setCellValue(sheetTitle);
  }

  /**
   * 列頭單元格樣式
   */
  private static HSSFCellStyle getColumnTitleCellStyle(HSSFWorkbook workbook) {
    HSSFFont font = workbook.createFont();
    font.setFontHeightInPoints(mainConfig.getTitleFontSize());
    font.setBold(mainConfig.isTitleFontBold());
    font.setFontName(mainConfig.getTitleFontName());

    HSSFCellStyle style = workbook.createCellStyle();
    style.setBorderBottom(BorderStyle.MEDIUM);
    style.setBorderRight(BorderStyle.MEDIUM);
    style.setBorderTop(BorderStyle.MEDIUM);

    style.setFont(font);
    //設置自動換行;
    style.setWrapText(false);
    //設置水平對齊的樣式爲居中對齊;
    style.setAlignment(HorizontalAlignment.CENTER);
    //設置垂直對齊的樣式爲居中對齊;
    style.setVerticalAlignment(VerticalAlignment.CENTER);
    return style;
  }

  /**
   * 列數據信息單元格樣式
   */
  private static HSSFCellStyle getContentCellStyle(HSSFWorkbook workbook) {
    // 設置字體
    HSSFFont font = workbook.createFont();
    font.setFontHeightInPoints(mainConfig.getContentFontSize());
    font.setFontName(mainConfig.getContentFontName());
    font.setBold(mainConfig.isContentFontBold());

    HSSFCellStyle style = workbook.createCellStyle();
    // 設置邊框風格和顏色
    style.setBorderBottom(BorderStyle.THIN);
    style.setBorderRight(BorderStyle.THIN);
    style.setBorderTop(BorderStyle.THIN);

    style.setFont(font);
    //設置自動換行;
    style.setWrapText(false);
    //設置水平對齊的樣式爲居中對齊;
    style.setAlignment(HorizontalAlignment.CENTER);
    //設置垂直對齊的樣式爲居中對齊;
    style.setVerticalAlignment(VerticalAlignment.CENTER);
    return style;
  }
}

轉載 https://blog.csdn.net/kcp606/article/details/79435757

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