You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中无需手动转换将多字段结构体写入Excel?

Rust 中无需手动转换结构体即可写入 Excel 的方案

方案1:rust_xlsxwriter 结合 serde 自动处理转换

rust_xlsxwriter 本身没有原生支持结构体直接写入,但可以借助 serde 的序列化能力,自动提取结构体字段和值,避免手动逐个转换。

示例代码:

use rust_xlsxwriter::{Workbook, Worksheet, Format};
use serde::Serialize;
use serde_json::Value;

#[derive(Serialize)]
struct User {
    id: u32,
    name: String,
    email: String,
    age: u8,
    // 可添加任意数量字段
}

// 将结构体转为值列表
fn struct_to_values<T: Serialize>(item: &T) -> Vec<Value> {
    let json = serde_json::to_value(item).unwrap();
    if let Value::Object(obj) = json {
        obj.into_values().collect()
    } else {
        Vec::new()
    }
}

// 获取结构体字段名作为表头
fn get_struct_fields<T: Serialize>() -> Vec<String> {
    let dummy = std::mem::MaybeUninit::<T>::uninit();
    let json = serde_json::to_value(unsafe { dummy.assume_init_ref() }).unwrap();
    if let Value::Object(obj) = json {
        obj.keys().cloned().collect()
    } else {
        Vec::new()
    }
}

fn main() {
    let mut workbook = Workbook::new();
    let mut worksheet = workbook.add_worksheet();
    
    // 准备测试数据
    let users = vec![
        User { id: 1, name: "Alice".into(), email: "alice@example.com".into(), age: 30 },
        User { id: 2, name: "Bob".into(), email: "bob@example.com".into(), age: 25 },
    ];
    
    // 写入表头
    let headers = get_struct_fields::<User>();
    for (col, header) in headers.iter().enumerate() {
        worksheet.write(0, col as u16, header).unwrap();
    }
    
    // 写入行数据
    for (row_idx, user) in users.iter().enumerate() {
        let values = struct_to_values(user);
        for (col_idx, value) in values.iter().enumerate() {
            match value {
                Value::Number(n) => {
                    if let Some(u) = n.as_u64() {
                        worksheet.write(row_idx as u16 +1, col_idx as u16, u).unwrap();
                    } else if let Some(f) = n.as_f64() {
                        worksheet.write(row_idx as u16 +1, col_idx as u16, f).unwrap();
                    }
                }
                Value::String(s) => worksheet.write(row_idx as u16 +1, col_idx as u16, s).unwrap(),
                Value::Bool(b) => worksheet.write(row_idx as u16 +1, col_idx as u16, b).unwrap(),
                _ => {}
            }
        }
    }
    
    workbook.save("users.xlsx").unwrap();
}

方案2:正确使用 Polars 转换结构体

你之前的 Polars 操作大概率是依赖特性没加全,或者转换方法用错了。Polars 支持通过 serde 直接将结构体集合转为 DataFrame,再写入 Excel。

示例代码:

use polars::prelude::*;
use serde::Serialize;

#[derive(Debug, Clone, Serialize)]
struct Product {
    id: u32,
    name: String,
    price: f64,
    in_stock: bool,
}

fn main() {
    let products = vec![
        Product { id: 1, name: "Laptop".into(), price: 999.99, in_stock: true },
        Product { id: 2, name: "Mouse".into(), price: 25.50, in_stock: false },
    ];
    
    // 结构体 Vec 转 DataFrame
    let df = DataFrame::from_iter(products).unwrap();
    
    // 写入 Excel
    df.write_excel("products.xlsx").unwrap();
}

需要在 Cargo.toml 中添加带 excel 特性的 Polars 依赖:

polars = { version = "0.35", features = ["serde", "excel", "lazy"] }

方案3:用 excel-writer 直接映射结构体

excel-writer 提供了自定义派生宏,可直接将结构体转为 Excel 行,还支持自定义表头名称,完全无需手动转换。

示例代码:

use excel_writer::{ExcelWriter, StructExcel};

#[derive(Debug, StructExcel)]
struct Order {
    #[excel(header = "订单ID")]
    order_id: u64,
    #[excel(header = "客户名称")]
    customer_name: String,
    #[excel(header = "订单金额")]
    amount: f64,
    #[excel(header = "是否完成")]
    is_completed: bool,
}

fn main() {
    let orders = vec![
        Order { order_id: 1001, customer_name: "张三".into(), amount: 150.0, is_completed: true },
        Order { order_id: 1002, customer_name: "李四".into(), amount: 200.5, is_completed: false },
    ];
    
    let mut writer = ExcelWriter::new();
    writer.add_sheet("订单数据", &orders).unwrap();
    writer.save("orders.xlsx").unwrap();
}

内容的提问来源于stack exchange,提问作者Mikhail Subbotin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:06:16