import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CreationHelper;
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.xssf.streaming.SXSSFWorkbook;
//需要的jar包:poi-3.15.jar、poi-ooxml-3.15.jar
/**
* 2002、2003的一個工作簿中最多含有256個工作表,默認情況下是三個工作表,工作表由65536行*256列組成,每行列交叉為一個單位格。
* 2007的無論是工作表個數、工作表列數、行數,都大大突破了這個數據,excel默認的工作薄擴展名為".xlsx",
* 這種格式的文件中每個工作頁包含1048576行(Row)*16384列(Column)。EXCEL的幫助文件上說的,理論上sheet是無限個,但受可用內存的限制,
* 你可以試著插入一個新工作表,然後按著F4,就會看見工作表不停的增加,我1G內存,工作表增加到10000個,還能正常進行基本操作 。
*/
/**
*
* Excel導出方法
*@param title Excel標題
*@param headersParams 以字符串"header = param"方式存儲元素的List<Striing>;header代表的是表頭,param代表的是表頭對應的屬性
*@param dataList 需要導出Excel數據
*@param sheetMaxCount 每一個sheet的最大存儲行數(數量)
*@return Workbook
*@since (此方法開始於哪個版本)0.0.3
*@author yangke
*
*/
public class NextExcelUtil {
/**
* 分sheet導出Excel的情況
* @param title Excel表的標題,如果不存在,則傳null
* @param headersParams 表頭與屬性值的對應關系數組
* @param dataList 導出Excel數據
* @param sheetMaxCount 單個sheet存儲數據量最大值
* */
@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
public static <T> Workbook getWorkbook(String title, List<String> headersParams, List<T> dataList, int sheetMaxCount) {
//獲取導出總數據量
int count = dataList.size();
//獲取要分多少個sheet
int page = count%sheetMaxCount > 0 ? count/sheetMaxCount + 1 : count/sheetMaxCount;
//拆分大的List為多個小的List
List<List> splitList = getSplitList(dataList, sheetMaxCount);
//建表
Workbook wb = new HSSFWorkbook();
for(int i = 0;i < page;i++){
int m = 0;
//創建sheet
Sheet sheet = wb.createSheet();
if(title != null){
wb.setSheetName(i, title+i);
//設置標題
for(int j = 0;j < 2;j++){
Row titleRow = sheet.createRow(i);
for(int k = 0;k < headersParams.size();k++){
Cell titleCell = titleRow.createCell(k);
CellStyle titleStyle = getStyle(wb);
titleCell.setCellStyle(titleStyle);
//標題內容只設置一次就行,且值只能設置在標題所占的位置的首行首列,否則合並單元格時值會被覆蓋
if(j == 0 && k == 0){
titleCell.setCellValue(title);
titleCell.setCellStyle(titleStyle);
}
}
}
//合並標題單元格
sheet.addMergedRegion(new CellRangeAddress(0, 1,0,headersParams.size()-1));
m = 2;
}
//獲取表頭及其對應的屬性
String[] headers = new String[headersParams.size()];
String[] params = new String[headersParams.size()];
for(int j = 0;j < headersParams.size();j++){
String[] hsPs = headersParams.get(j).toString().split("=");
headers[j] = hsPs[0];
params[j] = hsPs[1];
}
//設置表頭
Row headRow = sheet.createRow(m);
for(int j = 0;j < headers.length;j++){
Cell headerCell = headRow.createCell(j);
headerCell.setCellValue(headers[j]);
}
//獲取單個sheet需要填充的數據
List<T> smallList = splitList.get(i);
//給單個sheet填充數據
//獲取反射模版
Class clazz = null;
for(int j = 0;j < smallList.size();j++){
clazz = smallList.get(0).getClass();
Row paramRow = sheet.createRow(j + 1 + m);
for(int k = 0;k < params.length;k++){
try {
Field field = clazz.getDeclaredField(params[k]);
Method method = clazz.getMethod(getMethodName(params[k]));
Object obj = method.invoke(smallList.get(j));
Cell paramCell = paramRow.createCell(k);
//判斷是否為時間格式
if(obj.getClass() == Date.class){
if(obj != null){
CreationHelper creationHelper = wb.getCreationHelper();
CellStyle dateStyle = wb.createCellStyle();
dateStyle.setDataFormat(
creationHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
paramCell.setCellStyle(dateStyle);
paramCell.setCellValue((Date)obj);
}else{
paramCell.setCellValue("");
}
}else{
if(obj != null){
paramCell.setCellValue(obj.toString());
}else{
paramCell.setCellValue("");
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
return wb;
}
/**
* 導出單個sheet的Excel
* @param title Excel表的標題,如果不存在,則傳null
* @param headersParams 表頭與屬性值的對應關系數組
* @param dataList 導出Excel數據
* */
@SuppressWarnings({ "rawtypes", "unused", "unchecked" })
public static <T> Workbook getWorkbook(String title,List<String> headersParams,List<T> dataList) {
//建表
Workbook wb = new HSSFWorkbook();
//創建工作簿
Sheet sheet = wb.createSheet();
//設置起始行,默認為0
int m = 0;
//判斷是否存在標題
if(title != null){
wb.setSheetName(0, title);
//設置標題
for(int i = 0;i < 2;i++){
Row titleRow = sheet.createRow(i);
for(int j = 0;j < headersParams.size();j++){
Cell titleCell = titleRow.createCell(j);
CellStyle titleStyle = getStyle(wb);
titleCell.setCellStyle(titleStyle);
//標題內容只設置一次就行,且值只能設置在標題所占的位置的首行首列,否則合並單元格時值會被覆蓋
if(j == 0 && i == 0){
titleCell.setCellValue(title);
titleCell.setCellStyle(titleStyle);
}
}
}
//合並標題單元格
sheet.addMergedRegion(new CellRangeAddress(0, 1,0,headersParams.size()-1));
m = 2;
}
String[] headers = new String[headersParams.size()];
String[] params = new String[headersParams.size()];
for(int i = 0;i < headersParams.size();i++){
String[] headerParam = headersParams.get(i).split("=");
headers[i] = headerParam[0];
params[i] = headerParam[1];
}
//設置表頭
Row headRow = sheet.createRow(m);
for(int i = 0;i < headers.length;i++){
Cell headerCell = headRow.createCell(i);
headerCell.setCellValue(headers[i]);
}
//填入數據
//獲取反射模版
Class clazz = null;
if(dataList != null && dataList.size() > 0){
clazz = dataList.get(0).getClass();
for(int i = 0;i < dataList.size();i++){
Row paramRow = sheet.createRow(i + 1 + m);
for(int j = 0;j < params.length;j++){
try {
Cell paramCell = paramRow.createCell(j);
Field field = clazz.getDeclaredField(params[j]);
Method method = clazz.getMethod(getMethodName(params[j]));
Object obj = method.invoke(dataList.get(i));
//判斷是否為時間格式
if(obj.getClass() == Date.class){
if(obj != null){
CreationHelper creationHelper = wb.getCreationHelper();
CellStyle dateStyle = wb.createCellStyle();
dateStyle.setDataFormat(
creationHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
paramCell.setCellStyle(dateStyle);
paramCell.setCellValue((Date)obj);
}else{
paramCell.setCellValue("");
}
}else{
if(obj != null){
paramCell.setCellValue(obj.toString());
}else{
paramCell.setCellValue("");
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
return wb;
}
/**
*
* 設置標題邊框
*@param workbook Excel對象
*@param titleRow 標題行
*@param headersParams 列名屬性名,對應關系的List
*@return CellStyle 標題樣式
*@since (此方法開始於哪個版本)0.0.3
*@author yk
*
*/
@SuppressWarnings("deprecation")
public static CellStyle getStyle(Workbook wb) {
//創建顯示樣式
CellStyle style = wb.createCellStyle();
//創建字體樣式
Font font = wb.createFont();
font.setFontHeight((short) 280);
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
style.setAlignment(HorizontalAlignment.CENTER);
//設置邊框
style.setBorderBottom(CellStyle.BORDER_THIN);
style.setBorderLeft(CellStyle.BORDER_THIN);
style.setBorderRight(CellStyle.BORDER_THIN);
style.setBorderTop(CellStyle.BORDER_THIN);
style.setFont(font);
return style;
}
/*
* 標題樣式
*/
@SuppressWarnings("deprecation")
public static <T> CellStyle getTitleStyle(Workbook workbook) {
// 設置字體
Font font = workbook.createFont();
//設置字體大小
font.setFontHeightInPoints((short)11);
//字體加粗
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
//設置字體名字
font.setFontName("Courier New");
//設置樣式;
CellStyle style = workbook.createCellStyle();
style.setFont(font);
//設置自動換行;
style.setWrapText(false);
//設置水平對齊的樣式為居中對齊;
style.setAlignment(CellStyle.ALIGN_CENTER);
//設置垂直對齊的樣式為居中對齊;
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
return style;
}
/*
* 列頭單元格樣式
*/
@SuppressWarnings("deprecation")
public CellStyle getColumnTopStyle(Workbook workbook) {
// 設置字體
Font font = workbook.createFont();
//設置字體大小
font.setFontHeightInPoints((short)11);
//字體加粗
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
//設置字體名字
font.setFontName("Courier New");
//設置樣式;
CellStyle style = workbook.createCellStyle();
//設置底邊框;
style.setBorderBottom(CellStyle.BORDER_THIN);
//設置左邊框;
style.setBorderLeft(CellStyle.BORDER_THIN);
//設置右邊框;
style.setBorderRight(CellStyle.BORDER_THIN);
//設置頂邊框;
style.setBorderTop(CellStyle.BORDER_THIN);
//在樣式用應用設置的字體;
style.setFont(font);
//設置自動換行;
style.setWrapText(false);
//設置水平對齊的樣式為居中對齊;
style.setAlignment(CellStyle.ALIGN_CENTER);
//設置垂直對齊的樣式為居中對齊;
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
return style;
}
/*
* 列數據信息單元格樣式
*/
@SuppressWarnings("deprecation")
public CellStyle getCellStyle(Workbook workbook) {
// 設置字體
Font font = workbook.createFont();
//設置字體大小
//font.setFontHeightInPoints((short)10);
//字體加粗
//font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
//設置字體名字
font.setFontName("Courier New");
//設置樣式;
CellStyle style = workbook.createCellStyle();
//設置底邊框;
style.setBorderBottom(CellStyle.BORDER_THIN);
//設置左邊框;
style.setBorderLeft(CellStyle.BORDER_THIN);
//設置右邊框;
style.setBorderRight(CellStyle.BORDER_THIN);
//設置頂邊框;
style.setBorderTop(CellStyle.BORDER_THIN);
//在樣式用應用設置的字體;
style.setFont(font);
//設置自動換行;
style.setWrapText(false);
//設置水平對齊的樣式為居中對齊;
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
//設置垂直對齊的樣式為居中對齊;
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
return style;
}
/*
* 獲取方法名
* @param 屬性名
* */
private static String getMethodName(String fieldName){
return "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
}
}