Skip to content

导出导入

说明

本项目采用了easy-poi来实现导入导出功能,easy-poi的详细使用请参考easy-poi官方文档。下面介绍本项目的二次封装:

后端实现导入

  1. PoiController 公共导入
java
default R<Boolean> importExcel(@RequestParam(value = "file") MultipartFile simpleFile, HttpServletRequest request,
                               HttpServletResponse response) throws Exception {
    ImportParams params = new ImportParams();

    params.setTitleRows(StrUtil.isEmpty(request.getParameter("titleRows")) ? 0 : Convert.toInt(request.getParameter("titleRows")));
    params.setHeadRows(StrUtil.isEmpty(request.getParameter("headRows")) ? 1 : Convert.toInt(request.getParameter("headRows")));
    List<Map<String, String>> list = ExcelImportUtil.importExcel(simpleFile.getInputStream(), Map.class, params);

    if (list != null && !list.isEmpty()) {
        return handlerImport(list);
    }
    return validFail("导入Excel无有效数据!");
}
default R<Boolean> importExcel(@RequestParam(value = "file") MultipartFile simpleFile, HttpServletRequest request,
                               HttpServletResponse response) throws Exception {
    ImportParams params = new ImportParams();

    params.setTitleRows(StrUtil.isEmpty(request.getParameter("titleRows")) ? 0 : Convert.toInt(request.getParameter("titleRows")));
    params.setHeadRows(StrUtil.isEmpty(request.getParameter("headRows")) ? 1 : Convert.toInt(request.getParameter("headRows")));
    List<Map<String, String>> list = ExcelImportUtil.importExcel(simpleFile.getInputStream(), Map.class, params);

    if (list != null && !list.isEmpty()) {
        return handlerImport(list);
    }
    return validFail("导入Excel无有效数据!");
}
  1. 参考用户导入
java
@Override
public R<Boolean> importExcel(@RequestParam("file") MultipartFile simpleFile, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
    ImportParams params = new ImportParams();
    params.setTitleRows(0);
    params.setHeadRows(1);
    params.setNeedVerify(true);
    params.setVerifyGroup(new Class[]{Default.class});
    // 下面的2个handler只能支持少量数据导入,因为每一条数据都会执行N次查询。有谁能提供优雅解决方式,欢迎PR
    params.setVerifyHandler(excelUserVerifyHandler);
    params.setDictHandler(userExcelDictHandlerIImpl);

    ExcelImportResult<UserExcelVO> result = ExcelImportUtil.importExcelMore(simpleFile.getInputStream(), UserExcelVO.class, params);

    if (result.isVerifyFail()) {
        // 更加优雅的方式,应该是让用户下载错误的数据, 有谁能提供优雅解决方式,欢迎PR
        return R.validFail(result.getFailList().stream()
                .map(item -> StrUtil.format("第{}行检验错误: {}", item.getRowNum(), item.getErrorMsg()))
                .collect(Collectors.joining("<br/>")));
    }

    List<UserExcelVO> list = result.getList();
    if (list.isEmpty()) {
        return this.validFail("导入数据不能为空");
    }

    Set<String> accounts = new HashSet<>();
    List<User> userList = list.stream().map(item -> {
        ArgumentAssert.notContain(accounts, item.getAccount(), "Excel中存在重复的账号: {}", item.getAccount());

        accounts.add(item.getAccount());
        User user = new User();
        BeanUtil.copyProperties(item, user);
        user.setSalt(RandomUtil.randomString(20));
        user.setPassword(SecureUtil.sha256(BizConstant.DEF_PASSWORD + user.getSalt()));
        return user;
    }).collect(Collectors.toList());

    baseService.saveBatch(userList);
    return this.success(true);
}
@Override
public R<Boolean> importExcel(@RequestParam("file") MultipartFile simpleFile, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
    ImportParams params = new ImportParams();
    params.setTitleRows(0);
    params.setHeadRows(1);
    params.setNeedVerify(true);
    params.setVerifyGroup(new Class[]{Default.class});
    // 下面的2个handler只能支持少量数据导入,因为每一条数据都会执行N次查询。有谁能提供优雅解决方式,欢迎PR
    params.setVerifyHandler(excelUserVerifyHandler);
    params.setDictHandler(userExcelDictHandlerIImpl);

    ExcelImportResult<UserExcelVO> result = ExcelImportUtil.importExcelMore(simpleFile.getInputStream(), UserExcelVO.class, params);

    if (result.isVerifyFail()) {
        // 更加优雅的方式,应该是让用户下载错误的数据, 有谁能提供优雅解决方式,欢迎PR
        return R.validFail(result.getFailList().stream()
                .map(item -> StrUtil.format("第{}行检验错误: {}", item.getRowNum(), item.getErrorMsg()))
                .collect(Collectors.joining("<br/>")));
    }

    List<UserExcelVO> list = result.getList();
    if (list.isEmpty()) {
        return this.validFail("导入数据不能为空");
    }

    Set<String> accounts = new HashSet<>();
    List<User> userList = list.stream().map(item -> {
        ArgumentAssert.notContain(accounts, item.getAccount(), "Excel中存在重复的账号: {}", item.getAccount());

        accounts.add(item.getAccount());
        User user = new User();
        BeanUtil.copyProperties(item, user);
        user.setSalt(RandomUtil.randomString(20));
        user.setPassword(SecureUtil.sha256(BizConstant.DEF_PASSWORD + user.getSalt()));
        return user;
    }).collect(Collectors.toList());

    baseService.saveBatch(userList);
    return this.success(true);
}
  1. 实体类字段上标记@Excel注解
java
public class UserExcelVO implements Serializable, IExcelModel, IExcelDataModel {
    private String errorMsg;
    private Integer rowNum;
  
    @Excel(name = "账号")
    private String account;
}
public class UserExcelVO implements Serializable, IExcelModel, IExcelDataModel {
    private String errorMsg;
    private Integer rowNum;
  
    @Excel(name = "账号")
    private String account;
}

后端导出

java
@RequestMapping(value = "/export", method = RequestMethod.POST, produces = "application/octet-stream")
default void exportExcel(@RequestBody @Validated PageParams<PageQuery> params, HttpServletRequest request, HttpServletResponse response) {
    ExportParams exportParams = getExportParams(params);

    List<?> list = findExportList(params);

    Map<String, Object> map = new HashMap<>(7);
    map.put(NormalExcelConstants.DATA_LIST, list);
    map.put(NormalExcelConstants.CLASS, getExcelClass());
    map.put(NormalExcelConstants.PARAMS, exportParams);
    Object fileName = params.getExtra().getOrDefault(NormalExcelConstants.FILE_NAME, "临时文件");
    map.put(NormalExcelConstants.FILE_NAME, fileName);
    PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);
}
@RequestMapping(value = "/export", method = RequestMethod.POST, produces = "application/octet-stream")
default void exportExcel(@RequestBody @Validated PageParams<PageQuery> params, HttpServletRequest request, HttpServletResponse response) {
    ExportParams exportParams = getExportParams(params);

    List<?> list = findExportList(params);

    Map<String, Object> map = new HashMap<>(7);
    map.put(NormalExcelConstants.DATA_LIST, list);
    map.put(NormalExcelConstants.CLASS, getExcelClass());
    map.put(NormalExcelConstants.PARAMS, exportParams);
    Object fileName = params.getExtra().getOrDefault(NormalExcelConstants.FILE_NAME, "临时文件");
    map.put(NormalExcelConstants.FILE_NAME, fileName);
    PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);
}

后端导出预览

java
@RequestMapping(value = "/preview", method = RequestMethod.POST)
default R<String> preview(@RequestBody @Validated PageParams<PageQuery> params) {
    ExportParams exportParams = getExportParams(params);
    List<?> list = findExportList(params);
    Workbook workbook = ExcelExportUtil.exportExcel(exportParams, getExcelClass(), list);
    return success(ExcelXorHtmlUtil.excelToHtml(new ExcelToHtmlParams(workbook)));
}
@RequestMapping(value = "/preview", method = RequestMethod.POST)
default R<String> preview(@RequestBody @Validated PageParams<PageQuery> params) {
    ExportParams exportParams = getExportParams(params);
    List<?> list = findExportList(params);
    Workbook workbook = ExcelExportUtil.exportExcel(exportParams, getExcelClass(), list);
    return success(ExcelXorHtmlUtil.excelToHtml(new ExcelToHtmlParams(workbook)));
}

acuity-web-plus 前端实现

  • 导出预览组件: PreviewExcelModel.vue
  • 导入组件:ImportExcelModel.vue
typescript
// 导入按钮
<a-button type="primary" @click="handleImport">{{ t('common.title.import') }}</a-button>
// 导入页面
<ImpExcelModel
  @register="importRegister"
  @success="handleImportSuccess"
  :api="importFile"
  :templateHref="templateUrl.user"
/>
// 导入按钮
<a-button type="primary" @click="handleImport">{{ t('common.title.import') }}</a-button>
// 导入页面
<ImpExcelModel
  @register="importRegister"
  @success="handleImportSuccess"
  :api="importFile"
  :templateHref="templateUrl.user"
/>
  • 导出 和 导出预览功能:
typescript
// 导出按钮
<a-button type="primary" @click="handleExport">{{ t('common.title.export') }}</a-button>

// 导出预览页面
<PreviewExcelModel
  width="70%"
  @register="exportRegister"
  @success="handleExportSuccess"
  :exportApi="exportFile"
  :previewApi="exportPreview"
/>

// 点击导出按钮执行后台方法
function handleExport() {
  const form = getForm();
  let params = { ...form.getFieldsValue() };
  params = handleSearchInfoByCreateTime(params);
  params.extra = {
    ...{
      fileName: t('acuity.org.user.table.title'),
    },
    ...params?.extra,
  };
  params.size = 20000;

  exportModel.openModal(true, {
    params,
  });
}
// 导出按钮
<a-button type="primary" @click="handleExport">{{ t('common.title.export') }}</a-button>

// 导出预览页面
<PreviewExcelModel
  width="70%"
  @register="exportRegister"
  @success="handleExportSuccess"
  :exportApi="exportFile"
  :previewApi="exportPreview"
/>

// 点击导出按钮执行后台方法
function handleExport() {
  const form = getForm();
  let params = { ...form.getFieldsValue() };
  params = handleSearchInfoByCreateTime(params);
  params.extra = {
    ...{
      fileName: t('acuity.org.user.table.title'),
    },
    ...params?.extra,
  };
  params.size = 20000;

  exportModel.openModal(true, {
    params,
  });
}

acuity-web 前端实现

  • 导入组件: Import.vue

欢迎使用天源云Saas快速开发系统