You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python pandas写入Excel格式被覆盖:如何实现数据追加?

问题:Excel追加数据时保留原格式与表头说明信息

使用Python 3.11.5结合os与pandas开发项目,需求如下:

  • 读取9个源文件,将每个文件中File NameX和File CategoryX(X为1-26)对应的数据,迁移至对应dest (X).xlsx文件的ITEM_DOCUMENT和ITEM_DOCUMENT_TYPE列
  • 目标文件第一行为分析师说明信息,第二行为表头,数据从第三行开始,初始无数据

当前代码运行后出现问题:目标文件虽保留表头,但第一行分析师信息丢失、部分字体样式(如红粗变黑粗)被修改、列宽改变,并非单纯追加数据。核心代码如下:

for i, (file_name_col, file_category_col) in \
                enumerate(zip(file_name_cols, file_category_cols), start=1):
                dest_file = os.path.join(dest_folder, f"dest ({i}).xlsx")

                # Check Column Existence:
                file_name_col = f'File Name{i}'
                file_category_col = f'File Category{i}'

                if file_name_col in source_data.columns and \
                    file_category_col in source_data.columns:
                    # Create destination DataFrame with specified headers if the file doesn't exist
                    if not os.path.isfile(dest_file):
                        dest_columns = ['PART_NUMBER', 'LANGUAGE_CODE', 'MANUFACTURER_NAME',
                                        'BRAND_NAME', 'ITEM_DOCUMENT', 'ITEM_DOCUMENT_TYPE']
                        dest_data = pd.DataFrame(columns=dest_columns)
                        dest_data.to_excel(dest_file, index=False)

                    # Read the existing destination data or
                    # create an empty DataFrame if the file doesn't exist
                    dest_data = pd.read_excel(dest_file, header=1) \
                        if os.path.isfile(dest_file) else pd.DataFrame()

                    dest_columns = ['PART_NUMBER', 'LANGUAGE_CODE', 'MANUFACTURER_NAME',
                                    'BRAND_NAME', 'ITEM_DOCUMENT', 'ITEM_DOCUMENT_TYPE']

                    # Ensure that the destination file has the required columns
                    for col in dest_columns:
                        if col not in dest_data.columns:
                            dest_data[col] = ''

                    new_data = source_data[['PART_NUMBER', 'LANGUAGE_CODE', \
                        'MANUFACTURER_NAME', 'BRAND_NAME']].copy()
                    new_data['ITEM_DOCUMENT'] = source_data[file_name_col].copy()
                    new_data['ITEM_DOCUMENT_TYPE'] = \
                        new_data['ITEM_DOCUMENT'].apply(determine_document_type)

                    # Append new data to the existing destination file
                    dest_data = pd.concat([dest_data, new_data], ignore_index=True)

                    # Write the combined data to the destination file
                    dest_data.to_excel(dest_file, index=False, sheet_name='Sheet1', engine='openpyxl')
                else:
                    # Handle the case where the columns don't exist
                    raise ValueError(f"Columns '{file_name_col}' \
                                    and/or '{file_category_col}' do not exist in source_data.")
解决方案:使用openpyxl直接操作工作簿,保留原格式

问题根源在于pandas.to_excel()会重新生成整个Excel文件,覆盖原有格式和非数据行(第一行的分析师说明)。解决思路是用openpyxl直接操作现有工作簿,仅追加数据行,完全保留原有样式。

步骤说明

  1. 处理目标文件不存在的情况:如果文件未创建,先通过openpyxl生成包含分析师说明、表头的模板文件,并设置好所需格式(如表头字体红粗)
  2. 打开现有工作簿:保留所有原有格式、列宽、说明行
  3. 定位数据起始行:找到当前数据的最后一行,从下一行开始写入新数据
  4. 逐行写入新数据:将pandas处理好的新数据逐行写入工作簿,不修改原有格式

修改后的核心代码

import openpyxl
from openpyxl.styles import Font, Alignment

# ... 其他原有代码(读取源数据、处理new_data的部分保持不变)

for i, (file_name_col, file_category_col) in enumerate(zip(file_name_cols, file_category_cols), start=1):
    dest_file = os.path.join(dest_folder, f"dest ({i}).xlsx")
    file_name_col = f'File Name{i}'
    file_category_col = f'File Category{i}'

    if file_name_col in source_data.columns and file_category_col in source_data.columns:
        # 处理目标文件不存在的情况:创建带格式的模板
        if not os.path.isfile(dest_file):
            wb = openpyxl.Workbook()
            ws = wb.active
            ws.title = 'Sheet1'
            
            # 写入第一行:分析师说明信息(根据实际内容修改)
            ws['A1'] = "分析师说明:此文件用于存放对应类文档数据,请勿随意修改格式"
            ws['A1'].font = Font(bold=True)
            ws.merge_cells('A1:F1')  # 合并第一行所有列
            ws['A1'].alignment = Alignment(horizontal='left')
            
            # 写入第二行:表头
            dest_columns = ['PART_NUMBER', 'LANGUAGE_CODE', 'MANUFACTURER_NAME',
                            'BRAND_NAME', 'ITEM_DOCUMENT', 'ITEM_DOCUMENT_TYPE']
            for col_idx, col_name in enumerate(dest_columns, start=1):
                cell = ws.cell(row=2, column=col_idx, value=col_name)
                cell.font = Font(bold=True, color='FF0000')  # 设置红粗字体
                # 自定义列宽(根据实际需求调整)
                ws.column_dimensions[openpyxl.utils.get_column_letter(col_idx)].width = 20
            
            wb.save(dest_file)
        
        # 打开现有工作簿,保留格式
        wb = openpyxl.load_workbook(dest_file)
        ws = wb['Sheet1']
        
        # 找到当前数据的最后一行(数据从第3行开始)
        last_row = ws.max_row
        start_row = last_row + 1 if last_row >=2 else 3
        
        # 处理新数据(原有逻辑不变)
        new_data = source_data[['PART_NUMBER', 'LANGUAGE_CODE', 
                                'MANUFACTURER_NAME', 'BRAND_NAME']].copy()
        new_data['ITEM_DOCUMENT'] = source_data[file_name_col].copy()
        new_data['ITEM_DOCUMENT_TYPE'] = new_data['ITEM_DOCUMENT'].apply(determine_document_type)
        
        # 逐行写入新数据
        for _, row in new_data.iterrows():
            for col_idx, col_name in enumerate(new_data.columns, start=1):
                ws.cell(row=start_row, column=col_idx, value=row[col_name])
            start_row += 1
        
        # 保存工作簿
        wb.save(dest_file)
    else:
        raise ValueError(f"Columns '{file_name_col}' and/or '{file_category_col}' do not exist in source_data.")

关键注意点

  • 若目标文件是预先设置好格式的模板,可直接跳过“创建模板”的步骤,直接打开模板文件进行追加
  • 列宽、字体样式等可根据实际需求调整,代码中已给出示例
  • 使用openpyxl.load_workbook()时默认保留原有格式,不会覆盖任何非数据内容

内容的提问来源于stack exchange,提问作者workhorse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 21:24:51