copy_range
Transfer a specified cell range within an Excel sheet or between sheets using source and target coordinates. Ideal for reorganizing or duplicating data efficiently.
Instructions
Copy a range of cells to another location.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filepath | Yes | ||
| sheet_name | Yes | ||
| source_end | Yes | ||
| source_start | Yes | ||
| target_sheet | No | ||
| target_start | Yes |
Implementation Reference
- src/excel_mcp/server.py:482-509 (handler)MCP tool handler for 'copy_range': handles input parameters, resolves file path, imports and calls the core copy_range_operation function from sheet.py, and returns the result message or error.
@mcp.tool() def copy_range( filepath: str, sheet_name: str, source_start: str, source_end: str, target_start: str, target_sheet: Optional[str] = None ) -> str: """Copy a range of cells to another location.""" try: full_path = get_excel_path(filepath) from excel_mcp.sheet import copy_range_operation result = copy_range_operation( full_path, sheet_name, source_start, source_end, target_start, target_sheet or sheet_name # Use source sheet if target_sheet is None ) return result["message"] except (ValidationError, SheetError) as e: return f"Error: {str(e)}" except Exception as e: logger.error(f"Error copying range: {e}") raise - src/excel_mcp/sheet.py:261-314 (helper)Core helper function implementing the range copy logic: loads workbook, validates sheets and ranges, calculates offsets, copies cell values and styles cell-by-cell, and saves the workbook.
def copy_range_operation( filepath: str, sheet_name: str, source_start: str, source_end: str, target_start: str, target_sheet: Optional[str] = None ) -> Dict: """Copy a range of cells to another location.""" 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") source_ws = wb[sheet_name] target_ws = wb[target_sheet] if target_sheet else source_ws # Parse source range try: start_row, start_col, end_row, end_col = parse_cell_range(source_start, source_end) except ValueError as e: logger.error(f"Invalid source range: {e}") raise ValidationError(f"Invalid source range: {str(e)}") # Parse target starting point try: target_row = int(''.join(filter(str.isdigit, target_start))) target_col = column_index_from_string(''.join(filter(str.isalpha, target_start))) except ValueError as e: logger.error(f"Invalid target cell: {e}") raise ValidationError(f"Invalid target cell: {str(e)}") # Copy the range row_offset = target_row - start_row col_offset = target_col - start_col for i in range(start_row, end_row + 1): for j in range(start_col, end_col + 1): source_cell = source_ws.cell(row=i, column=j) target_cell = target_ws.cell(row=i + row_offset, column=j + col_offset) target_cell.value = source_cell.value if source_cell.has_style: target_cell._style = copy(source_cell._style) wb.save(filepath) return {"message": f"Range copied successfully"} except (ValidationError, SheetError): raise except Exception as e: logger.error(f"Failed to copy range: {e}") raise SheetError(f"Failed to copy range: {str(e)}") - src/excel_mcp/sheet.py:83-171 (helper)Supporting helper function for copying ranges between worksheets, including detailed style copying (font, border, fill, format, alignment). Not directly called by the tool but provides similar copy logic.
def copy_range( source_ws: Worksheet, target_ws: Worksheet, source_range: str, target_start: Optional[str] = None, ) -> None: """Copy range from source worksheet to target worksheet.""" # Parse source range if ':' in source_range: source_start, source_end = source_range.split(':') else: source_start = source_range source_end = None src_start_row, src_start_col, src_end_row, src_end_col = parse_cell_range( source_start, source_end ) if src_end_row is None: src_end_row = src_start_row src_end_col = src_start_col if target_start is None: target_start = source_start tgt_start_row, tgt_start_col, _, _ = parse_cell_range(target_start) for i, row in enumerate(range(src_start_row, src_end_row + 1)): for j, col in enumerate(range(src_start_col, src_end_col + 1)): source_cell = source_ws.cell(row=row, column=col) target_cell = target_ws.cell(row=tgt_start_row + i, column=tgt_start_col + j) target_cell.value = source_cell.value try: # Copy font font_kwargs = {} if hasattr(source_cell.font, 'name'): font_kwargs['name'] = source_cell.font.name if hasattr(source_cell.font, 'size'): font_kwargs['size'] = source_cell.font.size if hasattr(source_cell.font, 'bold'): font_kwargs['bold'] = source_cell.font.bold if hasattr(source_cell.font, 'italic'): font_kwargs['italic'] = source_cell.font.italic if hasattr(source_cell.font, 'color'): font_color = None if source_cell.font.color: font_color = source_cell.font.color.rgb font_kwargs['color'] = font_color target_cell.font = Font(**font_kwargs) # Copy border new_border = Border() for side in ['left', 'right', 'top', 'bottom']: source_side = getattr(source_cell.border, side) if source_side and source_side.style: side_color = source_side.color.rgb if source_side.color else None setattr(new_border, side, Side( style=source_side.style, color=side_color )) target_cell.border = new_border # Copy fill if hasattr(source_cell, 'fill'): fill_kwargs = {'patternType': source_cell.fill.patternType} if hasattr(source_cell.fill, 'fgColor') and source_cell.fill.fgColor: fg_color = None if hasattr(source_cell.fill.fgColor, 'rgb'): fg_color = source_cell.fill.fgColor.rgb fill_kwargs['fgColor'] = fg_color if hasattr(source_cell.fill, 'bgColor') and source_cell.fill.bgColor: bg_color = None if hasattr(source_cell.fill.bgColor, 'rgb'): bg_color = source_cell.fill.bgColor.rgb fill_kwargs['bgColor'] = bg_color target_cell.fill = PatternFill(**fill_kwargs) # Copy number format and alignment if source_cell.number_format: target_cell.number_format = source_cell.number_format if source_cell.alignment: target_cell.alignment = source_cell.alignment except Exception: continue def delete_range(worksheet: Worksheet, start_cell: str, end_cell: Optional[str] = None) -> None: