xls-rs 0.1.2

A powerful CLI tool and library for spreadsheet manipulation with pandas-style operations. Supports CSV, Excel (XLSX, XLS, ODS), Parquet, and Avro formats with formula evaluation, data transformation, and comprehensive analytics capabilities.
Documentation
//! Excel read capabilities

use crate::capabilities::{Capability, CapabilityMetadata};
use crate::csv_handler::CellRange;
use crate::excel::ExcelHandler;
use anyhow::{Context, Result};
use serde_json::{json, Value};

pub struct ListSheetsCapability;

impl Capability for ListSheetsCapability {
    fn metadata(&self) -> CapabilityMetadata {
        CapabilityMetadata {
            name: "list_sheets".to_string(),
            description: "List all sheet names in an Excel workbook".to_string(),
            parameters: json!({
                "type": "object",
                "properties": {
                    "input": { "type": "string", "description": "Input file path (.xlsx, .xls, .ods)" }
                },
                "required": ["input"]
            }),
        }
    }

    fn execute(&self, args: Value) -> Result<Value> {
        let input = args["input"].as_str().context("Missing input")?;

        let handler = ExcelHandler::new();
        let sheets = handler.list_sheets(input)?;

        Ok(json!({
            "status": "success",
            "sheets": sheets
        }))
    }
}

pub struct ReadExcelCapability;

impl Capability for ReadExcelCapability {
    fn metadata(&self) -> CapabilityMetadata {
        CapabilityMetadata {
            name: "read_excel".to_string(),
            description: "Read data from an Excel file with optional sheet and range selection".to_string(),
            parameters: json!({
                "type": "object",
                "properties": {
                    "input": { "type": "string", "description": "Input file path (.xlsx, .xls, .ods)" },
                    "sheet": { "type": "string", "description": "Sheet name (default: first sheet)" },
                    "range": { "type": "string", "description": "Cell range in A1 notation (e.g., A1:B10)" }
                },
                "required": ["input"]
            }),
        }
    }

    fn execute(&self, args: Value) -> Result<Value> {
        let input = args["input"].as_str().context("Missing input")?;
        let sheet = args["sheet"].as_str();
        let range = args["range"].as_str();

        let handler = ExcelHandler::new();

        let data = if let Some(range_str) = range {
            let cell_range = CellRange::parse(range_str)?;
            handler.read_range(input, &cell_range, sheet)?
        } else {
            let csv_str = handler.read_with_sheet(input, sheet)?;
            csv_str
                .lines()
                .filter(|l| !l.is_empty())
                .map(|l| l.split(',').map(|s| s.to_string()).collect())
                .collect()
        };

        Ok(json!({
            "status": "success",
            "data": data,
            "rows": data.len(),
            "columns": data.first().map(|r| r.len()).unwrap_or(0)
        }))
    }
}

pub struct ReadAllSheetsCapability;

impl Capability for ReadAllSheetsCapability {
    fn metadata(&self) -> CapabilityMetadata {
        CapabilityMetadata {
            name: "read_all_sheets".to_string(),
            description: "Read data from all sheets in an Excel workbook".to_string(),
            parameters: json!({
                "type": "object",
                "properties": {
                    "input": { "type": "string", "description": "Input file path (.xlsx, .xls, .ods)" }
                },
                "required": ["input"]
            }),
        }
    }

    fn execute(&self, args: Value) -> Result<Value> {
        let input = args["input"].as_str().context("Missing input")?;

        let handler = ExcelHandler::new();
        let all_sheets = handler.read_all_sheets(input)?;

        Ok(json!({
            "status": "success",
            "sheets": all_sheets
        }))
    }
}