已整理成完整项目,并进行了优化。看参考地址:java
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltoolsgit
<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>
/** * @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> * 一、导出的类必须添加注解类ExcelExportConfig<br> * 二、该注解类用在类属性上,获取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(); }
/** * @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> * 一、导出的类必须添加该注解类 <br> * 二、默认导出的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; }
/** * 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; } }
已整理成完整项目,并进行了优化。看参考地址:github
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltoolssql