如何在Rust中高效合并大型XLSX文件并添加附加信息
优化大型Excel文件合并的高效实现方案
针对你目前逐单元格复制导致的效率问题,核心优化方向是避免逐个操作单元格,改成按行批量处理数据,同时满足添加时间戳、来源文件名的需求。以下是调整后的实现:
优化后的代码
use std::path::Path; use chrono::{Local, DateTime}; // 需要在Cargo.toml中添加chrono = "0.4"依赖 pub fn insert_data_from_file( from_file: &Path, to_file: &Path, ) -> Result<(), std::io::Error> { // 获取来源文件名 let file_name = from_file .file_name() .unwrap() .to_owned() .into_string() .unwrap(); // 生成当前时间戳(格式可自定义) let timestamp = Local::now().format("%Y-%m-%d %H:%M:%S").to_string(); // 读取输出文件与输入文件 let mut output_ss = reader::xlsx::read(to_file).unwrap(); let output_ws = output_ss.get_sheet_mut(&0).unwrap(); let input_ss = reader::xlsx::read(from_file).unwrap(); let input_ws = input_ss.get_sheet(&0).unwrap(); // 确定输出表的起始写入行(跳过表头) let (_, output_max_row) = output_ws.get_highest_column_and_row(); let mut current_output_row = if output_max_row == 1 { 2 } else { output_max_row + 1 }; // 遍历输入表的每一行(从第2行开始,跳过表头) for row_idx in 2..=input_ws.get_highest_row() { // 批量读取当前行的所有单元格数据 let row_data: Vec<_> = input_ws.get_row(row_idx) .unwrap() .iter() .map(|cell| cell.get_value().clone()) .collect(); // 构造包含附加信息的新行:原数据 + 来源文件名 + 复制时间戳 let mut new_row = row_data; new_row.push(file_name.clone().into()); new_row.push(timestamp.clone().into()); // 批量写入输出表的当前行 for (col_idx, value) in new_row.iter().enumerate() { let col_pos = (col_idx + 1) as u32; // Excel列索引从1开始 output_ws.get_cell_value_mut((col_pos, current_output_row)) .set_value(value.clone()); } current_output_row += 1; } // 写入最终合并文件 writer::xlsx::write(&output_ss, to_file)?; Ok(()) }
核心优化说明
- 按行批量处理:直接读取整行数据,大幅减少循环次数,避免逐单元格遍历的额外开销
- 简化索引逻辑:直接基于输出表的最大行号定位写入起始位置,省去复杂的索引计数逻辑
- 内存中构造新行:先在内存中组合原数据与附加信息,再统一写入,降低工作表的IO操作次数
- 时间戳标准化:用
chrono库生成可读的时间戳,替代手动处理时间的繁琐逻辑
额外性能建议
- 若输出文件初始为空,建议预先创建带表头的模板文件,避免每次判断表头的额外逻辑
- 针对超大型文件,可考虑分批次读取写入,避免内存占用过高
- 合并多文件时,尽量一次性读取所有输入文件数据后再统一写入输出文件,减少重复读写操作
内容的提问来源于stack exchange,提问作者Syed Kamran
相关产品推荐
相关产品推荐

