已整理成完整項目,並進行了優化。看參考地址: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