Skip to main content

excel_mcp_server/tools/
layout.rs

1use super::common::workbook_not_found;
2use crate::store::WorkbookStore;
3use crate::types::inputs::*;
4use crate::types::responses::*;
5
6pub fn set_column_width(
7    store: &mut WorkbookStore,
8    input: SetColumnWidthInput,
9) -> Result<String, anyhow::Error> {
10    let entry = match store.get_mut(&input.workbook_id) {
11        Some(e) => e,
12        None => return Ok(workbook_not_found(store, &input.workbook_id)),
13    };
14    let idx = match find_sheet(&entry.data, &input.sheet_name) {
15        Some(i) => i,
16        None => return Ok(sheet_err(&input.sheet_name)),
17    };
18    let col =
19        zavora_xlsx::utility::col_from_letter(&input.column).map_err(|e| anyhow::anyhow!("{e}"))?;
20    entry
21        .data
22        .worksheet(idx)
23        .map_err(|e| anyhow::anyhow!("{e}"))?
24        .set_column_width(col, input.width)
25        .map_err(|e| anyhow::anyhow!("{e}"))?;
26    Ok(success_no_data(&format!(
27        "Column {} width set to {}",
28        input.column, input.width
29    )))
30}
31
32pub fn set_row_height(
33    store: &mut WorkbookStore,
34    input: SetRowHeightInput,
35) -> Result<String, anyhow::Error> {
36    let entry = match store.get_mut(&input.workbook_id) {
37        Some(e) => e,
38        None => return Ok(workbook_not_found(store, &input.workbook_id)),
39    };
40    let idx = match find_sheet(&entry.data, &input.sheet_name) {
41        Some(i) => i,
42        None => return Ok(sheet_err(&input.sheet_name)),
43    };
44    let row = input.row.saturating_sub(1); // input is 1-based
45    entry
46        .data
47        .worksheet(idx)
48        .map_err(|e| anyhow::anyhow!("{e}"))?
49        .set_row_height(row, input.height)
50        .map_err(|e| anyhow::anyhow!("{e}"))?;
51    Ok(success_no_data(&format!(
52        "Row {} height set to {}",
53        input.row, input.height
54    )))
55}
56
57pub fn freeze_panes(
58    store: &mut WorkbookStore,
59    input: FreezePanesInput,
60) -> Result<String, anyhow::Error> {
61    let entry = match store.get_mut(&input.workbook_id) {
62        Some(e) => e,
63        None => return Ok(workbook_not_found(store, &input.workbook_id)),
64    };
65    let idx = match find_sheet(&entry.data, &input.sheet_name) {
66        Some(i) => i,
67        None => return Ok(sheet_err(&input.sheet_name)),
68    };
69    let (row, col) =
70        zavora_xlsx::utility::parse_cell_ref(&input.cell).map_err(|e| anyhow::anyhow!("{e}"))?;
71    entry
72        .data
73        .worksheet(idx)
74        .map_err(|e| anyhow::anyhow!("{e}"))?
75        .set_freeze_panes(row, col)
76        .map_err(|e| anyhow::anyhow!("{e}"))?;
77    Ok(success_no_data(&format!("Panes frozen at {}", input.cell)))
78}
79
80fn find_sheet(wb: &zavora_xlsx::Workbook, name: &str) -> Option<usize> {
81    wb.sheet_names().iter().position(|n| *n == name)
82}
83fn sheet_err(name: &str) -> String {
84    error(
85        ErrorCategory::NotFound,
86        &format!("Sheet '{}' not found", name),
87        "Check sheet name.",
88    )
89}