mirror of
https://github.com/haris-musa/excel-mcp-server.git
synced 2025-12-08 17:12:41 +08:00
Merge pull request #46 from haris-musa/feat/excel-table-support-34
Feat: Add create_excel_table function for native table support. Closes #34
This commit is contained in:
23
TOOLS.md
23
TOOLS.md
@ -233,6 +233,29 @@ create_pivot_table(
|
|||||||
- `agg_func`: Aggregation function (sum, count, average, max, min)
|
- `agg_func`: Aggregation function (sum, count, average, max, min)
|
||||||
- Returns: Success message
|
- Returns: Success message
|
||||||
|
|
||||||
|
## Table Operations
|
||||||
|
|
||||||
|
### create_table
|
||||||
|
|
||||||
|
Creates a native Excel table from a specified range of data.
|
||||||
|
|
||||||
|
```python
|
||||||
|
create_table(
|
||||||
|
filepath: str,
|
||||||
|
sheet_name: str,
|
||||||
|
data_range: str,
|
||||||
|
table_name: str = None,
|
||||||
|
table_style: str = "TableStyleMedium9"
|
||||||
|
) -> str
|
||||||
|
```
|
||||||
|
|
||||||
|
- `filepath`: Path to the Excel file.
|
||||||
|
- `sheet_name`: Name of the worksheet.
|
||||||
|
- `data_range`: The cell range for the table (e.g., "A1:D5").
|
||||||
|
- `table_name`: Optional unique name for the table.
|
||||||
|
- `table_style`: Optional visual style for the table.
|
||||||
|
- Returns: Success message.
|
||||||
|
|
||||||
## Worksheet Operations
|
## Worksheet Operations
|
||||||
|
|
||||||
### copy_worksheet
|
### copy_worksheet
|
||||||
|
|||||||
@ -25,6 +25,7 @@ from excel_mcp.chart import create_chart_in_sheet as create_chart_impl
|
|||||||
from excel_mcp.workbook import get_workbook_info
|
from excel_mcp.workbook import get_workbook_info
|
||||||
from excel_mcp.data import write_data
|
from excel_mcp.data import write_data
|
||||||
from excel_mcp.pivot import create_pivot_table as create_pivot_table_impl
|
from excel_mcp.pivot import create_pivot_table as create_pivot_table_impl
|
||||||
|
from excel_mcp.tables import create_excel_table as create_table_impl
|
||||||
from excel_mcp.sheet import (
|
from excel_mcp.sheet import (
|
||||||
copy_sheet,
|
copy_sheet,
|
||||||
delete_sheet,
|
delete_sheet,
|
||||||
@ -350,6 +351,31 @@ def create_pivot_table(
|
|||||||
logger.error(f"Error creating pivot table: {e}")
|
logger.error(f"Error creating pivot table: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def create_table(
|
||||||
|
filepath: str,
|
||||||
|
sheet_name: str,
|
||||||
|
data_range: str,
|
||||||
|
table_name: str = None,
|
||||||
|
table_style: str = "TableStyleMedium9"
|
||||||
|
) -> str:
|
||||||
|
"""Creates a native Excel table from a specified range of data."""
|
||||||
|
try:
|
||||||
|
full_path = get_excel_path(filepath)
|
||||||
|
result = create_table_impl(
|
||||||
|
filepath=full_path,
|
||||||
|
sheet_name=sheet_name,
|
||||||
|
data_range=data_range,
|
||||||
|
table_name=table_name,
|
||||||
|
table_style=table_style
|
||||||
|
)
|
||||||
|
return result["message"]
|
||||||
|
except DataError as e:
|
||||||
|
return f"Error: {str(e)}"
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error creating table: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
def copy_worksheet(
|
def copy_worksheet(
|
||||||
filepath: str,
|
filepath: str,
|
||||||
|
|||||||
69
src/excel_mcp/tables.py
Normal file
69
src/excel_mcp/tables.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import uuid
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from openpyxl import load_workbook
|
||||||
|
from openpyxl.worksheet.table import Table, TableStyleInfo
|
||||||
|
from .exceptions import DataError
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def create_excel_table(
|
||||||
|
filepath: str,
|
||||||
|
sheet_name: str,
|
||||||
|
data_range: str,
|
||||||
|
table_name: str | None = None,
|
||||||
|
table_style: str = "TableStyleMedium9"
|
||||||
|
) -> dict:
|
||||||
|
"""Creates a native Excel table for the given data range.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filepath: Path to the Excel file.
|
||||||
|
sheet_name: Name of the worksheet.
|
||||||
|
data_range: The cell range for the table (e.g., "A1:D5").
|
||||||
|
table_name: A unique name for the table. If not provided, a unique name is generated.
|
||||||
|
table_style: The visual style to apply to the table.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dictionary with a success message and table details.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
wb = load_workbook(filepath)
|
||||||
|
if sheet_name not in wb.sheetnames:
|
||||||
|
raise DataError(f"Sheet '{sheet_name}' not found.")
|
||||||
|
|
||||||
|
ws = wb[sheet_name]
|
||||||
|
|
||||||
|
# If no table name is provided, generate a unique one
|
||||||
|
if not table_name:
|
||||||
|
table_name = f"Table_{uuid.uuid4().hex[:8]}"
|
||||||
|
|
||||||
|
# Check if table name already exists
|
||||||
|
if table_name in ws.parent.defined_names:
|
||||||
|
raise DataError(f"Table name '{table_name}' already exists.")
|
||||||
|
|
||||||
|
# Create the table
|
||||||
|
table = Table(displayName=table_name, ref=data_range)
|
||||||
|
|
||||||
|
# Apply style
|
||||||
|
style = TableStyleInfo(
|
||||||
|
name=table_style,
|
||||||
|
showFirstColumn=False,
|
||||||
|
showLastColumn=False,
|
||||||
|
showRowStripes=True,
|
||||||
|
showColumnStripes=False
|
||||||
|
)
|
||||||
|
table.tableStyleInfo = style
|
||||||
|
|
||||||
|
ws.add_table(table)
|
||||||
|
|
||||||
|
wb.save(filepath)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"message": f"Successfully created table '{table_name}' in sheet '{sheet_name}'.",
|
||||||
|
"table_name": table_name,
|
||||||
|
"range": data_range
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to create table: {e}")
|
||||||
|
raise DataError(str(e))
|
||||||
Reference in New Issue
Block a user