Skip to main content
Glama
hyunjae-labs

xlwings Excel MCP Server

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
Behavior2/5

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

With no annotations provided, the description carries full burden but offers minimal behavioral information. It states what the tool does but doesn't disclose whether this operation requires specific permissions, what happens if target_sheet already exists, whether formatting/formulas are preserved, or what the output contains. For a mutation tool with zero annotation coverage, this is inadequate.

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

Conciseness4/5

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

The description is efficiently structured with a clear purpose statement followed by parameter explanations. Each sentence serves a purpose, though the parameter explanations could be more informative. The formatting with 'Args:' section aids readability.

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

Completeness3/5

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

Given 3 parameters with 0% schema coverage and no annotations, the description provides basic parameter semantics but lacks behavioral context for a mutation operation. The existence of an output schema reduces the need to describe return values, but important operational details (error conditions, dependencies, side effects) remain undocumented.

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

Parameters3/5

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

Schema description coverage is 0%, but the description provides basic semantic meaning for all three parameters: session_id is 'from open_workbook', source_sheet is 'Name of the source worksheet', and target_sheet is 'Name of the target worksheet'. This adds value beyond the bare schema, though it doesn't explain format constraints or edge cases.

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

Purpose4/5

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

The description clearly states the action ('Copy worksheet') and resource ('within workbook'), making the purpose immediately understandable. However, it doesn't differentiate from sibling tools like 'copy_range' or 'rename_worksheet' which also manipulate worksheet content.

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 is provided about when to use this tool versus alternatives like 'copy_range' (for partial content) or 'create_worksheet' (for new sheets). The description mentions 'session_id from open_workbook' as a prerequisite but doesn't explain the broader context or exclusions.

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

Install Server

Other Tools

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