Excel / CSV
Feature: excel | 依赖: calamine, rust_xlsxwriter, csv
简介
表格文件读写工具。支持读取 .xlsx / .xls / .xlsb / .ods / .csv,写入 .xlsx / .csv。
无需实例化,Excel 为静态工具结构体,所有方法均可直接调用。
自动识别:read_path 根据文件扩展名自动选择解析器(.csv → CSV,其他 → Excel)。
单 Sheet:当前所有 API 操作单个工作表。Excel 可通过 sheet 参数选择 sheet,CSV 无 sheet 概念。
大文件:当前 Excel API 全量加载到内存。超大文件请使用 RowReader / RowWriter 流式 API。
依赖配置
[dependencies]
afaster = { version = "0.0.6", features = ["excel"] }
读取 API
read_path — 自动识别格式读取
根据文件扩展名自动选择解析器:
#![allow(unused)]
fn main() {
use afaster::Excel;
// .csv → CSV 解析器;.xlsx → Excel 解析器
let data = Excel::read_path("data.csv", None)?;
let data = Excel::read_path("data.xlsx", None)?;
let data = Excel::read_path("data.xlsx", Some("Sheet1"))?; // Excel 指定 sheet
// 返回 Vec<Vec<CellValue>>
}
read_bytes — 从字节数据读取
适合 HTTP 上传、数据库 BLOB 等场景:
#![allow(unused)]
fn main() {
let bytes = reqwest::get(url).await?.bytes().await?;
let data = Excel::read_bytes(&bytes, None)?;
}
read_bytes_as — 指定或自动检测格式
#![allow(unused)]
fn main() {
use afaster::Format;
let data = Excel::read_bytes_as(&bytes, Some(Format::Csv), None)?; // 强制 CSV
let data = Excel::read_bytes_as(&bytes, Some(Format::Xlsx), None)?; // 强制 Excel
let data = Excel::read_bytes_as(&bytes, None, None)?; // 自动检测
}
read_all — 读取所有工作表
#![allow(unused)]
fn main() {
let sheets = Excel::read_all("multi.xlsx")?;
// CSV 返回单个 sheet,key 为 "Sheet1"
let sheets = Excel::read_all("data.csv")?;
for (name, rows) in &sheets {
println!("📄 {}: {} 行", name, rows.len());
}
}
read_skip — 跳过前 N 行
#![allow(unused)]
fn main() {
let data = Excel::read_skip("data.xlsx", None, 2)?; // 跳过前 2 行
}
read_with_headers — 第一行作为表头
#![allow(unused)]
fn main() {
let (headers, rows) = Excel::read_with_headers("data.csv", None)?;
println!("表头: {:?}", headers);
}
read_to_json — 读取为 JSON 数组
#![allow(unused)]
fn main() {
let json = Excel::read_to_json("users.xlsx", None)?;
for item in &json {
println!("{}", serde_json::to_string(item)?);
}
}
显式格式读取
#![allow(unused)]
fn main() {
// 显式 CSV
let data = Excel::read_csv_path("data.csv")?;
let data = Excel::read_csv_bytes(&csv_bytes)?;
// 显式 Excel
let data = Excel::read_xlsx_path("data.xlsx", Some("Sheet1"))?;
let data = Excel::read_xlsx_bytes(&xlsx_bytes, None)?;
let sheets = Excel::read_xlsx_all("multi.xlsx")?;
}
写入 API
write / write_as — 纯字符串写入
#![allow(unused)]
fn main() {
use afaster::{Excel, Format};
// 默认 XLSX
let bytes = Excel::write(&[&["Name", "Age"], &["Alice", "25"]])?;
// 指定格式
let bytes = Excel::write_as(&[&["Name", "Age"], &["Alice", "25"]], Format::Csv)?;
let bytes = Excel::write_as(&[&["Name", "Age"], &["Alice", "25"]], Format::Xlsx)?;
}
write_typed / write_typed_as — 带类型写入
#![allow(unused)]
fn main() {
use afaster::{Excel, CellValue, Format};
let data = vec![
vec![CellValue::String("Name".into()), CellValue::String("Age".into())],
vec![CellValue::String("Alice".into()), CellValue::Int(25)],
];
// XLSX(保留类型)
let bytes = Excel::write_typed(&data, Some("Users"))?;
// CSV(数字/布尔自动转字符串)
let bytes = Excel::write_typed_as(&data, Format::Csv, None)?;
}
write_with_headers / write_with_headers_as — 带表头写入
#![allow(unused)]
fn main() {
let headers = vec!["Language", "Rating"];
let rows = vec![
vec![CellValue::String("Rust".into()), CellValue::Int(10)],
];
let bytes = Excel::write_with_headers(&headers, &rows, Some("Sheet1"))?;
let bytes = Excel::write_with_headers_as(&headers, &rows, Format::Csv, None)?;
}
write_multi / write_multi_as — 多工作表写入
#![allow(unused)]
fn main() {
let sheets = vec![
("Users", vec![...]),
("Orders", vec![...]),
];
let bytes = Excel::write_multi(&sheets)?; // XLSX 多 sheet
let bytes = Excel::write_multi_as(&sheets, Format::Csv)?; // CSV 仅写第一个 sheet
}
Format 枚举
#![allow(unused)]
fn main() {
use afaster::Format;
Format::Xlsx // Excel .xlsx 格式
Format::Csv // CSV 格式
}
CSV 特性
- 智能类型推断:读取 CSV 时自动将数字解析为
Int/Float,true/false/yes/no/1/0解析为Bool - 单 Sheet:CSV 无 sheet 概念,
read_all返回单个"Sheet1" - 多 Sheet 写入降级:
write_multi_as对 CSV 仅写第一个 sheet - 无格式信息:CSV 中所有类型写入时转为字符串,读取时重新推断
CellValue 类型
| 变体 | 说明 | Excel | CSV 读取时 |
|---|---|---|---|
Empty | 空值 | 空单元格 | 空字段 |
String(String) | 字符串 | 文本 | 无法解析为数字/布尔的文本 |
Float(f64) | 浮点数 | 数字(有小数) | 含小数点的数字 |
Int(i64) | 整数 | 数字(无小数) | 整数 |
Bool(bool) | 布尔值 | TRUE / FALSE | true/false/yes/no/1/0 |
Error(String) | 错误 | #ERR | — |
CellValue 方法
#![allow(unused)]
fn main() {
let cell = CellValue::Int(42);
cell.as_str() // Option<&str> — 仅 String 变体返回 Some
cell.as_f64() // Option<f64> — Float/Int 返回 Some
cell.as_i64() // Option<i64> — Int/Float 返回 Some
cell.as_bool() // Option<bool> — 仅 Bool 变体返回 Some
cell.is_empty() // bool
cell.to_json() // serde_json::Value
cell.to_string() // String(Display trait)
}
完整示例
#![allow(unused)]
fn main() {
use afaster::{Excel, CellValue, Format};
// 自动识别读取 CSV
let (headers, rows) = Excel::read_with_headers("users.csv", None)?;
// 导出为 CSV
let bytes = Excel::write_with_headers_as(
&headers, &rows, Format::Csv, None
)?;
std::fs::write("export.csv", bytes)?;
// 导出为 Excel
let bytes = Excel::write_with_headers_as(
&headers, &rows, Format::Xlsx, Some("Users")
)?;
std::fs::write("export.xlsx", bytes)?;
}
流式 API
大文件场景使用 RowReader(逐行读取)和 RowWriter(逐行写入),避免一次性加载全部数据到内存。
RowReader — 流式读取
CSV 真正逐行流式读取;Excel 内部加载后逐行迭代(calamine 限制)。
#![allow(unused)]
fn main() {
use afaster::RowReader;
// 自动识别格式
let mut reader = RowReader::from_path("large.csv", None)?;
// 提取表头(跳过第一行)
let headers = reader.headers(); // Option<Vec<String>>
// 逐行读取
while let Some(row) = reader.next_row() {
let row = row?; // Vec<CellValue>
println!("{:?}", row);
}
// 或使用 Iterator trait
let reader = RowReader::from_path("data.xlsx", Some("Sheet1"))?;
for row in reader {
let cells = row?;
// ...
}
// 收集剩余行
let mut reader = RowReader::from_csv_path("data.csv")?;
reader.headers(); // 跳过表头
let data_rows = reader.collect_remaining()?;
}
RowReader 构造方法
| 方法 | 说明 |
|---|---|
from_path(path, sheet) | 自动识别格式 |
from_csv_path(path) | CSV 文件流式读取 |
from_csv_bytes(bytes) | CSV 字节流式读取 |
from_xlsx_path(path, sheet) | Excel 文件 |
from_xlsx_bytes(bytes, sheet) | Excel 字节 |
RowReader 方法
| 方法 | 说明 |
|---|---|
headers() | 提取第一行为表头 |
next_row() | 读取下一行 Option<Result<Vec<CellValue>>> |
total_rows() | 总行数(仅 Excel) |
sheet_names() | 工作表名列表(仅 Excel) |
selected_sheet() | 当前工作表名(仅 Excel) |
collect_remaining() | 收集剩余所有行 |
支持 Iterator trait,可直接用于 for 循环。
RowWriter — 流式写入
逐行写入,最后一次性生成输出。
#![allow(unused)]
fn main() {
use afaster::{RowWriter, CellValue, Format};
// 方式 1:内存积累,最后生成字节
let mut writer = RowWriter::new();
writer.write_row_str(&["Name", "Age"])?;
writer.write_row(&[CellValue::String("Alice".into()), CellValue::Int(25)])?;
writer.write_row(&[CellValue::String("Bob".into()), CellValue::Int(30)])?;
let csv_bytes = writer.finish_csv_bytes()?;
let xlsx_bytes = writer.finish_xlsx_bytes(Some("Sheet1"))?;
let bytes = writer.finish_bytes(Format::Csv)?; // 指定格式
// 方式 2:直接写入 CSV 文件(边写边输出,不积累内存)
let mut writer = RowWriter::from_csv_path("output.csv")?;
writer.write_row_str(&["Name", "Age"])?;
writer.write_row(&[CellValue::String("Alice".into()), CellValue::Int(25)])?;
writer.finish()?; // 关闭文件
// 方式 3:保存到文件
let mut writer = RowWriter::new();
writer.write_row_str(&["Name", "Age"])?;
writer.write_row(&[CellValue::String("Alice".into()), CellValue::Int(25)])?;
writer.finish_csv_path("output.csv")?;
writer.finish_xlsx_path("output.xlsx", None)?;
writer.finish_path("output.csv", Format::Csv)?; // 指定格式
}
RowWriter 构造方法
| 方法 | 说明 |
|---|---|
new() | 内存积累模式 |
from_csv_path(path) | 直接写入 CSV 文件(流式输出) |
RowWriter 方法
| 方法 | 说明 |
|---|---|
write_row(&[CellValue]) | 写入一行 |
write_row_str(&[&str]) | 写入一行纯字符串 |
len() / is_empty() | 已写入行数 |
finish() | 关闭文件(仅 from_csv_path 模式) |
finish_csv_bytes() | 生成 CSV 字节 |
finish_xlsx_bytes(sheet) | 生成 Excel 字节 |
finish_bytes(format) | 指定格式生成字节 |
finish_csv_path(path) | 保存 CSV 文件 |
finish_xlsx_path(path, sheet) | 保存 Excel 文件 |
finish_path(path, format) | 指定格式保存文件 |
错误码
| code | 含义 |
|---|---|
| 51601 | 打开 Excel 文件失败(文件不存在、格式错误等) |
| 51602 | 工作表不存在或读取失败 |
| 51603 | 写入 Excel 失败 |
| 51604 | CSV 解析失败 |