准备工作
- 准备依赖,这期导出使用easyexcel
<!-- excel导入导出功能 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
- 准备后面需要的导出模板
模板中使用{.content}占位符进行后续列表数据填充,如果是对象数据可以直接使用{content}进行占位符填充即可。
常见的两种导出方式
- 第一种:直接根据查询出来的数据,使用实体类注解进行导出设置,不是用模板。
在实体类根据注解进行设置,需要注意的是设置好规定的属性和单元格坐标,表格坐标是从0开始,不是1哦,各位靓仔请注意,需要导出的字段都加上
@ExcelProperty(
value = "你的属性",index = 0,
)
- 第二种:将导出的列表数据根据创建的模板,进行数据填充。
这种就是使用自己创建的模板了,模板遵循占位符,上面讲到了{}大括号就行,这里的实体类不需要额外添加注解了。就使用正常的实体类就行了。
字典转换
业务开发中常常会遇到数据库存储的是字典数字,但是表示的含义又是中文形式的,例如1表示男性,2表示女性,如果不处理的话导出会展示成数字,显然是不符合逻辑的。现在我们来将一种字典格式转换器。
- 创建我们的性别转换器
/**
* Excel 性别转换器
*
* @author swt */
public class GenderConverter implements Converter<Integer> {
@Override
public Class<?> supportJavaTypeKey() {
return Integer.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public Integer convertToJavaData(ReadConverterContext<?> context) {
return GenderEnum.convert(context.getReadCellData().getStringValue()).getValue();
}
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<Integer> context) {
return new WriteCellData<>(GenderEnum.convert(context.getValue()).getDescription());
}
}
- 其中的值使用字典枚举进行对应
/**
* 性别枚举
*
* @author william@StarImmortal
*/
@Getter
@AllArgsConstructor
public enum GenderEnum {
/**
* 未知
*/
UNKNOWN(0, "未知"),
/**
* 男性
*/
MALE(1, "男性"),
/**
* 女性
*/
FEMALE(2, "女性");
private final Integer value;
@JsonFormat
private final String description;
public static GenderEnum convert(Integer value) {
return Stream.of(values())
.filter(bean -> bean.value.equals(value))
.findAny()
.orElse(UNKNOWN);
}
public static GenderEnum convert(String description) {
return Stream.of(values())
.filter(bean -> bean.description.equals(description))
.findAny()
.orElse(UNKNOWN);
}
}
- 这时我们的转换器就创建好了,如何使用呢?很简单
只需要在我们需要转换的实体类属性上进行添加就好了,例如:
@ExcelProperty(
converter = GenderConverter.class
)
- 这样我们在数据进行导出填充的时候就会自动去解析了。是不是很方便,当然有优点也有缺点。
web端支持用户下载
- 我们在实际开发业务中常常需要用户通过浏览器点击按钮进行excel表格导出,这是怎么做的呢?其实也很简单。
- 我们可以在我们的excelUtil工具类中添加如下方法后续调用就好了,具体怎么用请往后看。
/**
* 设置响应结果
*
* @param response 响应结果对象
* @param rawFileName 文件名
* @throws
*/
private static void setExcelResponseProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("'\'+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
}
直接导出不使用模板,支持用户下载
铺垫也做的差不多了,该准备的也准备了。现在要开始导出了。
- 使用直接导出的方法,只需要在excelUtil工具类中添加这个方法就行了:
/**
* 正常数据填充 不适用模板,支持用户下载
* @param response
* @param fileName
* @param clazz
* @param excelType
* @param sheetName
* @param data
*/
public static void write(HttpServletResponse response,
String fileName,
Class<?> clazz,
ExcelTypeEnum excelType,
String sheetName,
Collection<?> data){
try {
setExcelResponseProp(response, fileName);
EasyExcel.write(response.getOutputStream())
.head(clazz)
// .registerWriteHandler(new ExcelMergeStrategy(clazz))
// .excelType(excelType)
.sheet(sheetName)
.doWrite(data);
} catch (IOExceptiwon e) {
e.printStackTrace();
}
}
- 其中
setExcelResponseProp(response, fileName);
就是调用前面咱们刚刚说的web端支持用户下载的方法就好了。 - 后续导出直接使用方法进行调用,别忘了参数哈。
- 使用示例:
ExcelWriteUtil.write(treeceBillUrl,tReceiveBillToDTOS,TReceiveBillToDTO.class,response,
"来料检验单导出"+suffix);
按照模板导出,支持用户下载
- 咱们前面准备工作已经做好了,实体类也不用处理。
- 在excelUtil类中添加这个方法就行了
/**
* 使用模板导出 通过miniio下载模板,进行数据填充,支持用户下载
* @param pathUrl
* @param data
* @param clazz
* @param response
* @param fileName
* @param <T>
*/
//将数据填充到模板并下载
public static <T> void fillTepmlateExport(String pathUrl, List<T> data, Class<T> clazz, HttpServletResponse response, String fileName) {
try {
//获取模板的url
InputStream is = null;
// 构造URL
URL url = new URL(pathUrl);
// 打开连接
URLConnection con = url.openConnection();
// 输入流
is = con.getInputStream();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
// 导出:
EasyExcel.write(response.getOutputStream(), clazz)
.withTemplate(is)
.sheet("Sheet1")
// .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(getHeightAndFontStrategy())
.doFill(data);
} catch (IOException e) {
e.printStackTrace();
}
}
- 这个方法注意区分哈,这个方法的模板是通过网络连接下载的模板,因为实际开发过程中,也使用的文件管理工具较多,比如miniio之类的。
- 这时我们直接调用方法就行了,使用示例
ExcelWriteUtil.fillTepmlateExport(treeceBillUrl,tReceiveBillToDTOS,TReceiveBillToDTO.class,response,
"来料检验单导出"+suffix);
总结
- 看到这里是不是觉得导出很简单了,本文中的代码只是部分代码,但是核心都讲到了,需要源代码,或者不清楚的地方可以提问
- 本文中所有代码收录在gitee仓库中,仓库地址: 点我我是仓库地址有需要的小伙伴可以自取**
- 如果要使用的话还是要认真读读本文的,不然可就会报错了。