利用 easyexcel 读取 excel 转换字符串的代码实现

一、引入 easyexcel 依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>${easyexcel.version}</version>
</dependency>

二、核心代码

public String readExcel(MultipartFile file) throws IOException {
        // 创建 StringBuilder
        StringBuilder stringBuilder = new StringBuilder("原始的excel数据\n");

        // 获取文件字节数组
        byte[] fileBytes = file.getBytes();

        // 创建 Excel 读取器
        // ByteInputSream(byte[] buf) -> 从字节数组创建一个内存输入流
        // EasyExcel.raed(InputStream inputStream) -> ExcelReaderBuilder 对象
        // .build() -> 来自 ExcelReaderBuilder类,返回值为 ExcelReader 对象
        ExcelReader excelReader = EasyExcel.read(new ByteArrayInputStream(fileBytes)).build();
        // .excelExecutor() -> 来自于 ExcelReader 执行器对象,获取执行器对象,用于执行各种操作, 返回 ExcelExecutor 对象
        // .sheetList() -> 来自于 ExcelExecutor 类,读取 Excel 文件中所有工作表的元数据,放回值为 List<ReadSheet>
        List<ReadSheet> readSheets = excelReader.excelExecutor().sheetList();

        // 遍历每一个 sheet
        for(ReadSheet readSheet : readSheets) {
            // .getSheetNo() 方法 -> 来自 ReadSheet 类
            // 获取当前工作表的序号(索引)
            int sheetNo = readSheet.getSheetNo();

            // 创建行数据容器
            List<List<String>> sheetRows = new ArrayList<>();

            // new ByteArrayInputStream(fileBytes) -> 再次创建内存输出流, 指定要处理的数据
            // Map<Integer, String> 指定每行数据的类型,这次用 Map, 键是列索引(Integer), 值是单元格内容(String)
            // new ReadListener<Map<Integer, String>>() {...}  -> 匿名内部类写法, ReadListener是 EasyExcel 的读取监听器接口, 定义如何处理每一行数据(通过 ReadListener 监听器)
            EasyExcel.read(new ByteArrayInputStream(fileBytes), new ReadListener<Map<Integer, String>>() {
                // 重写 invoke 方法
                // invoke 方法来自 ReadListener 接口 -> 每读取一行数据就会自动回调此方法
                // 参数1data: 当前行的数据, Map<Integer, String> 类型
                // 参数2analysisContext: 分析上下文
                @Override
                public void invoke(Map<Integer, String> data, AnalysisContext context) {
                    // 创建当前行的列数据容器
                    List<String> rowData = new ArrayList<>();
                    // 这行代码的作用是找出当前行最大的列列索引,如果没有任何列(空行)则返回-1
                    // data.KeySet() -> 来自 Map 接口,获取 Map 中所有键的集合, 返回值 Set<Integer>,所有列索引的集合
                    // .stream() -> 来自 Collection 接口,将集合转换为 Stream 流,用于函数式操作,返回值为 Stream<Integer> 流对象
                    // .mapToInt(Integer::intValue) -> 来自 Stream 接口,将 Stream 中的所有元素映射为 int 基本类型, 返回值为 IntStream 整数流
                    // .max() -> 来自 IntStream 接口,获取流中的最大值, 返回值为 OptionalInt, 可能包含最大值,也可能为空(如果流为空)
                    // .orElse(-1) -> 来时 OptionalInt 类, 如果 OptionalInt 有值则返回该值, 否则返回默认值
                    int maxColumnIndex = data.keySet().stream().mapToInt(Integer::intValue).max().orElse(-1);
                    for(int i = 0; i <= maxColumnIndex; i++) {
                        // value 为单元格值或空字符串
                        String value = data.getOrDefault(i, "");
                        // trim() -> 来自 String 类,去除字符串首尾的空白字符
                        rowData.add(value.trim());
                    }
                    sheetRows.add(rowData);
                }

                // 重写 doAfterAllAnalysed 方法
                // doAfterAllAnalysed 方法,来自 ReadListener 接口, 将所有行读取完毕后自动回调次方法
                // 参数 AnalysisContext 分析上下文
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {

                }
            // .sheet(sheetNo) -> 来自 ExcelReaderBuilder 类,指定要读取的 sheet(按序号),返回值为  ExcelReaderBuilder自身
            // .headRowNumber(0) -> 来自 ExcelReaderBuilder 类,设置表头函数, 参数0表示不跳过任何行,从第一行开始读取,ExcelReaderBuilder(自身)
            // .doRead() -> 来自 ExcelReaderBUilder 类,真正开始执行读取操作, 会触发 invoke 方法逐行回调
            }).sheet(sheetNo).headRowNumber(0).doRead();

            // 拼接 Sheet 标题
            stringBuilder.append("\n==sheet: ").append(readSheet.getSheetName())
                    .append("(第").append(sheetNo + 1).append("个工作表)==\n");

            for(List<String> row : sheetRows) {
                for(int i = 0; i < row.size(); i++) {
                    if(i > 0) {
                        stringBuilder.append("|");
                    }
                    stringBuilder.append(row.get(i));
                }
                stringBuilder.append("\n");
            }
        }
        return stringBuilder.toString();
    }

三、测试

package com.linzhixin.test;

import com.linzhixin.service.ChatService;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

public class ChatServiceTest {
    private ChatService chatService = new ChatService();

    @Test
    public void testReadExcel() throws IOException {
        String path = "D:\\浏览器下载\\chat2excel-master\\excel数据\\国家GDP.xlsx";

        // 创建 File 对象
        File excelFile = new File(path);
        // 读取文件为字节数组
        byte[] excelBytes = Files.readAllBytes(excelFile.toPath());
        // 创建 MultipartFile 对象
        // MockMultipartFile -> Spring 测试工具类,用于模拟文件上传对象
        // 第一个参数:excelFile.getName -> 文件名参数表
        // 第二个参数:excelFile.getName -> 原始文件名
        // 第三个参数:application/vnd.openxmlformats-officedocument.spreadshhettml.sheet" -> 文件 MIME 类型
        // 第四个参数:excelBytes -> 文件字节内容
        MultipartFile file = new MockMultipartFile(
                excelFile.getName(),
                excelFile.getName(),
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                excelBytes
        );

        //执行并打印结果
        System.out.println(chatService.readExcel(file));
    }
}

五、参考文档链接

读Excel | Easy Excel 官网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值