From 7bb48381321bc4af59eebbccbb0b1fb1c417fd2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Sat, 30 Aug 2025 18:09:01 +0800 Subject: [PATCH] =?UTF-8?q?feat=20add=20Excel=E5=B7=A5=E5=85=B7=E7=B1=BB?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=9B=B4=E7=81=B5=E6=B4=BB=E7=9A=84=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=AF=BC=E5=87=BA=E6=96=B9=E5=BC=8F=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E4=BE=BF=E7=94=A8=E6=88=B7=E5=88=86=E6=89=B9=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=AF=BC=E5=87=BA=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/excel/utils/ExcelUtil.java | 40 ++++++ .../common/excel/utils/ExcelWriterHelper.java | 135 ++++++++++++++++++ .../demo/controller/TestExcelController.java | 12 ++ .../demo/service/IExportExcelService.java | 9 ++ .../service/impl/ExportExcelServiceImpl.java | 62 ++++++++ 5 files changed, 258 insertions(+) create mode 100644 ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelWriterHelper.java diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java index 1b35e559a..de6c11b50 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java +++ b/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 void exportExcel(Class headType, OutputStream os, List options, Consumer 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 void exportExcel(Class headType, OutputStream os, Consumer consumer) { + exportExcel(headType, os, null, consumer); + } + /** * 单表多数据模板导出 模板格式为 {.属性} * diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelWriterHelper.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelWriterHelper.java new file mode 100644 index 000000000..f835986de --- /dev/null +++ b/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写出助手 + *
+ * 提供了一组与 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> 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> 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 supplier, WriteSheet writeSheet) { + excelWriter.fill(supplier, writeSheet); + } + + public void fill(Supplier 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 + +} diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestExcelController.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestExcelController.java index 3fd124c78..64243b77c 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestExcelController.java +++ b/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导出 */ diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IExportExcelService.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IExportExcelService.java index 4dfa5effa..ad2392b97 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IExportExcelService.java +++ b/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; } diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java index 69cf0a8af..3a3bde171 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java +++ b/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 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 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); + }); + } }