Skip to main content
Glama

create_chart

Generate charts in Excel worksheets by specifying data range, chart type, and target cell. Use this tool to visualize data with customizable titles and axis labels directly within Excel files.

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 handler for 'create_chart'. Registers the tool with FastMCP and handles input parameters, path resolution, and delegates execution to the implementation while catching specific exceptions.
    @mcp.tool() def create_chart( filepath: str, sheet_name: str, data_range: str, chart_type: str, target_cell: str, title: str = "", x_axis: str = "", y_axis: str = "" ) -> str: """Create chart in worksheet.""" try: full_path = get_excel_path(filepath) result = create_chart_impl( 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 ) return result["message"] except (ValidationError, ChartError) as e: return f"Error: {str(e)}" except Exception as e: logger.error(f"Error creating chart: {e}") raise
  • Core implementation of chart creation. Loads the workbook, parses data range, creates the specified chart type (line, bar, pie, etc.) using openpyxl, configures titles, axes, data series, styles, and anchors the chart at the target cell.
    def create_chart_in_sheet( filepath: str, sheet_name: str, data_range: str, chart_type: str, target_cell: str, title: str = "", x_axis: str = "", y_axis: str = "", style: Optional[Dict] = None ) -> dict[str, Any]: """Create chart in sheet with enhanced styling options""" # Ensure style dict exists and defaults to showing data labels if style is None: style = {"show_data_labels": True} else: # If caller omitted the flag, default to True style.setdefault("show_data_labels", True) try: wb = load_workbook(filepath) if sheet_name not in wb.sheetnames: logger.error(f"Sheet '{sheet_name}' not found") raise ValidationError(f"Sheet '{sheet_name}' not found") worksheet = wb[sheet_name] # Initialize collections if they don't exist if not hasattr(worksheet, '_drawings'): worksheet._drawings = [] if not hasattr(worksheet, '_charts'): worksheet._charts = [] # Parse the data range if "!" in data_range: range_sheet_name, cell_range = data_range.split("!") if range_sheet_name not in wb.sheetnames: logger.error(f"Sheet '{range_sheet_name}' referenced in data range not found") raise ValidationError(f"Sheet '{range_sheet_name}' referenced in data range not found") else: cell_range = data_range try: start_cell, end_cell = cell_range.split(":") start_row, start_col, end_row, end_col = parse_cell_range(start_cell, end_cell) except ValueError as e: logger.error(f"Invalid data range format: {e}") raise ValidationError(f"Invalid data range format: {str(e)}") # Validate chart type chart_classes = { "line": LineChart, "bar": BarChart, "pie": PieChart, "scatter": ScatterChart, "area": AreaChart } chart_type_lower = chart_type.lower() ChartClass = chart_classes.get(chart_type_lower) if not ChartClass: logger.error(f"Unsupported chart type: {chart_type}") raise ValidationError( f"Unsupported chart type: {chart_type}. " f"Supported types: {', '.join(chart_classes.keys())}" ) chart = ChartClass() # Basic chart settings chart.title = title if hasattr(chart, "x_axis"): chart.x_axis.title = x_axis if hasattr(chart, "y_axis"): chart.y_axis.title = y_axis try: # Create data references if chart_type_lower == "scatter": # For scatter charts, create series for each pair of columns for col in range(start_col + 1, end_col + 1): x_values = Reference( worksheet, min_row=start_row + 1, max_row=end_row, min_col=start_col ) y_values = Reference( worksheet, min_row=start_row + 1, max_row=end_row, min_col=col ) series = Series(y_values, x_values, title_from_data=True) chart.series.append(series) else: # For other chart types data = Reference( worksheet, min_row=start_row, max_row=end_row, min_col=start_col + 1, max_col=end_col ) cats = Reference( worksheet, min_row=start_row + 1, max_row=end_row, min_col=start_col ) chart.add_data(data, titles_from_data=True) chart.set_categories(cats) except Exception as e: logger.error(f"Failed to create chart data references: {e}") raise ChartError(f"Failed to create chart data references: {str(e)}") # Apply style if provided try: if style.get("show_legend", True): chart.legend = Legend() chart.legend.position = style.get("legend_position", "r") else: chart.legend = None if style.get("show_data_labels", False): data_labels = DataLabelList() # Gather optional overrides dlo = style.get("data_label_options", {}) if isinstance(style.get("data_label_options", {}), dict) else {} # Helper to read bool with fallback def _opt(name: str, default: bool) -> bool: return bool(dlo.get(name, default)) # Apply options – Excel will concatenate any that are set to True data_labels.showVal = _opt("show_val", True) data_labels.showCatName = _opt("show_cat_name", False) data_labels.showSerName = _opt("show_ser_name", False) data_labels.showLegendKey = _opt("show_legend_key", False) data_labels.showPercent = _opt("show_percent", False) data_labels.showBubbleSize = _opt("show_bubble_size", False) chart.dataLabels = data_labels if style.get("grid_lines", False): if hasattr(chart, "x_axis"): chart.x_axis.majorGridlines = ChartLines() if hasattr(chart, "y_axis"): chart.y_axis.majorGridlines = ChartLines() except Exception as e: logger.error(f"Failed to apply chart style: {e}") raise ChartError(f"Failed to apply chart style: {str(e)}") # Set chart size chart.width = 15 chart.height = 7.5 # Create drawing and anchor try: drawing = SpreadsheetDrawing() drawing.chart = chart # Validate target cell format if not target_cell or not any(c.isalpha() for c in target_cell) or not any(c.isdigit() for c in target_cell): raise ValidationError(f"Invalid target cell format: {target_cell}") # Create anchor col = column_index_from_string(target_cell[0]) - 1 row = int(target_cell[1:]) - 1 anchor = OneCellAnchor() anchor._from = AnchorMarker(col=col, row=row) drawing.anchor = anchor # Add to worksheet worksheet._drawings.append(drawing) worksheet._charts.append(chart) except ValueError as e: logger.error(f"Invalid target cell: {e}") raise ValidationError(f"Invalid target cell: {str(e)}") except Exception as e: logger.error(f"Failed to create chart drawing: {e}") raise ChartError(f"Failed to create chart drawing: {str(e)}") try: wb.save(filepath) except Exception as e: logger.error(f"Failed to save workbook: {e}") raise ChartError(f"Failed to save workbook with chart: {str(e)}") return { "message": f"{chart_type.capitalize()} chart created successfully", "details": { "type": chart_type, "location": target_cell, "data_range": data_range } } except (ValidationError, ChartError): raise except Exception as e: logger.error(f"Unexpected error creating chart: {e}") raise ChartError(f"Unexpected error creating chart: {str(e)}")
  • Enum defining valid chart types for input validation in the create_chart tool.
    class ChartType(str, Enum): """Supported chart types""" LINE = "line" BAR = "bar" PIE = "pie" SCATTER = "scatter" AREA = "area" BUBBLE = "bubble" STOCK = "stock" SURFACE = "surface" RADAR = "radar"
  • Import of the chart implementation function aliased for use in the handler.
    from excel_mcp.chart import create_chart_in_sheet as create_chart_impl

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/haris-musa/excel-mcp-server'

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