Python使用pandas分类保存.xlsm宏Excel文件后文件损坏问题求助
问题原因
- 你代码中保存的是预先定义的空
DataFrame对象,没有写入原文件任何内容,生成的是空文件,所以打开时报错。 - pandas的
to_excel方法默认不支持保留xlsm文件的宏、控件、隐藏表等特殊内容,即使写入读取到的表格内容,也会丢失宏信息导致文件损坏。 - 逻辑错误:你循环遍历每张工作表判断条件,每判断一张表就覆盖写入一次文件,同一个文件会被反复覆盖,逻辑混乱。
修复方案
你的需求是仅判断文件内容、原封不动分类保存原文件,完全不需要用pandas写入文件,只需要在判断完条件后,直接复制原文件到对应目录即可。
修复后的代码如下:
from pathlib import Path import time import argparse import pandas as pd import os import shutil import warnings warnings.filterwarnings("ignore") parser = argparse.ArgumentParser(description="Classify xlsm files by specified field.") parser.add_argument("path", help="define the directory to folder/file") parser.add_argument("--verbose", help="display processing information") def main(path_xlsm, verbose): # 定义目标目录,不存在则创建 peel_path = Path("C:\\Users\\ShantanuGupta\\Desktop\\Incoming\\Peel") resolution_path = Path("C:\\Users\\ShantanuGupta\\Desktop\\Incoming\\Resolution") peel_path.mkdir(parents=True, exist_ok=True) resolution_path.mkdir(parents=True, exist_ok=True) # 读取所有待处理xlsm文件 if (".xlsm" in str(path_xlsm).lower()) and path_xlsm.is_file(): xlsm_files = [Path(path_xlsm)] else: xlsm_files = list(Path(path_xlsm).glob("*.xlsm")) for fn in xlsm_files: match_flag = False # 读取文件所有工作表判断条件 all_dfs = pd.read_excel(fn, sheet_name=None, header=None, engine="openpyxl") # 排除不需要判断的工作表 for skip_sheet in ["Lookups", "Instructions For Use", "Drop Down Boxes", "ResolutionLookups"]: all_dfs.pop(skip_sheet, None) # 遍历剩余工作表判断是否符合条件 for ws_name, df1 in all_dfs.items(): try: if df1.iloc[3, 0] == "Client Representative" and df1.iloc[4, 1] == "DATE" and df1.iloc[4, 3] == "SHIFT": match_flag = True break # 找到符合条件的表就跳出循环 except IndexError: # 部分工作表行数/列数不足,跳过判断 continue # 按判断结果复制原文件到对应目录 if match_flag: target_path = peel_path / fn.name else: target_path = resolution_path / fn.name shutil.copy2(fn, target_path) # copy2会保留文件原属性 if verbose: print(f"文件{fn.name}已分类到{target_path.parent}") if __name__ == "__main__": start = time.time() args = parser.parse_args() path = Path(args.path) verbose = args.verbose main(path, verbose) print("处理总耗时:", time.time() - start)
修复说明
- 新增
shutil.copy2直接复制原文件,100%保留原文件的所有内容、宏、属性信息,不会损坏文件 - 优化了判断逻辑,同一个文件只需判断到符合条件的工作表就停止判断,避免重复操作
- 新增目录自动创建逻辑,目标目录不存在时会自动生成,不会报路径不存在错误
- 新增索引错误捕获,避免部分工作表行列数不足导致代码报错
内容的提问来源于stack exchange,提问作者gupta
相关产品推荐
相关产品推荐

