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;
}
}
Excel單元格
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.