如何用Python更新Excel指定工作表且不删除其他工作表?
问题与解决方案
问题背景
我有一个包含3个工作表的Excel文件:
- 第一个工作表(员工部门表)内容:
Name Dept John Smith candy Diana Princ candy Tyler Perry candy Perry Plat wood Jerry Springer clothes Calvin Klein clothes Mary Poppins clothes Ivan Evans clothes Lincoln Tun warehouse Oliver Twist kitchen Herman Sherman kitchen
- 第二个工作表(Depts Responded)内容:
Depts Responded candy wood clothes warehouse kitchen
- 第三个工作表(Depts Not Responded)内容:
Depts Not Responded chocolate vanilla computers
我需要用Python更新该表格,比如把chocolate从「未响应部门」移到「已响应部门」,但原代码运行后会删除第一个工作表,且新数据带有索引编号,需求是仅编辑指定工作表、保留原工作表、去掉索引编号。
原代码如下:
from openpyxl import load_workbook import pandas as pd import os, csv, sys excel_data = 'file.xlsx' responded = ['candy', 'wood', 'clothes', 'warehouse', 'kitchen','chocolate'] not_responded = ['vanilla', 'computers'] test_nr = pd.DataFrame(not_responded) test_r = pd.DataFrame(responded) # 此处存在未定义变量:notemp_df、empty_df,运行会报错 test_r = notemp_df.rename({0: 'Depts Responded'}, axis=1) test_nr = empty_df.rename({0: 'Depts Not Responded'}, axis=1) test_nr = test_nr.reset_index(drop=True) test_r = test_r.reset_index(drop=True) # create excel writer object writer = pd.ExcelWriter(excel_data) test_nr.to_excel(writer, 'Departments Not Responded') test_r.to_excel(writer, 'Departments Responded') # save the excel file writer.save() writer.close()
运行后出现的问题:
- 原第一个工作表被删除,仅保留后两个工作表
- 表格中出现索引编号(0、1、2...)
问题分析
pd.ExcelWriter默认以覆盖模式写入文件,会清空原文件所有内容后重新写入指定工作表,导致原有的第一个工作表丢失DataFrame.to_excel()方法默认参数index=True,会把DataFrame的索引写入表格,产生多余的编号- 代码中存在未定义变量
notemp_df和empty_df,属于语法错误,无法正常运行
可行解决方案
方案1:基于openpyxl的直接编辑(修正你的代码)
openpyxl可以直接加载原Excel文件,仅修改指定工作表,不会影响其他工作表。以下是修正并优化后的代码:
from openpyxl import load_workbook def clear_sheet_content(sheet): # 保留表头,删除所有数据行 while sheet.max_row > 1: sheet.delete_rows(2) excel_data = 'file.xlsx' output_file = 'output.xlsx' # 更新后的部门列表 responded = ['candy', 'wood', 'clothes', 'warehouse', 'kitchen', 'chocolate'] not_responded = ['vanilla', 'computers'] # 加载原工作簿 wb = load_workbook(excel_data) # 处理「Depts Not Responded」工作表 ws_nr = wb['Depts Not Responded'] clear_sheet_content(ws_nr) # 写入新数据 for idx, dept in enumerate(not_responded, start=2): # 从第2行开始写入(第1行是表头) ws_nr.cell(row=idx, column=1, value=dept) # 处理「Depts Responded」工作表 ws_r = wb['Depts Responded'] clear_sheet_content(ws_r) # 写入新数据 for idx, dept in enumerate(responded, start=2): ws_r.cell(row=idx, column=1, value=dept) # 保存到新文件(也可以直接覆盖原文件,建议先备份) wb.save(output_file)
方案2:Pandas结合openpyxl保留原工作表
如果习惯用Pandas处理数据,可以使用mode='a'(追加模式)结合engine='openpyxl',同时设置index=False去掉索引:
import pandas as pd excel_data = 'file.xlsx' output_file = 'output.xlsx' responded = ['candy', 'wood', 'clothes', 'warehouse', 'kitchen', 'chocolate'] not_responded = ['vanilla', 'computers'] # 转换为DataFrame并设置表头 df_responded = pd.DataFrame(responded, columns=['Depts Responded']) df_not_responded = pd.DataFrame(not_responded, columns=['Depts Not Responded']) # 加载原工作簿,指定engine为openpyxl,模式为追加 with pd.ExcelWriter(output_file, engine='openpyxl', mode='a', if_sheet_exists='replace') as writer: # 写入时去掉索引 df_responded.to_excel(writer, sheet_name='Depts Responded', index=False) df_not_responded.to_excel(writer, sheet_name='Depts Not Responded', index=False)
说明:
if_sheet_exists='replace'会替换原有工作表的内容,而不是新增工作表mode='a'会保留原工作簿中的所有其他工作表(即第一个员工部门表不会丢失)index=False避免写入DataFrame的索引编号
内容的提问来源于stack exchange,提问作者noobCoder
相关产品推荐
相关产品推荐

