#xlsx #excel #xml

excel_reader

An Excel reader in pure rust

7 releases

new 0.1.6 Apr 18, 2025
0.1.5 Apr 18, 2025

#807 in Parser implementations

Download history 502/week @ 2025-04-12

502 downloads per month

Custom license

1MB
15K SLoC

Excel Reader (Rust)

An Excel reader in pure Rust.

Crate.io

Capabilities

Excel Reader is a pure Rust library to read and parse xlsx files.

You can use this library to get

  • An overview of Sheets in the workbook
  • Detail information on worksheets including dimension, merged cells, tables, and some other properties
  • Cell values, formatting, and styles including hyperlink, border, fill, font, alignment and etc.

If the processed information above does not meet your needs, you can also get the raw version (parsed xml in Rust structures) directly for the following elements.

  • Workbook and Worksheet Relationships
  • Stylesheet
  • Workbook
  • Sharedstrings
  • Theme
  • Worksheet
  • Tables

Installation

Run the following Cargo command in the project directory:

cargo add excel_reader

Or add the following line to Cargo.toml:

excel_reader = "0.1.4"

Examples

Basic Usage

Initialization

To create an Excel structure, a representation of the zipped excel file and is what use to retireve further information, we can either provide a path, or a reader that implements Read and Seek.

let path = "examples/sample.xlsx";

// excel from a reader
let reader = BufReader::new(File::open(path)?);
let mut archive = ZipArchive::new(reader)?;
let mut excel = Excel::from_path(path)?;

// excel directly from path
let mut excel = Excel::from_path(path)?;

Usage

Here is how we can get sheets within the workbook, worksheet details, and cell information (value, format, and styles).

// get basic sheet info
let sheets = excel.get_sheets()?;
if sheets.is_empty() {
    println!("Excel contains no sheets");
    return Ok(());
}
println!("sheets: ");
for sheet in sheets.clone() {
    println!("--------");
    println!("id: {}", sheet.sheet_id);
    println!("name: {}", sheet.name);
    println!("type: {:?}", sheet.r#type);
    println!("visiblity: {:?}", sheet.visible_state);
}
println!("--------");
println!("--------");

// get worksheet detail
let mut worksheet = excel.get_worksheet(&sheets[2].clone())?;
println!("worksheet: {}", worksheet.name);
println!("dimension: {:?}", worksheet.dimension);
println!(
    "Use 1904 backward compatibility date system: {:?}",
    worksheet.is_1904
);
println!(
    "Calculation reference: {:?}",
    worksheet.calculation_reference_mode
);
if !worksheet.clone().merged_cells.is_empty() {
    println!("merged cells: ");
    for (index, merged_cell) in worksheet.clone().merged_cells.iter().enumerate() {
        println!("{}: {:?}", index + 1, merged_cell);
    }
}
if !worksheet.clone().tables.is_empty() {
    println!("tables: ");
    for (index, table) in worksheet.clone().tables.iter().enumerate() {
        println!("--------");
        println!("{}: {:?}", index + 1, table.display_name);
        println!("dimension: {:?}", table.dimension);
        println!("columns: {:?}", table.columns);
        println!("table style: {:?}", table.table_style.name);
    }
    println!("--------");
}

// get cells (value and style) in a worksheet
let Some(dimension) = worksheet.dimension else {
    println!("No cells available in worksheet");
    return Ok(());
};

let (start, end) = (dimension.start, dimension.end);
let mut row_index = start.row;

println!("Cells: ");

while row_index <= end.row {
    let mut col_index = start.col;
    while col_index <= end.col {
        let cell = worksheet.get_cell(Coordinate::from_point((row_index, col_index)))?;
        println!("--------");
        println!("coordinate: {:?}", cell.coordinate);
        println!("value {:?}.", cell.value);
        if let CellValueType::Numeric(_) = cell.value {
            println!(
                "Numeric format: {:?}",
                cell.property.numbering_format.format_code
            )
        }
        let properties = cell.property;

        println!("size: {} * {}", properties.width, properties.height);
        println!("hidden : {:?}", properties.hidden);
        println!("show_phonetic : {:?}", properties.show_phonetic);
        println!("hyperlink : {:?}", properties.hyperlink);
        println!("font : {:?}", properties.font);
        println!("border : {:?}", properties.border);
        println!("fill : {:?}", properties.fill);
        println!("alignment : {:?}", properties.alignment);
        col_index += 1;
    }
    row_index += 1;
}

Getting Raw (Parsed XML)

If you want to write the processing logic to determine the style/format/value by yourself, there is also a list of functions provided to get the raw structures.

  • no additional processing is done, XML to Rust Structure and that's it!
use excel_reader::excel::Excel;

/// Demo for getting raw rust structure directly parsed from XML
///
/// No additional processing done in addition to parsing.
fn main() -> anyhow::Result<()> {
    let path = "examples/sample.xlsx";
    let mut excel = Excel::from_path(path)?;

    // Get stylesheet parsed from xl/styles.xml
    let _stylesheet = excel.get_raw_stylesheet()?;

    // Get theme used parsed from get stylesheet parsed from xl/theme/theme{}.xml
    let _theme = excel.get_raw_theme()?;

    // Get shared string parsed from xl/sharedStrings.xml
    let _shared_strings = excel.get_raw_shared_strings()?;

    // Get workbook relationships
    let _workbook_relationships = excel.get_raw_workbook_relationship();

    // Get workbook parsed from xl/workbook.xml
    let _workbook = excel.get_raw_workbook()?;

    // Get a specific worksheet parsed from xl/worksheets/sheet{}.xml
    // `get_raw_worksheet_with_sheet_id` function or `get_raw_worksheet` function is also available.
    let _worksheet = excel.get_raw_worksheet_with_sheet_id(&1)?;

    // Get all tables defined in a worksheet parsed from xl/tables/table{}.xml, ..., xl/tables/table{n}.xml
    // `get_raw_tables_for_worksheet_with_name` function or `get_raw_tables_for_worksheet` function is also available
    let _tables = excel.get_raw_tables_for_worksheet_with_sheet_id(&1)?;

    // Get sheet relationships
    // `get_raw_sheet_relationship_with_name` function or `get_raw_sheet_relationship` function is also available
    // NOTE: if the sheet does not link with any target package or external resource, xl/worksheets/_rels/sheet{}.xml.rels might not exist.
    let _sheet_relationships = excel.get_raw_sheet_relationship_with_sheet_id(&1)?;

    Ok(())
}

Dependencies

~15MB
~318K SLoC