学习实践
目标:
1、简化POI导出Excel的调用,方便使用(只提供数据即可)。
2、具有一定的扩展性(整体默认样式、单元格样式)。
3、对一些设计模式的具体实践。
技术要求:
对POI进行扩展。
模仿JSONObject(JsonValueProcessor)、easyui的datagrid(formatter/styler)。
模板方法模式、桥接模式。
涉及的类:
ExportGenerator | 核心类 | 导出具体实现类,子类可对其进行扩展 |
ExportConfig | 核心类 | 用于保存导出相关配置 |
CellValueProcessor | 核心接口 | 单元格处理器接口 |
YearReportExportGenerator | 扩展类 | 对ExportGenerator的扩展,提供一些基础样式 |
整个程序的执行过程:
具体代码:
/**
* 该类只提供生成workbook、填充数据到workbook
* 子类可对支持的数据格式进行拓展 子类可在生成前后加逻辑进行拓展
*
* 支持的数据格式: List<Map>、List<DynaBean>、List<List>
* 其他数据格式可自己扩展 Collention<?> + ?[]
* (Collention各种+数组各种) SimpleExportGenerator --> 简单导出,支持常见的格式
* ComplexExportGenerator(implements simple) --> 复杂导出,支持Collention<?>
*
* 生成workbook执行顺序(子类可重写)
* 1、postProcessBeforeGenerate()
* 2、generate()
* 3、postProcessAfterGenerate()
*/
public class ExportGenerator {
private List<Map> dataList; //所要导出的数据
private HSSFWorkbook workBook; //workBook实体类
private ExportConfig exportConfig; //导出配置信息
public ExportGenerator() {
this(new ArrayList<Map>());
};
public ExportGenerator(List<Map> dataList) {
this(dataList==null?new ArrayList<Map>():dataList, new ExportConfig());
};
public ExportGenerator(List<Map> dataList, ExportConfig exportConfig) {
this.dataList = dataList==null?new ArrayList<Map>():dataList;
this.exportConfig = exportConfig==null?new ExportConfig():exportConfig;
};
public ExportConfig getExportConfig() {
return this.exportConfig;
}
public void setExportConfig(ExportConfig exportConfig) {
this.exportConfig = exportConfig;
}
public List<Map> getDataList() {
return this.dataList;
};
public void setDataList(List<Map> dataList) {
this.dataList = dataList;
};
public HSSFWorkbook getWorkBook() {
return workBook;
}
public void setWorkBook(HSSFWorkbook workBook) {
this.workBook = workBook;
}
/**
* 获取 HSSFWorkbook 的源头 子类可以进行拓展
*/
protected HSSFWorkbook initWorkbook() {
return new HSSFWorkbook();
}
/**
* 生成excel模板方法 主要确定方法执行顺序
*/
public void generateWorkBook() {
workBook = initWorkbook();
postProcessBeforeGenerate(dataList, workBook);
generate(dataList, workBook);
postProcessAfterGenerate(dataList, workBook);
}
/**
* 填充数据前调用该方法
*/
public void postProcessBeforeGenerate(List<Map> dataList,HSSFWorkbook workBook) {};
/**
* 填充完数据后调用该方法
*/
public void postProcessAfterGenerate(List<Map> dataList,HSSFWorkbook workBook) {};
/**
* 获取sheet
*/
protected HSSFSheet getOrCreateSheet(int index,HSSFWorkbook workBook){
if(workBook.getNumberOfSheets()>0){
return workBook.getSheetAt(0);
}
return workBook.createSheet();
}
/**
* 具体生成workBook方法
*/
protected void generate(List<Map> dataList, HSSFWorkbook workBook) {
HSSFSheet sheet = getOrCreateSheet(0,workBook);
int rowIndex = exportConfig.getRowStartIndex(), colIndex = exportConfig.getColStartIndex();
for (Map m : dataList) {
HSSFRow row = sheet.createRow(rowIndex);
for (Object k : m.keySet()) {
HSSFCell cell = row.createCell(colIndex);
Object value = processCellValue(m.get(k), row, cell);
setValue(cell, value);
cell.setCellStyle(processCellStyle(value, row, cell));
colIndex++;
}
colIndex = 0;
rowIndex++;
}
}
/**
* 对poi中的cell进行赋值
*/
protected void setValue(HSSFCell cell, Object value) {
if (null == value) {
cell.setCellValue((java.lang.String) value);//如果值为null的话,poi自己会处理
} else if (value instanceof java.lang.String) {
cell.setCellValue((java.lang.String) value);
} else if (value instanceof java.lang.Double) {
cell.setCellValue((double) value);
} else if (value instanceof java.lang.Float) {
cell.setCellValue((float) value);
} else if (value instanceof java.lang.Long) {
cell.setCellValue((long) value);
} else if (value instanceof java.lang.Integer) {
cell.setCellValue((int) value);
} else if (value instanceof java.lang.Short) {
cell.setCellValue((short) value);
} else if (value instanceof java.lang.Boolean) {
cell.setCellValue((boolean) value);
} else if (value instanceof java.util.Date) {
cell.setCellValue((java.util.Date) value);
} else if (value instanceof java.util.Calendar) {
cell.setCellValue((java.util.Calendar) value);
} else if (value instanceof org.apache.poi.ss.usermodel.RichTextString) {
cell.setCellValue((org.apache.poi.ss.usermodel.RichTextString) value);
} else {
cell.setCellValue(value.toString());// 无匹配类型按String处理
}
}
/**
* 根据Processor获取值
*/
protected Object processCellValue(Object obj, HSSFRow row, HSSFCell cell) {
CellValueProcessor cvp = exportConfig.getCellValueProcessor();
if (null == cvp) {
return obj;
}
return cvp.processCellValue(obj, row, cell);
}
/**
* 根据Processor获取值 返回空不影响已有样式
*/
protected CellStyle processCellStyle(Object value, HSSFRow row,HSSFCell cell) {
CellValueProcessor cvp = exportConfig.getCellValueProcessor();
if (null == cvp) {
return null;
}
return cvp.processCellStyle(value, row, cell);
}
public HSSFWorkbook getWorkBookInstance() {
return getWorkBookInstance(false);
}
/**
* 向外部提供获取 HSSFWorkbook 的方法 refresh 是否重新生成HSSFWorkbook
*/
public HSSFWorkbook getWorkBookInstance(boolean refresh) {
if (refresh || null == workBook) {
generateWorkBook();
}
return workBook;
}
}
/**
* 导出配置,方便传递各种参数
*/
public class ExportConfig {
/**
* 填充数据的开始行坐标
*/
private int rowStartIndex=0;
/**
* 填充数据的开始列坐标
*/
private int colStartIndex=0;
/**
* 填充单元格时的值处理器
*/
CellValueProcessor cellValueProcessor;
public CellValueProcessor getCellValueProcessor(){
return cellValueProcessor;
}
public void setCellValueProcessor(CellValueProcessor cellValueProcessor){
this.cellValueProcessor = cellValueProcessor;
}
public int getRowStartIndex() {
return rowStartIndex;
}
public void setRowStartIndex(int rowStartIndex) {
this.rowStartIndex = rowStartIndex;
}
public int getColStartIndex() {
return colStartIndex;
}
public void setColStartIndex(int colStartIndex) {
this.colStartIndex = colStartIndex;
}
}
/**
* 值产生器接口
*/
public interface CellValueProcessor {
Object processCellValue(Object value,HSSFRow row,HSSFCell cell);
CellStyle processCellStyle(Object value,HSSFRow row,HSSFCell cell);
}
简单扩展:
public class YearReportExportGenerator extends ExportGenerator{
public YearReportExportGenerator(List<Map> dataList) {
super(dataList);
}
public YearReportExportGenerator(List<Map> dataList, ExportConfig exportConfig) {
super(dataList, exportConfig);
}
/**
* 添加表头数据
*/
@Override
public void postProcessBeforeGenerate(List<Map> dataList,HSSFWorkbook workBook) {
createHead();
}
@Override
public void postProcessAfterGenerate(List<Map> dataList,HSSFWorkbook workBook) {
createBottom();
createBorder();
}
/**
* 生成一个简易的表头
*/
public void createHead(){
HSSFSheet sheet = getWorkBook().createSheet();
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell(0);
row.setHeight((short)500);
cell.setCellValue("2015年XXX全年报表");
for(int i=1;i<13;i++){
row.createCell(i);
}
sheet.addMergedRegion(new CellRangeAddress(0,0,0,12));
HSSFCellStyle style = getWorkBook().createCellStyle();
HSSFFont font = getWorkBook().createFont();
font.setBold(true);
font.setFontHeightInPoints((short)16);
style.setFont(font);
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cell.setCellStyle(style);
HSSFRow row2 = sheet.createRow(1);
HSSFCellStyle centerStyle = getWorkBook().createCellStyle();
centerStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
for(int i=0;i<13;i++){
HSSFCell c = row2.createCell(i);
if(i>0){
c.setCellValue(i+"月");
c.setCellStyle(centerStyle);
}
}
ExportConfig cfg = getExportConfig();
cfg.setRowStartIndex(cfg.getRowStartIndex()+2);
}
/**
* 添加边框
*/
public void createBorder(){
HSSFSheet sheet = getWorkBook().getSheetAt(0);
int rows = sheet.getLastRowNum();
HSSFCellStyle style;
for(int i=0;i<rows+1;i++){
HSSFRow row = sheet.getRow(i);
Iterator<Cell> iter = row.cellIterator();
while(iter.hasNext()){
Cell c = iter.next();
style = row.getSheet().getWorkbook().createCellStyle();
style.cloneStyleFrom(c.getCellStyle());
style.setBorderTop((short)1);
style.setBorderBottom((short)1);
style.setBorderLeft((short)1);
style.setBorderRight((short)1);
c.setCellStyle(style);
}
}
}
/**
* 创建底部信息
*/
public void createBottom(){
HSSFSheet sheet = getWorkBook().getSheetAt(0);
int rows = sheet.getLastRowNum();
HSSFRow row = sheet.createRow(rows+1);
for(int i=1;i<13;i++){
row.createCell(i);
}
Cell c = row.createCell(0);
c.setCellValue("报告人:多啦a芊 报告日期:2015-12-17");
HSSFCellStyle style = row.getSheet().getWorkbook().createCellStyle();
style.cloneStyleFrom(c.getCellStyle());
style.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
c.setCellStyle(style);
sheet.addMergedRegion(new CellRangeAddress(row.getRowNum(),row.getRowNum(),0,12));
}
}
以下为调用端代码:
public class Client {
public static void main(String[] args) throws IOException {
test01();
test02();
test03();
}
/**
* 只导出数据Excel
*/
public static void test01() throws IOException{
List<Map> l = getList();
ExportGenerator generator = new ExportGenerator(l);
HSSFWorkbook workBook = generator.getWorkBookInstance();
FileOutputStream out = new FileOutputStream("D:\\excel1.xls");
workBook.write(out);
}
/**
* 导出带表头、带边框的Excel
*/
public static void test02() throws IOException{
List<Map> l = getList();
ExportGenerator generator = new YearReportExportGenerator(l);
HSSFWorkbook workBook = generator.getWorkBookInstance();
FileOutputStream out = new FileOutputStream("D:\\excel2.xls");
workBook.write(out);
}
/**
* 导出带表头、带边框和行样式的Excel
*/
public static void test03() throws IOException{
List<Map> l = getList();
CellValueProcessor cvp = new CellValueProcessor(){
@Override
public Object processCellValue(Object value, HSSFRow row,HSSFCell cell) {
return value==null?"-":value;
}
@Override
public CellStyle processCellStyle(Object value, HSSFRow row,HSSFCell cell) {
HSSFCellStyle style = null;
if(value instanceof Number){
int v = (int)value;
if(v<0){
style = row.getSheet().getWorkbook().createCellStyle();
style.cloneStyleFrom(cell.getCellStyle());
style.setFillForegroundColor(HSSFColor.RED.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
}else if(v>100){
style = row.getSheet().getWorkbook().createCellStyle();
style.cloneStyleFrom(cell.getCellStyle());
style.setFillForegroundColor(HSSFColor.BRIGHT_GREEN.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
}
}else{
style = row.getSheet().getWorkbook().createCellStyle();
style.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
}
return style;
}
};
ExportConfig cfg = new ExportConfig();
cfg.setCellValueProcessor(cvp);
ExportGenerator generator = new YearReportExportGenerator(l,cfg);
HSSFWorkbook workBook = generator.getWorkBookInstance();
FileOutputStream out = new FileOutputStream("D:\\excel3.xls");
workBook.write(out);
}
/**
* 获取假数据
*/
public static List<Map> getList(){
List<Map> l = new ArrayList<Map>();
Random r = new Random();
Map m;
for(int i=0;i<10;i++){
m = new LinkedMap();
m.put("name", "指标"+i);
for(int j=0;j<12;j++){
if(r.nextInt(20)<1){
m.put(j, null);
}else{
m.put(j, r.nextInt(120)-10);
}
}
l.add(m);
}
return l;
}
}
test01()生成结果:
test02()生成结果:
test03()生成结果: