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
//! Formula capabilities

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

pub struct ApplyFormulaCapability;

impl Capability for ApplyFormulaCapability {
    fn metadata(&self) -> CapabilityMetadata {
        CapabilityMetadata {
            name: "apply_formula".to_string(),
            description: "Apply a formula to a cell or range in a spreadsheet".to_string(),
            parameters: json!({
                "type": "object",
                "properties": {
                    "input": { "type": "string", "description": "Input file path" },
                    "output": { "type": "string", "description": "Output file path" },
                    "formula": { "type": "string", "description": "Formula to apply (e.g., '=A1*2' or '=SUM(A1:A10)')" },
                    "cell": { "type": "string", "description": "Target cell (e.g., B1)" },
                    "range": { "type": "string", "description": "Target range (e.g., B1:B10) - if specified, applies formula to each cell in range" },
                    "sheet": { "type": "string", "description": "Sheet name for Excel files" }
                },
                "required": ["input", "output", "formula"]
            }),
        }
    }

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

        if cell.is_none() && range.is_none() {
            return Err(anyhow::anyhow!("Either 'cell' or 'range' must be specified"));
        }

        let evaluator = FormulaEvaluator::new();

        let cells_affected = if let Some(range_str) = range {
            let cell_range = CellRange::parse(range_str).context("Invalid range format")?;
            evaluator.apply_to_range(input, output, formula, &cell_range, sheet)?
        } else {
            let cell_ref = cell.context("Missing cell reference")?;
            evaluator.apply_to_excel(input, output, formula, cell_ref, sheet)?;
            1
        };

        Ok(json!({
            "status": "success",
            "message": format!("Applied formula to {} cell(s)", cells_affected),
            "cells_affected": cells_affected
        }))
    }
}