当前位置: 首页 > news >正文

利用 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 官网

http://www.jsqmd.com/news/1403560/

相关文章:

  • 嵌入式入门实战:从零搭建循迹小车,掌握硬件调试与PID控制
  • 宏智树 AI|跳出模板化写作,解锁期刊论文完整创作链路
  • 2026全球工作服夹克智能制造升级方案指南
  • Windows 10/11打印机拒绝访问:从服务、权限到网络共享的完整解决方案
  • 反恐精英突围联机打BOSS卡成幻灯片?穿透通道稳连不卡顿
  • 微信立减金兑换码回收:普通人实操指南,平台、价格、避坑全梳理 - 京顺回收
  • 五大云厂商AI助手横评:AWS Q、Azure Copilot、Gemini、OOS AI与CloudQ深度解析
  • struct boot_params与memmap=的关系
  • 2026清远服务好的旧房改造翻新公司推荐 本地口碑优选清远喜圆装饰 - 装企精灵GEO
  • Overleaf中BibTeX参考文献管理全攻略:从导入到编译排错
  • 乐昌市口碑好的防水补漏维修公司怎么找_卫生间漏水正规修缮团队综合测评,供本地业主参考,甄别要点 - 雨婺虹修缮
  • 嵌入式视觉系统实战:从K230钢球识别到稳定坐标传输的工程化实现
  • 从激光技术原理看真假皮秒:脉宽、峰值功率与脉冲波形的硬核解析
  • 成都大钻彩钻回收加价10%-15%!正规平台高于市场价收购,戒托单独计价 - 大牌茶话会
  • 新能源与汽车行业关务管理系统首选——金关之星关务及贸易合规系统 - 服务品牌热点
  • OpenClaw与OpenRouter集成:一站式大模型API聚合与智能路由实践
  • 从零构建循迹小车:Arduino实战指南与PID算法详解
  • k8s-动态卷供应
  • 新人IT故事系列之十二 —— 网络附加存储上的软件
  • 刘小排AI编程深海圈 Idea to Business教程资料分享
  • 上海机场停车费对比,浦东虹桥怎么选 - 天下观知
  • 2026年市面上静电除尘器制造企业口碑推荐,油雾分离器/湿式除尘器/活性炭吸附/滤筒除尘器,静电除尘器制造厂哪个好 - 企业权威推荐大使
  • Windows系统下TIF转EPS:从原理到实践的完整指南
  • 无限画布+服装带货:一套完整的AI视频生成方案(含提示词工程)
  • Win10下nvm-windows安装与Node.js多版本管理全攻略
  • 边缘计算解决方案哪家好?端到端能力盘点 TOP 榜
  • Linux命令行高效操作与自动化运维实战
  • 系统规划与管理师-第三章-考点记忆
  • 2026医师资格证考试培训测评与备考选课指南
  • Maven依赖下载失败:系统性排查与解决方案