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

按城市过滤DataFrame数据并导入带格式Excel模板时,仅首个城市生效的问题排查

按城市过滤DataFrame数据并导入带格式Excel模板时,仅首个城市生效的问题排查

看起来你已经搭好了核心的数据过滤逻辑,但遇到了后续城市无法正确写入Excel模板的问题,我帮你梳理下代码里的几个关键问题,以及对应的修复方案:

一、核心问题分析

你的代码里有几个细节错误,导致只有第一个城市能正常生成文件,后续城市复用了错误的状态或者计算逻辑:

  1. last_row变量未正确初始化与重置
    每次处理新城市时,你需要重新从模板的Ind工作表中计算最后一行的位置,而不是沿用之前循环的last_row值。当前代码里last_row在第一次循环后会保留上一次的结果,导致后续写入位置错误,甚至可能跳过写入。

  2. 拼写错误导致的逻辑异常

    • 原DataFrame里的列是County,但代码里写的是df_city['Country'].unique(),这会导致KeyError(除非你实际数据里有Country列),如果是笔误的话需要修正。
    • 写入单元格时的参数错误:sheet.cell(rows=last_row+index,column=col,value=value)里的rows应该是row,这个拼写错误会导致写入失败。
  3. 模板数据写入逻辑顺序错误
    你在循环写入模板数据的同时,反复设置sheet.cell(row=2,column=2,value=accountname),这会覆盖之前的设置,而且应该在写入数据前先处理这类固定值。

  4. vote_startdate变量未定义
    代码里使用了vote_startdate但没有看到定义,这会导致运行报错,需要补充这个变量的定义。

二、修复后的完整代码

我把这些问题都修正了,你可以参考下面的代码:

import pandas as pd
from openpyxl import load_workbook
# 补充定义vote_startdate,这里假设你有一个datetime对象,可根据实际情况修改
from datetime import datetime
vote_startdate = datetime.now()

df = pd.DataFrame({
    'State': ['Colorado', 'Colorado', 'Colorado', 'Colorado'], 
    'County': ['Denver', 'El Paso', 'Larimar', 'Larimar'],
    'City': ['Denver', 'Colorado Springs', 'Fort Collins', 'Loveland']
})

for city_name in df['City'].unique():
    df_city = df[df['City'] == city_name]
    # 修正County的拼写错误
    for val in df_city['County'].unique():
        accountname = val
        # 创建模板DataFrame,修正Country为County
        template = pd.DataFrame(columns=['State','County','City','Pincode','Corporater','Population'])
        template['State'] = df_city['State']
        template['County'] = df_city['County']
        template['City'] = df_city['City']
        template['Pincode'] = ''
        template['Corporater'] = 'Mr.'
        template['Population'] = ''
        template = template.reset_index(drop=True)  # 加上drop=True避免保留原索引列
        
        # 每次处理新城市时,重新加载干净的模板文件
        workbook = load_workbook('Master.xlsm', keep_vba=True)
        sheet = workbook['Ind']
        
        # 计算Ind工作表中第6列(Population)最后一个非空行的位置
        last_row = 0
        for row in range(sheet.max_row, 0, -1):
            if sheet.cell(row=row, column=6).value is not None:
                last_row = row
                break
        # 从下一行开始写入数据
        start_row = last_row + 1
        
        # 先设置固定值
        sheet.cell(row=2, column=2, value=accountname)
        title1 = f"{vote_startdate.strftime('%d%d%y')}"
        # 这里可以根据需要设置title1的位置,比如sheet.cell(row=?, column=?, value=title1)
        
        # 写入模板数据
        for index, row in template.iterrows():
            # 从第2列开始写入(对应State列)
            for col_idx, value in enumerate(row, start=2):
                # 修正rows为row,计算当前写入的行号:start_row + index
                sheet.cell(row=start_row + index, column=col_idx, value=value)
        
        # 删除多余行(如果需要保留113行的话)
        if start_row + len(template) < 113:
            num_rows_to_delete = 113 - (start_row + len(template))
            sheet.delete_rows(start_row + len(template), num_rows_to_delete)
        
        # 处理Rule工作表
        sheet_rule = workbook['Rule']
        sheet_rule.cell(row=3, column=2, value=vote_startdate.strftime("%b%y"))
        
        # 处理Front Page工作表
        sheet_front = workbook['Front Page']
        sheet_front.cell(row=5, column=2, value=accountname)
        
        # 修正输出文件名的语法错误(多了一个})
        output_filename = f'{city_name[0]}_{accountname}.xlsm'
        workbook.save(output_filename)

三、关键修改点说明

  • 重置last_row计算:每次加载模板后,重新计算Ind工作表的最后非空行,确保从正确的位置开始写入数据。
  • 修正拼写错误:把Country改为County,rows改为row,修复文件名的语法错误。
  • 调整写入顺序:先设置固定值(比如accountname),再写入数据,避免重复覆盖。
  • 明确索引处理:reset_index(drop=True)避免把原索引列写入Excel。
  • 每次重新加载模板:确保每个城市处理的都是干净的原始模板,不会被之前的修改影响。

备注:内容来源于stack exchange,提问作者Sandeep Moholkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 15:48:08