Excel自动化:跨工作表精准复制透视表的魔法指令
评论
收藏

Excel自动化:跨工作表精准复制透视表的魔法指令

经验分享
所谓良知
2026-05-19 11:10·浏览量:142
所谓良知
影刀中级开发者
发布于 2026-05-19 11:10142浏览

魔法指令:将指定sheet页中指定透视表拷贝到指定sheet页中指定单元格中。

import os
import builtins
import win32com.client as win32
from typing import *

try:
    from xbot.app.logging import trace as print
except:
    from xbot import print

# =======================================================
# 🚀 魔法:全局劫持并重写原生的 print 函数
# =======================================================
_original_print = builtins.print

def print(*args, sep=' ', **kwargs):
    """
    无缝接管当前模块下的所有 print 语句,将输出强行重定向到影刀的日志控制台。
    """
    msg = sep.join(map(str, args))
    try:
        import xbot
        xbot.logging.info(msg)
    except Exception:
        _original_print(*args, sep=sep, **kwargs)

# ======================================================

def copy_excel_pivot_table_active(
    file_path,
    source_sheet_name,
    pivot_table_name,
    dest_sheet_name,
    dest_cell="A3"
):
    """
    title: 接管当前Excel并拷贝透视表
    description: 将 %source_sheet_name% Sheet页中 %pivot_table_name% 透视表,拷贝至 %dest_sheet_name% Sheet页中的 %dest_cell% 单元格中。
    inputs:
    - file_path (str): Excel文件的绝对路径(用于匹配当前打开的窗口),eg: "C:\\测试\\业务分析报告.xlsx"
    - source_sheet_name (str): 透视表所在的源Sheet页名称,eg: "数据看板"
    - pivot_table_name (str): 要复制的透视表名称,eg: "数据透视表1"
    - dest_sheet_name (str): 目标Sheet页名称,eg: "备份归档页"
    - dest_cell (str): 目标起始单元格,粘贴到目标Sheet页的起始单元格位置,eg: "A3"
    outputs:
    - None
    """
    # 1. 安全校验与提取目标文件名
    if not dest_cell:
        print("【错误】检测到目标单元格为空,请检查影刀传入的 dest_cell 变量!")
        return
        
    target_filename = os.path.basename(file_path)
    print(f"▶ 准备接管已打开的工作簿: {target_filename}")

    # 2. 尝试抓取当前活动的 Excel / WPS 进程
    excel_app = None
    try:
        excel_app = win32.GetActiveObject("Excel.Application")
        print("成功接管微软 Excel 进程。")
    except Exception:
        try:
            excel_app = win32.GetActiveObject("et.Application")
            print("未检测到微软 Excel,成功接管 WPS 表格进程。")
        except Exception:
            print("【错误】未检测到正在运行的 Excel 或 WPS 窗口!请确保在调用此指令前,影刀已经打开了该文件。")
            return

    # 正式运行时关闭警告,防止 Excel 弹窗卡死 RPA 自动化流程
    excel_app.DisplayAlerts = False

    wb = None
    try:
        # 3. 遍历当前应用内所有已经打开的工作簿,找到名字匹配的那一个
        for workbook in excel_app.Workbooks:
            if workbook.Name == target_filename:
                wb = workbook
                break
                
        if wb is None:
            print(f"【错误】应用进程正在运行,但没有找到名为 '{target_filename}' 的文件,请检查文件是否确实处于打开状态。")
            return

        # 4. 获取源工作表
        try:
            ws_source = wb.Sheets(source_sheet_name)
        except Exception:
            print(f"【错误】在文件中找不到源工作表: '{source_sheet_name}'")
            return

        # 5. 获取目标工作表(如果不存在则自动创建到最后一个)
        try:
            ws_dest = wb.Sheets(dest_sheet_name)
        except Exception:
            try:
                # 【底层修复】:使用位置参数 (None, 最后一个Sheet对象) 确保绝对创建在末尾,防止错乱
                ws_dest = wb.Sheets.Add(None, wb.Sheets(wb.Sheets.Count))
                ws_dest.Name = dest_sheet_name
                print(f"【提示】目标工作表不存在,已自动创建在末尾: '{dest_sheet_name}'")
            except Exception as e:
                print(f"【错误】创建工作表失败!请检查名称 '{dest_sheet_name}' 是否包含非法字符或与隐藏表重名。")
                return

        # 6. 获取指定的透视表对象
        try:
            pt = ws_source.PivotTables(pivot_table_name)
        except Exception:
            print(f"【错误】在工作表 '{source_sheet_name}' 中找不到名为 '{pivot_table_name}' 的透视表。")
            # 安全地获取当前工作表内现有的所有透视表名称,方便用户排查
            existing_pts = []
            try:
                pivots = ws_source.PivotTables()
                for i in range(1, pivots.Count + 1):
                    existing_pts.append(pivots(i).Name)
            except Exception:
                pass
            print(f" 当前 '{source_sheet_name}' 页内现有的透视表名称有: {existing_pts}")
            return

        # 7. 解析目标单元格并执行复制粘贴
        try:
            dest_range = ws_dest.Range(dest_cell) 
        except Exception:
            print(f"【错误】目标单元格 '{dest_cell}' 格式不合法(例如包含空格或非法字符),请检查!")
            return

        try:
            # 【底层修复】:不再走系统剪贴板,直接通过 Destination 参数在 Excel 内存中完成克隆,最稳定!
            pt.TableRange2.Copy(Destination=dest_range)
        except Exception as e:
            # 【核心拦截】:如果粘贴位置有重叠,拦截崩溃并给出白话文提示
            print(f"【拦截崩溃】粘贴失败!极可能是因为目标位置 '{dest_sheet_name}' 页的 {dest_cell} 单元格及附近,已经存在其他数据或透视表,导致了重叠冲突。请在影刀中更换一个完全空白的 dest_cell 参数!")
            return

        # 8. 执行保存操作
        wb.Save()
        print(f"【成功】已将透视表 '{pivot_table_name}' 成功拷贝至 '{dest_sheet_name}' 页面的 {dest_cell} 单元格!")

    except Exception as e:
        print(f"【运行异常】发生未知错误,可能脱离了常规监控范围: {e}")

    finally:
        if excel_app:
            # 无论成功或失败,将控制权交还给用户/影刀前,务必恢复弹窗警告功能
            excel_app.DisplayAlerts = True


# ==================== 测试调用示例 ====================
if __name__ == "__main__":
    # 仅作脱离影刀环境时的本地代码测试用
    FILE_PATH = "业务分析报告.xlsx"  
    SOURCE_SHEET = "数据看板"  
    PIVOT_NAME = "数据透视表1" 
    DEST_SHEET = "备份归档页"  
    TARGET_CELL = "B3"  

    copy_excel_pivot_table_active(
        file_path=FILE_PATH,
        source_sheet_name=SOURCE_SHEET,
        pivot_table_name=PIVOT_NAME,
        dest_sheet_name=DEST_SHEET,
        dest_cell=TARGET_CELL,
    )

收藏1
全部评论1
最新
发布评论
评论