copy_range
Transfer cell ranges between locations in Excel workbooks securely using xlwings. Specify source and target ranges to automate data movement without direct file access.
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/xlwings_mcp/server.py:1109-1178 (registration)Registration and handler for the MCP 'copy_range' tool. Validates session/filepath and calls appropriate xlwings implementation.def copy_range( sheet_name: str, source_start: str, source_end: str, target_start: str, session_id: Optional[str] = None, filepath: Optional[str] = None, target_sheet: Optional[str] = None ) -> str: """ Copy a range of cells to another location. Args: sheet_name: Name of source worksheet source_start: Starting cell of source range source_end: Ending cell of source range target_start: Starting cell of target range session_id: Session ID from open_workbook (preferred) filepath: Path to Excel file (legacy, deprecated) target_sheet: Target worksheet (optional, uses source sheet if not provided) 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.range_xlw import copy_range_xlw_with_wb result = copy_range_xlw_with_wb( session.workbook, sheet_name, source_start, source_end, target_start, target_sheet or sheet_name # Use source sheet if target_sheet is None ) 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.range_xlw import copy_range_xlw result = copy_range_xlw( full_path, sheet_name, source_start, source_end, target_start, target_sheet or sheet_name # Use source sheet if target_sheet is None ) else: return ERROR_TEMPLATES['PARAMETER_MISSING'].format( param1='session_id', param2='filepath' ) return result.get("message", "Range copied successfully") if "error" not in result else f"Error: {result['error']}" except (ValidationError, SheetError) as e: return f"Error: {str(e)}" except Exception as e: logger.error(f"Error copying range: {e}") raise
- Core xlwings implementation for copying a range (legacy filepath mode). Opens workbook, copies range preserving formatting/formulas, saves and closes.def copy_range_xlw( filepath: str, sheet_name: str, source_start: str, source_end: str, target_start: str, target_sheet: Optional[str] = None ) -> Dict[str, Any]: """ Copy a range of cells to another location using xlwings. Args: filepath: Path to Excel file sheet_name: Name of source worksheet source_start: Top-left cell of source range source_end: Bottom-right cell of source range target_start: Top-left cell of target location target_sheet: Name of target worksheet (optional, defaults to source sheet) Returns: Dict with success message or error """ app = None wb = None # Initialize COM for thread safety (Windows) _com_initialize() try: # Use target_sheet if provided, otherwise use source sheet target_sheet = target_sheet or sheet_name logger.info(f"Copying range {source_start}:{source_end} to {target_start} in {target_sheet}") # 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 sheets exist sheet_names = [s.name for s in wb.sheets] if sheet_name not in sheet_names: return {"error": f"Source sheet '{sheet_name}' not found"} if target_sheet not in sheet_names: return {"error": f"Target sheet '{target_sheet}' not found"} source_sheet = wb.sheets[sheet_name] dest_sheet = wb.sheets[target_sheet] # Get source range source_range = source_sheet.range(f"{source_start}:{source_end}") # Copy to target location # xlwings copy method preserves formatting and formulas source_range.copy(destination=dest_sheet.range(target_start)) # Calculate target end cell rows = source_range.rows.count cols = source_range.columns.count target_end_row = dest_sheet.range(target_start).row + rows - 1 target_end_col = dest_sheet.range(target_start).column + cols - 1 target_end = dest_sheet.cells(target_end_row, target_end_col).address.replace("$", "") # Save the workbook wb.save() logger.info(f"β Successfully copied range to {target_start}:{target_end}") return { "message": f"Successfully copied range {source_start}:{source_end} to {target_start}", "source_range": f"{source_start}:{source_end}", "target_range": f"{target_start}:{target_end}", "source_sheet": sheet_name, "target_sheet": target_sheet } except Exception as e: logger.error(f"β Error copying range: {str(e)}") return {"error": str(e)} finally: if wb: wb.close() if app: app.quit()
- Session-optimized xlwings helper for copying range using existing open workbook object (no open/close overhead).def copy_range_xlw_with_wb( wb, sheet_name: str, source_start: str, source_end: str, target_start: str, target_sheet: Optional[str] = None ) -> Dict[str, Any]: """ Session-based range copying using existing workbook object. Args: wb: Workbook object from session sheet_name: Name of source worksheet source_start: Top-left cell of source range source_end: Bottom-right cell of source range target_start: Top-left cell of target location target_sheet: Name of target worksheet (optional, defaults to source sheet) Returns: Dict with success message or error """ try: # Use target_sheet if provided, otherwise use source sheet target_sheet = target_sheet or sheet_name logger.info(f"π Copying range {source_start}:{source_end} to {target_start} in {target_sheet}") # Check if sheets exist sheet_names = [s.name for s in wb.sheets] if sheet_name not in sheet_names: return {"error": f"Source sheet '{sheet_name}' not found"} if target_sheet not in sheet_names: return {"error": f"Target sheet '{target_sheet}' not found"} source_sheet = wb.sheets[sheet_name] dest_sheet = wb.sheets[target_sheet] # Get source range source_range = source_sheet.range(f"{source_start}:{source_end}") # Copy to target location # xlwings copy method preserves formatting and formulas source_range.copy(destination=dest_sheet.range(target_start)) # Calculate target end cell rows = source_range.rows.count cols = source_range.columns.count target_end_row = dest_sheet.range(target_start).row + rows - 1 target_end_col = dest_sheet.range(target_start).column + cols - 1 target_end = dest_sheet.cells(target_end_row, target_end_col).address.replace("$", "") # Save the workbook wb.save() logger.info(f"β Successfully copied range to {target_start}:{target_end}") return { "message": f"Successfully copied range {source_start}:{source_end} to {target_start}", "source_range": f"{source_start}:{source_end}", "target_range": f"{target_start}:{target_end}", "source_sheet": sheet_name, "target_sheet": target_sheet } except Exception as e: logger.error(f"β Error copying range: {str(e)}") return {"error": str(e)}
- src/xlwings_mcp/sheet.py:62-74 (helper)Wrapper operation in sheet.py that calls copy_range_xlw and raises custom exception.def copy_range_operation( filepath: str, sheet_name: str, source_start: str, source_end: str, target_start: str, target_sheet: str ) -> Dict[str, Any]: """Copy a range of cells to another location.""" result = copy_range_xlw(filepath, sheet_name, source_start, source_end, target_start, target_sheet) if "error" in result: raise SheetError(result["error"]) return result