POI封裝二:導出 Export

已整理成完整項目,並進行了優化。看參考地址:java

https://gitee.com/andy_longjie/exceltools   或者 https://github.com/youmulongjie/exceltoolsgit

POI 導出篇

一、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>

二、項目目錄樹:

 

三、定義註解類:

(一):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>
 * 一、導出的類必須添加註解類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();
}

(二)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>
 * 一、導出的類必須添加該註解類 <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

相關文章
相關標籤/搜索