springboot使用EasyExcel进行导入导出
1、添加依赖
com.alibaba
easyexcel
2.1.1
org.apache.poi
poi
3.17
org.apache.poi
poi-ooxml
3.17
2、创建导入导出的映射实体类
导出
package com.zl.model.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Builder;
import lombok.Data;
/**
* 导出VO
*
* @author z
* @date 2022-03-14 18:01
*/
@Data
@HeadRowHeight(value = 20)
public class ExportModeSheetOneVO {
/**
* id
*/
@ExcelProperty(value = "编号",index = 0)
@ColumnWidth(value = 20)
private String id;
/**
* 名称
*/
@ExcelProperty(value = "名称",index = 1)
@ColumnWidth(value = 20)
private String name;
/**
* 类型
*/
@ExcelProperty(value = "类型",index = 2)
@ColumnWidth(value = 20)
private String type;
/**
* 描述
*/
@ExcelProperty(value = "描述",index = 3)
@ColumnWidth(value = 20)
private String des;
/**
* 创建日期
*/
@ExcelProperty(value = "创建日期",index = 4)
@ColumnWidth(value = 20)
private String createDt;
/**
* 创建者
*/
@ExcelProperty(value = "创建者",index = 5)
@ColumnWidth(value = 20)
private String createBy;
/**
* 更新日期
*/
@ExcelProperty(value = "更新日期",index = 6)
@ColumnWidth(value = 20)
private String updateDt;
/**
* 更新者
*/
@ExcelProperty(value = "更新者",index = 7)
@ColumnWidth(value = 20)
private String updateBy;
}
导入
package com.zl.model.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* 导入VO
*
* @author z
* @date 2022-03-15 16:08
*/
@Data
public class ImportModeVO {
/**
* 模型名称
*/
@ExcelProperty("名称")
private String name;
/**
* 类型
*/
@ExcelProperty("类别")
private String type;
/**
* 描述
*/
@ExcelProperty("描述")
private String des;
}
建议类型都写为String,可以减少不必要的类型转换
3、实现
Controller层代码实现:
/**
* 导入导出测试
*
* @author z
* @since 2022-03-12
*/
@RestController
@RequestMapping("/myTest")
@Api(tags = "数据导入导出")
@Slf4j
public class MyInfoController {
@Autowired
private MyInfoService myInfoService;
/**
* 模型导入
* @param file
* @return
*/
@PostMapping("/importMode")
@ApiOperation("导入")
@ApiImplicitParam(name = "file",value = "上传的数据",required = true)
public Result importMode(@RequestParam("file") MultipartFile file){
if (file==null||file.isEmpty()) {
return Result.error();
}
int flag= 0;
try {
flag = myInfoService.importMode(file);
} catch (IOException e) {
e.printStackTrace();
}
return flag==1?Result.success():Result.error();
}
/**
* 导出
* @param type 导出类别
*/
@GetMapping("/exportMode")
@ApiOperation("导出")
@ApiImplicitParam(name="type",value="导出类别",required = true)
public void exportMode(String type, HttpServletResponse response){
try {
myInfoService.exportMode(type,response);
} catch (Exception e) {
e.printStackTrace();
}
}
Service层实现:
/**
* 导入
* @param file
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int importMode(MultipartFile file) throws IOException {
InputStream in =file.getInputStream();
EasyExcel.read(in, ImportModeVO.class,new ImportExcelListenerUtil())
.sheet("Sheet1")
.doRead();
// 每次EasyExcel的read方法读取完之后都会关闭流,我这里为了试验doReadAll方法,所以重新获取了一次
// in = file.getInputStream();
// EasyExcel.read(in,ImportModeVO.class,new ImportExcelListenerUtil()).doReadAll();
List list = ImportExcelListenerUtil.list;
for(int i=0;i exportModeSheetOneVOS = this.selectModelShowOne(type);
List exportModeSheetTwoVOS = this.selectModelShowTwo(type);
// 写出
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
// ExportModeSheetOneVO 是导出的映射实体类,exportModeSheetOneVOS 是导出的数据集合,registerWriteHandler(new CustomCellWriteHandlerUtil()) 设置表头自适应,这是多个sheet导出,只有一个只需导出需要的sheet即可
// 不设置自适应表头:EasyExcel.writerSheet(0,sheetNameOne).head(ExportModeSheetOneVO.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet(0,sheetNameOne).head(ExportModeSheetOneVO.class).registerWriteHandler(new CustomCellWriteHandlerUtil()).build();
excelWriter.write(exportModeSheetOneVOS,writeSheet);
writeSheet = EasyExcel.writerSheet(1,sheetNameTwo).head(ExportModeSheetTwoVO.class).registerWriteHandler(new CustomCellWriteHandlerUtil()).build();
excelWriter.write(exportModeSheetTwoVOS,writeSheet);
//千万别忘记关流,finish会帮忙关流
excelWriter.finish();
}
- 导入需要设置一个自定义Easyexcel的监听类
package com.zl.util;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.zl.model.vo.ImportModeVO;
import java.util.ArrayList;
import java.util.List;
/**
* 导入监听工具类
*
* @author z
* @date 2022-03-15 16:17
*/
public class ImportExcelListenerUtil extends AnalysisEventListener {
public static final List list = new ArrayList<>();
@Override
public void invoke(ImportModeVO excelEntity, AnalysisContext context) {
list.add(excelEntity);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
- 自定义表头需要的工具类
package com.zl.util;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 导出自适应列宽
*
* @author z
* @date 2022-03-15 14:57
*/
public class CustomCellWriteHandlerUtil extends AbstractColumnWidthStyleStrategy {
private Map> CACHE = new HashMap<>();
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List cellDataList, Cell cell, Head head, Integer integer, Boolean isHead) {
boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
if (needSetWidth) {
Map maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo());
if (maxColumnWidthMap == null) {
maxColumnWidthMap = new HashMap<>();
CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
}
Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
if (columnWidth>= 0) {
if (columnWidth> 255) {
columnWidth = 255;
}
Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
if (maxColumnWidth == null || columnWidth> maxColumnWidth) {
maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
}
}
}
}
private Integer dataLength(List cellDataList, Cell cell, Boolean isHead) {
if (isHead) {
return cell.getStringCellValue().getBytes().length;
} else {
CellData cellData = cellDataList.get(0);
CellDataTypeEnum type = cellData.getType();
if (type == null) {
return -1;
} else {
switch (type) {
case STRING:
return cellData.getStringValue().getBytes().length;
case BOOLEAN:
return cellData.getBooleanValue().toString().getBytes().length;
case NUMBER:
return cellData.getNumberValue().toString().getBytes().length;
default:
return -1;
}
}
}
}
}
4、测试
- 使用 postman 测试导入导出接口