Excel 导入
简介
背景
在数据处理和分析的过程中,读取和解析 Excel 文件是常见的需求。Java 开发中,有许多库可以帮助我们实现这一需求。本文将介绍如何使用 Alibaba 的 EasyExcel 库读取 Excel 文件,并将内容转换为自定义的数据结构。
我们将通过一个具体的例子,演示如何读取 Excel 文件中的数据,并将其转换为 TableInput
对象。
依赖项
首先,需要在项目中引入 api-table
和 EasyExcel
的依赖项:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.10</version>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>api-table</artifactId>
<version>${api-table.version}</version>
</dependency>
需要注意的是,EasyExcel 会引入 Apache POI 的依赖,这可能会增加项目的打包体积。
异步导入
示例
以下是一个完整的代码示例,演示如何读取 Excel 文件并处理其内容:
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;
import org.junit.Test;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.litongjava.table.model.TableInput;
import com.litongjava.tio.utils.hutool.FileUtil;
import com.litongjava.tio.utils.hutool.ResourceUtil;
import com.litongjava.tio.utils.json.FastJson2Utils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ReadExcelTest {
@Test
public void readExcel() {
// 获取 Excel 文件的 URL
URL resource = ResourceUtil.getResource("tio_boot_admin_system_article-2024_7_10 12_29_08.xlsx");
// 读取 Excel 文件的字节内容
byte[] bytes = FileUtil.readUrlAsBytes(resource);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
// 定义 Excel 解析监听器
AnalysisEventListener<Map<Integer, Object>> readListener = new AnalysisEventListener<Map<Integer, Object>>() {
private Map<Integer, String> headMap = null;
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 全部解析完成后的处理
}
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
// 处理表头数据
String json = FastJson2Utils.toJson(headMap);
log.info("json:{}", json);
this.headMap = headMap;
}
@Override
public void invoke(Map<Integer, Object> data, AnalysisContext context) {
// 处理每一行数据
String json = FastJson2Utils.toJson(data);
log.info("json:{}", json);
TableInput ti = TableInput.create();
for (Entry<Integer, Object> e : data.entrySet()) {
String keyName = headMap.get(e.getKey());
Object value = e.getValue();
ti.set(keyName, value);
}
json = FastJson2Utils.toJson(ti);
log.info("json:{}", json);
}
};
// 构建 Excel 读取器
ExcelReaderBuilder readBuilder = EasyExcel.read(byteArrayInputStream, readListener);
readBuilder.doReadAll();
}
}
表头数据示例
在 invokeHeadMap
方法中,解析并打印了表头数据,示例如下:
{
"0": "id",
"1": "orders",
"2": "title",
"3": "content",
"4": "category_id",
"5": "summary",
"6": "locale",
"7": "status",
"8": "files",
"9": "remark",
"10": "creator",
"11": "create_time",
"12": "updater",
"13": "update_time",
"14": "deleted",
"15": "tenant_id"
}
行数据示例
在 invoke
方法中,处理并打印了每一行数据,示例如下:
{
"1": "1",
"2": "测试展示youtube视频",
"3": "",
"4": "400537606909092000",
"6": "zh_cn",
"7": "1",
"8": "[{\"uid\":\"1720576961389\",\"size\":3103640,\"name\":\"image.png\",\"id\":\"400560112936251392\",\"type\":\"image/png\",\"url\":\"https://sejie.s3.us-west-1.amazonaws.com/default/400560065427369984.png\",\"status\":\"done\"}]"
}
TableInput
数据示例
最终转换后的 TableInput
对象数据如下:然后您可以使用 ApiTable 的 Save 方法将 TableInput
存入数据库中。
{
"title": "测试展示youtube视频",
"locale": "zh_cn",
"content": "",
"category_id": "400537606909092000",
"files": "[{\"uid\":\"1720576961389\",\"size\":3103640,\"name\":\"image.png\",\"id\":\"400560112936251392\",\"type\":\"image/png\",\"url\":\"https://sejie.s3.us-west-1.amazonaws.com/default/400560065427369984.png\",\"status\":\"done\"}]",
"orders": "1",
"status": "1"
}
通过上述代码和示例,您可以了解到如何使用 EasyExcel 读取 Excel 文件,并将其内容转换为自定义的数据结构 TableInput
。这种方式可以方便地进行数据处理和分析,适用于各种应用场景。
同步导入
使用 doReadAllSync
方法同步导入
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.litongjava.tio.utils.hutool.FileUtil;
import com.litongjava.tio.utils.hutool.ResourceUtil;
import com.litongjava.tio.utils.json.JsonUtils;
public class ReadExcelDoReadAllSyncTest {
@Test
public void doReadAllSync() {
// 获取 Excel 文件的 URL
URL resource = ResourceUtil.getResource("tio_boot_admin_system_article-2024_7_10 12_29_08.xlsx");
// 读取 Excel 文件的字节内容
byte[] bytes = FileUtil.readUrlAsBytes(resource);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
// 构建 Excel 读取器
ExcelReaderBuilder readBuilder = EasyExcel.read(byteArrayInputStream);
// 同步读取数据
List<Map<String, Object>> tableInputList = readBuilder.doReadAllSync();
System.out.println(tableInputList.size());
System.out.println(JsonUtils.toJson(tableInputList));
}
}
注意:使用 doReadAllSync
导入后返回的 List<Map>
中的 map
的键是 0,1,2,3,4
的形式,您需要在使用前对其进行处理。
{ "0": "400637631022534660", "1": "1", "2": "其他数据" }
使用自定义 Excel 解析监听器读取数据
package com.sejie.service;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.junit.Test;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.litongjava.tio.utils.hutool.FileUtil;
import com.litongjava.tio.utils.hutool.ResourceUtil;
import com.litongjava.tio.utils.json.JsonUtils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ReadExcelSyncTest {
@Test
public void readExcelSync() {
// 获取 Excel 文件的 URL
URL resource = ResourceUtil.getResource("tio_boot_admin_system_article-2024_7_10 12_29_08.xlsx");
// 读取 Excel 文件的字节内容
byte[] bytes = FileUtil.readUrlAsBytes(resource);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
// 读取数据
List<Map<String, Object>> tableInputList = doReadAllSync(byteArrayInputStream);
System.out.println(tableInputList.size());
System.out.println(JsonUtils.toJson(tableInputList));
}
private List<Map<String, Object>> doReadAllSync(InputStream inputStream) {
// 存放
解析后的所有数据
List<Map<String, Object>> tableInputList = new ArrayList<>();
// 定义 Excel 解析监听器
AnalysisEventListener<Map<Integer, Object>> readListener = new AnalysisEventListener<Map<Integer, Object>>() {
private Map<Integer, String> headMap = null;
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 全部解析完成后的处理
log.info("所有数据解析完成,总共 {} 行数据", tableInputList.size());
}
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
// 处理表头数据
this.headMap = headMap;
}
@Override
public void invoke(Map<Integer, Object> data, AnalysisContext context) {
// 处理每一行数据并转换为 TableInput 对象
Map<String, Object> map = new HashMap<>();
for (Entry<Integer, Object> e : data.entrySet()) {
map.put(headMap.get(e.getKey()), e.getValue());
}
tableInputList.add(map);
}
};
// 构建 Excel 读取器
ExcelReaderBuilder readBuilder = EasyExcel.read(inputStream, readListener);
readBuilder.doReadAll();
return tableInputList;
}
}
通过上述代码示例,您可以了解如何使用自定义的 Excel 解析监听器同步读取 Excel 数据,并将其转换为所需的格式。这个方法适用于对数据有特殊处理需求的场景。