mirror of
				https://github.com/dromara/RuoYi-Vue-Plus.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	feat add Excel工具类支持更灵活的自定义导出方式,以便用户分批处理导出数据
This commit is contained in:
		@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 单表多数据模板导出 模板格式为 {.属性}
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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导出
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user