主要的难点在service层解析excel表格数据这里,因为java这里有好多种数据,一旦excel表格里面不是java对应的数据类型就会报错。还有就是在数据库批量导入的时候mybatis有大小限制的
首先是导入前的下载模板
public class HolidayConfigController {
@GetMapping(value = "/downloadTemplate")
public void downloadTemplate(HttpServletResponse response, HttpServletRequest request){
log.info("HolidayController.downloadTemplate success Enter this method");
try {
//生成Excel文件
HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
HSSFSheet sheet = hssfWorkbook.createSheet("Sheet0");
// 设置表格默认列宽度为15个字节
sheet.setDefaultColumnWidth((short)15);
HSSFRow headRow = sheet.createRow(0);
headRow.createCell(0).setCellValue("节假日日期");
headRow.createCell(1).setCellValue("节假日描述");
HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum()+1);
dataRow.createCell(0).setCellValue("2018-10-01");
dataRow.createCell(1).setCellValue("国庆节");
dataRow.createCell(2).setCellValue("请严格按此格式录入数据");
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
String filename = "节假日数据导入模板.xls";
String agent = request.getHeader("user-agent");//获得游览器
String downloadFilename = FileUtil.encodeDownloadFilename(filename, agent); //使用工具类解决文件乱码的问题
response.addHeader("Content-Disposition", "attachment;filename="+downloadFilename);
ServletOutputStream outputStream = response.getOutputStream();
hssfWorkbook.write(outputStream);
//关闭
hssfWorkbook.close();
} catch (IOException e) {
log.error("HolidayController.downloadTemplate Exception",e);
}
}
使用FileUtil工具类处理因浏览器不同导致的乱码问题
public class FileUtil {
/**
* 下载文件时,针对不同浏览器,进行附件名的编码
*
* @param filename
* 下载文件名
* @param agent
* 客户端浏览器
* @return 编码后的下载附件名
* @throws IOException
*/
public static String encodeDownloadFilename(String filename, String agent)
throws IOException {
if (agent.contains("Firefox")) { // 火狐浏览器
filename = "=?UTF-8?B?"
+ new BASE64Encoder().encode(filename.getBytes("utf-8"))
+ "?=";
filename = filename.replaceAll("\r\n", "");
} else { // IE及其他浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+"," ");
}
return filename;
}
}
其次是导入Execl数据,这里分2003版和2007版两个版本,同时用一种解析方式解析
@PostMapping(value = "/importExecl")
public PojoResult importExecl(@RequestParam("file")MultipartFile file){
try{
InputStream inputStream = file.getInputStream();
if(!inputStream.markSupported()) {
inputStream = new PushbackInputStream(inputStream, 8);
}
if(POIFSFileSystem.hasPOIFSHeader(inputStream)) {
log.info("HolidayController.importExecl Execl is 2003 and below");
Workbook workbook = new HSSFWorkbook(new POIFSFileSystem(file.getInputStream()));
String importXls = HolidayConfigService .importXlsOrXlsx(workbook);
if("success".equals(importXls)){
log.info("HolidayController.importExecl Execl data import successfully");
return PojoResultUtil.success(Boolean.TRUE);
}
log.error("HolidayController.importExecl Execl data import failed");
ProductionMessageCode.BATCH_IMPORT_FAILURE.setMessage(importXls);
return PojoResultUtil.fail(ProductionMessageCode.BATCH_IMPORT_FAILURE);
}else if(POIXMLDocument.hasOOXMLHeader(inputStream)){
log.info("HolidayController.importExecl Execl is version 2007 and above");
Workbook workbook = new XSSFWorkbook(file.getInputStream());
String importXls = HolidayConfigService .importXlsOrXlsx(workbook);
if("success".equals(importXls)){
log.info("HolidayController.importExecl Execl data import successfully");
return PojoResultUtil.success(Boolean.TRUE);
}
log.error("HolidayController.importExecl Execl data import failed");
ProductionMessageCode.BATCH_IMPORT_FAILURE.setMessage(importXls);
return PojoResultUtil.fail(ProductionMessageCode.BATCH_IMPORT_FAILURE);
}else {
log.error("HolidayController.importExecl Execl Format does not exist");
return PojoResultUtil.fail(ProductionMessageCode.EXECL_NOT_EXISTS);
}
}catch (Exception e){
log.error("HolidayController.importExecl Execl data import Execption",e);
return PojoResultUtil.fail(ProductionMessageCode.QUERY_FAIL);
}
}
然后是service层的解析方式
public class HolidayConfigService {
@Transactional
public String importXlsOrXlsx(Workbook workbook){
UserInfo userInfo = UserInfoThreadLocal.get();
//获取Excel第一个sheet页
DataFormatter formatter = new DataFormatter();
List holidayConfigs = new ArrayList<>();
//定义错误信息记录集合
List list = new ArrayList<>();
for(int numOfSheet = 0;numOfSheet < workbook.getNumberOfSheets(); numOfSheet++){
Sheet sheets =workbook.getSheetAt(numOfSheet);
list.add("第Sheet" + numOfSheet +"页");
//遍历行row
for(int rowNum = 0; rowNum<=sheets.getLastRowNum();rowNum++){
Row row = sheets.getRow(rowNum);
if(row.getRowNum()==0){
//如果是第一行直接跳出本次循环
continue;
}
HolidayConfigDO holidayConfigDO = new HolidayConfigDO();
//将每一行数据的每一单元格数据取出
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String dateCellValue = dateFormat.format(row.getCell(0).getDateCellValue());
if(StringUtils.isEmpty(dateCellValue)){
list.add("第"+(rowNum+1)+"行,第1格节假日日期不能为空");
}else{
Date day = dateFormat.parse(dateCellValue);
holidayConfigDO.setDay(day);
}
} catch (Exception e) {
list.add("第"+(rowNum+1)+"行,第1格节假日日期格式错误");
}
String description = formatter.formatCellValue(row.getCell(1));
if(StringUtils.isEmpty(description)){
list.add("第"+(rowNum+1)+"行,第2格节假日描述不能为空");
}else{
holidayConfigDO.setDescription(description);
}
holidayConfigDO.setDeleted(false);
holidayConfigDO.setType((byte)1);
holidayConfigDO.setCreator(userInfo.getEmpId());
holidayConfigDO.setModifier(userInfo.getEmpId());
holidayConfigs.add(holidayConfigDO);
}
//如果没有错误就将错误记录集合数据清空
if(!CollectionUtils.isEmpty(list) && list.size() == 1){
list.remove(0);
}
}
if(!CollectionUtils.isEmpty(list)){
return list.toString();
}
holidayConfigManager.batchInsertHolidayConfig(holidayConfigs);
return "success";
}
在附上批量插入数据的Mapper.xml文件
insert into dcc_holiday_config
(gmt_create, gmt_modified, creator, modifier,day,type,is_deleted,description)
values
(
current_timestamp,
current_timestamp,
#{holidayConfig.creator,jdbcType=VARCHAR},
#{holidayConfig.modifier,jdbcType=VARCHAR},
#{holidayConfig.day,jdbcType=DATE},
#{holidayConfig.type,jdbcType=TINYINT},
#{holidayConfig.deleted,jdbcType=BIT},
#{holidayConfig.description,jdbcType=VARCHAR}
)
ON DUPLICATE KEY UPDATE
gmt_create = values (gmt_create),
gmt_modified = values (gmt_modified),
creator = values (creator),
modifier = values (modifier),
day = values (day),
type = values (type),
is_deleted = values (is_deleted),
description = values (description)
使用EasyPoi导出
引入相关maven依赖
cn.afterturn
easypoi-base
4.1.3
cn.afterturn
easypoi-annotation
4.1.3
cn.afterturn
easypoi-web
4.1.3
EasyPOI 导出代码示例
ExportParams exportParams = new ExportParams();
exportParams.setStyle(ExcelExportStyler.class); // 设置样式
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, CallPoolExcelVo.class, voList);
其中 ExcelExportStyler 就是我的自定义样式类。
官方默认提供了一个样式枚局类 ExcelStyleType,但是在 4.2 的版本中,BORDER、COLOR 这两个已经被标记为淘汰,不建议继续使用。
官方地址介绍:https://opensource.afterturn.cn/doc/easypoi.html#304
public enum ExcelStyleType {
NONE("默认样式", ExcelExportStylerDefaultImpl.class),
BORDER("边框样式", ExcelExportStylerBorderImpl.class),
COLOR("间隔行样式", ExcelExportStylerColorImpl.class);
....
}
所以,我们可以继承 ExcelExportStylerDefaultImpl 或者实现 IExcelExportStyler 接口,完善其中方法即可。
public interface IExcelExportStyler {
/**
* 列表头样式
* @param headerColor
* @return
*/
public CellStyle getHeaderStyle(short headerColor);
/**
* 标题样式
* @param color
* @return
*/
public CellStyle getTitleStyle(short color);
/**
* 获取样式方法
* @param Parity
* @param entity
* @return
*/
public CellStyle getStyles(boolean Parity, ExcelExportEntity entity);
}
创建自定义导出Excel样式类
/**
* @author: huangyibo
* @Date: 2020/11/10 16:59
* @Description: easypoi 导出excel样式修改
*/
public class ExcelStyleUtil extends AbstractExcelExportStyler implements IExcelExportStyler {
private static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT");
private static final short FONT_SIZE_TEN = 10;
private static final short FONT_SIZE_ELEVEN = 18;
private static final short FONT_SIZE_TWELVE = 18;
private static final short FONT_Height_LEN = 10;
/**
* 大标题样式
*/
private CellStyle headerStyle;
/**
* 每列标题样式
*/
private CellStyle titleStyle;
/**
* 数据行样式
*/
private CellStyle styles;
public ExcelStyleUtil(Workbook workbook) {
this.init(workbook);
}
/**
* 初始化样式
*
* @param workbook
*/
private void init(Workbook workbook) {
this.headerStyle = initHeaderStyle(workbook);
this.titleStyle = initTitleStyle(workbook);
this.styles = initStyles(workbook);
}
/**
* 大标题样式
*
* @param color
* @return
*/
@Override
public CellStyle getHeaderStyle(short color) {
return headerStyle;
}
/**
* 每列标题样式
*
* @param color
* @return
*/
@Override
public CellStyle getTitleStyle(short color) {
return titleStyle;
}
/**
* 数据行样式
*
* @param parity 可以用来表示奇偶行
* @param entity 数据内容
* @return 样式
*/
@Override
public CellStyle getStyles(boolean parity, ExcelExportEntity entity) {
return styles;
}
/**
* 获取样式方法
*
* @param dataRow 数据行
* @param obj 对象
* @param data 数据
*/
@Override
public CellStyle getStyles(Cell cell, int dataRow, ExcelExportEntity entity, Object obj, Object data) {
return getStyles(true, entity);
}
/**
* 模板使用的样式设置
*/
@Override
public CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams) {
return null;
}
/**
* 初始化--大标题样式
*
* @param workbook
* @return
*/
private CellStyle initHeaderStyle(Workbook workbook) {
CellStyle style = getBaseCellStyle(workbook);
style.setFont(getFont(workbook, FONT_SIZE_TWELVE, true));
return style;
}
/**
* 初始化--每列标题样式
*
* @param workbook
* @return
*/
private CellStyle initTitleStyle(Workbook workbook) {
CellStyle style = getBaseCellStyle(workbook);
style.setFont(getFont(workbook, FONT_SIZE_ELEVEN, false));
//背景色
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
return style;
}
/**
* 初始化--数据行样式
*
* @param workbook
* @return
*/
private CellStyle initStyles(Workbook workbook) {
CellStyle style = getBaseCellStyle(workbook);
style.setFont(getFont(workbook, FONT_SIZE_TEN, false));
style.setDataFormat(STRING_FORMAT);
return style;
}
/**
* 基础样式
*
* @return
*/
private CellStyle getBaseCellStyle(Workbook workbook) {
CellStyle style = workbook.createCellStyle();
//水平居中
style.setAlignment(HorizontalAlignment.CENTER);
//上下居中
style.setVerticalAlignment(VerticalAlignment.CENTER);
//设置自动换行
style.setWrapText(true);
return style;
}
/**
* 字体样式
*
* @param size 字体大小
* @param isBold 是否加粗
* @return
*/
private Font getFont(Workbook workbook, short size, boolean isBold) {
Font font = workbook.createFont();
//字体样式
font.setFontName("宋体");
//是否加粗
font.setBold(isBold);
//字体大小
font.setFontHeightInPoints(size);
return font;
}
}
创建核心导出工具类
/**
* @author: huangyibo
* @Date: 2020/11/10 16:57
* @Description:
*/
public class EasyPOIUtil {
/**
* 下载文件时,针对不同浏览器,进行附件名的编码
*
* @param filename
* 下载文件名
* @param agent
* 客户端浏览器
* @return 编码后的下载附件名
* @throws IOException
*/
public static String encodeDownloadFilename(String filename, String agent)
throws IOException {
if (agent.contains("Firefox")) { // 火狐浏览器
filename = "=?UTF-8?B?"
+ Base64.getEncoder().encode(filename.getBytes("utf-8"))
+ "?=";
filename = filename.replaceAll("\r\n", "");
} else { // IE及其他浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+"," ");
}
return filename;
}
/**
* 设置导出Excel格式
* @param response
* @param request
* @param filename
* @throws IOException
*/
public static void setExportExcelFormat(HttpServletResponse response, HttpServletRequest request,String filename) throws IOException {
String agent = request.getHeader("user-agent");//获得游览器
filename = filename + ".xls";
String downloadFilename = encodeDownloadFilename(filename, agent); //使用工具类解决文件乱码的问题
response.setCharacterEncoding("UTF-8");
// 设置响应输出的头类型
response.setHeader("content-Type", "application/vnd.ms-excel");
// 下载文件的默认名称
response.setHeader("Content-Disposition", "attachment;filename="+downloadFilename);
response.setHeader("Pragma", "public");
response.setHeader("Cache-Control", "no-store");
response.addHeader("Cache-Control", "max-age=0");
}
public static void writeExcel(HttpServletResponse response, HttpServletRequest request, Class> clazz, List> exportModelList, String filename, String sheetName) throws IOException {
//设置导出Excel格式
setExportExcelFormat(response,request,filename);
ExportParams exportParams = new ExportParams();
exportParams.setStyle(ExcelStyleUtil.class); // 设置样式
// 设置sheet得名称
exportParams.setSheetName(sheetName);
Map deptExportMap = new HashMap<>();
// title的参数为ExportParams类型,目前仅仅在ExportParams中设置了sheetName
deptExportMap.put("title", exportParams);
// 模版导出对应得实体类型
deptExportMap.put("entity", clazz);
// sheet中要填充得数据
deptExportMap.put("data", exportModelList);
List
创建导出对象实体Bean
关于合并都在实体类里面(主要是结构和注解)
关于合并只有两点:
1、类的数据结构。
2、注解
@ExcelCollection(name = "") 集合使用
@Excel(name = "采购数量合计(支)", width = 30, orderNum = "5",needMerge = true, isStatistics = true)
name:列的标题名称,width :表格的宽度, orderNum :排序(注意每个类中的排序为单独的 不同类排序不通用)
needMerge : 是否合并单元格, isStatistics:是否进行统计(若为true,则在表格最后自动生成最终统计)
@Data
@ExcelTarget("empUtil")
public class DeptUtil {
@Excel(name = "部门编号", width = 30 , needMerge = true)
private Integer id;
@Excel(name = "部门名称", width = 30 , needMerge = true)
private String deptName;
@Excel(name = "薪酬", width = 30, type = 10,replace="{0_null}")
private BigDecimal salary;
@ExcelCollection(name = "")
private List emps;
}
@Data
@ExcelTarget("empUtil")
public class EmpUtil {
@Excel(name = "序号", width = 30, groupName="你好")
private Integer id;
@Excel(name = "员工姓名", width = 30,groupName="你好")
private String empName;
@Excel(name = "年龄", width = 30, type = 10)
private Integer age;
@Excel(name = "入职时间", width = 30, format = "yyyy-MM-dd")
private Date hiredate;
@Excel(name = "薪酬", width = 30, type = 10,replace="{0_null}")
private BigDecimal salary;
}
导出controller
@RestController
@RequestMapping("/export")
@Slf4j
public class ExportController {
@GetMapping("/excel")
public String excel(HttpServletResponse response, HttpServletRequest request){
try {
List exportList = selectDeptList();
String fileName = "员工管理";
String sheetName = "sheet1";
EasyPOIUtil.writeExcel(response, request, DeptUtil.class,exportList, fileName, sheetName);
} catch (Exception e) {
log.error("error", e);
}
return "success";
}
}
多sheet页导入导出
public class EasyPoiUtil {
/**
* 下载文件时,针对不同浏览器,进行附件名的编码
*
* @param filename
* 下载文件名
* @param agent
* 客户端浏览器
* @return 编码后的下载附件名
* @throws IOException
*/
public static String encodeDownloadFilename(String filename, String agent)
throws IOException {
if (agent.contains("Firefox")) { // 火狐浏览器
filename = "=?UTF-8?B?"
+ Base64.getEncoder().encode(filename.getBytes("utf-8"))
+ "?=";
filename = filename.replaceAll("\r\n", "");
} else { // IE及其他浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+"," ");
}
return filename;
}
/**
* 设置导出Excel格式
* @param response
* @param request
* @param filename
* @throws IOException
*/
public static void setExportExcelFormat(HttpServletResponse response, HttpServletRequest request, String filename) throws IOException {
String agent = request.getHeader("user-agent");//获得游览器
filename = filename + ".xls";
String downloadFilename = encodeDownloadFilename(filename, agent); //使用工具类解决文件乱码的问题
response.setCharacterEncoding("UTF-8");
// 设置响应输出的头类型
response.setHeader("content-Type", "application/vnd.ms-excel");
// 下载文件的默认名称
response.setHeader("Content-Disposition", "attachment;filename="+downloadFilename);
response.setHeader("Pragma", "public");
response.setHeader("Cache-Control", "no-store");
response.addHeader("Cache-Control", "max-age=0");
}
/**
* 构建 sheet
* @param sheetName sheet 名字
* @param clazz clazz
* @param list 列表
* @return {@link Map}
*/
public static Map buildSheet(String sheetName, Class> clazz, List> list) {
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
exportParams.setSheetName(sheetName);
// 导出样式
exportParams.setStyle(ExcelStyleUtil.class);
Map map = new HashMap<>(8);
// title的参数为ExportParams类型
map.put("title", exportParams);
// 模版导出对应得实体类型
map.put("entity", clazz);
// sheet中要填充得数据
map.put("data", list);
return map;
}
/**
* 导出数据创建Workbook,便于转成MultipartFile,用于文件上传
* Excel导出, 支持多sheet导出, 根据数据量自动切换sheet
* Excel2003版最大行数是65536行。
* Excel2007开始的版本最大行数是1048576行
* Excel2010最大行数是1048576行
* @param clazz
* @param exportModelList
* @return
*/
public static Workbook createWorkbook(Class> clazz, List> exportModelList) {
List
导出
导出实体类
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(description="看房楼盘估价表")
public class DictGardenAppraisalExport implements Serializable {
@ApiModelProperty(value = "城市")
@Excel(name = "城市", orderNum = "0", width = 20)
private String cityName;
@ApiModelProperty(value = "区域")
@Excel(name = "区域", orderNum = "1", width = 20)
private String regionName;
@ApiModelProperty(value = "商圈")
@Excel(name = "商圈", orderNum = "2", width = 20)
private String businessAreaName;
@ApiModelProperty(value = "楼盘名称")
@Excel(name = "楼盘名称", orderNum = "3", width = 20)
private String gardenName;
@ApiModelProperty(value = "物业类型(普通住宅/公寓/酒店)")
@Excel(name = "物业类型", orderNum = "4", width = 20)
private String usageName;
@ApiModelProperty(value = "委托套数")
@Excel(name = "委托套数", orderNum = "5", width = 20)
private Integer trustNum;
@ApiModelProperty(value = "委托均价")
@Excel(name = "委托均价", orderNum = "6", width = 20)
private BigDecimal trustAvgPrice;
@ApiModelProperty(value = "委托总价")
private BigDecimal trustTotalPrice;
@ApiModelProperty(value = "委托总面积")
private BigDecimal trustTotalArea;
@ApiModelProperty(value = "成交套数")
@Excel(name = "成交套数", orderNum = "7", width = 20)
private Integer tradeNum;
@ApiModelProperty(value = "成交均价")
@Excel(name = "成交均价", orderNum = "8", width = 20)
private BigDecimal tradeAvgPrice;
@ApiModelProperty(value = "成交总价")
private BigDecimal tradeTotalPrice;
@ApiModelProperty(value = "成交总面积")
private BigDecimal tradeTotalArea;
@ApiModelProperty(value = "外部参考价")
@Excel(name = "外部参考价", orderNum = "9", width = 20)
private BigDecimal outerReferPrice;
@ApiModelProperty(value = "参考价")
@Excel(name = "参考价", orderNum = "10", width = 20)
private BigDecimal referPrice;
@ApiModelProperty(value = "政府指导价")
@Excel(name = "政府指导价", orderNum = "11", width = 20)
private BigDecimal governGuidePrice;
@ApiModelProperty(value = "价差幅度1 (参考价/第三方委托均价)")
@Excel(name = "价差幅度1", orderNum = "12", width = 20)
private BigDecimal diffPriceRange1;
@ApiModelProperty(value = "价差幅度2 (参考价/第三方成交均价)")
@Excel(name = "价差幅度2", orderNum = "13", width = 20)
private BigDecimal diffPriceRange2;
@ApiModelProperty(value = "价差幅度3 (参考价/第三方参考价)")
@Excel(name = "价差幅度3", orderNum = "14", width = 20)
private BigDecimal diffPriceRange3;
@ApiModelProperty(value = "估价日期")
@Excel(name = "估价日期", exportFormat = "yyyy-MM-dd", orderNum = "15", width = 20)
private Date referDate;
@ApiModelProperty(value = "发布状态:已发布=PUBLISHED、待发布=TOBE_PUBLISH、已撤回=REVOKE")
@Excel(name = "状态", orderNum = "16", width = 20)
private String publishStatus;
}
导出逻辑
@PostMapping(value = "/exportGardenAppraisal")
@ApiOperation(value = "导出估价信息")
@ApiResponses({
@ApiResponse(message = "导出估价信息", code = 200, response = DictGardenAppraisalVo.class)
})
public String exportGardenAppraisal(@RequestBody DictGardenAppraisalQueryPageForm queryPageForm, HttpServletResponse response, HttpServletRequest request) {
queryPageForm.setPageSize(100000);
Pagination page = dictGardenAppraisalRemote.queryDictGardenAppraisalPage(queryPageForm);
if(page != null){
if(!CollectionUtils.isEmpty(page.getItems())){
List exportList = page.getItems().stream().map(item -> {
DictGardenAppraisalExport export = new DictGardenAppraisalExport();
BeanUtils.copyProperties(item, export);
return export;
}).collect(Collectors.toList());
try {
EasyPoiUtil.writeExcel(response, request, DictGardenAppraisalExport.class, exportList, "估价");
} catch (IOException e) {
log.error("估价数据导出excel Exception",e);
}
}
}
return successInfo(true);
}
导入
导入实体类
@Data
public class DictImportTradeDetailDTO implements Serializable {
@ApiModelProperty(value = "批次号:yyyy-MM格式")
@Excel(name = "日期")
@NotNull(message = "日期不能为空")
private String batchNum;
@ApiModelProperty(value = "贝壳楼盘名")
@Excel(name = "贝壳楼盘名")
private String bkGardenName;
@ApiModelProperty(value = "贝壳小区ID")
@Excel(name = "贝壳小区ID")
private String bkGardenId;
@ApiModelProperty(value = "小区ID")
@Excel(name = "小区ID")
@NotNull(message = "小区ID不能为空")
private String kfGardenId;
@ApiModelProperty(value = "城市")
@Excel(name = "城市")
private String cityName;
@ApiModelProperty(value = "区域")
@Excel(name = "区域")
private String regionName;
@ApiModelProperty(value = "成交日期")
@Excel(name = "成交时间", exportFormat = "yyyy-MM-dd", importFormat = "yyyy-MM-dd")
private Date tradeDate;
@ApiModelProperty(value = "房源价格")
@Excel(name = "房源价格")
@NotNull(message = "房源价格不能为空")
@DecimalMin(value = "0.00",message = "房源价格不能小于0")
private BigDecimal roomPrice;
@ApiModelProperty(value = "房源面积(单位M2)")
@Excel(name = "房源面积")
@NotNull(message = "房源面积不能为空")
@DecimalMin(value = "0.00",message = "房源面积不能小于0")
private BigDecimal roomArea;
@ApiModelProperty(value = "楼层")
@Excel(name = "楼层")
private String floor;
@ApiModelProperty(value = "朝向")
@Excel(name = "朝向")
private String towards;
@ApiModelProperty(value = "户型")
@Excel(name = "户型")
private String roomType;
@ApiModelProperty(value = "房屋用途")
@Excel(name = "房屋用途")
private String roomUse;
@ApiModelProperty(value = "房源链接")
@Excel(name = "房源ID")
@NotNull(message = "房源ID不能为空")
private String roomLink;
}
导入具体逻辑
@RestController
@RequestMapping("/security/dictImportTradeDetail")
@Slf4j
public class DictImportTradeDetailController extends WebBaseController {
@Resource
private DictImportTradeDetailRemote dictImportTradeDetailRemote;
@Resource
private AliyunOss aliyunOss;
@PostMapping("/import")
@ApiOperation(value = "导入交易明细数据")
@ApiResponses({
@ApiResponse(message = "导入交易明细数据", code = 200, response = DictImportDataReturnVo.class)
})
public String importData(@RequestParam("file") MultipartFile file) {
DictImportDataReturnVo returnVo = new DictImportDataReturnVo();
try {
JwtUserInfo userInfo = getCurrentUserInfo();
Workbook workbook = EasyPoiUtil.getWorkBook(file);
int sheetNum = workbook.getNumberOfSheets();
List failList = new ArrayList<>();
List successList = new ArrayList<>();
for (int i = 0; i < sheetNum; i++) {
ExcelImportResult importResult = EasyPoiUtil.importExcel(file, i, 0, 1, DictImportTradeDetailDTO.class);
//失败结果集
List failTradeList = importResult.getFailList();
if(!CollectionUtils.isEmpty(failTradeList)){
failList.addAll(failTradeList);
}
//导入成功的数据
List successTradeList = importResult.getList();
if(!CollectionUtils.isEmpty(successTradeList)){
successTradeList.forEach(trade -> {
//房源价格导入的单位为万,这里转为元
trade.setRoomPrice(trade.getRoomPrice().multiply(new BigDecimal(10000)));
});
successList.addAll(successTradeList);
}
}
if(CollectionUtils.isEmpty(successList)){
return successInfo(false);
}
DictImportDataRecordDTO dictImportDataRecordDTO = new DictImportDataRecordDTO();
if(!CollectionUtils.isEmpty(failList)){
//失败的数据需要写入Workbook
Workbook workbookFile = EasyPoiUtil.createWorkbook(DictImportTradeDetailDTO.class, failList);
//Workbook转成MultipartFile
MultipartFile multipartFile = FileUtil.getMultipartFileFromWorkbook(workbookFile, "导入失败数据-"+file.getOriginalFilename());
//上传aliyun 对象存储 OSS
AliyunUploadRequest uploadRequest = new AliyunUploadRequest(multipartFile);
AliyunUploadResult result = aliyunOss.fileUpload(uploadRequest);
log.info("导入交易明细数据, 校验不通过数据写入excel上传到阿里云oss成功, result:{}", JSON.toJSONString(result));
if(result != null){
dictImportDataRecordDTO.setFailDataFileUrl(result.getUrl());
}
}
dictImportDataRecordDTO.setFailNum(failList.size());
dictImportDataRecordDTO.setTradeDetailList(successList);
dictImportDataRecordDTO.setImportTotalNum(successList.size() + failList.size());
dictImportDataRecordDTO.setSuccessNum(successList.size());
dictImportDataRecordDTO.setBatchNum(successList.get(0).getBatchNum());
dictImportDataRecordDTO.setCityName(successList.get(0).getCityName());
dictImportDataRecordDTO.setDataType(DataTypeEnum.TRADE_DATA);
dictImportDataRecordDTO.setCreateId(userInfo.getUserId());
dictImportDataRecordDTO.setModifyId(userInfo.getUserId());
dictImportDataRecordDTO.setStatus(StatusEnum.ENABLED);
dictImportTradeDetailRemote.importData(dictImportDataRecordDTO);
returnVo.setImportTotalNum(dictImportDataRecordDTO.getImportTotalNum());
returnVo.setSuccessNum(dictImportDataRecordDTO.getSuccessNum());
returnVo.setFailNum(dictImportDataRecordDTO.getFailNum());
returnVo.setSuccess(Boolean.TRUE);
log.info("导入交易明细数据 SUCCESS, dictImportDataRecordDTO,{}, returnVo:{}", JSON.toJSONString(dictImportDataRecordDTO), JSON.toJSONString(returnVo));
} catch (Exception e) {
returnVo.setSuccess(Boolean.FALSE);
returnVo.setErrCode(DictReturnCodeEnum.F6000000.name());
returnVo.setErrMessage(DictReturnCodeEnum.F6000000.getMessage());
log.info("导入交易明细数据 Exception, returnVo:{}", JSON.toJSONString(returnVo), e);
}
return successInfo(returnVo);
}
}
参考:
http://www.ibloger.net/article/3392.html