1. 程式人生 > >匯出資料至Excel表格的幫助類

匯出資料至Excel表格的幫助類

此幫助類可以將物件通過反射的方式根據類中成員變數的宣告順序將資料對映到Excel表格中,支援設定行樣式,程式碼如下

package com.yc.utils;


import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


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.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;


/**
 * <b> 匯出資料的幫助類,用於將資料匯出至Excel表格中,可調整匯出資料的樣式,如:行(分為標題行和資料行)的背景顏色,字型顏色,字型高度,
 * 字型是否加粗, 是否條紋展示資料<b>
 * 
 * @author 劉亞樓
 *
 */
public class ExportHelper {

// 列寬
private int columWidth;
// 標題行背景顏色
private short headerBackground;
// 標題行字型顏色
private short headerFontColor;
// 標題行字型是否加粗
private boolean isHeaderFontBold;
// 標題行字型高度
private short headerFontWeight;
// 資料行背景顏色
private short dataRowBackground;
// 資料行另一種背景色,用於顯示條紋效果
private short dataRowBackground2;
// 資料行字型顏色
private short dataRowFontColor;
// 資料行字型是否加粗
private boolean isDataRowFontBold;
// 資料行字型高度
private short dataRowFontWeight;
// 是否給資料行加條紋
private boolean isStriped;


public ExportHelper() {
this.columWidth = 12;
this.headerBackground = HSSFColor.WHITE.index;
this.headerFontColor = HSSFColor.BLACK.index;
this.isHeaderFontBold = false;
this.headerFontWeight = 0;
this.dataRowBackground = HSSFColor.WHITE.index;
this.dataRowBackground2 = HSSFColor.GREY_25_PERCENT.index;
this.dataRowFontColor = HSSFColor.BLACK.index;
this.isDataRowFontBold = false;
this.dataRowFontWeight = 0;
this.isStriped = false;
}


/**
* 設定列寬

* @param columWidth
*/
public void setColumWidth(int columWidth) {
this.columWidth = columWidth;
}


/**
* 設定標題行字型顏色,可通過HSSFColor.colorClass.index設定

* @param headerFontColor
*/
public void setHeaderFontColor(short headerFontColor) {
this.headerFontColor = headerFontColor;
}


/**
* 設定資料行字型顏色,可通過HSSFColor.colorClass.index設定

* @param dataRowFontColor
*/
public void setDataRowFontColor(short dataRowFontColor) {
this.dataRowFontColor = dataRowFontColor;
}


/**
* 設定標題行的背景顏色,可通過HSSFColor.colorClass.index設定

* @param headerBackground
*/
public void setHeaderBackground(short headerBackground) {
this.headerBackground = headerBackground;
}


/**
* 設定資料行的背景顏色,可通過HSSFColor.colorClass.index設定

* @param dataRowBackground
*/
public void setDataRowBackground(short dataRowBackground) {
this.dataRowBackground = dataRowBackground;
}


/**
* 設定標題行字型粗度,預設為false

* @param isHeaderFontBold
*/
public void setHeaderFontBold(boolean isHeaderFontBold) {
this.isHeaderFontBold = isHeaderFontBold;
}


/**
* 設定資料行字型粗度,預設為false

* @param isDataRowFontBold
*/
public void setDataRowFontBold(boolean isDataRowFontBold) {
this.isDataRowFontBold = isDataRowFontBold;
}


/**
* 設定標題行字型高度

* @param headerFontWeight
*/
public void setHeaderFontWeight(short headerFontWeight) {
this.headerFontWeight = headerFontWeight;
}


/**
* 設定資料行字型高度

* @param dataRowFontWeight
*/
public void setDataRowFontWeight(short dataRowFontWeight) {
this.dataRowFontWeight = dataRowFontWeight;
}


/**
* 設定資料行是否條紋展示

* @param isStriped
*/
public void setStriped(boolean isStriped) {
this.isStriped = isStriped;
}


/**
* 資料行另一種背景顏色,用於顯示條紋效果

* @param dataRowBackground2
*/
public void setDataRowBackground2(short dataRowBackground2) {
this.dataRowBackground2 = dataRowBackground2;
}


/**
* 將list中的物件轉換為Workbook,並且將Workbook寫到輸出流中

* @param sheetName
*            表單的名字
* @param headers
*            標題
* @param list
*            包含物件的list集合
* @param os
*            輸出流
* @throws NoSuchMethodException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws IOException
*/
public <T> void exportToExcel(String sheetName, String[] headers, List<T> list, OutputStream os)
throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException, IOException {
// 宣告一個工作簿,HSSFWorkbook為2007以上的版本
HSSFWorkbook workbook = new HSSFWorkbook();
// 宣告一個表格
HSSFSheet sheet = workbook.createSheet(sheetName);
// 設定預設的列寬
sheet.setDefaultColumnWidth(columWidth);
// 建立標題行樣式
HSSFCellStyle headerStyle = createRowStyle(workbook, headerBackground, headerFontColor, headerFontWeight,
isHeaderFontBold);
// 建立資料樣式
HSSFCellStyle rowStyle = createRowStyle(workbook, dataRowBackground, dataRowFontColor, dataRowFontWeight,
isDataRowFontBold);
HSSFCellStyle rowStyle2 = null;
if (isStriped) {
// 有條紋展示,建立另一種資料行樣式
rowStyle2 = createRowStyle(workbook, dataRowBackground2, dataRowFontColor, dataRowFontWeight,
isDataRowFontBold);
}
// 為表格填充內容
fillContentsForSheet(headers, list, sheet, headerStyle, rowStyle, rowStyle2);
// 將表格中的內容寫入輸出流中
workbook.write(os);
os.flush();
}


/**
* 建立行樣式

* @param workbook
*            工作簿物件
* @param background
*            行背景顏色
* @param fontColor
*            字型顏色
* @param fontWeight
*            字型高度
* @param isFontBold
*            字型是否加粗
* @return
*/
private HSSFCellStyle createRowStyle(HSSFWorkbook workbook, short background, short fontColor, short fontWeight,
boolean isFontBold) {
// 建立樣式
HSSFCellStyle rowStyle = workbook.createCellStyle();
// 設定填充顏色
rowStyle.setFillForegroundColor(background);
// 設定填充樣式
rowStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
// 設定邊框
rowStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
rowStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
rowStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
rowStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 設定水平對齊方式
rowStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 設定垂直對齊方式
rowStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 建立字型
HSSFFont rowFont = workbook.createFont();
rowFont.setColor(fontColor);
if (fontWeight != 0) {
rowFont.setFontHeightInPoints(fontWeight);
}
// 預設設為normal
rowFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
if (isFontBold) {
rowFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
}
// 把字型應用到當前的樣式
rowStyle.setFont(rowFont);
return rowStyle;
}


// 為表格填充內容
private <T> void fillContentsForSheet(String[] headers, List<T> list, HSSFSheet sheet, HSSFCellStyle headerStyle,
HSSFCellStyle rowStyle, HSSFCellStyle rowStyle2)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
// 是否存在標題行
boolean isHeaderRowExisted = false;
if (headers != null && headers.length > 0) {
isHeaderRowExisted = true;
// 建立標題行
HSSFRow headerRow = sheet.createRow(0);
for (int i = 0; i < headers.length; i++) {
HSSFCell headerCell = headerRow.createCell(i);
headerCell.setCellStyle(headerStyle);
headerCell.setCellValue(headers[i]);
}
}
if (list != null && list.size() > 0) {
// 獲得list中物件的執行時類
Class<T> clazz = (Class<T>) list.get(0).getClass();
List<Method> methodList = getAllGetMethods(clazz);
int rowNum = 0;
if (isHeaderRowExisted) {
rowNum = 1;// 如果有標題行行號則從1開始,沒有從0開始
}
HSSFCellStyle style = null;
for (int row = rowNum, index = 0; index < list.size(); row++, index++) {
T t = list.get(index);
// 如果有條紋展示,奇偶行樣式各不同
if (rowStyle2 != null && index % 2 == 0) {
style = rowStyle2;
} else {
style = rowStyle;
}
// 建立資料行
HSSFRow dataRow = sheet.createRow(row);
// 一個getXXX方法代表一個欄位值,根據欄位值生成列的個數
for (int cell = 0; cell < methodList.size(); cell++) {
HSSFCell dataCell = dataRow.createCell(cell);
dataCell.setCellStyle(style);
// 通過反射呼叫對應的getXXX方法
Object obj = methodList.get(cell).invoke(t);
// 判斷資料型別,設定單元格的值
if (obj instanceof Integer) {
Integer value = (Integer) obj;
dataCell.setCellValue(String.valueOf(value));
} else if (obj instanceof Float) {
Float value = (Float) obj;
double doubleValue = Double.parseDouble(String.valueOf(value));
dataCell.setCellValue(doubleValue);
} else if (obj instanceof Long) {
Long value = (Long) obj;
dataCell.setCellValue(String.valueOf(value));
} else if (obj instanceof Double) {
Double value = (Double) obj;
dataCell.setCellValue(value);
} else if (obj instanceof Boolean) {
Boolean value = (Boolean) obj;
dataCell.setCellValue(value);
} else if (obj instanceof Date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dataCell.setCellValue(sdf.format(obj));
} else if (obj instanceof Calendar) {
Calendar c = (Calendar) obj;
Date date = c.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dataCell.setCellValue(sdf.format(date));
} else {
String value = (String) obj;
dataCell.setCellValue(value);
}
}
}
}
}


// 獲取類中每個成員變數對應的get方法,存入集合中
private List<Method> getAllGetMethods(Class<?> clazz) throws NoSuchMethodException, SecurityException {
List<Method> methodList = new ArrayList<Method>();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 如果名字為serialVersionUID,代表欄位值為序列化編號,應該跳過
if (field.getName().equals("serialVersionUID")) {
continue;
}
String fieldName = field.getName();
String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
Method getMethod = clazz.getDeclaredMethod(methodName);
methodList.add(getMethod);
}
return methodList;
}
}