已整理成完整项目,并进行了优化。看参考地址:
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltools
POI 导出篇
1、maven jar 包依赖:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<poi.version>3.12</poi.version>
<dict>exceltools</dict><!-- 项目名称 -->
</properties>
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
2、项目目录树:
3、定义注解类:
(一):ExcelExportCol.java
/**
* @package :com.andy.demo.execltools.exports.annotation<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:26:29<br>
*/
package com.andy.demo.execltools.exports.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 描述:Excel 导出属性注解类<br>
* <br>
* 1、导出的类必须添加注解类ExcelExportConfig<br>
* 2、该注解类用在类属性上,获取Excel的列标题头和列索引(从0开始)<br>
*
* @package :com.andy.demo.execltools.exports.annotation<br>
* @file :ExcelExportCol.java<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:26:29<br>
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface ExcelExportCol {
/**
*
* 描述:列标题头说明 <br>
*
* @method :colHeaderDesc<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:27:15 <br>
* @return 列标题头说明
*/
String colHeaderDesc();
/**
*
* 描述:所在列索引,下标从0开始 <br>
*
* @method :cols<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:27:38 <br>
* @return 所在列索引,下标从0开始
*/
int cols();
}
(二)ExcelExportConfig.java
/**
* @package :com.andy.demo.execltools.exports.annotation<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:22:43<br>
*/
package com.andy.demo.execltools.exports.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 描述:Excel 导出注解类 <br>
* <br>
* 1、导出的类必须添加该注解类 <br>
* 2、默认导出的Excel第0行为标题行,对象记录行从第1行开始<br>
*
* @package :com.andy.demo.execltools.exports.annotation<br>
* @file :ExcelExportConfig.java<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:22:43<br>
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface ExcelExportConfig {
/**
*
* 描述: 生成Excel文件的 标题所在的行数,默认为0<br>
*
* @method :headerRow<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:23:29 <br>
* @return 生成Excel文件的 标题所在的行数
*/
int headerRow() default 0;
/**
*
* 描述:生成Excel文件的 对象记录所在的行数,默认从1开始 <br>
*
* @method :lineStartRow<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:23:56 <br>
* @return 生成Excel文件的 对象记录所在的行数
*/
int lineStartRow() default 1;
}
3、导出工具类:
/**
* Excel 导出 包 <br>
* @package :com.andy.demo.execltools.exports<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:20:18<br>
*/
package com.andy.demo.execltools.exports;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
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.xssf.usermodel.XSSFWorkbook;
import com.andy.demo.execltools.exports.annotation.ExcelExportCol;
import com.andy.demo.execltools.exports.annotation.ExcelExportConfig;
/**
* 描述:Excel 导出工具类 <br>
*
* @package :com.andy.demo.execltools.exports<br>
* @file :ExcelToolsExport.java<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:20:18<br>
*
*/
public class ExcelToolsExport {
private static final String DATE_FORMAT = "yyyy-mm-dd";
private static final String NUMERIC_FORMAT = "#############0.00######";
private static final int BUFFER_SIZE = 4096 * 10;
/**
*
* 描述:将List对象集合 转化为 byte 数组,生成一张sheet的byte数组源 <br>
*
* @method :createExcelExport<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午4:02:35 <br>
* @param list
* : 对象集合数据源
* @param sheetName
* :要生成的 sheet 的名称
* @return byte数组
* @throws Exception
*/
public static <T> byte[] createExcelExport(List<T> list, String sheetName)
throws Exception {
checkValidate(list);
Workbook wb = createWorkbook(true);
sheetName = (null == sheetName || sheetName.equals("")) ? "sheet1"
: sheetName;
Sheet sheet = wb.createSheet(sheetName);
setExcelHeader(sheet, list.get(0));
setExcelLines(sheet, list, wb);
return getByteFormWb(wb);
}
/**
*
* 描述:将List对象集合 转化为 byte 数组,同一Excel生成多张sheet的byte数组源 <br>
*
* @method :createExcelExport<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午4:12:03 <br>
* @param map
* : 封装的sheet的数据源集合
* @return byte数组
* @throws Exception
*/
public static byte[] createExcelExport(Map<String, List<?>> map)
throws Exception {
if (null != map && map.size() > 0) {
Workbook wb = createWorkbook(true);
Iterator<String> it = map.keySet().iterator();
Sheet sheet = null;// 生成的 sheet 对象
String sheetName = null;// sheet 名称
List<?> list = null; // sheet 数据源
while (it.hasNext()) {
sheetName = (String) it.next();
list = map.get(sheetName);
checkValidate(list);
sheet = wb.createSheet(sheetName);
setExcelHeader(sheet, list.get(0));
setExcelLines(sheet, list, wb);
}
return getByteFormWb(wb);
}
return null;
}
/**
*
* 描述:设置 生成Excel的内容记录行 <br>
*
* @method :setExcelLines<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午3:23:25 <br>
* @param sheet
* :创建的 Sheet对象
* @param list
* :对象集合数据源
* @param wb
* :创建的WorkBook 工作薄对象
* @throws Exception
*/
private static <T> void setExcelLines(Sheet sheet, List<T> list, Workbook wb)
throws Exception {
int lineStartRow = getLineStartRow(list.get(0).getClass());
Row row = null;
for (int i = 0; i < list.size(); i++) {
row = sheet.createRow(lineStartRow);
obj2Cell(row, list.get(i), wb);
lineStartRow++;
}
}
/**
*
* 描述:设置 生成Excel的标题头行 <br>
*
* @method :setExcelHeader<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午3:20:11 <br>
* @param sheet
* :Sheet 对象
* @param t
* :Excel 的载体实体类对象
* @throws Exception
*/
private static <T> void setExcelHeader(Sheet sheet, T t) throws Exception {
int headRow = getHeaderRow(t.getClass());
Row row = sheet.createRow(headRow);
List<Field> list = getExcelExportColAnnoFields(t.getClass());
ExcelExportCol excelExportCol = null;
int cols = 0;// 标题列索引
String colHeaderDesc = null;// 标题头说明
for (Field f : list) {
excelExportCol = f.getAnnotation(ExcelExportCol.class);
cols = excelExportCol.cols();
colHeaderDesc = excelExportCol.colHeaderDesc();
row.createCell(cols).setCellValue(colHeaderDesc);
}
}
/**
*
* 描述:填充 Excel 数据行 <br>
*
* @method :obj2Cell<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午3:59:57 <br>
* @param row
* : 创建的Row 行对象
* @param t
* :对象数据源
* @param wb
* :创建的Workbook 工作薄对象
* @throws Exception
*/
private static <T> void obj2Cell(Row row, T t, Workbook wb)
throws Exception {
List<Field> list = getExcelExportColAnnoFields(t.getClass());
ExcelExportCol excelExportCol = null;
Cell cell = null; // 单元格
int cols = 0;// 单元格 列索引
Object value = null;// 单元格内容(反射获取的属性值)
PropertyDescriptor pd = null;
Method m = null;
for (Field f : list) {
excelExportCol = f.getAnnotation(ExcelExportCol.class);
cols = excelExportCol.cols();
// 反射获取对象的属性值
pd = new PropertyDescriptor(f.getName(), t.getClass());
m = pd.getReadMethod();
value = m.invoke(t);
if (null == value) {
// 属性值为空,则不需要填充单元格,返回
return;
}
cell = row.createCell(cols);
fillCell(value, cell, wb);
}
}
/**
*
* 描述:填充 单元格 <br>
*
* @method :fillCell<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午3:57:40 <br>
* @param value
* :单元格 内容
* @param cell
* :要填充的单元格
* @param wb
* : 创建的WorkBook 工作薄对象
*/
private static void fillCell(Object value, Cell cell, Workbook wb) {
if (value instanceof java.util.Date) {
java.util.Date d = (java.util.Date) value;
DataFormat format = wb.createDataFormat();
// 日期格式化
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(format.getFormat(DATE_FORMAT));
cell.setCellStyle(cellStyle);
cell.setCellValue(d);
return;
}
if (value instanceof java.sql.Date) {
java.sql.Date d = (java.sql.Date) value;
cell.setCellValue(d);
return;
}
if (value instanceof Timestamp) {
Timestamp ts = (Timestamp) value;
cell.setCellValue(ts);
return;
}
if (value instanceof BigDecimal) {
BigDecimal b = (BigDecimal) value;
cell.setCellValue(b.doubleValue());
return;
}
if (value instanceof Double) {
Double d = (Double) value;
DataFormat format = wb.createDataFormat();
// 数字格式化
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(format.getFormat(NUMERIC_FORMAT));
cell.setCellStyle(cellStyle);
cell.setCellValue(d);
return;
}
if (value instanceof Float) {
Float f = (Float) value;
DataFormat format = wb.createDataFormat();
// 数字格式化
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(format.getFormat(NUMERIC_FORMAT));
cell.setCellStyle(cellStyle);
cell.setCellValue(f);
return;
}
if (value instanceof Long) {
Long l = (Long) value;
cell.setCellValue(l);
return;
}
if (value instanceof Integer) {
Integer i = (Integer) value;
cell.setCellValue(i);
return;
}
if (value instanceof Boolean) {
Boolean b = (Boolean) value;
cell.setCellValue(b);
return;
}
if (value instanceof String) {
String s = (String) value;
cell.setCellValue(s);
return;
}
}
/**
*
* 描述:创建 WorkBook 工作薄对象 <br>
*
* @method :createWorkbook<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午3:01:03 <br>
* @param flag
* :true:xls(1997-2007) false:xlsx(2007以上)
* @return WorkBook 工作薄对象
*/
private static Workbook createWorkbook(boolean flag) {
Workbook wb;
if (flag) {
wb = new XSSFWorkbook();
} else {
wb = new HSSFWorkbook();
}
return wb;
}
/**
*
* 描述:将创建的 Workbook 工作薄对象转化为byte输出流 <br>
*
* @method :getByteFormWb<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:59:10 <br>
* @param wb
* : 创建的 Workbook 工作薄对象
* @return byte输出流
* @throws Exception
*/
private static byte[] getByteFormWb(Workbook wb) throws Exception {
if (null != wb) {
ByteArrayOutputStream byStream = new ByteArrayOutputStream(
BUFFER_SIZE);
wb.write(byStream);
return byStream.toByteArray();
}
return null;
}
/**
*
* 描述: 读取生成Excel文件的 标题所在的行数 <br>
*
* @method :getHeaderRow<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:35:20 <br>
* @param cla
* :Excel 的载体实体类
* @return
* @throws Exception
*/
private static <T> int getHeaderRow(Class<T> cla) throws Exception {
return cla.getAnnotation(ExcelExportConfig.class).headerRow();
}
/**
*
* 描述:读取生成Excel文件的 对象记录所在的行数 <br>
*
* @method :getLineStartRow<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:36:15 <br>
* @param cla
* :Excel 的载体实体类
* @return
* @throws Exception
*/
private static <T> int getLineStartRow(Class<T> cla) throws Exception {
return cla.getAnnotation(ExcelExportConfig.class).lineStartRow();
}
/**
*
* 描述: 获取Excel的载体实体类中添加ExcelExportCol注解的属性集合<br>
*
* @method :getExcelExportColAnnoFields<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:39:16 <br>
* @param cla
* :Excel 的载体实体类
* @return
* @throws java.lang.Exception
*/
private static <T> List<Field> getExcelExportColAnnoFields(Class<T> cla)
throws Exception {
List<Field> list = new ArrayList<Field>();
Field[] fields = cla.getDeclaredFields();
for (Field f : fields) {
if (f.isAnnotationPresent(ExcelExportCol.class)) {
list.add(f);
}
}
return list;
}
/**
*
* 描述:验证导出Excel的载体实体类是否合法 <br>
*
* @method :checkValidate<br>
* @author :wanglongjie<br>
* @createDate :2015年12月2日下午2:54:59 <br>
* @param list
* :对象集合数据源
* @return
* @throws Exception
*/
private static boolean checkValidate(List<?> list) throws Exception {
if (null == list || list.size() == 0) {
throw new Exception("指定的对象集合数据源为null,或者长度等于0!");
}
Class<?> cla = list.get(0).getClass();
if (!cla.isAnnotationPresent(ExcelExportConfig.class)) {
throw new Exception("指定的实体类" + list.get(0).getClass().getName()
+ " 缺少ExcelExportConfig注解!");
}
int headerRow = getHeaderRow(cla);
int lineStartRow = getLineStartRow(cla);
if (headerRow >= lineStartRow) {
throw new Exception("指定的实体类" + cla.getName()
+ " 设置的标题头行应该小于内容记录开始行!");
}
if (getExcelExportColAnnoFields(cla).size() == 0) {
throw new Exception("指定的实体类" + cla.getName()
+ " 属性缺少ExcelExportCol注解!");
}
return true;
}
}
已整理成完整项目,并进行了优化。看参考地址:
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltools