需求
一次在查看项目代码时,无意发现项目中一段导出excel文档的接口。但是导出写的很敷衍,就是纯人工导出差别不大。大概有五个类型集合的导出,每个类型都写了一个导出,整个类有2000多行代码。简直不能忍,于是就决定修改这部分代码。先搞个导出的工具类。四处查找之后 ,经过几次修改,最后成型。
引入jar包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.9</version>
</dependency>
自定义注解
实现导出的时候,我觉定采用注解的形式标注column name
,列宽 ,还有列顺序。等设置。
package com.xescm.whc.annotation;
import com.xescm.whc.utils.DateUtils;
import lombok.Data;
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author huxingnan
* @date 2018/3/2113:30
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface ExcelColumn {
String name() default "";//列名
int index() default 0;//列的顺序
short width() default 10;//列宽
//注解内部类 列的配置
@Data
class ExcellColumnConfig{
private int index;//列顺序
private short width;//列宽
private String columnName;//列名
private Field field;//对应属性
}
// 转换器 ,本来可以设计一个接口的,但是目前能用,就没有这么设计。
class CellDataConvertor{
public static String convertor(Object o){
if(o == null){return "";}
if(o instanceof Date){
return DateUtils.getDate2String(DateUtils.YYYY_MM_DD_HH_MM_SS,(Date) o);
}
if(o instanceof BigDecimal){
return ((BigDecimal) o).toPlainString();
}
return o.toString();
}
}
}
工具实现
直接上代码
package com.xescm.whc.utils;
import com.xescm.whc.annotation.ExcelColumn;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import java.lang.reflect.Field;
import java.util.*;
/**
* 通用的 导出 Excel 文件
* 需要配合 注解 ExcelColumn
* @see ExcelColumn
* @author huxingnan
* @date 2018/3/21 13:14
*/
public class ExportBeanExcelUtil {
/**
*
* @param dtoList 数据集合
* @param type 数据类型
* @param title 工作薄标题
* @param <T> 泛型类
* @return HSSFWorkbook 对象
*/
public static<T> HSSFWorkbook exportExcell(List<T> dtoList,Class<T> type,String title){
//1.解析注解 属性名 和 列名
List<ExcelColumn.ExcellColumnConfig> columnConfigList = processAnnotation(type);//
//2. 按照指定顺序 对列进行排序
columnConfigList = sortColumn(columnConfigList);
//3.创建工作薄
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet(title);
//4.初始化列宽 表头
initTableHeader(sheet,columnConfigList);
//5. 导出数据
createTableBody(sheet,columnConfigList,dtoList);
return wb;
}
/**
* 根据 数据 集合 创建表体
* @param sheet 工作薄对象
* @param columnConfigArray 排序后的
* @param dtoList 数据集合
* @param <T> 泛型
*/
private static <T> void createTableBody(HSSFSheet sheet, List<ExcelColumn.ExcellColumnConfig> columnConfigArray, List<T> dtoList) {
int lineNo = 1;
HSSFRow row;
HSSFCell cell;
try {
int size = columnConfigArray.size();
for (T t : dtoList) {
row = sheet.createRow(lineNo++);
for (int i = 0; i < size; i++) {
cell = row.createCell(i);
ExcelColumn.ExcellColumnConfig excellColumnConfig = columnConfigArray.get(i);
Field field = excellColumnConfig.getField();
field.setAccessible(true);
Object cellData = field.get(t);//获取数据
String cellDataStr = ExcelColumn.CellDataConvertor.convertor(cellData);//转换数据
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue(cellDataStr);
}
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 初始化 表头 设置列宽
* @param sheet 工作薄 对象
* @param columnConfigArray 排序后的
*/
private static void initTableHeader(HSSFSheet sheet, List<ExcelColumn.ExcellColumnConfig> columnConfigArray) {
HSSFRow row = sheet.createRow(0);
int size = columnConfigArray.size();
HSSFCell cell;
for (int i = 0 ; i < size;i++){
cell = row.createCell(i, HSSFCellStyle.ALIGN_CENTER);
ExcelColumn.ExcellColumnConfig excellColumnConfig = columnConfigArray.get(i);
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue(excellColumnConfig.getColumnName());
short width = excellColumnConfig.getWidth();
sheet.setColumnWidth(i,width*256);
}
}
/**
* 解析 注解
* @param type Class
* @return columnConfig 集合
*/
private static List<ExcelColumn.ExcellColumnConfig> processAnnotation(Class type){
Field[] fields = type.getDeclaredFields();
List<ExcelColumn.ExcellColumnConfig> columnConfigList = new ArrayList<>();
for (Field field : fields) {
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
if(annotation != null){
//列顺序
int index = annotation.index();
//列宽度
short width = annotation.width();
//当前列名
String name = annotation.name().equals("")?field.getName():annotation.name();
ExcelColumn.ExcellColumnConfig excellColumnConfig = new ExcelColumn.ExcellColumnConfig();
excellColumnConfig.setColumnName(name);
excellColumnConfig.setField(field);
excellColumnConfig.setIndex(index);
excellColumnConfig.setWidth(width);
columnConfigList.add(excellColumnConfig);
}
}
return columnConfigList;
}
/**
* 排序列 按照 columnConfig 中的index 排序
*
* @param columnConfigList columnCofig集合
* @return columnConfig 排序后的
*/
private static List<ExcelColumn.ExcellColumnConfig> sortColumn(List<ExcelColumn.ExcellColumnConfig> columnConfigList){
Collections.sort(columnConfigList,new Comparator<ExcelColumn.ExcellColumnConfig>() {
@Override
public int compare(ExcelColumn.ExcellColumnConfig o1, ExcelColumn.ExcellColumnConfig o2) {
return o1.getIndex()-o2.getIndex();
}
});
return columnConfigList;
}
}
用例
package com.xescm.whc.domain;
import com.xescm.whc.annotation.ExcelColumn;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 库存冻结单
*/
@Data
public class WhcFrozen implements Serializable {
private static final long serialVersionUID = 1826699766249042796L;
/**
* 冻结单号
*/
@ExcelColumn(name = "冻结单号")
private String holdOrderCode;
/**
* 批次号
*/
@ExcelColumn(name = "批次号")
private String lotNum;
/**
* 库位
*/
//默认的index = 0
@ExcelColumn(name = "库位" index='-1')
private String locationCode;
}
网友评论