Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >EasyExcel实现文件上传下载(百万级数据、单元格自定义样式)

EasyExcel实现文件上传下载(百万级数据、单元格自定义样式)

作者头像
Java微观世界
发布于 2025-01-21 02:15:40
发布于 2025-01-21 02:15:40
27200
代码可运行
举报
文章被收录于专栏:springbootspringboot
运行总次数:0
代码可运行

一、EasyExcel介绍

Java解析、生成Excel比较有名的框架有Apache poijxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。 EasyExcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便。

官方网站:https://easyexcel.opensource.alibaba.com/docs/current

maven依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.0</version>
</dependency>

特别说明:Excel不同版本最多的行和列

  • Excel2003(xls) 最多65536(六万多)行,256 列,超过就会报错
  • Excel2007(xlsx) 最多1048576(一百万多)行,16384列(采取的是xml存储),超过就会报错

二、写Excel

1、最简单的写

实体类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Data
public class Employee {
    @ExcelProperty(value = "用户编号")
    private Integer id;

    @ExcelProperty(value = "姓名")
    private String name;

    @ExcelProperty(value = "性别")
    private String gender;

    @ExcelProperty(value = "工资")
    private Double salary;

    @ExcelProperty(value = "入职时间")
    private Date hireDate;
}

通用数据生成 后面不会重复写

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private List<Employee> employeeData() {
    List<Employee> employeeList = new ArrayList<>();
    for (int i = 1; i <= 10; i++) {
        Employee employee = new Employee();
        employee.setId(i);
        employee.setName("emp" + i);
        employee.setGender(i % 2 == 0 ? "男" : "女");
        employee.setSalary(i * 1000.00);
        employee.setHireDate(new Date());
        employeeList.add(employee);
    }
    return employeeList;
}

最简单的写代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void simpleWrite() {
    String fileName = "/Users/xuchang/Documents/simpleWrite.xlsx";
    EasyExcel.write(fileName, Employee.class)
            .sheet("Sheet名称")
            .doWrite(employeeData());
}

🌈效果

注意⚠️在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照重复多次写入

2、列宽、行高、背景颜色、字体大小颜色、对齐方式

2.1、编码方式

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void customWrite() {
    String fileName = "/Users/xuchang/Documents/customWrite.xlsx";
    EasyExcel.write(fileName, Employee.class)
            .sheet("Sheet名称")
            /**
            自动列宽(不太精确)
            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
            */
            // 简单的列宽策略,列宽20
            .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20))
            // 简单的行高策略:头行高30,内容行高20
            .registerWriteHandler(new SimpleRowHeightStyleStrategy((short)30,(short)20))
            // 自定义样式
            .registerWriteHandler(getStyleStrategy())
            .doWrite(employeeData());
}


// 设置样式
public static HorizontalCellStyleStrategy getStyleStrategy() {
    // 内容样式策略
    WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
    // 垂直居中,水平居中
    contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
    contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
    // 上下左右边框设置
    contentWriteCellStyle.setBorderLeft(BorderStyle.DASHED);
    contentWriteCellStyle.setBorderTop(BorderStyle.MEDIUM);
    contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
    contentWriteCellStyle.setBorderBottom(BorderStyle.THICK);
    // 设置 自动换行
    contentWriteCellStyle.setWrapped(true);
    // 字体策略
    WriteFont contentWriteFont = new WriteFont();
    // 字体大小
    contentWriteFont.setFontHeightInPoints((short) 12);
    contentWriteFont.setColor(IndexedColors.GREEN.getIndex());
    contentWriteCellStyle.setWriteFont(contentWriteFont);

    // 头策略使用默认
    WriteCellStyle headWriteCellStyle = new WriteCellStyle();
    headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
    return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
}

🌈效果

2.2、注解方式

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@ContentRowHeight(20) // 设置每个表格的高度
@HeadRowHeight(50) // 设置每个表头的高度
@ColumnWidth(20) // 设置每个表格的宽度

// 头背景设置成红色
// fillForegroundColor(填充颜色):枚举类IndexedColors 10-红色 12-蓝色 17-绿色。。。
// fillPatternType(填充方式):枚举类FillPatternTypeEnum SOLID_FOREGROUND-实心填充 还有其他填充方式,则不需要填写颜色了
// horizontalAlignment(水平对齐类型):枚举类HorizontalAlignmentEnum LEFT-左对齐 CENTER-居中 RIGHT-右对齐
@HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 10, horizontalAlignment = HorizontalAlignmentEnum.CENTER)
// 头字体设置成20,表头字体颜色设置为蓝色
@HeadFontStyle(fontHeightInPoints = 30, color = 12)

// 内容的背景设置成绿色(与HeadStyle注解一致)
@ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 17, horizontalAlignment = HorizontalAlignmentEnum.LEFT)
// 内容字体设置成20,内容字体颜色设置为红色
@ContentFontStyle(fontHeightInPoints = 10, color = 13)

@Data
public class Employee {
    @ColumnWidth(30)
    @ExcelProperty(value = "用户编号")
    private Integer id;

    @ExcelProperty(value = "姓名")
    private String name;

    @ExcelProperty(value = "性别")
    private String gender;

    @ExcelProperty(value = "工资")
    private Double salary;

    @ColumnWidth(40)
    @ExcelProperty(value = "入职时间")
    private Date hireDate;
}

🌈效果

3、复杂头与修改列顺序

代码(只需要改下数据实体注解

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Data
public class Employee {
    @ExcelProperty(value = {"主标题", "用户编号"}, index = 1)
    private Integer id;

    @ExcelProperty(value = {"主标题", "姓名"}, index = 0)
    private String name;

    @ExcelProperty(value = {"主标题", "性别"}, index = 4)
    private String gender;

    @ExcelProperty(value = {"主标题", "工资"}, index = 2)
    private Double salary;

    @ExcelProperty(value = {"主标题", "入职时间"}, index = 3)
    private Date hireDate;
}

🌈效果

4、日期、数字类型和自定义格式化

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void converterWrite() {
    List<DataInfo> list = Lists.newArrayList();
    list.add(new DataInfo("张三", 1, new Date(), new BigDecimal("0.5")));
    list.add(new DataInfo("李四", 2, new Date(), new BigDecimal("0.123")));
    list.add(new DataInfo("王五", 3, new Date(), new BigDecimal("0.4567")));
    list.add(new DataInfo("赵六", 4, new Date(), new BigDecimal("0.55789")));

    String fileName = "/Users/xuchang/Documents/converterWrite.xlsx";
    EasyExcel.write(fileName, DataInfo.class)
            .sheet("Sheet名称")
            .doWrite(list);
}

// 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataInfo {
    @ExcelProperty(value = "名称")
    private String name;
	
	// 自定义格式化,java的数字类型,导出excel为字符串类型
    @ExcelProperty(value = "季节", converter = IntegerToStringConverter.class)
    private Integer season;

    @ExcelProperty(value = "日期")
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    private Date date;

    // 最后一位默认四舍五入
    @ExcelProperty(value = "百分比")
    @NumberFormat(value = "0.00%")
    private BigDecimal percent;
}

// 自定义格式化转换类
public class IntegerToStringConverter implements Converter<Integer> {

    // 设置Java类型
    @Override
    public Class<?> supportJavaTypeKey() {
        return Integer.class;
    }

    // 设置Excel类型
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }


    // 读操作时候 将 excel 对象转换为 Java 对象
    @Override
    public Integer convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        switch (cellData.getStringValue()) {
            case "春天":
                return 1;
            case "夏天":
                return 2;
            case "秋天":
                return 3;
            case "冬天":
                return 4;
            default:
                break;
        }
        throw new Exception("未知季节类型");
    }

    // 写操作时 将 Java 对象转换为 excel 对象
    @Override
    public WriteCellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        switch (value) {
            case 1:
                return new WriteCellData<>("春天");
            case 2:
                return new WriteCellData<>("夏天");
            case 3:
                return new WriteCellData<>("秋天");
            case 4:
                return new WriteCellData<>("冬天");
            default:
                break;
        }
        throw new Exception("未知季节类型");
    }
}

🌈效果

5、设置单元格下拉

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void selectWrite() {
    String fileName = "/Users/xuchang/Documents/selectWrite.xlsx";
    EasyExcel.write(fileName, Employee.class)
            .registerWriteHandler(new SelectWriteHandler())
            .sheet("Sheet名称")
            .doWrite(employeeData());
}

// 设置下拉的实现
public class SelectWriteHandler implements SheetWriteHandler {
    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        // 定义一个map key是需要添加下拉框的列的index value是下拉框数据
        Map<Integer, String[]> mapDropDown = new HashMap<>(1);
        // 设置性别的码值
        String[] sex = {"男", "女"};

        // 下拉选在Excel中对应的列
        mapDropDown.put(2, sex);

        // 获取工作簿
        Sheet sheet = writeSheetHolder.getSheet();
        ///开始设置下拉框
        DataValidationHelper helper = sheet.getDataValidationHelper();
        // 设置下拉框
        for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
            // 起始行、终止行、起始列、终止列  起始行为1即表示表头不设置
            CellRangeAddressList addressList = new CellRangeAddressList(1, 65535, entry.getKey(), entry.getKey());
            /*设置下拉框数据**/
            DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
            DataValidation dataValidation = helper.createValidation(constraint, addressList);
            sheet.addValidationData(dataValidation);
        }
    }
}

🌈效果

6、重复多次写入(百万数据)

代码(16g内存mac耗时6秒多)真快🚀

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void repeatedWrite() {
    long start = System.currentTimeMillis();
    String fileName = "/Users/xuchang/Documents/repeatedWrite.xlsx";
    try (ExcelWriter excelWriter = EasyExcel.write(fileName, Employee.class).build()) {
        // 如果写入同一个Sheet,创建WriteSheet就写在这里
        // 如果想要写入多个Sheet,创建WriteSheet就放入for循环中,每组10万个数据放入同一个sheet中
        WriteSheet writeSheet = EasyExcel.writerSheet("Sheet名称").build();
        // 每次写入10万数据,循环写入10次,一共写入100万数据
        for (int i = 1; i <= 10; i++) {
            excelWriter.write(employeeMoreData(100000), writeSheet);
        }
    }
    System.out.println("耗时:" + (System.currentTimeMillis() - start));// 耗时:6732
}

🌈效果

7、导出指定列

代码(可以选择忽略只导出的字段)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void excludeOrIncludeWrite() {
    String excludeFileName = "/Users/xuchang/Documents/testExclude.xlsx";
    // 我们要忽略 “工资” 这一列不导出
    EasyExcel.write(excludeFileName, Employee.class)
            .excludeColumnFieldNames(Arrays.asList("salary"))
            .sheet("Sheet名称")
            .doWrite(employeeData());

    String includeFileName = "/Users/xuchang/Documents/testInclude.xlsx";
    // 我们只要导出 "编号和名称" 这两列,其他列不导出
    EasyExcel.write(includeFileName, Employee.class)
            .includeColumnFieldNames(Arrays.asList("id", "name"))
            .sheet("Sheet名称")
            .doWrite(employeeData());
}

🌈效果

8、动态生成表头

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void dynamicHeadWrite() {
    String fileName = "/Users/xuchang/Documents/dynamicHeadWrite.xlsx";
    EasyExcel.write(fileName)
            // 这里放入动态头
            .head(head()).sheet("Sheet名称")
            // 自动列宽(不太精确)
            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
            // 当然这里数据也可以用 List<List<String>> 去传入
            .doWrite(employeeData());
}

private List<List<String>> head() {
    List<List<String>> list = new ArrayList<>();
    list.add(Arrays.asList("用户编号" + "自定义字符串1"));
    list.add(Arrays.asList("姓名" + "自定义字符串2"));
    list.add(Arrays.asList("性别" + "自定义字符3"));
    list.add(Arrays.asList("工资" + "自定义字符串4"));
    list.add(Arrays.asList("入职时间" + "自定义字符串5"));
    return list;
}

🌈效果

9、模板填充Excel

  • 向预设样式的表格中直接写入数据,写入数据的时候会保持原有样式

📊准备模板

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void templateFill() {
    // 模板路径
    String templateFileName = "/Users/xuchang/Documents/templateFill.xlsx";

    // 生成文件excel路径
    String fileName = "/Users/xuchang/Documents/simpleFill.xlsx";

    // 基础信息
    HashMap<String, Object> map1 = new HashMap<>();
    map1.put("recipient", "张无忌");
    HashMap<String, Object> map2 = new HashMap<>();
    map2.put("addresser", "赵敏");
    HashMap<String, Object> map3 = new HashMap<>();
    map3.put("phone", "13552454101");
    HashMap<String, Object> map4 = new HashMap<>();
    map4.put("date", "2020-01-01");

    // 报价单
    List<QuotationInfo> quotationInfoList = Lists.newArrayList();
    quotationInfoList.add(new QuotationInfo(1,"电饭锅", 100D, 2, 200D, "备注1"));
    quotationInfoList.add(new QuotationInfo(2,"手电筒", 25D, 4, 100D, "备注2"));
    quotationInfoList.add(new QuotationInfo(3,"台灯", 40D, 10, 400D, "备注3"));
    quotationInfoList.add(new QuotationInfo(4,"手机", 3000D, 2, 6000D, "备注4"));
    quotationInfoList.add(new QuotationInfo(5,"电脑", 5000D, 10, 50000D, "备注5"));
    quotationInfoList.add(new QuotationInfo(6,"微波炉", 100D, 2, 200D, "备注6"));

    try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build()) {
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        excelWriter.fill(map1, writeSheet);
        excelWriter.fill(map2, writeSheet);
        excelWriter.fill(map3, writeSheet);
        excelWriter.fill(map4, writeSheet);
        excelWriter.fill(quotationInfoList, writeSheet);
    }
}

@Data
@AllArgsConstructor
public class QuotationInfo {
    private Integer no;
    private String name;
    private Double price;
    private Integer number;
    private Double total;
    private String notes;
}

🌈效果

10、springboot项目中写法

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@GetMapping("/download")
public void download(HttpServletResponse response) throws IOException {
    response.setContentType("application/vnd.ms-excel;charset=utf-8");
    response.setCharacterEncoding("utf-8");
    String fileName = URLEncoder.encode("测试文件名.xlsx", "UTF-8");
    response.setHeader("Content-disposition", "attachment;filename=" + fileName);
    EasyExcel.write(response.getOutputStream(), Employee.class).sheet().doWrite(employeeData());
}

三、读Excel

1、最简单的读

代码(自带监听PageReadListener,每次读取100条)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void simpleRead() {
    // 使用最简单的写法生成的simpleWrite.xlsx来读取
    String fileName = "/Users/xuchang/Documents/simpleWrite.xlsx";
    // 这里默认每次会读取100条数据 然后返回过来 直接调用使用数据就行
    // PageReadListener里面定义了每次返回100行数据
    EasyExcel.read(fileName, Employee.class, new PageReadListener<Employee>(dataList -> {
        for (Employee employee : dataList) {
            System.out.println("读取到一条数据" + JSON.toJSONString(employee));
        }
    })).sheet().doRead();
}
  • @ExcelIgnoreUnannotated:没有注解的字段都不转换(全局控制)
  • @ExcelIgnore:不将该字段转换成Excel(单个控制)
  • 当读取的表头与@ExcelProperty注解的数量顺序不一致的情况下,如果两个注解都不加,则读取数量错乱
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Data
@ExcelIgnoreUnannotated
public class Employee {
    // @ColumnWidth(30)
    @ExcelProperty(value = "用户编号")
    private Integer id;

    @ExcelProperty(value = "姓名")
    private String name;

    // @ExcelProperty(value = "性别")
    @ExcelIgnore
    private String gender;

    // @ExcelProperty(value = "工资")
    @ExcelIgnore
    private Double salary;

    // @ColumnWidth(40)
    @ExcelProperty(value = "入职时间")
    private Date hireDate;
}

🌈效果

2、自定义监听器

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void customRead() {
    // 使用最简单的写法生成的simpleWrite.xlsx来读取
    String fileName = "/Users/xuchang/Documents/simpleWrite.xlsx";
    // 每次读取500条数据入库
    EasyExcel.read(fileName, DataInfo.class, new DataInfoListener()).sheet().doRead();
}
  • 自定义监听器(每次读取500条数据)
  • 不能被spring管理,要每次读取excel都要new,需要通过构造函数方式注入xxxService
  • 或者也可以使用匿名内部类的方式,也就不需要注入xxxService了
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Slf4j
public class DataInfoListener implements ReadListener<DataInfo> {
    /**
     * 设置多少条数据入库
     */
    private static final int BATCH_COUNT = 500;

    /**
     * 缓存的数据
     */
    private List<DataInfo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    /**
     * DataInfoListener不能被spring管理,要每次读取excel都要new
     * 需要使用构造方法注入方式将dataInfoService注入进来
     */
    private DataInfoService dataInfoService;

    public DemoDataListener(DataInfoService dataInfoService) {
        this.dataInfoService = dataInfoService;
    }

    /**
     * 这个每一条数据解析都会来调用
     */
    @Override
    public void invoke(DataInfo data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理,实际就是新建一个空集合
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了都会来调用
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 插入数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        dataInfoService.save(cachedDataList);
        log.info("存储数据库成功!");
    }
}

3、同步的返回(适合小数据量)

代码(一次性读取所有的数据,适合数据量小的情况)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void synchronousRead() {
    // 使用最简单的写法生成的simpleWrite.xlsx来读取
    String fileName = "/Users/xuchang/Documents/simpleWrite.xlsx";
    List<Employee> employeeList = EasyExcel.read(fileName).head(Employee.class).doReadAllSync();
}

4、日期、数字类型和自定义格式化

代码(实体类注解及自定义转化器与写Excel里面一样,写和读配置一套即可)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void converterRead() {
    String fileName = "/Users/xuchang/Documents/converterWrite.xlsx";
    EasyExcel.read(fileName, DataInfo.class, new PageReadListener<DataInfo>(dataList -> {
        for (DataInfo dataInfo : dataList) {
            System.out.println("读取到一条数据" + JSON.toJSONString(dataInfo));
        }
    })).sheet().doRead();
}

// 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataInfo {
    @ExcelProperty(value = "名称")
    private String name;
	
	// 自定义格式化,java的数字类型,导出excel为字符串类型
    @ExcelProperty(value = "季节", converter = IntegerToStringConverter.class)
    private Integer season;

    @ExcelProperty(value = "日期")
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    private Date date;

    // 最后一位默认四舍五入
    @ExcelProperty(value = "百分比")
    @NumberFormat(value = "0.00%")
    private BigDecimal percent;
}

// 自定义格式化转换类
public class IntegerToStringConverter implements Converter<Integer> {

    // 设置Java类型
    @Override
    public Class<?> supportJavaTypeKey() {
        return Integer.class;
    }

    // 设置Excel类型
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }


    // 读操作时候 将 excel 对象转换为 Java 对象
    @Override
    public Integer convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        switch (cellData.getStringValue()) {
            case "春天":
                return 1;
            case "夏天":
                return 2;
            case "秋天":
                return 3;
            case "冬天":
                return 4;
            default:
                break;
        }
        throw new Exception("未知季节类型");
    }

    // 写操作时 将 Java 对象转换为 excel 对象
    @Override
    public WriteCellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        switch (value) {
            case 1:
                return new WriteCellData<>("春天");
            case 2:
                return new WriteCellData<>("夏天");
            case 3:
                return new WriteCellData<>("秋天");
            case 4:
                return new WriteCellData<>("冬天");
            default:
                break;
        }
        throw new Exception("未知季节类型");
    }
}

🌈效果

5、springboot项目中读法

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@PostMapping("/upload")
@ResponseBody
public void upload(MultipartFile file) throws IOException {
    EasyExcel.read(file.getInputStream(), DataInfo.class, new PageReadListener<DataInfo>(list -> {
        for (DataInfo dataInfo : list) {
            System.out.println("读取到一条数据" + JSON.toJSONString(dataInfo));
        }
    })).sheet().doRead();
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
百度公共IM系统的Andriod端IM SDK组件架构设计与技术实现
移动互联网时代,随着社交媒体、移动支付、线上购物等行业的快速发展,对即时通讯功能的需求不断增加。对于各APP而言,接入IM SDK(即时通讯软件开发工具包)能够大大降低开发成本、提高开发效率,快速构建自己的IM系统。
JackJiang
2024/10/11
1070
百度公共IM系统的Andriod端IM SDK组件架构设计与技术实现
直播系统聊天技术(四):百度直播的海量用户实时消息系统架构演进实践
本文原题“百度直播消息服务架构实践”,由百度APP消息中台团队原创分享于“百度Geek说”公众号,为了让文章内容更通俗易懂,本次已做排版优化和内容重新划分,原文链接在文末。
JackJiang
2021/04/27
1.4K0
揭秘百度IM消息中台的全量用户消息推送技术改造实践
本文内容由百度技术团队分享,原题“基于公共信箱的全量消息实现”,为了帮助理解,有较多修订、内容重组和重新排版。
JackJiang
2023/05/26
6610
揭秘百度IM消息中台的全量用户消息推送技术改造实践
基于Netty,徒手撸IM(一):IM系统设计篇
本文收作者“大白菜”分享,有改动。注意:本系列是给IM初学者的文章,IM老油条们还望海涵,勿喷!
JackJiang
2022/07/04
2.2K0
基于Netty,徒手撸IM(一):IM系统设计篇
基于实践:一套百万消息量小规模IM系统技术要点总结
本文由公众号“后台技术汇”分享,原题“基于实践,设计一个百万级别的高可用 & 高可靠的 IM 消息系统”,原文链接在文末。由于原文存在较多错误和不准确内容,有大量修订和改动。
JackJiang
2021/11/27
2.2K0
基于实践:一套百万消息量小规模IM系统技术要点总结
跟着源码学IM(十一):一套基于Netty的分布式高可用IM详细设计与实现(有源码)
本文将要分享的是如何从零实现一套基于Netty框架的分布式高可用IM系统,它将支持长连接网关管理、单聊、群聊、聊天记录查询、离线消息存储、消息推送、心跳、分布式唯一ID、红包、消息同步等功能,并且还支持集群部署。
JackJiang
2023/06/09
1.3K0
跟着源码学IM(十一):一套基于Netty的分布式高可用IM详细设计与实现(有源码)
转转平台IM系统架构设计与实践(二):详细设计与实现
接上篇《整体架构设计》,笔者将以转转IM架构为起点,介绍IM相关组件以及组件间的关系;以IM登陆和发消息的数据流转为跑道,介绍IM静态数据结构、登陆和发消息时的动态数据变化;以IM常见问题为风景,介绍保证IM实时性、可靠性、一致性的一般方案;以高可用、高并发为终点,介绍保证IM系统稳定及性能的小技巧。
JackJiang
2025/02/13
1950
转转平台IM系统架构设计与实践(二):详细设计与实现
从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结
移动互联网技术改变了旅游的世界,这个领域过去沉重的信息分销成本被大大降低。用户与服务供应商之间、用户与用户之间的沟通路径逐渐打通,沟通的场景也在不断扩展。这促使所有的移动应用开发者都要从用户视角出发,更好地满足用户需求。
JackJiang
2019/10/21
1.2K0
从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结
从新手到专家:如何设计一套亿级消息量的分布式IM系统
本文原作者Chank,原题“如何设计一个亿级消息量的 IM 系统”,为了提升内容质量,本次有修订和改动。
JackJiang
2021/03/29
3.7K0
听说你会架构设计?来,弄一个群聊系统
大家好,我是小❤,一个漂泊江湖多年的 985 非科班程序员,曾混迹于国企、互联网大厂和创业公司的后台开发攻城狮。
xin猿意码
2023/11/08
6270
听说你会架构设计?来,弄一个群聊系统
IM系统设计
即时通讯(Instant Messaging,简称IM)是一个实时通信系统,允许两人或多人使用网络实时的传递文字消息、文件、语音与视频交流。实现方式有两种。第一种基于Server转发的,Client双方通信会经过Server转发来完成消息传递。例如QQ、微信。
gglinux
2019/02/23
3.8K0
听说你会架构设计?来,弄一个微信群聊系统
当我那天拿着手机,正在和朋友们的微信群里畅聊着八卦新闻和即将到来的周末计划时,忽然一条带着喜意的消息扑面而来,消息正中间写着八个大字:恭喜发财,大吉大利。
xin猿意码
2023/11/02
9260
听说你会架构设计?来,弄一个微信群聊系统
Android即时通讯设计——腾讯IM接入和WebSocket接入
之前项目的群聊是用数据库直接操作的,体验很差,消息很难即时反馈,所以最后考虑到了使用腾讯的IM完成群聊的接入,不过中途还是有点小坎坷的,接入完成之后发现体验版一个群聊只有20人,当时看到体验版支持100个用户也就忍了,现在一个群聊只能20用户,忍不了了,所以暂时找到了WebSocket作为临时的解决方案(等有钱了再换),同时支持50个用户在线聊天,也算还行,勉强够用,下面就介绍两种实现方案的接入,正文即将开始~~
wresource
2023/01/31
3.8K0
Web端实时通信技术SSE在携程机票业务中的实践应用
本文介绍了携程机票前端基于Server-Sent Events(SSE)实现服务端推送的企业级全链路通用技术解决方案。文章深入探讨了 SSE 技术在应用过程中包括方案对比、技术选型、链路层优化以及实际效果等多维度的技术细节,为类似使用场景提供普适性参考和借鉴。该方案设计目标是实现通用性,适用于各种网络架构和业务场景。
JackJiang
2025/05/31
1260
Web端实时通信技术SSE在携程机票业务中的实践应用
转转平台IM系统架构设计与实践(一):整体架构设计
转转是二手电商平台,在这个平台上,人人可以是买家,人人也可以是卖家。转转从最初的信息模式升级为一个闭环的交易模式,IM打通了买家与卖家之间的通道。本文描述了转转IM为整个平台提供的支撑能力,给出了系统的整体架构设计,分析了系统架构的特性。
JackJiang
2025/01/09
1320
转转平台IM系统架构设计与实践(一):整体架构设计
一套分布式IM即时通讯系统的技术选型和架构设计
针对聊天本身来说,最核心的需求就是:发送文字、图片、文件、语音、视频、消息缓存、消息存储、消息未读、已读、撤回,离线消息、历史消息、单聊、群聊,多端同步,以及其他一些需求。
JackJiang
2023/12/21
2.8K0
一套分布式IM即时通讯系统的技术选型和架构设计
零基础IM开发入门(四):什么是IM系统的消息时序一致性?
本文引用了沈剑《如何保证IM实时消息的“时序性”与“一致性”?》一文的图片和内容(由于太懒,图没重新画),原文链接在文末。
JackJiang
2020/11/04
1.4K0
零基础IM开发入门(四):什么是IM系统的消息时序一致性?
从客户端的角度来谈谈移动端IM的消息可靠性和送达机制
IM App 是我做过 App 类型里复杂度最高的一类,里面可供深究探讨的技术难点非常之多。这篇文章和大家聊下从移动端客户端的角度所关注的IM消息可靠性和送达机制(因为我个人对移动客户端的经验积累的比较丰富嘛)。
JackJiang
2018/08/29
2.6K0
springboot mybatis 后台框架平台模块设计方案
2.流程管理    :导入导出流程资源文件、查看流程图、根据流程实例反射出流程模型、激活挂起 、自由跳转
FHAdmin
2021/10/18
5880
基于Netty,从零开发IM(三):编码实践篇(群聊功能)
本文由作者“大白菜”分享,有较多修订和改动。注意:本系列是给IM初学者的文章,IM老油条们还望海涵,勿喷!
JackJiang
2022/07/18
4670
基于Netty,从零开发IM(三):编码实践篇(群聊功能)
推荐阅读
相关推荐
百度公共IM系统的Andriod端IM SDK组件架构设计与技术实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档