wg-basic-doc/docs/code-template/excel-upload.md
2022-05-25 18:33:19 +08:00

9.0 KiB
Raw Blame History

EasyExcel 上传(导入)

以人口Population导入为例

  1. 包含 Excel实体类错误实体类导入监听器,其中 错误实体类 非必须。

  2. 如果不需要返回错误,可忽略输出错误文件的代码。

Excel实体类

import com.alibaba.excel.annotation.ExcelProperty;

public class PopulationExcel {

    @ExcelProperty(index = 0)
    private String name;
    @ExcelProperty(index = 1)
    private String idCard;
    @ExcelProperty(index = 2)
    private String areaCode;
    @ExcelProperty(index = 3)
    private String homeAddress;

    // get set
}

错误试题类

import com.alibaba.excel.annotation.ExcelProperty;

public class PopulationExcelError {

    @ExcelProperty(index = 0)
    private String name;
    @ExcelProperty(index = 1)
    private String idCard;
    @ExcelProperty(index = 2)
    private String areaCode;
    @ExcelProperty(index = 3)
    private String homeAddress;
    @ExcelProperty(index = 4)
    private String reason;

    // get set
}

监听器

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

import java.util.ArrayList;
import java.util.List;

public abstract class PopulationExcelListener extends AnalysisEventListener<PopulationExcel> {

    private static final Integer MAX_READ_COUNT = 100;
    private List<PopulationExcel> populationExcels = new ArrayList<>();

    @Override
    public void invoke(PopulationExcel populationExcel, AnalysisContext analysisContext) {
        if (populationExcels.size() > MAX_READ_COUNT) {
            // 超过读取最大量,执行保存,
            handle(populationExcels);
            populationExcels.clear();
        } else {
            // 未达到读取最大量,继续读取
            populationExcels.add(populationExcel);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        handle(populationExcels);
        populationExcels.clear();
    }

    /**
     * 处理
     *
     * @param rows
     */
    public abstract void handle(List<PopulationExcel> rows);

}

导入代码

controller 层

@ApiOperation(value = "试题Excel", notes = "试题Excel接口")
@ApiImplicitParams({
        @ApiImplicitParam(name = "excel", value = "文件名称", paramType = "form"),
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("import-excel")
public UploadExcelResultDTO importExcel(MultipartFile excel) throws IOException {
    if (Objects.isNull(excel)) {
        throw new ParamsException("Excel不能为空");
    }
    // 判断后缀
    if (!excel.getOriginalFilename().endsWith(IFileConstant.EXCEL_SUFFIX_XLS)
            && !excel.getOriginalFilename().endsWith(IFileConstant.EXCEL_SUFFIX_XLSX)) {
        throw new ParamsException("文件格式为Excel");
    }
    return populationService.importExcel(excel);
}

service 层

@Override
public UploadExcelResultDTO importExcel(MultipartFile excel) throws IOException {

    // 要输出的错误内容
    List<PopulationExcelError> populationExcelErrors = new ArrayList<>();

    long startTime = System.currentTimeMillis();
    // 读取 Excel
    EasyExcel.read(excel.getInputStream(), PopulationExcel.class, new PopulationExcelListener() {
        @Override
        public void handle(List<PopulationExcel> populationExcels) {
            // 这里处理数据,一般是入库

        }
    }).headRowNumber(2).sheet().doRead();
    long endTime = System.currentTimeMillis();

    // 生成的错误文件ID下载时使用
    String excelFileId = null;
    if (populationExcelErrors.size() > 0) {
        excelFileId = new AbstractErrorExcelHandler<PopulationExcelError>(fileService) {
            @Override
            public List<List<String>> excelHeaderNames() {
                // 构建错误 Excel 标题,与错误类对应
                return simpleExcelHeader(new String[]{"序号", "姓名", "身份证", "错误原因"});
            }
        }.saveErrorExcel(populationExcelErrors);
    }
    // 返回实体类,
    return new UploadExcelResultDTO(populationExcelErrors.size(), endTime - startTime, excelFileId);
}

模板下载接口

@GetMapping("upload/upload-excel-template")
public void excelTemplate(HttpServletResponse response) throws IOException {
    InputStream inputStream = PopulationRouteController.class.getClassLoader().getResourceAsStream("templates/population/upload/upload-excel-template.xls");
    RequestUtil.download(response, inputStream, "人口导入模板.xls");
}

列表导入按钮

<button type="button" class="layui-btn layui-btn-sm" id="uploadExcel">
    <i class="fa fa-lg fa-cloud-upload"></i> 导入数据
</button>

列表导入事件

$(document).on('click', '#uploadExcel', function() {
    top.dialog.open({
        url: top.restAjax.path('route/population/upload/upload-excel', []),
        title: '导入人口数据',
        width: '300px',
        height: '196px',
        onClose: function() {
            reloadTable();
        }
    });
});

导入页面代码

<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <base th:href="${#request.getContextPath() + '/'}">
    <meta charset="utf-8">
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link rel="stylesheet" href="assets/fonts/font-awesome/css/font-awesome.css"/>
    <link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="assets/layuiadmin/style/admin.css" media="all">
</head>
<body>
<div class="layui-anim layui-anim-fadein">
    <div class="layui-card" style="text-align: center;">
        <div class="layui-card-body" style="padding: 15px;">
            <blockquote class="layui-elem-quote">下载“下载模板”整理数据点击“导入数据”上传格式为xls或xlsx</blockquote>
            <button id="downloadFile" type="button" class="layui-btn layui-btn" onclick="window.open('route/population/upload/upload-excel-template', 'downloadTarget')">
                <i class="fa fa-lg fa-cloud-download"></i> 下载模板
            </button>
            <button type="button" class="layui-btn layui-btn" id="uploadExcel">
                <i class="fa fa-lg fa-cloud-upload"></i> 导入数据
            </button>
        </div>
    </div>
    <iframe style="display: none" name="downloadTarget"></iframe>
</div>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script>
    layui.config({
        base: 'assets/layuiadmin/' //静态资源所在路径
    }).extend({
        index: 'lib/index' //主入口模块
    }).use(['index', 'upload', 'common'], function(){
        var $ = layui.$;
        var form = layui.form;
        var common = layui.common;

        function closeBox() {
            parent.layer.close(parent.layer.getFrameIndex(window.name));
        }

        // 初始化Excel上传
        function initExcelUpload() {
            // Excel上传
            var uploadLoading;
            layui.upload.render({
                elem: '#uploadExcel',
                url: 'api/population/import-excel',
                accept: 'file',
                exts: 'xls|xlsx',
                field: 'excel',
                before: function() {
                    uploadLoading = layer.msg('正在上传,请稍后...', {icon: 16, time: 0, shade: 0.3});
                },
                done: function(data) {
                    layer.close(uploadLoading);
                    if(data.failedCount > 0) {
                        layer.open({
                            type: 1,
                            title: false,
                            closeBtn: 0,
                            shadeClose: true,
                            skin: '',
                            content: '<div style="padding: 15px;">' +
                                '<div>失败数量:'+ data.failedCount +'</div><br/>' +
                                '<div><a class="error-excel" href="javascript:void(0);" onclick="window.open(\'route/file/download/false/'+ data.errorExcel +'\');" target="downloadTarget">点击下载错误信息</a></div>' +
                                '</div>'
                        });
                    } else {
                        layer.msg('导入成功', {time: 2000}, function() {
                            closeBox();
                        });
                    }
                },
                error: function(data, index){
                    layer.close(uploadLoading);
                    if(data != null) {
                        top.dialog.msg(data.msg);
                    }
                },
            });
        }
        initExcelUpload();

        $('.close').on('click', function() {
            closeBox();
        });
    });
</script>
</body>
</html>