使用AlibabaEasyExcel v2.1.6导出excel文件,的确很方便。不过,想要设置一下单元格样式,看了官网文档,没找到。看了几篇网友的文章,综合了一下。分享出来。如果你也有类似的需求,也许可以少走一些弯路。
摘抄了一个网友的自定义注解方法,感觉很方便。在实际调试过程中发现,如果样式自定义方法与样式自定义注解发生冲突,注解会失效,输出excel文件中的格式是自定义方法中的。方法和注解结合起来设置样式,感觉很舒适。上代码。
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("t_demo_data")
@ContentRowHeight(20)
@HeadRowHeight(30)
public class DownloadData extends Model<DownloadData> implements Serializable {
private static final long serialVersionUID = 279957714570873289L;
@ExcelProperty("字符串标题")
@ColumnWidth(30)
private String string;
@ExcelProperty("日期标题")
@ColumnWidth(46)
private Date date;
@ExcelProperty("数字标题")
@ColumnWidth(20)
@ExcelStyle(fontName = "黑体", horizontalAlignment = HorizontalAlignment.RIGHT)
private Double doubleData;
}
/**
* @ClassName ExcelStyle
* @Description easyExcel-v2.1,自定义注解,实现不同单元格格式的自定义
* @Author Lx
* @Date 2020.03.26 15:53
* @Version 1.0
**/
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcelStyle {
String fontName() default "宋体";
short fontHeightInPoints() default 12;
HorizontalAlignment horizontalAlignment() default HorizontalAlignment.LEFT;
VerticalAlignment verticalAlignment() default VerticalAlignment.CENTER;
}
/**
* @ClassName ExcelStyleAnnotationCellWriteHandler
* @Description 通过自定义注解的方式实现。因为我们可以获取到field的name,
* 那么就会想到反射,只要给到field的name的class,
* 就可以获取到Field。通过反射获取到field上的注解,给field设置单元格格式
* @Author Lx
* @Date 2020.03.26 15:59
* @Version 1.0
**/
@Slf4j
public class ExcelStyleAnnotationCellWriteHandler extends HorizontalCellStyleStrategy {
private Class c;
ExcelStyleAnnotationCellWriteHandler(Class c, WriteCellStyle headWriteCellStyle,
WriteCellStyle contentWriteCellStyle) {
super(headWriteCellStyle, contentWriteCellStyle);
this.c = c;
}
@Override
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
try {
Field declaredField = c.getDeclaredField(head.getFieldName());
ExcelStyle annotation = declaredField.getAnnotation(ExcelStyle.class);
if (annotation != null) {
Workbook wb = cell.getSheet().getWorkbook();
CellStyle cellStyle = wb.createCellStyle();
Font font = wb.createFont();
font.setFontName(annotation.fontName());
font.setFontHeightInPoints(annotation.fontHeightInPoints());
cellStyle.setFont(font);
cellStyle.setAlignment(annotation.horizontalAlignment());
cellStyle.setVerticalAlignment(annotation.verticalAlignment());
cell.setCellStyle(cellStyle);
}else {
super.setContentCellStyle(cell,head,relativeRowIndex);
}
} catch (NoSuchFieldException e) {
log.error("ExcelStyleAnnotationCellWriteHandler error{0}",e);
}
}
}
/**
* @ClassName DownloadServiceImpl
* @Description 导出excel方法实现类。
* @Author Lx
* @Date 2020.03.25 11:01
* @Version 1.0
**/
@Service
public class DownloadServiceImpl extends ServiceImpl<DownloadMapper,DownloadData>
implements DownloadService {
@Resource
DownloadService downloadService;
@Override
public void downloadExcel(HttpServletResponse response) throws IOException {
try {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
// 这里需要设置不关闭流
EasyExcel.write(response.getOutputStream(), DownloadData.class)
.autoCloseStream(Boolean.FALSE).sheet("模板")
//自定义方法输出样式设置。可以不写,就默认缺省。
.registerWriteHandler(myHorizontalCellStyleStrategy())
//自定义注解excel单元格样式,在字段上注解。
//自定义注解如果与自定义方法冲突,则自定义方法优先,自定义注解失效。
.registerWriteHandler(myAnnotHoriCellStyleStrategy())
.doWrite(data());
} catch (Exception e) {
// 重置response
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, String> map = new HashMap<>(8);
map.put("status", "failure");
map.put("message", "下载文件失败" + e.getMessage());
response.getWriter().println(JSON.toJSONString(map));
}
}
private HorizontalCellStyleStrategy myAnnotHoriCellStyleStrategy(){
return new ExcelStyleAnnotationCellWriteHandler(DownloadData.class,
new WriteCellStyle(), new WriteCellStyle());
}
private HorizontalCellStyleStrategy myHorizontalCellStyleStrategy(){
//表头样式策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
//设置表头居中对齐
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
//表头前景设置淡蓝色
headWriteCellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setBold(true);
headWriteFont.setFontName("宋体");
headWriteFont.setFontHeightInPoints((short)12);
headWriteCellStyle.setWriteFont(headWriteFont);
//内容样式策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
WriteFont contentWriteFont = new WriteFont();
//内容字体大小
contentWriteFont.setFontName("宋体");
contentWriteFont.setFontHeightInPoints((short)11);
contentWriteCellStyle.setWriteFont(contentWriteFont);
//设置自动换行
contentWriteCellStyle.setWrapped(true);
//设置垂直居中
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//设置水平靠左
//contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
//设置边框样式
setBorderStyle(contentWriteCellStyle);
//内容风格可以定义多个。
List<WriteCellStyle> listCntWritCellSty = new ArrayList<>();
listCntWritCellSty.add(contentWriteCellStyle);
WriteCellStyle contentWriteCellStyle2 = new WriteCellStyle();
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色。
// 头默认了 FillPatternType所以可以不指定。
contentWriteCellStyle2.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
// 背景绿色
contentWriteCellStyle2.setFillForegroundColor(IndexedColors.GREEN.getIndex());
//设置垂直居中
contentWriteCellStyle2.setVerticalAlignment(VerticalAlignment.CENTER);
//设置边框样式
setBorderStyle(contentWriteCellStyle2);
listCntWritCellSty.add(contentWriteCellStyle2);
// 水平单元格风格综合策略(表头 + 内容)
// return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
return new HorizontalCellStyleStrategy(headWriteCellStyle, listCntWritCellSty);
}
private void setBorderStyle(WriteCellStyle contentWriteCellStyle){
//设置边框样式
contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
// contentWriteCellStyle.setBottomBorderColor(IndexedColors.BLUE.getIndex()); //颜色
contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
}
private List<DownloadData> data() {
List<DownloadData> list = downloadService.list();
System.out.println(list);
return list;
}
}
数据库操作使用的是myBatisPlus 3.2 , mysql 8.0。
开发平台 idea 2018.3。
系统框架 SpringBoot 2.0。