Skip to main content
Glama
hyunjae-labs

xlwings Excel MCP Server

by hyunjae-labs

create_chart

Generate charts in Excel worksheets by specifying filepath, sheet name, data range, chart type, and target cell. Customize with titles and axis labels.

Instructions

Create chart in worksheet.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chart_typeYes
data_rangeYes
filepathYes
sheet_nameYes
target_cellYes
titleNo
x_axisNo
y_axisNo

Implementation Reference

  • MCP tool registration for 'create_chart'. Delegates to session-based or legacy filepath-based xlwings implementations.
    @mcp.tool() def create_chart( sheet_name: str, data_range: str, chart_type: str, target_cell: str, session_id: Optional[str] = None, filepath: Optional[str] = None, title: str = "", x_axis: str = "", y_axis: str = "" ) -> str: """ Create chart in worksheet. Args: sheet_name: Name of worksheet data_range: Data range for chart chart_type: Type of chart target_cell: Cell where chart will be placed session_id: Session ID from open_workbook (preferred) filepath: Path to Excel file (legacy, deprecated) title: Chart title (optional) x_axis: X-axis label (optional) y_axis: Y-axis label (optional) Note: Use session_id for better performance. filepath parameter is deprecated. """ try: # Support both new (session_id) and old (filepath) API if session_id: # New API: use session session = SESSION_MANAGER.get_session(session_id) if not session: return ERROR_TEMPLATES['SESSION_NOT_FOUND'].format( session_id=session_id, ttl=10 # Default TTL is 10 minutes (600 seconds) ) with session.lock: from xlwings_mcp.xlwings_impl.advanced_xlw import create_chart_xlw_with_wb result = create_chart_xlw_with_wb( session.workbook, sheet_name=sheet_name, data_range=data_range, chart_type=chart_type, target_cell=target_cell, title=title, x_axis=x_axis, y_axis=y_axis ) elif filepath: # Legacy API: backwards compatibility logger.warning("Using deprecated filepath parameter. Please use session_id instead.") full_path = get_excel_path(filepath) from xlwings_mcp.xlwings_impl.advanced_xlw import create_chart_xlw result = create_chart_xlw( filepath=full_path, sheet_name=sheet_name, data_range=data_range, chart_type=chart_type, target_cell=target_cell, title=title, x_axis=x_axis, y_axis=y_axis ) else: return ERROR_TEMPLATES['PARAMETER_MISSING'].format( param1='session_id', param2='filepath' ) return result.get("message", "Chart created successfully") if "error" not in result else f"Error: {result['error']}" except (ValidationError, ChartError) as e: return f"Error: {str(e)}" except Exception as e: logger.error(f"Error creating chart: {e}") raise
  • Primary handler function for creating charts in an open workbook session using xlwings. Handles chart type mapping, positioning, sizing, titles, and axis labels.
    def create_chart_xlw_with_wb( wb, sheet_name: str, data_range: str, chart_type: str, target_cell: str, title: str = "", x_axis: str = "", y_axis: str = "" ) -> Dict[str, Any]: """Session-based version using existing workbook object. Args: wb: Workbook object from session sheet_name: Name of worksheet data_range: Range of data for chart (e.g., "A1:C10") chart_type: Type of chart (line, bar, pie, scatter, area, column) target_cell: Cell where chart will be positioned title: Chart title x_axis: X-axis label y_axis: Y-axis label Returns: Dict with success message or error """ try: logger.info(f"πŸ“ˆ Creating {chart_type} chart in {sheet_name}") # Check if sheet exists sheet_names = [s.name for s in wb.sheets] if sheet_name not in sheet_names: return {"error": f"Sheet '{sheet_name}' not found"} sheet = wb.sheets[sheet_name] # Map chart types to Excel constants (Microsoft XlChartType enumeration) chart_type_map = { 'column': -4100, # xlColumnClustered 'bar': -4099, # xlBarClustered 'line': 4, # xlLine 'pie': 5, # xlPie 'area': 1, # xlArea 'scatter': -4169, # xlXYScatter 'doughnut': -4120, # xlDoughnut 'radar': -4151, # xlRadarMarkers } if chart_type.lower() not in chart_type_map: available_types = ', '.join(chart_type_map.keys()) return {"error": f"CHART_TYPE_ERROR: '{chart_type}' is not supported. Available types: {available_types}"} excel_chart_type = chart_type_map[chart_type.lower()] # Get data range first data_range_obj = sheet.range(data_range) # Create chart using xlwings method chart = sheet.charts.add() # Set data source chart.set_source_data(data_range_obj) # Set chart type - use xlwings chart_type property or COM API try: # First try xlwings native method (accepts string) if hasattr(chart, 'chart_type'): try: # xlwings accepts the string directly chart.chart_type = chart_type.lower() logger.info(f"Set chart type to {chart_type} using xlwings method") except: # If string doesn't work, try the constant chart.chart_type = excel_chart_type logger.info(f"Set chart type to {chart_type} using constant {excel_chart_type}") else: # Fallback to COM API chart_api = chart.api if hasattr(chart_api, 'ChartType'): chart_api.ChartType = excel_chart_type logger.info(f"Set chart type to {chart_type} via COM API (constant: {excel_chart_type})") else: # Last resort - chart may already have correct type from creation logger.warning(f"Could not explicitly set chart type, using default") except Exception as e: # Non-fatal: log but continue (chart may still work with default type) logger.warning(f"Chart type setting had issues but continuing: {e}") # Set chart position target = sheet.range(target_cell) chart.top = target.top chart.left = target.left # Calculate chart size based on data range data_rows = data_range_obj.rows.count data_cols = data_range_obj.columns.count # Dynamic sizing based on data chart.width = min(600, max(400, data_cols * 80)) # Adjust width based on columns chart.height = min(450, max(300, data_rows * 15)) # Adjust height based on rows # Set chart properties safely try: chart_com = chart.api # Set title if title and hasattr(chart_com, 'HasTitle'): chart_com.HasTitle = True if hasattr(chart_com, 'ChartTitle'): chart_com.ChartTitle.Text = title # Set axis labels if hasattr(chart_com, 'Axes'): try: if x_axis: x_axis_obj = chart_com.Axes(1) # xlCategory x_axis_obj.HasTitle = True x_axis_obj.AxisTitle.Text = x_axis if y_axis: y_axis_obj = chart_com.Axes(2) # xlValue y_axis_obj.HasTitle = True y_axis_obj.AxisTitle.Text = y_axis except Exception as e: logger.warning(f"Axis label setting failed: {e}") except: # Some chart types don't have axes pass # Save the workbook wb.save() logger.info(f"βœ… Successfully created {chart_type} chart") return { "message": f"Successfully created {chart_type} chart", "chart_type": chart_type, "data_range": data_range, "position": target_cell, "sheet": sheet_name } except Exception as e: logger.error(f"❌ Error creating chart: {str(e)}") return {"error": str(e)}
  • Legacy handler that opens workbook from filepath, creates chart using xlwings, then closes.
    def create_chart_xlw( filepath: str, sheet_name: str, data_range: str, chart_type: str, target_cell: str, title: str = "", x_axis: str = "", y_axis: str = "" ) -> Dict[str, Any]: """ Create a chart in Excel using xlwings. Args: filepath: Path to Excel file sheet_name: Name of worksheet data_range: Range of data for chart (e.g., "A1:C10") chart_type: Type of chart (line, bar, pie, scatter, area, column) target_cell: Cell where chart will be positioned title: Chart title x_axis: X-axis label y_axis: Y-axis label Returns: Dict with success message or error """ app = None wb = None # Initialize COM for thread safety (Windows) _com_initialize() try: logger.info(f"Creating {chart_type} chart in {sheet_name}") # Check if file exists if not os.path.exists(filepath): return {"error": f"File not found: {filepath}"} # Open Excel app and workbook app = xw.App(visible=False, add_book=False) wb = app.books.open(filepath) # Check if sheet exists sheet_names = [s.name for s in wb.sheets] if sheet_name not in sheet_names: return {"error": f"Sheet '{sheet_name}' not found"} sheet = wb.sheets[sheet_name] # Map chart types to Excel constants chart_type_map = { 'line': 4, # xlLine 'bar': 57, # xlBarClustered 'column': 51, # xlColumnClustered 'pie': 5, # xlPie 'scatter': 74, # xlXYScatter 'area': 1, # xlArea } if chart_type.lower() not in chart_type_map: return {"error": f"Unsupported chart type: {chart_type}"} excel_chart_type = chart_type_map[chart_type.lower()] # Get data range first data_range_obj = sheet.range(data_range) # Create chart using xlwings method chart = sheet.charts.add() # Set data source chart.set_source_data(data_range_obj) # Set chart type - handle COM API properly try: if hasattr(chart, 'chart_type'): # Use xlwings built-in chart type property chart.chart_type = chart_type.lower() else: # Use COM API more carefully chart_api = chart.api if hasattr(chart_api, 'ChartType'): chart_api.ChartType = excel_chart_type else: logger.warning("Cannot set chart type - using default") except Exception as e: logger.warning(f"Chart type setting failed: {e}, using default") # Set chart position target = sheet.range(target_cell) chart.top = target.top chart.left = target.left # Calculate chart size based on data range data_rows = data_range_obj.rows.count data_cols = data_range_obj.columns.count # Dynamic sizing based on data chart.width = min(600, max(400, data_cols * 80)) # Adjust width based on columns chart.height = min(450, max(300, data_rows * 15)) # Adjust height based on rows # Set chart properties safely try: chart_com = chart.api # Set title if title and hasattr(chart_com, 'HasTitle'): chart_com.HasTitle = True if hasattr(chart_com, 'ChartTitle'): chart_com.ChartTitle.Text = title # Set axis labels if hasattr(chart_com, 'Axes'): try: if x_axis: x_axis_obj = chart_com.Axes(1) # xlCategory x_axis_obj.HasTitle = True x_axis_obj.AxisTitle.Text = x_axis if y_axis: y_axis_obj = chart_com.Axes(2) # xlValue y_axis_obj.HasTitle = True y_axis_obj.AxisTitle.Text = y_axis except Exception as e: logger.warning(f"Axis label setting failed: {e}") except: # Some chart types don't have axes pass # Save the workbook wb.save() logger.info(f"βœ… Successfully created {chart_type} chart") return { "message": f"Successfully created {chart_type} chart", "chart_type": chart_type, "data_range": data_range, "position": target_cell, "sheet": sheet_name } except Exception as e: logger.error(f"❌ Error creating chart: {str(e)}") return {"error": str(e)} finally: if wb: wb.close() if app: app.quit()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hyunjae-labs/xlwings-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server