Python实现Excel数据追加至CSV时列移位的代码问题求助
问题排查与修复方案
核心问题分析
你的代码出现数据偏移、原有列被覆盖的现象,根源是两个DataFrame的列名不匹配:
- 从CSV加载的
latest_df使用文件自带的表头作为列名 - 从Excel提取的
data_df使用默认的数字索引(0、1...87)作为列名
当执行pd.concat([latest_df, data_df], ignore_index=True)时,Pandas会按列名对齐,将两个DataFrame的所有列合并,导致原有CSV数据和新提取数据分别位于不同列组,看起来像是原有数据被右移,前88列被替换。
此外,代码还存在两个潜在问题:
- 重复打开/关闭Excel文件,可能引发文件锁定或缓存读取问题
- 提取Excel数据时未区分表头与数据行,可能导致结构混乱
修复后的代码
import os import datetime import win32com.client as win32 import pandas as pd # 路径配置 network_path_endfile = r"K:\folder\name\endfile.xlsm" network_folder_path_output = r"C:\folder2\name2\files" # 初始化Excel应用 excel_app = win32.Dispatch('Excel.Application') excel_app.Visible = False # 优化宏执行:单次打开文件运行多个宏,减少文件操作 def run_macros(workbook_path, macro_names): workbook = excel_app.Workbooks.Open(workbook_path) for macro in macro_names: excel_app.Application.Run(f"'{workbook.Name}'!{macro}") workbook.Save() workbook.Close() # 执行初始宏 run_macros(network_path_endfile, ['ProcessReports', 'DeleteRowsByCurrentMonthYear']) # 获取上一工作日日期 today = datetime.datetime.today() previous_business_day = today - datetime.timedelta(days=1) # 处理周一的情况(回到上周五) if today.weekday() == 0: previous_business_day -= datetime.timedelta(days=2) previous_business_day_str = previous_business_day.strftime('%Y%m%d') # 定位目标CSV文件 target_csv_name = f"concatenated_file_123_as_of_{previous_business_day_str}.csv" target_csv_path = os.path.join(network_folder_path_output, target_csv_name) # 加载CSV数据 latest_df = pd.read_csv(target_csv_path) # 用Pandas读取Excel的1-88列(A到CH列),自动匹配列名 # 若Excel无表头,设置header=None后手动指定列名与CSV一致 data_df = pd.read_excel(network_path_endfile, usecols="A:CH", header=None) data_df.columns = latest_df.columns # 强制对齐列名 # 追加数据(此时列名完全匹配,会按行追加) updated_df = pd.concat([latest_df, data_df], ignore_index=True) # 保存更新后的CSV updated_df.to_csv(target_csv_path, index=False) # 执行最终宏并关闭Excel run_macros(network_path_endfile, ['deleteall']) excel_app.Quit()
关键修复点说明
- 统一列名对齐:通过
data_df.columns = latest_df.columns强制让Excel提取的数据使用与CSV完全一致的列名,确保pd.concat按行追加而非合并列 - 优化宏执行逻辑:将多次打开/关闭Excel文件改为单次打开运行多个宏,避免文件访问冲突
- 简化Excel数据读取:用
pd.read_excel替代openpyxl,更高效且便于列名控制 - 明确列范围:用
usecols="A:CH"直接指定读取1-88列,避免索引错误
额外注意事项
- 如果endfile.xlsm的第一行是表头,需将
pd.read_excel的header参数改为0,并移除data_df.columns = latest_df.columns,避免重复设置表头 - 若需要处理节假日的上一工作日,需引入第三方库(如
holidays)来排除法定节假日 - 运行代码前确保目标文件未被其他程序锁定
内容的提问来源于stack exchange,提问作者Sam Smith
相关产品推荐
相关产品推荐

