项目中经常需要导出对象列表。每次都觉得每次手工写太麻烦了,今天基于java反射机制和泛型完成了对象的excel导出。可灵活配置表头。当然功能非常简陋还,会接着完善。
包含四个文件:
PrintConstant.java 常量信息
ExcelSheet.java excel实体类
ExcelColumn.java excel中的列
JXLExcelView.java 生成excel的主要逻辑
PrintConstant.java
package com.anansi.gamemis.print;
import java.util.ArrayList;
import com.anansi.gs.city.model.RewardCode;
public class PrintConstant {
public enum ExcelEntity{
@SuppressWarnings("unchecked")
REWARD_CODE(1, "验证码.xls", "导出验", new ExcelSheet[]{
new ExcelSheet(RewardCode.class, "验证码", "验证码", 1, null, new ExcelColumn[]{
new ExcelColumn("period", "期数", 30, COLUMN_ALIGN.CENTER),
new ExcelColumn("code", "验证码", 40, COLUMN_ALIGN.CENTER),
new ExcelColumn("createAt", "创建时间", 30, COLUMN_ALIGN.CENTER),
new ExcelColumn("status", "状态", 30, COLUMN_ALIGN.CENTER),
new ExcelColumn("consumeAt", "消费时间", 30, COLUMN_ALIGN.CENTER),
new ExcelColumn("playerId", "消费人", 30, COLUMN_ALIGN.CENTER),
})
});
private final int id;
private final String excelName;
private final String note;
private final ExcelSheet[] sheets;
private ExcelEntity(int id, String excelName, String note, ExcelSheet[] sheets) {
this.id = id;
this.excelName = excelName;
this.note = note;
this.sheets = sheets;
}
public int getId() {
return id;
}
public String getExcelName() {
return excelName;
}
public String getNote() {
return note;
}
public ExcelSheet[] getSheets() {
return sheets;
}
public static ExcelEntity getById(int id){
ExcelEntity entity = null;
for (ExcelEntity element : ExcelEntity.values()) {
if(element.getId() == id){
entity = element;
break;
}
}
return entity;
}
}
public enum COLUMN_ALIGN{
LEFT,
CENTER,
RIGHT
}
}
ExcelSheet.java
package com.anansi.gamemis.print;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.record.formula.functions.T;
public class ExcelSheet<T> {
/*
* sheet中要打印的实体的clazz类型
*/
private Class<T> clazz;
/*
* sheet的主题
*/
private String subject;
/*
* sheet的名称
*/
private String sheetName;
/*
* 该sheet在excel中所处的页签
*/
private int sheetIndex;
/*
* 所有的列
*/
private ExcelColumn[] columns;
/*
* 数据
*/
private ArrayList<T> data;
ExcelSheet(Class<T> clazz, String subject, String sheetName, int sheetIndex, ArrayList<T> data, ExcelColumn[] columns) {
super();
this.clazz = clazz;
this.subject = subject;
this.sheetName = sheetName;
this.sheetIndex = sheetIndex;
this.columns = columns;
this.data = data;
}
public Class<T> getClazz() {
return clazz;
}
public void setClazz(Class<T> clazz) {
this.clazz = clazz;
}
public String getSheetName() {
return sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public int getSheetIndex() {
return sheetIndex;
}
public void setSheetIndex(int sheetIndex) {
this.sheetIndex = sheetIndex;
}
public ExcelColumn[] getColumns() {
return columns;
}
public void setColumns(ExcelColumn[] columns) {
this.columns = columns;
}
public ArrayList<T> getData() {
return data;
}
public void setData(ArrayList<T> data) {
this.data = data;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
}
ExcelColumn.java
package com.anansi.gamemis.print;
import com.anansi.gamemis.print.PrintConstant.COLUMN_ALIGN;
public class ExcelColumn {
/*
* 实体属性域名称
*/
private String classFieldName;
/*
* 这一列的title
*/
private String title;
/*
* 宽度
*/
private int width;
/*
* 对其方式
*/
private COLUMN_ALIGN align;
ExcelColumn(String classFieldName, String title, int width, COLUMN_ALIGN align) {
super();
this.classFieldName = classFieldName;
this.title = title;
this.width = width;
this.align = align;
}
public String getClassFieldName() {
return classFieldName;
}
public void setClassFieldName(String classFieldName) {
this.classFieldName = classFieldName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public COLUMN_ALIGN getAlign() {
return align;
}
public void setAlign(COLUMN_ALIGN align) {
this.align = align;
}
}
JXLExcelView.java
package com.anansi.gamemis.model;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jxl.Workbook;
import jxl.WorkbookSettings;
import jxl.format.Alignment;
import jxl.format.UnderlineStyle;
import jxl.format.VerticalAlignment;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;
import org.springframework.web.servlet.view.document.AbstractJExcelView;
import com.anansi.gamemis.exception.EnumNotFoundException;
import com.anansi.gamemis.exception.MisException;
import com.anansi.gamemis.print.ExcelSheet;
import com.anansi.gamemis.print.PrintConstant.ExcelEntity;
public class NewJXLExcelView extends AbstractJExcelView {
private WritableCellFormat wcfFC;
@SuppressWarnings("unchecked")
@Override
public void buildExcelDocument(Map<String, Object> map, WritableWorkbook work, HttpServletRequest req,
HttpServletResponse response) {
OutputStream os = null;
WritableSheet ws = null;
try {
ExcelEntity entity = (ExcelEntity) map.get("excelEntity");
if (entity == null) {
throw new MisException("the excelEntity is null");
}
int startRow = 0;
String excelName = entity.getExcelName();
if (os == null) {
// 设置response方式,使执行此controller时候自动出现下载页面,而非直接使用excel打开
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition",
"attachment; filename=" + URLEncoder.encode(excelName, "UTF-8"));
os = response.getOutputStream();
// 全局设置
WorkbookSettings setting = new WorkbookSettings();
java.util.Locale locale = new java.util.Locale("zh", "CN");
setting.setLocale(locale);
setting.setEncoding("ISO-8859-1");
// 创建工作薄
work = Workbook.createWorkbook(os); // 建立excel文件
}
for (ExcelSheet sheet : entity.getSheets()) {
if (sheet != null) {
String sheetName = sheet.getSheetName();
ws = work.createSheet(sheetName, sheet.getSheetIndex()); // sheet名称
// 添加标题
addColumNameToWsheet(ws, startRow, sheet);
startRow = fullTplWsheet(sheet, ws, startRow);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 写入文件
try {
work.write();
work.close();
os.flush();
os.close();
} catch (WriteException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public <T> int fullTplWsheet(ExcelSheet sheet, WritableSheet wsheet, int startRow) throws RowsExceededException,
WriteException, EnumNotFoundException, SecurityException, IllegalArgumentException, InstantiationException,
IllegalAccessException, NoSuchMethodException, InvocationTargetException {
int row = startRow;
int index = 0;
ArrayList<T> list = sheet.getData();
wsheet.mergeCells(0, row, 5, 0); // 为title,合并单元格
for (; row < startRow + list.size(); row++, index++) {
T object = list.get(index);
int column = 0;
wsheet.addCell(new jxl.write.Label(column, (row + 2), String.valueOf(index + 1), wcfFC));
fillContent(object, sheet, wsheet, column, row);
}
return row + 10;
}
/**
* 添加标题样式
*
* @param wsheet
* @param startRow
* 开始写标题所处的行数
* @throws RowsExceededException
* @throws WriteException
*/
private void addColumNameToWsheet(jxl.write.WritableSheet wsheet, int startRow, ExcelSheet sheet)
throws RowsExceededException, WriteException {
// head样式
WritableCellFormat format = getFormat(getFont());
format.setBackground(jxl.format.Colour.ORANGE);
// 内容样式
WritableFont contentFont = getContentFont();
wcfFC = getFormat(contentFont);
// title样式
WritableCellFormat titleFormat = getTitleFormat(getTitleFont());
int colSize = sheet.getColumns().length;
// title
wsheet.addCell(new jxl.write.Label(0, startRow, sheet.getSubject(), titleFormat));
String colName = null;
int witdh = 0;
// 加入编号列
fullSubject(wsheet, 0, "编号", 20, startRow, format);
for (int i = 1; i <= colSize; i++) {
colName = sheet.getColumns()[i - 1].getTitle();
witdh = sheet.getColumns()[i - 1].getWidth();
fullSubject(wsheet, i, colName, witdh, startRow, format);
}
}
/**
* 填充标题栏
*/
private void fullSubject(WritableSheet wsheet, int index, String colName, int witdh, int startRow,
WritableCellFormat format) throws RowsExceededException, WriteException {
if (null == colName || "".equals(colName))
colName = "";
Label wlabel1 = new Label(index, startRow + 1, colName, format);
wsheet.addCell(wlabel1);
// 默认设置列宽
witdh = witdh == 0 ? 20 : witdh;
wsheet.setColumnView(index, witdh);
}
// 设置title格式
private WritableCellFormat getTitleFormat(WritableFont wfont) {
WritableCellFormat wcfTitle = new WritableCellFormat(wfont);
try {
wcfTitle.setBackground(jxl.format.Colour.BLACK); // 设置单元格的背景颜色
wcfTitle.setAlignment(jxl.format.Alignment.LEFT); // 设置对齐方式
} catch (WriteException e) {
e.printStackTrace();
}
return wcfTitle;
}
// 设置格式
private WritableCellFormat getFormat(WritableFont wfont) {
WritableCellFormat wcfFC = new WritableCellFormat(wfont);
try {
wcfFC.setWrap(true);
wcfFC.setAlignment(Alignment.CENTRE);
wcfFC.setVerticalAlignment(VerticalAlignment.CENTRE);
} catch (WriteException e) {
e.printStackTrace();
}
return wcfFC;
}
// 设置head字体
private WritableFont getTitleFont() {
return new WritableFont(WritableFont.ARIAL, 20, WritableFont.BOLD, false, UnderlineStyle.NO_UNDERLINE,
jxl.format.Colour.BLACK);
}
// 设置head字体
private WritableFont getFont() {
return new WritableFont(WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.BOLD);
}
// 设置content字体
private WritableFont getContentFont() {
return new WritableFont(WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE);
}
public <T> void fillContent(T instance, ExcelSheet sheet, WritableSheet wsheet, int column, int row)
throws RowsExceededException, WriteException, InstantiationException, IllegalAccessException,
SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
// Object invokeTest = type.newInstance();
for (int k = 0; k < sheet.getColumns().length; k++) { // 用前台传递的每一个dataIndex字段去和类的属性比较
String data = sheet.getColumns()[k].getClassFieldName(); // 得到每一个字段值,如orgId,orgName……
// 第一个参数为getXXX datasubString(0,1)
// 截取第一个字母,如orgId截取o再otUpperCase变成大写
Method method = sheet.getClazz().getMethod(
"get" + data.substring(0, 1).toUpperCase() + data.substring(1, data.length()), new Class[] {});
Object result = method.invoke(instance, new Object[] {});
wsheet.addCell(new jxl.write.Label(++column, (row + 2), result + "", wcfFC));
}
}
}
代码有点乱,很高兴你能看到这里。哈哈