前言
语雀社区的EasyExcel 导入导出,都是在已知需要哪些表头的情况下。往往实际情况,一张表有很多的字段,有些字段用户并不需要那么多,他只想看关键的部分。假设就有客户提出:我不需要那么多列,我的数据并没有那么多表头项,我想省事,该怎么办? 只能是动态实现,我不知道用户会填什么列,只管接收到,然后返回给用户。 话不多说,直接上码实现。
代码实现
springboot 的项目搭建省略,所用的SQL、配置和依赖请参考我之前写过的:EasyExcel3.0.5导出多个sheet,含查询优化,这里有详细的交代,此篇省略繁琐的步骤,进入核心内容。
新建两张核心的表
我们要实现动态导入,需要借助这两张表做周旋。一张是导入结果表,另一张是导入结果明细表,为什么这么做呢?
思路:
因为每个用户导入的内容可以不一样,所以每次导入可以用唯一的批次作为该用户执行的结果,另一个用户导的是另一批次。每个批次有N多条数据,就是导入的明细。当用户要查询自己到的文件内容,可以根据批次号关联导入数据明细。看具体的数据表设计~~~
导入结果表: tb_import_result
CREATE TABLE `tb_import_result` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`batch_number` varchar(50) NOT NULL COMMENT '导入批次号',
`file_name` varchar(100) DEFAULT NULL COMMENT '文件名称',
`upload_time` datetime DEFAULT NULL COMMENT '上传时间',
`total` bigint(20) DEFAULT NULL COMMENT '总数',
`headers` varchar(4000) DEFAULT NULL COMMENT '表头',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
导入结果明细表:tb_import_result_detail
明细表除了包含数据表的完整字段,还有批次号(batch_number)。但是这么多字段用户并非全部需要。
CREATE TABLE `tb_import_result_detail` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`batch_number` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '导入批次号',
`total_pay` bigint(20) DEFAULT NULL COMMENT '总金额,单位为分',
`actual_pay` bigint(20) DEFAULT NULL COMMENT '实付金额。单位:分。如:20007,表示:200元7分',
`payment_type` tinyint(1) unsigned zerofill DEFAULT NULL COMMENT '支付类型,1、在线支付,2、货到付款',
`post_fee` bigint(20) DEFAULT NULL COMMENT '邮费。单位:分。如:20007,表示:200元7分',
`create_time` datetime DEFAULT NULL COMMENT '订单创建时间',
`shipping_name` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流名称',
`shipping_code` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流单号',
`buyer_message` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '买家留言',
`buyer_nick` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '买家昵称',
`buyer_rate` tinyint(1) DEFAULT NULL COMMENT '买家是否已经评价,0未评价,1已评价',
`receiver_state` varchar(100) COLLATE utf8_bin DEFAULT '' COMMENT '收获地址(省)',
`receiver_city` varchar(255) COLLATE utf8_bin DEFAULT '' COMMENT '收获地址(市)',
`receiver_district` varchar(255) COLLATE utf8_bin DEFAULT '' COMMENT '收获地址(区/县)',
`receiver_address` varchar(255) COLLATE utf8_bin DEFAULT '' COMMENT '收获地址(街道、住址等详细地址)',
`receiver_mobile` varchar(12) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人手机',
`receiver_zip` varchar(15) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人邮编',
`receiver` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人',
`invoice_type` int(1) DEFAULT '0' COMMENT '发票类型(0无发票1普通发票,2电子发票,3增值税发票)',
`source_type` int(1) DEFAULT '2' COMMENT '订单来源:1:app端,2:pc端,3:M端,4:微信端,5:手机qq端',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
所谓的动态导入,不管用户导入什么表头(前提是你数据库中的一张表中的部分字段,字段很多,每个用户导入的内容不一样),后端只需要保存用户每次导入的表头和数据。开干!
Controller 层
package cn.com.easyExcel.controller;
import cn.com.easyExcel.param.OrderExportParam;
import cn.com.easyExcel.service.OrderExcelService;
import cn.com.easyExcel.vo.ResultVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Api(tags = "订单信息导入导出")
@RestController
@RequestMapping(value = "/order/excel")
public class OrderExcelController {
@Autowired
private OrderExcelService orderExcelService;
@ApiOperation(value = "动态导入")
@PostMapping(value="/dynamicImport")
public ResultVo<Void> dynamicImportExcel(@RequestParam(name = "file") MultipartFile file) throws IOException {
orderExcelService.dynamicImportExcel(file);
return ResultVo.successMsg("导入成功");
}
@ApiOperation(value = "动态导出")
@PostMapping(value="/dynamicExport")
public void dynamicExportExcel(@RequestBody OrderExportParam param, HttpServletResponse response) throws IOException {
orderExcelService.dynamicExportExcel(param, response);
}
}
Service 实现
动态导出的完整代码全部在这个实现类里面,动态导入还有一个 监听器,重点部分,后面会补充解释。
package cn.com.easyExcel.service.impl;
import cn.com.easyExcel.excel.converter.CellWriteWeight;
import cn.com.easyExcel.excel.listener.OrderImportListener;
import cn.com.easyExcel.excel.util.EasyExcelUtils;
import cn.com.easyExcel.mapper.ImportResultDetailMapper;
import cn.com.easyExcel.mapper.ImportResultMapper;
import cn.com.easyExcel.param.OrderExportParam;
import cn.com.easyExcel.pojo.ExcelHeader;
import cn.com.easyExcel.pojo.ImportResult;
import cn.com.easyExcel.pojo.ImportResultDetail;