package org.fanlychie.excel;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.fanlychie.util.DynaBean;
* 可进行写操作的 EXCEL 工具类
*
* @author fanlychie
*/
public class WritableExcel {
private List<?> list;
private String[] props;
private String[] title;
private DynaBean dynaBean;
private XSSFSheet sheet;
private String sheetName;
private XSSFWorkbook workbook;
private static Map<Class<?>, String> dataFormat;
* 构造一个可写的 Excel 实例
*
* @param list
* 数据列表
* @param mapper
* 数据对象的属性名称与Excel文档标题之间的映射关系
*/
public WritableExcel(List<?> list, LinkedHashMap<String, String> mapper) {
init(list, mapper);
}
* 写出到文件
*
* @param file
* 文件对象
*/
public boolean write(File file) {
try {
return write(new FileOutputStream(file));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
* 写出到输出流
*
* @param out
* 输出流
*/
public boolean write(OutputStream out) {
try {
sheet = workbook.createSheet(sheetName);
fillTitleRow();
int rowIndex = 1;
for (Object bean : list) {
fillCreatedRow(rowIndex++, bean);
}
workbook.write(out);
return true;
} catch (Throwable e) {
throw new RuntimeException(e);
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {}
}
}
* 设置工作表的名称, 默认名称 Sheet1
*
* @param sheetName
* 工作表的名称
*/
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
* 设置日期格式, 默认格式 yyyy-MM-dd
*
* @param dateFormat
* 日期格式
*/
public void setDateFormat(String dateFormat) {
dataFormat.put(Date.class, dateFormat);
}
* 初始化
*
* @param list
* 数据列表
* @param mapper
* 数据对象的属性名称与Excel文档标题之间的映射关系
*/
private void init(List<?> list, LinkedHashMap<String, String> mapper) {
this.list = list;
int index = 0;
int size = mapper.size();
props = new String[size];
title = new String[size];
for (String prop : mapper.keySet()) {
props[index] = prop;
title[index] = mapper.get(prop);
index++;
}
this.workbook = new XSSFWorkbook();
this.dynaBean = new DynaBean(list.get(0).getClass());
this.sheetName = "Sheet1";
}
* 构建并填充标题行
*
* @throws Throwable
*/
private void fillTitleRow() throws Throwable {
int cellIndex = 0;
int cellWidth = 18 * 256;
XSSFRow row = sheet.createRow(0);
row.setHeightInPoints(25);
CellStyle style = getTitleCellStyle();
for (String text : title) {
sheet.setColumnWidth(cellIndex, cellWidth);
XSSFCell cell = row.createCell(cellIndex++);
cell.setCellStyle(style);
cell.setCellValue(text);
}
}
* 创建并填充行
*
* @param index
* 行的索引
* @param bean
* 填充行的对象
* @throws Throwable
*/
private void fillCreatedRow(int index, Object bean) throws Throwable {
int cellIndex = 0;
XSSFRow row = sheet.createRow(index);
row.setHeightInPoints(20);
for (String prop : props) {
Object value = dynaBean.getFieldValue(bean, prop);
Class<?> type = dynaBean.getFieldType(prop);
XSSFCell cell = row.createCell(cellIndex++);
if (value == null) {
cell.setCellValue("");
cell.setCellStyle(getBodyCellStyle(String.class));
} else {
if (type == Boolean.TYPE || type == Boolean.class) {
boolean boolValue = Boolean.parseBoolean(value.toString());
cell.setCellValue(boolValue);
} else if ((Number.class.isAssignableFrom(type) || type.isPrimitive())
&& type != Byte.TYPE && type != Character.TYPE) {
double doubleValue = Double.parseDouble(value.toString());
cell.setCellValue(doubleValue);
} else if (type == Date.class) {
Date dateValue = (Date) value;
cell.setCellValue(dateValue);
} else {
cell.setCellValue(value.toString());
}
cell.setCellStyle(getBodyCellStyle(type));
}
}
}
* 主体单元格样式
*
* @param type
* 单元格填充的数据的类型
* @return CellStyle
*/
private CellStyle getBodyCellStyle(Class<?> type) {
CellStyle style = workbook.createCellStyle();
String cellDataFormat = dataFormat.get(type);
if (cellDataFormat == null) {
cellDataFormat = dataFormat.get(String.class);
}
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
setBackgroundColor(style, IndexedColors.LIGHT_TURQUOISE.index);
style.setFont(getFont(11, IndexedColors.GREY_50_PERCENT.index));
style.setDataFormat(workbook.createDataFormat().getFormat(cellDataFormat));
style.setWrapText(true);
return style;
}
* 标题行样式
*
* @return CellStyle
*/
private CellStyle getTitleCellStyle() {
CellStyle style = workbook.createCellStyle();
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
setBackgroundColor(style, IndexedColors.YELLOW.index);
style.setFont(getFont(12, IndexedColors.BLUE_GREY.index));
style.setDataFormat(workbook.createDataFormat().getFormat("GENERAL"));
style.setWrapText(true);
return style;
}
* 设置单元格背景颜色
*
* @param style
* 单元格样式
* @param color
* 颜色值
*/
private void setBackgroundColor(CellStyle style, short color) {
style.setBorderBottom(CellStyle.BORDER_THIN);
style.setBorderLeft(CellStyle.BORDER_THIN);
style.setBorderRight(CellStyle.BORDER_THIN);
style.setBorderTop(CellStyle.BORDER_THIN);
style.setBottomBorderColor(IndexedColors.GREY_25_PERCENT.index);
style.setLeftBorderColor(IndexedColors.GREY_25_PERCENT.index);
style.setRightBorderColor(IndexedColors.GREY_25_PERCENT.index);
style.setTopBorderColor(IndexedColors.GREY_25_PERCENT.index);
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
style.setFillForegroundColor(color);
}
* 获取字体
*
* @param fontSize
* 字体大小
* @param fontColor
* 字体颜色
* @return Font
*/
private Font getFont(int fontSize, short fontColor) {
Font font = workbook.createFont();
font.setColor(fontColor);
font.setFontHeightInPoints((short) fontSize);
if (System.getProperty("os.name").contains("Windows")) {
font.setFontName("Microsoft YaHei");
}
return font;
}
static {
dataFormat = new HashMap<Class<?>, String>();
dataFormat.put(Short.TYPE, "0");
dataFormat.put(Short.class, "0");
dataFormat.put(Integer.TYPE, "0");
dataFormat.put(Integer.class, "0");
dataFormat.put(Long.TYPE, "0");
dataFormat.put(Long.class, "0");
dataFormat.put(Float.TYPE, "0.00");
dataFormat.put(Float.class, "0.00");
dataFormat.put(Double.TYPE, "0.00");
dataFormat.put(Double.class, "0.00");
dataFormat.put(String.class, "GENERAL");
dataFormat.put(Date.class, "yyyy-MM-dd");
}
}