Skip to main content
Glama
hyunjae-labs

xlwings Excel MCP Server

by hyunjae-labs

copy_worksheet

Copy a worksheet within an Excel workbook to create duplicates for data analysis, reporting, or template reuse.

Instructions

Copy worksheet within workbook.

Args:
    session_id: Session ID from open_workbook (required)
    source_sheet: Name of the source worksheet
    target_sheet: Name of the target worksheet

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
session_idYes
source_sheetYes
target_sheetYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • Registration and handler function for the 'copy_worksheet' tool. Validates session, locks it, calls the implementation, and returns result or error.
    def copy_worksheet(
        session_id: str,
        source_sheet: str,
        target_sheet: str
    ) -> str:
        """
        Copy worksheet within workbook.
        
        Args:
            session_id: Session ID from open_workbook (required)
            source_sheet: Name of the source worksheet
            target_sheet: Name of the target worksheet
        """
        try:
            # Validate session using centralized helper
            session = get_validated_session(session_id)
            if isinstance(session, str):  # Error message returned
                return session
                
            with session.lock:
                from xlwings_mcp.xlwings_impl.sheet_xlw import copy_worksheet_xlw_with_wb
                result = copy_worksheet_xlw_with_wb(session.workbook, source_sheet, target_sheet)
            
            return result.get("message", "Worksheet 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 worksheet: {e}")
            raise
  • Core implementation of worksheet copying using xlwings. Handles both COM API copy and fallback data copy, checks for sheet existence and duplicates, saves the workbook.
    def copy_worksheet_xlw_with_wb(wb, source_sheet: str, target_sheet: str) -> Dict[str, Any]:
        """Session-based version using existing workbook object.
        
        Args:
            wb: Workbook object from session
            source_sheet: 원본 시트명
            target_sheet: 대상 시트명
            
        Returns:
            복사 결과 딕셔너리
        """
        try:
            # 원본 시트 확인
            existing_sheets = [sheet.name for sheet in wb.sheets]
            if source_sheet not in existing_sheets:
                return {"error": f"Source sheet '{source_sheet}' not found"}
            
            # 대상 이름 중복 확인
            if target_sheet in existing_sheets:
                return {"error": f"Target sheet '{target_sheet}' already exists"}
            
            # 시트 복사
            source = wb.sheets[source_sheet]
            
            # xlwings에서 시트 복사하기 - COM API 사용
            try:
                # COM API를 통한 시트 복사
                source.api.Copy(After=source.api)
                
                # 복사된 시트는 보통 마지막에 추가됨
                # 복사된 시트 찾기
                new_sheets = [sheet.name for sheet in wb.sheets]
                copied_sheet_name = None
                
                for sheet_name in new_sheets:
                    if sheet_name not in existing_sheets:
                        copied_sheet_name = sheet_name
                        break
                
                if copied_sheet_name:
                    # 복사된 시트 이름 변경
                    wb.sheets[copied_sheet_name].name = target_sheet
                else:
                    # 대안 방법: 수동으로 시트 생성 후 데이터 복사
                    new_sheet = wb.sheets.add(name=target_sheet)
                    source_range = source.used_range
                    if source_range:
                        new_sheet.range("A1").value = source_range.value
                        
            except Exception as copy_error:
                logger.warning(f"COM API 복사 실패, 대안 방법 사용: {copy_error}")
                # 대안 방법: 새 시트를 만들고 데이터를 복사
                new_sheet = wb.sheets.add(name=target_sheet)
                source_range = source.used_range
                if source_range:
                    new_sheet.range("A1").value = source_range.value
            
            # 파일 저장
            wb.save()
            
            return {"message": f"Sheet '{source_sheet}' copied to '{target_sheet}'"}
            
        except Exception as e:
            logger.error(f"xlwings 워크시트 복사 실패: {e}")
            return {"error": f"Failed to copy worksheet: {str(e)}"}
  • Legacy/filepath-based implementation of worksheet copying (not used by the main tool handler). Opens workbook, performs copy, cleans up resources.
    def copy_worksheet_xlw(filepath: str, source_sheet: str, target_sheet: str) -> Dict[str, Any]:
        """xlwings를 사용한 워크시트 복사
    
        Args:
            filepath: Excel 파일 경로
            source_sheet: 원본 시트명
            target_sheet: 대상 시트명
    
        Returns:
            복사 결과 딕셔너리
        """
        app = None
        wb = None
    
        # Initialize COM for thread safety (Windows)
        _com_initialize()
    
        try:
            # 파일 경로 검증
            file_path = Path(filepath)
            if not file_path.exists():
                return {"error": f"File not found: {filepath}"}
            
            # Excel 앱 시작
            app = xw.App(visible=False, add_book=False)
            
            # 워크북 열기
            wb = app.books.open(filepath)
            
            # 원본 시트 확인
            existing_sheets = [sheet.name for sheet in wb.sheets]
            if source_sheet not in existing_sheets:
                return {"error": f"Source sheet '{source_sheet}' not found"}
            
            # 대상 이름 중복 확인
            if target_sheet in existing_sheets:
                return {"error": f"Target sheet '{target_sheet}' already exists"}
            
            # 시트 복사
            source = wb.sheets[source_sheet]
            
            # xlwings에서 시트 복사하기 - COM API 사용
            try:
                # COM API를 통한 시트 복사
                source.api.Copy(After=source.api)
                
                # 복사된 시트는 보통 마지막에 추가됨
                # 복사된 시트 찾기
                new_sheets = [sheet.name for sheet in wb.sheets]
                copied_sheet_name = None
                
                for sheet_name in new_sheets:
                    if sheet_name not in existing_sheets:
                        copied_sheet_name = sheet_name
                        break
                
                if copied_sheet_name:
                    # 복사된 시트 이름 변경
                    wb.sheets[copied_sheet_name].name = target_sheet
                else:
                    # 대안 방법: 수동으로 시트 생성 후 데이터 복사
                    new_sheet = wb.sheets.add(name=target_sheet)
                    source_range = source.used_range
                    if source_range:
                        new_sheet.range("A1").value = source_range.value
                        
            except Exception as copy_error:
                logger.warning(f"COM API 복사 실패, 대안 방법 사용: {copy_error}")
                # 대안 방법: 새 시트를 만들고 데이터를 복사
                new_sheet = wb.sheets.add(name=target_sheet)
                source_range = source.used_range
                if source_range:
                    new_sheet.range("A1").value = source_range.value
            
            # 파일 저장
            wb.save()
            
            return {"message": f"Sheet '{source_sheet}' copied to '{target_sheet}'"}
            
        except Exception as e:
            logger.error(f"xlwings 워크시트 복사 실패: {e}")
            return {"error": f"Failed to copy worksheet: {str(e)}"}
            
        finally:
            # 리소스 정리
            if wb:
                try:
                    wb.close()
                except Exception as e:
                    logger.warning(f"워크북 닫기 실패: {e}")
            
            if app:
                try:
                    app.quit()
                except Exception as e:
  • Legacy wrapper in sheet.py that calls the filepath-based impl and raises exceptions on error (not directly used by the tool).
    def copy_sheet(filepath: str, source_sheet: str, target_sheet: str) -> Dict[str, Any]:
        """Copy a worksheet within the same workbook."""
        result = copy_worksheet_xlw(filepath, source_sheet, target_sheet)
        if "error" in result:
            raise SheetError(result["error"])
        return result

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changed
    • removedInput schema / properties / filepath
      Removed value: -{
      -  "title": "Filepath",
      -  "type": "string"
      -}
    • addedInput schema / properties / session_id
      Added value: +{
      +  "title": "Session Id",
      +  "type": "string"
      +}
    • changedInput schema / required
      Previous value: -[
      -  "filepath",
      -  "source_sheet",
      -  "target_sheet"
      -]New value: +[
      +  "session_id",
      +  "source_sheet",
      +  "target_sheet"
      +]
  2. First observed

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, and the description does not disclose behavioral traits such as whether it copies formatting, validation rules, or data behavior. For a mutation tool, this is a significant gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Although short, the description redundantly lists parameters that are already defined in the input schema, wasting valuable description space that could provide additional context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 3 required parameters and no annotations, the description omits crucial details like expected return values, behavior on name conflicts, and whether the target sheet must exist or is created.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description adds no meaning beyond parameter names (e.g., 'Name of the source worksheet'). No constraints, formats, or required formats are specified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Copy worksheet within workbook' using a specific verb and resource, distinguishing it from sibling tools like rename_worksheet or delete_worksheet.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives, nor any prerequisites or exclusions. The description merely lists parameters without contextual usage advice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.