初识影刀:将多个相同格式EXCEL中内容汇总到一个EXCEL文件中去

发布于:2025-08-12 ⋅ 阅读:(20) ⋅ 点赞:(0)

原本每月都有表格汇总的,但领导说要统计一段时间内的内容,如果一个表格一个表格复制粘贴又太累了。所以使用影刀的功能。
文件夹中的数据表格如下
在这里插入图片描述
在这里插入图片描述
1、打开文件夹
2、获取文件夹中的文件名列表
3、如果文件名列表有“汇总”的内容则先删除
4、在这个文件夹下新建“汇总”的数据表格,用于存放复制来的数据
5、按文件名列表开始循环。
6、获取“汇总”表的总行数
7、依次打开文件夹中的各文件
8、获取打开文件的总行数
9、读取打开文件的内容,范围从A2到N总行数止。
10、将读取的内容复制到“汇总”数据表,开始行从1+“汇总”表总行数开始
11、关闭打开的文件
12、结束循环

以上基本上已经能获取数据了,但想将“汇总”的数据范围增加边框,经查询,没有很好的办法,后来在论坛上说可以使用魔法指令
在这里插入图片描述
在这里插入图片描述
所包含的代码如下

# pip install openpyxl pywin32

import openpyxl
from openpyxl.styles import Border, Side
from openpyxl.utils import get_column_letter
import os
import win32com.client
import time

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


def set_excel_data_border_keep_open(excel_file, sheet_name=None, border_style="thin", border_color="000000", has_header=True):
    """
    title: Excel数据区域设置边框(保持打开)
    description: 打开Excel文件,自动检测数据区域并设置边框,完成后保持Excel文件打开状态。
    inputs: 
        - excel_file (file): 输入的Excel文件路径,eg: "data.xlsx"
        - sheet_name (str): 要处理的工作表名称,不指定则使用活动工作表,eg: "Sheet1"
        - border_style (str): 边框样式,可选值:thin, medium, thick, double, dotted, dashed,eg: "thin"
        - border_color (str): 边框颜色,使用十六进制RGB值,eg: "000000"
        - has_header (bool): 数据是否包含表头,eg: True
    outputs: 
        - file_path (str): 处理后的Excel文件路径,eg: "E:\\KKK\\月汇总\\2025\\机加工时分析\\汇总.xlsx"
    """
    
    # 检查输入参数有效性
    valid_styles = ["thin", "medium", "thick", "double", "dotted", "dashed"]
    if border_style not in valid_styles:
        raise ValueError(f"边框样式必须是以下值之一: {', '.join(valid_styles)}")
    
    if not isinstance(border_color, str) or len(border_color) != 6:
        raise ValueError("边框颜色必须是6位十六进制RGB值,例如:000000")
    
    try:
        int(border_color, 16)
    except ValueError:
        raise ValueError("边框颜色必须是有效的十六进制值")
    
    # 确保文件路径是绝对路径
    excel_file = os.path.abspath(excel_file)
    
    # 检查文件是否存在
    if not os.path.exists(excel_file):
        raise FileNotFoundError(f"找不到Excel文件: {excel_file}")
    
    # 使用COM接口打开Excel应用程序
    try:
        excel = win32com.client.Dispatch("Excel.Application")
        excel.Visible = True  # 使Excel可见
        excel.DisplayAlerts = False  # 禁用警告弹窗
        
        # 尝试打开工作簿
        try:
            workbook = excel.Workbooks.Open(excel_file)
        except Exception as e:
            excel.Quit()
            raise Exception(f"无法打开Excel文件: {str(e)}")
        
        # 选择工作表
        if sheet_name:
            try:
                worksheet = workbook.Worksheets(sheet_name)
                worksheet.Activate()
            except:
                excel.Quit()
                raise ValueError(f"工作表 '{sheet_name}' 不存在")
        else:
            worksheet = workbook.ActiveSheet
        
        # 使用openpyxl处理边框设置
        # 先关闭Excel以便openpyxl可以访问文件
        workbook.Save()
        workbook.Close(False)
        excel.Quit()
        
        # 使用openpyxl设置边框
        wb = openpyxl.load_workbook(excel_file)
        if sheet_name:
            if sheet_name not in wb.sheetnames:
                raise ValueError(f"工作表 '{sheet_name}' 不存在")
            sheet = wb[sheet_name]
        else:
            sheet = wb.active
        
        # 检测数据区域
        def _detect_data_range():
            """检测工作表中的数据区域"""
            # 找到最大行和最大列
            max_row = 1
            max_col = 1
            
            for row in sheet.iter_rows():
                for cell in row:
                    if cell.value is not None:
                        max_row = max(max_row, cell.row)
                        max_col = max(max_col, cell.column)
            
            # 如果没有数据,返回默认范围
            if max_row == 1 and max_col == 1 and sheet.cell(1, 1).value is None:
                return None
            
            # 找到最小行和最小列
            min_row = max_row
            min_col = max_col
            
            for row_idx in range(1, max_row + 1):
                for col_idx in range(1, max_col + 1):
                    if sheet.cell(row_idx, col_idx).value is not None:
                        min_row = min(min_row, row_idx)
                        min_col = min(min_col, col_idx)
            
            return (min_row, min_col, max_row, max_col)
        
        # 获取数据范围
        data_range = _detect_data_range()
        if not data_range:
            raise ValueError("工作表中没有检测到数据")
        
        min_row, min_col, max_row, max_col = data_range
        
        # 创建边框样式
        border_styles = {
            "thin": Side(style="thin", color=border_color),
            "medium": Side(style="medium", color=border_color),
            "thick": Side(style="thick", color=border_color),
            "double": Side(style="double", color=border_color),
            "dotted": Side(style="dotted", color=border_color),
            "dashed": Side(style="dashed", color=border_color)
        }
        
        side = border_styles[border_style]
        normal_border = Border(left=side, right=side, top=side, bottom=side)
        
        # 如果有表头,为表头设置特殊边框
        if has_header and min_row < max_row:
            header_bottom = Side(style="double" if border_style == "thin" else border_style, color=border_color)
            header_border = Border(
                left=side, 
                right=side, 
                top=side, 
                bottom=header_bottom
            )
            
            # 为表头应用边框
            for col in range(min_col, max_col + 1):
                cell = sheet.cell(row=min_row, column=col)
                cell.border = header_border
            
            # 为数据行应用边框
            for row in range(min_row + 1, max_row + 1):
                for col in range(min_col, max_col + 1):
                    cell = sheet.cell(row=row, column=col)
                    cell.border = normal_border
        else:
            # 没有表头,为所有单元格应用相同边框
            for row in range(min_row, max_row + 1):
                for col in range(min_col, max_col + 1):
                    cell = sheet.cell(row=row, column=col)
                    cell.border = normal_border
        
        # 保存工作簿
        wb.save(excel_file)
        wb.close()
        
        # 打印设置的数据范围信息
        range_address = f"{get_column_letter(min_col)}{min_row}:{get_column_letter(max_col)}{max_row}"
        print(f"已为数据范围 {range_address} 设置边框")
        
        # 重新打开Excel文件
        excel = win32com.client.Dispatch("Excel.Application")
        excel.Visible = True
        workbook = excel.Workbooks.Open(excel_file)
        
        # 选择之前的工作表
        if sheet_name:
            worksheet = workbook.Worksheets(sheet_name)
            worksheet.Activate()
        
        # 选中设置了边框的区域
        cell_range = worksheet.Range(
            worksheet.Cells(min_row, min_col),
            worksheet.Cells(max_row, max_col)
        )
        cell_range.Select()
        
        # 不关闭Excel,让它保持打开状态
        print(f"Excel文件已打开,并已设置数据区域边框")
        
        return excel_file
        
    except Exception as e:
        # 确保在出错时关闭Excel
        try:
            if 'workbook' in locals():
                workbook.Close(False)
            if 'excel' in locals():
                excel.Quit()
        except:
            pass
        raise Exception(f"设置Excel边框时出错: {str(e)}")

效果如下
在这里插入图片描述

在这里插入图片描述