利用注解和反射,实现Excel通用导出
注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelAnnotation {
String filedName();
}
导出出参类
在类中属性上方加上先前自定义的注解,标识该列为可导出列,注解中的属性即为导出后的列名
import lombok.Data;
import java.util.Date;
/**
* @ClassName ExportExcelDto
* @Author zhang jie
* @Date 2021/9/22 16:42
* @Version 1.0
*/
@Data
public class ExportExcelDto {
@ExcelAnnotation(filedName = "序号")
@ApiModelProperty("序号")
private Integer sequenceNumber;
@ExcelAnnotation(filedName = "题库")
@ApiModelProperty("所属题库名称")
private String examName;
@ExcelAnnotation(filedName = "内容")
@ApiModelProperty("内容")
private String content;
@ExcelAnnotation(filedName = "评分规则")
@ApiModelProperty("评分规则")
private String scoringRule;
@ExcelAnnotation(filedName = "权重")
@ApiModelProperty("权重")
private Integer weight;
@ExcelAnnotation(filedName = "单位")
@ApiModelProperty("单位")
private String grpname;
@ExcelAnnotation(filedName = "是否需要提交材料")
@ApiModelProperty("是否允许上传材料 中文")
private String upload;
@ApiModelProperty("操作用户ID")
private String operationUserId;
@ApiModelProperty("创建时间")
private Date createTime;
@ApiModelProperty("修改时间")
private Date updateTime;
}
导出工具类
利用反射获取传入类的所有类名以及类上方所添加的注解
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* excel导出工具类
* @ClassName ExportExcelUtil
* @Author zhang jie
* @Date 2021/9/22 15:07
* @Version 1.0
*/
public class ExportExcelUtil<T> {
Class<T> clazz;
public ExportExcelUtil(Class<T> clazz){this.clazz = clazz;}
public void export(HttpServletResponse response, List<T> list){
try {
// 第一步,创建一个webBook,对应一个Excel文件
HSSFWorkbook wb = new HSSFWorkbook();
// 第二步,在webBook中添加一个sheet,对应Excel文件中的sheet
HSSFSheet sheet = wb.createSheet("sheet1");
// 默认列宽
sheet.setDefaultColumnWidth(20);
// 生成字体对象
HSSFFont font = wb.createFont();
font.setFontHeightInPoints((short) 14);
font.setFontName("宋体");
font.setFontName("Times New Roman");
font.setBold(true);
// 生成样式对象
HSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setFont(font); // 调用字体样式对象
// 得到目标目标类的所有的字段列表
Field[] filed = clazz.getDeclaredFields();
// 将所有标有Annotation的字段,也就是允许导入数据的字段,放入到一个map中
HashMap<String,Object> map = new HashMap<>();
for (Field f : filed){
// 得到单个字段上的Annotation,也就是导出后Excel表的列名
ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
if (exa != null) {
// 将获取到的列名存放到map中,以字段名为key,以列名为value
map.put(f.getName(), exa.filedName());
}
}
// 设置表格列名
int i = 0;
HashMap<String,Integer> columnMap = new HashMap<>();
HSSFRow row = sheet.createRow(0);
for (Map.Entry<String, Object> entry : map.entrySet()) {
row.createCell(i).setCellStyle(style);
row.getCell((short) i).setCellValue(String.valueOf(entry.getValue()));
columnMap.put(entry.getKey(),i); // 记录当前表头所在列数
i++;
}
//插入数据
int k = 1; // 行数
for (T t : list){
row = sheet.createRow(k);
Field[] fields = t.getClass().getDeclaredFields();
for (Field f : fields){
ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
if (exa != null){
if (map.containsKey(f.getName())){
String fieldName = f.getName();
String getMethodName = "get"
+ fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
Method getMethod =t.getClass().getDeclaredMethod(getMethodName);
int c = columnMap.get(fieldName); // 获取先前记录的列数
row.createCell(c).setCellStyle(style);
row.getCell((short) c).setCellValue(String.valueOf(getMethod.invoke(t))); // 调用get方法取值
}
}
}
k++;
}
String filename = "CountScore";
response.setCharacterEncoding("UTF-8");
response.setContentType("application/ms-excel;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(filename+".xls", "UTF-8"))));
//以流的形式输出
OutputStream outputStream = response.getOutputStream();
wb.write(outputStream);
wb.close();
outputStream.close();
}catch (Exception e){
LoggerUtil.error("导出文件失败!", e);
}
}
}
调用
@Override
public void exportScore(HttpServletResponse response) {
//获取导出数据
List<CountScoreDto> countScoreDtoList = mapper.selectAllList();
ArrayList<ExportExcelDto> list = new ArrayList<>();
// 利用springboot自带工具,将数据复制到Excel导出出参类集合中
countScoreDtoList.forEach(c ->{
ExportExcelDto exportExcelDto = new ExportExcelDto();
BeanUtils.copyProperties(c,exportExcelDto);
list.add(exportExcelDto);
});
ExportExcelUtil<ExportExcelDto> exportUtil = new ExportExcelUtil<>(ExportExcelDto.class);
exportUtil.export(response,list);
}
结束
ps:另外还有一个通用导入的工具类,实现原理跟这个完全相同,写在另一篇温州