项目特殊,数据源多种,导致导出sheet页各不相同且列超多(200+),客户变更频繁(开发阶段)。
设计用注解导出,节省开发时间。
涉及到注解的repeatable使用。
package com.hp.portal.util;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.StringUtils;
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.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Pageable;
import org.springframework.util.CollectionUtils;
import com.hp.portal.util.MyAnnotations.MyColumn;
import com.hp.portal.util.MyAnnotations.MyColumns;
import com.hp.portal.util.MyAnnotations.MySheet;
public class ExcelUtils {
private static Logger logger = LoggerFactory.getLogger(ExcelUtils.class);
private static String DATE_FORMAT = "yyyy-MM-dd";
private static String NUMBER_MATCHER = "^(-?\\d+)(\\.\\d+)?$";
public static SXSSFWorkbook getSXSSFWorkbook() {
return new SXSSFWorkbook(-1);
}
@SuppressWarnings("unchecked")
public static void sheetSort(SXSSFWorkbook wb, Collection categorys) {
List sheets = new ArrayList();
for (String category : categorys) {
sheets.add((MySheet) DocumentUtils.getClazz(category).getAnnotation(MySheet.class));
}
if (wb != null && !CollectionUtils.isEmpty(sheets) && wb.getNumberOfSheets() == sheets.size()) {
Collections.sort(sheets, new Comparator() {
@Override
public int compare(MySheet sheet1, MySheet sheet2) {
return sheet1.order() - sheet2.order();
}
});
for (int i = 0; i < sheets.size(); i++) {
wb.setSheetOrder(sheets.get(i).value(), i);
}
wb.setActiveSheet(0);
}
}
@SuppressWarnings("unchecked")
public static void createSheet(SXSSFWorkbook wb, List rows, List column, Pageable page) {
if (!CollectionUtils.isEmpty(rows)) {
Class clazz = (Class) rows.get(0).getClass();
if (clazz.isAnnotationPresent(MySheet.class)) {
List columns = getColumns(clazz, column);
String sheetName = StringUtils.isEmpty(clazz.getAnnotation(MySheet.class).value())
? clazz.getSimpleName() : clazz.getAnnotation(MySheet.class).value();
Sheet sheet = wb.getSheet(sheetName);
if (sheet == null) {
sheet = wb.createSheet(sheetName);
wb.setSheetOrder(sheetName, clazz.getAnnotation(MySheet.class).order() >= wb.getNumberOfSheets()
? wb.getNumberOfSheets() - 1 : clazz.getAnnotation(MySheet.class).order());
createTitle(sheet.createRow(0), columns, clazz);
}
fillDatas(sheet, columns, rows, page.getPageNumber() * page.getPageSize() + 1);
}
}
}
private static List getColumns(Class clazz, List column) {
List columns = new ArrayList();
Field[] fields = clazz.getDeclaredFields();
Field[] supFields = clazz.getSuperclass().getDeclaredFields();
if (CollectionUtils.isEmpty(column)) {
for (Field field : fields) {
if (field.isAnnotationPresent(MyColumn.class) && field.getAnnotation(MyColumn.class).display()) {
columns.add(field);
}
}
for (Field field : supFields) {
MyColumn mc = getMyColumnAnnotation(field, clazz);
if (mc != null && mc.display()) {
columns.add(field);
}
}
} else {
for (Field field : fields) {
if (field.isAnnotationPresent(MyColumn.class) && column.contains(field.getName())) {
columns.add(field);
}
}
for (Field field : supFields) {
MyColumn mc = getMyColumnAnnotation(field, clazz);
if (mc != null && column.contains(field.getName())) {
columns.add(field);
}
}
}
columns.sort(new Comparator() {
public int compare(Field f1, Field f2) {
return getOrder(f1) >= getOrder(f2) ? 1 : -1;
}
private int getOrder(Field field) {
int order = 0;
MyColumn mc = getMyColumnAnnotation(field, clazz);
if (mc != null) {
order = mc.order();
}
return order;
}
});
return columns;
}
private static void createTitle(Row row, List columns, Class clazz) {
int i = 0;
for (Field field : columns) {
Cell cell = row.createCell(i);
cell.getSheet().setColumnWidth(i, getMyColumnAnnotation(field, clazz).length() * 256);
cell.setCellValue(getMyColumnAnnotation(field, clazz).value());
i++;
}
}
private static void fillDatas(Sheet sheet, List columns, Collection rows, int startRow) {
CellStyle cellStyle = sheet.getWorkbook().createCellStyle();
DataFormat format = sheet.getWorkbook().createDataFormat();
cellStyle.setDataFormat(format.getFormat(DATE_FORMAT));
PropertyDescriptor pd;
try {
for (T t : rows) {
Row row = sheet.createRow(startRow);
int j = 0;
for (Field field : columns) {
Cell cell = row.createCell(j);
pd = new PropertyDescriptor(field.getName(), t.getClass());
Object o = pd.getReadMethod().invoke(t);
Class> clazz = pd.getPropertyType();
if (o != null) {
if (Date.class.equals(clazz)) {
cell.setCellValue((Date) o);
cell.setCellStyle(cellStyle);
} else if (StringUtils.isNotEmpty(String.valueOf(o))) {
if (String.valueOf(o).matches(NUMBER_MATCHER)) {
cell.setCellValue(Double.parseDouble(String.valueOf(o)));
} else {
cell.setCellValue(String.valueOf(o));
}
}
}
j++;
}
if (startRow % 1000 == 0) {
((SXSSFSheet) sheet).flushRows(1000);
}
startRow++;
}
} catch (IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| IOException e) {
logger.debug(e.getMessage());
}
}
private static MyColumn getMyColumnAnnotation(Field field, Class clazz) {
MyColumn myColumn = null;
if (field.isAnnotationPresent(MyColumn.class)) {
myColumn = field.getAnnotation(MyColumn.class);
if (StringUtils.isNotEmpty(myColumn.sheetName())
&& !StringUtils.equals(myColumn.sheetName(), clazz.getSimpleName())) {
myColumn = null;
}
} else if (field.isAnnotationPresent(MyColumns.class)) {
MyColumn[] mcs = field.getAnnotationsByType(MyColumn.class);
for (MyColumn mc : mcs) {
if (StringUtils.equals(mc.sheetName(), clazz.getSimpleName())) {
myColumn = mc;
break;
}
}
}
return myColumn;
}
}
package com.hp.portal.util;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;
public class MyAnnotations {
@Repeatable(MyColumns.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyColumn {
String value();
int order();
boolean display() default true;
String sheetName() default "";
int length() default 15;
}
@Target({ ElementType.FIELD })
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyColumns {
MyColumn[] value();
}
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface MySheet {
String value() default "";
int order();
}
}