Ver Fonte

feat add Excel工具类支持更灵活的自定义导出方式,以便用户分批处理导出数据

秋辞未寒 há 10 meses atrás
pai
commit
7bb4838132

+ 40 - 0
ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java

@@ -27,6 +27,7 @@ import java.io.UnsupportedEncodingException;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Consumer;
 
 /**
  * Excel相关处理
@@ -203,6 +204,45 @@ public class ExcelUtil {
         builder.doWrite(list);
     }
 
+    /**
+     * 导出excel
+     *
+     * @param headType 带Excel注解的类型
+     * @param os       输出流
+     * @param options  Excel下拉可选项
+     * @param consumer 导出助手消费函数
+     */
+    public static <T> void exportExcel(Class<T> headType, OutputStream os, List<DropDownOptions> options, Consumer<ExcelWriterHelper> consumer) {
+        try (ExcelWriter writer = FastExcel.write(os, headType)
+            .autoCloseStream(false)
+            // 自动适配
+            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+            // 大数值自动转换 防止失真
+            .registerConverter(new ExcelBigNumberConvert())
+            // 批注必填项处理
+            .registerWriteHandler(new DataWriteHandler(headType))
+            // 添加下拉框操作
+            .registerWriteHandler(new ExcelDownHandler(options))
+            .build()) {
+            ExcelWriterHelper helper = ExcelWriterHelper.of(writer);
+            // 执行消费函数
+            consumer.accept(helper);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 导出excel
+     *
+     * @param headType 带Excel注解的类型
+     * @param os       输出流
+     * @param consumer 导出助手消费函数
+     */
+    public static <T> void exportExcel(Class<T> headType, OutputStream os, Consumer<ExcelWriterHelper> consumer) {
+        exportExcel(headType, os, null, consumer);
+    }
+
     /**
      * 单表多数据模板导出 模板格式为 {.属性}
      *

+ 135 - 0
ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelWriterHelper.java

@@ -0,0 +1,135 @@
+package org.dromara.common.excel.utils;
+
+import cn.idev.excel.ExcelWriter;
+import cn.idev.excel.FastExcel;
+import cn.idev.excel.context.WriteContext;
+import cn.idev.excel.write.builder.ExcelWriterSheetBuilder;
+import cn.idev.excel.write.builder.ExcelWriterTableBuilder;
+import cn.idev.excel.write.metadata.WriteSheet;
+import cn.idev.excel.write.metadata.WriteTable;
+import cn.idev.excel.write.metadata.fill.FillConfig;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Collection;
+import java.util.function.Supplier;
+
+/**
+ * ExcelWriterHelper Excel写出助手
+ * <br>
+ * 提供了一组与 ExcelWriter 一一对应的写出方法,避免直接提供 ExcelWriter 而导致的一些不可控问题(比如提前关闭了IO流等)
+ *
+ *
+ * @see ExcelWriter
+ * @author 秋辞未寒
+ */
+@RequiredArgsConstructor
+public class ExcelWriterHelper {
+
+    @Getter(AccessLevel.PRIVATE)
+    private final ExcelWriter excelWriter;
+
+    public void write(Collection<?> data, WriteSheet writeSheet) {
+        excelWriter.write(data, writeSheet);
+    }
+
+    public void write(Supplier<Collection<?>> supplier, WriteSheet writeSheet) {
+        excelWriter.write(supplier, writeSheet);
+    }
+
+    public void write(Collection<?> data, WriteSheet writeSheet, WriteTable writeTable) {
+        excelWriter.write(data, writeSheet, writeTable);
+    }
+
+    public void write(Supplier<Collection<?>> supplier, WriteSheet writeSheet, WriteTable writeTable) {
+        excelWriter.write(supplier.get(), writeSheet, writeTable);
+    }
+
+    public void fill(Object data, WriteSheet writeSheet) {
+        excelWriter.fill(data, writeSheet);
+    }
+
+    public void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {
+        excelWriter.fill(data, fillConfig, writeSheet);
+    }
+
+    public void fill(Supplier<Object> supplier, WriteSheet writeSheet) {
+        excelWriter.fill(supplier, writeSheet);
+    }
+
+    public void fill(Supplier<Object> supplier, FillConfig fillConfig, WriteSheet writeSheet) {
+        excelWriter.fill(supplier, fillConfig, writeSheet);
+    }
+
+    public WriteContext writeContext() {
+        return excelWriter.writeContext();
+    }
+
+    /**
+     * 创建一个 ExcelWriterHelper
+     *
+     * @param excelWriter ExcelWriter
+     * @return ExcelWriterHelper
+     */
+    public static ExcelWriterHelper of(ExcelWriter excelWriter) {
+        return new ExcelWriterHelper(excelWriter);
+    }
+
+    // -------------------------------- sheet start
+
+    public static WriteSheet buildSheet(Integer sheetNo, String sheetName) {
+        return sheetBuilder(sheetNo, sheetName).build();
+    }
+
+    public static WriteSheet buildSheet(Integer sheetNo) {
+        return sheetBuilder(sheetNo).build();
+    }
+
+    public static WriteSheet buildSheet(String sheetName) {
+        return sheetBuilder(sheetName).build();
+    }
+
+    public static WriteSheet buildSheet() {
+        return sheetBuilder().build();
+    }
+
+    public static ExcelWriterSheetBuilder sheetBuilder(Integer sheetNo, String sheetName) {
+        return FastExcel.writerSheet(sheetNo, sheetName);
+    }
+
+    public static ExcelWriterSheetBuilder sheetBuilder(Integer sheetNo) {
+        return FastExcel.writerSheet(sheetNo);
+    }
+
+    public static ExcelWriterSheetBuilder sheetBuilder(String sheetName) {
+        return FastExcel.writerSheet(sheetName);
+    }
+
+    public static ExcelWriterSheetBuilder sheetBuilder() {
+        return FastExcel.writerSheet();
+    }
+
+    // -------------------------------- sheet end
+
+    // -------------------------------- table start
+
+    public static WriteTable buildTable(Integer tableNo) {
+        return tableBuilder(tableNo).build();
+    }
+
+    public static WriteTable buildTable() {
+        return tableBuilder().build();
+    }
+
+    public static ExcelWriterTableBuilder tableBuilder(Integer tableNo) {
+        return FastExcel.writerTable(tableNo);
+    }
+
+    public static ExcelWriterTableBuilder tableBuilder() {
+        return FastExcel.writerTable();
+    }
+
+    // -------------------------------- table end
+
+}

+ 12 - 0
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestExcelController.java

@@ -1,5 +1,6 @@
 package org.dromara.demo.controller;
 
+import cn.dev33.satoken.annotation.SaIgnore;
 import cn.hutool.core.collection.CollUtil;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
@@ -14,6 +15,7 @@ import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -94,6 +96,16 @@ public class TestExcelController {
         exportExcelService.exportWithOptions(response);
     }
 
+    /**
+     * 自定义导出
+     *
+     * @param response /
+     */
+    @GetMapping("/customExport")
+    public void customExport(HttpServletResponse response) throws IOException {
+        exportExcelService.customExport(response);
+    }
+
     /**
      * 多个sheet导出
      */

+ 9 - 0
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IExportExcelService.java

@@ -2,6 +2,8 @@ package org.dromara.demo.service;
 
 import jakarta.servlet.http.HttpServletResponse;
 
+import java.io.IOException;
+
 /**
  * 导出下拉框Excel示例
  *
@@ -15,4 +17,11 @@ public interface IExportExcelService {
      * @param response /
      */
     void exportWithOptions(HttpServletResponse response);
+
+    /**
+     * 自定义导出
+     *
+     * @param response /
+     */
+    void customExport(HttpServletResponse response) throws IOException;
 }

+ 62 - 0
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java

@@ -2,17 +2,22 @@ package org.dromara.demo.service.impl;
 
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.idev.excel.write.metadata.WriteSheet;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.Data;
 import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.constant.SystemConstants;
 import org.dromara.common.core.utils.StreamUtils;
+import org.dromara.common.core.utils.file.FileUtils;
+import org.dromara.common.excel.core.CellMergeStrategy;
 import org.dromara.common.excel.core.DropDownOptions;
 import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.excel.utils.ExcelWriterHelper;
 import org.dromara.demo.domain.vo.ExportDemoVo;
 import org.dromara.demo.service.IExportExcelService;
 import org.springframework.stereotype.Service;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -233,4 +238,61 @@ public class ExportExcelServiceImpl implements IExportExcelService {
             this.name = name;
         }
     }
+
+
+    @Override
+    public void customExport(HttpServletResponse response) throws IOException {
+        String filename = ExcelUtil.encodingFilename("自定义导出");
+        FileUtils.setAttachmentResponseHeader(response, filename);
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
+
+        ExcelUtil.exportExcel(ExportDemoVo.class, response.getOutputStream(), helper -> {
+            // 创建表格数据,业务中一般通过数据库查询
+            List<ExportDemoVo> excelDataList = new ArrayList<>();
+            for (int i = 0; i < 30; i++) {
+                // 模拟数据库中的一条数据
+                ExportDemoVo everyRowData = new ExportDemoVo();
+                everyRowData.setNickName("用户-" + i);
+                everyRowData.setUserStatus(SystemConstants.NORMAL);
+                everyRowData.setGender("1");
+                everyRowData.setPhoneNumber(String.format("175%08d", i));
+                everyRowData.setEmail(String.format("175%08d", i) + "@163.com");
+                everyRowData.setProvinceId(i);
+                everyRowData.setCityId(i);
+                everyRowData.setAreaId(i);
+                excelDataList.add(everyRowData);
+            }
+
+            // 创建表格
+            WriteSheet sheet = ExcelWriterHelper.sheetBuilder("自定义导出demo")
+                // 合并单元格
+                // .registerWriteHandler(new CellMergeStrategy(excelDataList, true))
+                .build();
+
+
+            helper.write(excelDataList, sheet);
+
+            List<ExportDemoVo> excelDataList2 = new ArrayList<>();
+            for (int i = 0; i < 20; i++) {
+                int index = 1000 + i;
+                // 模拟数据库中的一条数据
+                ExportDemoVo everyRowData = new ExportDemoVo();
+                everyRowData.setNickName("用户-" + index);
+                everyRowData.setUserStatus(SystemConstants.NORMAL);
+                everyRowData.setGender("1");
+                everyRowData.setPhoneNumber(String.format("175%08d", index));
+                everyRowData.setEmail(String.format("175%08d", index) + "@163.com");
+                everyRowData.setProvinceId(index);
+                everyRowData.setCityId(index);
+                everyRowData.setAreaId(index);
+                excelDataList2.add(everyRowData);
+            }
+
+            helper.write(excelDataList2, sheet);
+
+            // 或者在同一个excel中创建多个表格
+            // WriteSheet sheet2 = ExcelWriterHelper.sheetBuilder("自定义导出demo2").build();
+            // helper.write(excelDataList2, sheet2);
+        });
+    }
 }