最近又在使用poi进行execl的导入导出,然后思来想去,决定简单实现一个工具类。那么问题来了,要怎么实现呢?
- 首先肯定需要利用反射,根据列名进行值的设置。
- 然后是实体属性与列名的对应关系(不是每个字段都对应一个execl表中的一个列),最终决定使用自定义注解实现。
前置知识
- 反射
- 注解
思路
导出
- 参数
– 需要导出的数据集合。
– 要导出的列名的数组- 操作
– 遍历数据集合,创建行HSSFRow,遍历列名数组,创建列HSSFCell
– 反射获取属性和列名的对应关系,在遍历列名数组创建列时,获取对应的属性名,如果存在对应关系,则获取属性名,利用反射执行getXxx方法获取值,然后setCellValue();
导入
- 参数
– execl文件的输入流
– 标题所在行(方便遍历获取值)
– 实体类Class对象(最后生成实体集合)- 操作
– 反射获取实体类的注解(实体属性和列名的对应关系)
– 根据输入流创建HSSFWorkbook,然后遍历,如果存在属性和列名的对应,则反射实体类的属性,然后赋值。
代码
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
@TableId(type = IdType.AUTO)
private long id;
@ExeclTitleName("工号")
private String uno;
@ExeclTitleName("姓名")
private String uname;
private String upass;
@ExeclTitleName("头像")
private String uimage;
@ExeclTitleName("性别")
private long usex;
@ExeclTitleName("手机")
private String uphone;
@ExeclTitleName("邮箱")
private String uemail;
反射获取注解信息
/**
* 获取指定类中 @ExeclTitleName和属性的对应关系
*
* @param clazz
* @param <T>
* @return
*/
public static <T> Map<String, String> getAnnotationName(Class<T> clazz) {
Map<String, String> map = new HashMap<>();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.isAnnotationPresent(ExeclTitleName.class)) {
String propValue = field.getName();
ExeclTitleName annotation = field.getAnnotation(ExeclTitleName.class);
String execlValue = annotation.value();
map.put(execlValue, propValue);
}
}
return map;
}
导入
/**
* @param is execl文件输入流
* @param dataRow 标题开始行
* @param clazz 需要映射的实体类
* @param <T>
* @return 实体类集合
* @throws Exception
*/
public static <T> List<T> getData(InputStream is, int dataRow, Class<T> clazz) throws Exception {
HSSFWorkbook workbook = new HSSFWorkbook(is);
HSSFSheet sheet = workbook.getSheetAt(0);
int rowNum = sheet.getLastRowNum();
HSSFRow titleRow = sheet.getRow(dataRow);
//列名和属性名对应关系
Map<String, String> map = getAnnotationName(clazz);
//execl表中全部列和属性的对应关系
Map<Integer, String> propertyMap = new HashMap<>();
//获取列名,并获取属性
for (int i = 0; i < titleRow.getLastCellNum(); i++) {
HSSFCell cell = titleRow.getCell(i);
//列名
String titleName = cell.getStringCellValue();
//属性名
String propertyName = map.get(titleName);
propertyMap.put(i, propertyName);
}
//映射结果集合
List<T> list = new ArrayList<>();
for (int i = dataRow + 1; i <= rowNum; i++) {
HSSFRow row = sheet.getRow(i);
T object = clazz.newInstance();
if (row == null)
continue;
short cellNum = row.getLastCellNum();
for (int j = 0; j < cellNum; j++) {
HSSFCell cell = row.getCell(j);
String cellValue;
if (cell == null) {
cellValue = "";
} else if (cell.getCellType() == HSSFCell.CELL_TYPE_BOOLEAN) {// 对布尔值的处理
cellValue = String.valueOf(cell.getBooleanCellValue());
} else if (cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {// 对数字值的处理
cellValue = cell.getNumericCellValue() + "";
} else {
// 其余按照字符串处理
cellValue = cell.getStringCellValue();
}
if (cellValue != null && cellValue != "") {
//获取execl对应的属性名
String propertyNmme = propertyMap.get(j);
//存在对应关系则进行反射赋值
if (propertyNmme != null) {
Field field = clazz.getDeclaredField(propertyNmme);
field.setAccessible(true);
Type genericType = field.getGenericType();
if (genericType.toString().equals("long")) {
field.setLong(object, Long.valueOf(cellValue));
} else if (genericType.toString().equals("double")) {
field.setDouble(object, Double.valueOf(cellValue));
} else {
field.set(object, cellValue);
}
}
}
}
list.add(object);
}
return list;
}
导出
/**
* 导出Execl工具类
* @param titleName 大标题名称
* @param columns 列名数组
* @param clazz 导出的数据类型
* @param list 导出的数据集合
* @param <T>
* @return
* @throws Exception
*/
public static <T> HSSFWorkbook createWorkBook(String titleName, String[] columns, Class<T> clazz, List<T> list) throws Exception {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet(titleName);
int rowCount = 0;
//大标题,合并单元格
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, columns.length - 1));
HSSFRow bigtitleRow = sheet.createRow(rowCount++);
HSSFCell bigtitleCell = bigtitleRow.createCell(0);
//设置单元格样式
bigtitleCell.setCellStyle(bigTitleStyle(workbook));
bigtitleCell.setCellValue(titleName);
HSSFRow titleRow = sheet.createRow(rowCount++);
//创建标题栏
for (int i = 0; i < columns.length; i++) {
HSSFCell cell = titleRow.createCell(i);
cell.setCellStyle(smallCellStyle(workbook));
cell.setCellValue(columns[i]);
}
//属性和列名映射
Map<String, String> annotationName = getAnnotationName(clazz);
//创建数据
for (int i = 0; i < list.size(); i++ ) {
HSSFRow row = sheet.createRow(rowCount++);
T object = list.get(i);
for (int j = 0; j < columns.length; j++) {
sheet.setColumnWidth(j,22*256);//设置列宽为22个字符长度
String property = annotationName.get(columns[j]);
Object value;
if (property != null) {
String methodName = "get"+property.substring(0,1).toUpperCase()+property.substring(1);
Method method = clazz.getDeclaredMethod(methodName, null);
value = method.invoke(object, null);
}else{
value = "";
}
HSSFCell unoCell = row.createCell(j);
unoCell.setCellStyle(smallCellStyle(workbook));
unoCell.setCellValue(String.valueOf(value));
}
}
return workbook;
}
private static CellStyle bigTitleStyle(Workbook wb) {
//单元格样式
CellStyle curStyle = wb.createCellStyle();
//字体
Font curFont = wb.createFont();
curFont.setFontName("微软雅黑");
curFont.setFontHeightInPoints((short) 18);
//字体加粗
curFont.setBold(true);
curStyle.setFont(curFont); // 绑定字体
curStyle.setAlignment(HorizontalAlignment.CENTER); // 横向居中
curStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 纵向居中
curStyle.setFillBackgroundColor((short) 13);
return curStyle;
}
public static CellStyle smallCellStyle(Workbook wb) {
//单元格样式
CellStyle curStyle = wb.createCellStyle();
//字体
Font curFont = wb.createFont();
curFont.setFontName("微软雅黑");
curStyle.setFont(curFont); // 绑定字体
curStyle.setAlignment(HorizontalAlignment.CENTER); // 横向居中
curStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 纵向居中
return curStyle;
}