Richard.Huang 发表于 2024-2-26 12:15:48

SpreadJS+GcExcel实现大文件的动态加载

背景
随着业务的增长,常用报表展示的企业的数据量会越来越大,很多用户都会采用数据和模板分离的方式来构建整个报表展示的项目,然后通过reportsheet或者数据绑定的方式将数据回填到模板上进行展示,数据量过大的还会采用动态加载数据的方式来解决这个问题:
但是会有这样一种情况,用户有一份将所有数据集中起来的总报表用于年终等特殊情况的汇报使用,额外进行数据库表的开辟不是一个很好的选择,因为像这种数据量巨大的汇总报表使用频率可能并不高,然而大文件的传输耗时以及渲染耗时往往都是致命的。如果能够按需加载我们所激活的工作表,那么这将是一个很好的策略。

实现方式
1. 初始化加载工作簿,只加载激活的工作表,其余工作表只加载表名
/**
* 初始化工作簿
* @param fileName
* @return
* @throws IOException
*/
@RequestMapping(value = "/init", method = RequestMethod.GET)
public R initSpreadJS(@RequestParam("fileName") String fileName) throws IOException {
    int userId = 4;
    Workbook workbook = new Workbook();
    Workbook output = new Workbook();
    // 获取数据
    String filePath = "data/" + userId + "/" + fileName;
    File directory = new File(filePath);
    if (directory.exists()) {
      workbook.open(filePath);
    }
    // 将激活页数据先加载出来
    output.getWorksheets().get(0).fromJson(workbook.getWorksheets().get(0).toJson());
    int count = workbook.getWorksheets().getCount();
    // 其余表加载表名
    for(int i = 1; i < count; i++){
      IWorksheet tempSheet = output.getWorksheets().add();
      tempSheet.setName(workbook.getWorksheets().get(i).getName());
    }

    return R.success(CodeEnum.SUCCESS, output.toJson());
}2. 按需加载工作表
/**
* 按需加载工作表
*
* @param sheetName 工作表名
* @param fileName文件名
* @return 工作表的序列化数据
* @throws IOException
*/
@RequestMapping(value = "/get", method = RequestMethod.GET)
public R getSpreadJSOnDemand(@RequestParam("sheetName") String sheetName, @RequestParam("fileName") String fileName) throws IOException {
    int userId = 4;
    Workbook workbook = new Workbook();
    // 获取数据
    String filePath = "data/" + userId + "/" + fileName;
    File directory = new File(filePath);
    if (directory.exists()) {
      workbook.open(filePath);
    }
    IWorksheet worksheet = workbook.getWorksheets().get(sheetName);
    if (worksheet == null) {
      return R.fail(CodeEnum.FAIL);
    }
    return R.success(CodeEnum.SUCCESS, worksheet.toJson());
}3. 按需更新工作表
/**
* 按需更新工作表
*
* @param updateRequest
* @return
* @throws IOException
*/
@PostMapping("/update")
public R updateSpreadJSOnDemand(@RequestBody UpdateRequest updateRequest) throws IOException {
    int userId = 4;
    Workbook workbook = new Workbook();
    // 获取数据
    String filePath = "data/" + userId + "/" + updateRequest.getFileName();
    File directory = new File(filePath);
    if (directory.exists()) {
      workbook.open(filePath);
    }
    IWorksheet worksheet = null;
    if (workbook.getWorksheets().get(updateRequest.getSheetName()) != null) {
      worksheet = workbook.getWorksheets().get(updateRequest.getSheetName());
    } else {
      worksheet = workbook.getWorksheets().add();
      worksheet.setName(updateRequest.getSheetName());
    }

    worksheet.fromJson(updateRequest.getSheetJSON());
    // 创建文件对象
    File file = new File(filePath);
    // 使用 try-with-resources 语句确保 FileWriter 和 BufferedWriter 在操作完成后关闭
    try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
      writer.write(workbook.toJson());
      System.out.println("字符串已成功保存到文件:" + filePath);
    } catch (IOException e) {
      System.err.println("写入字符串时发生错误:" + e.getMessage());
    }
    // 一切正常
    return R.success(CodeEnum.SUCCESS, Constants.OK);
}完整代码


页: [1]
查看完整版本: SpreadJS+GcExcel实现大文件的动态加载