如何使用pandas将数据写入现有的Excel文件而不覆盖原有数据?

165

我使用pandas以以下方式将数据写入Excel文件:

import pandas

writer = pandas.ExcelWriter('Masterfile.xlsx') 

data_filtered.to_excel(writer, "Main", cols=['Diff1', 'Diff2'])

writer.save()

Masterfile.xlsx已经包含许多不同的选项卡。但是,它还没有包含“主要”。

Pandas正确地写入了“Main”工作表,但不幸的是它也删除了所有其他选项卡。


1
你能给一个ExcelReader的例子吗?我在文档中没有找到类似的东西。 - BP_
1
我认为在pandas中没有ExcelReader这样的东西。我使用read_excel从excel中读取数据。我不认为它会将数据保存到excel中。 - BP_
1
@nrathaus 看起来没有 ExcelReader - virtualxtc
请注意,有些答案对问题的要求存在一些混淆。有些答案假设“Main”尚不存在,而OP只是在现有的Excel工作簿中添加一个新工作表。其他人则认为“Main”已经存在,并且OP想要将新数据附加到“Main”的底部。 - T.C. Proctor
17个回答

1
def append_sheet_to_master(self, master_file_path, current_file_path, sheet_name):
    try:
        master_book = load_workbook(master_file_path)
        master_writer = pandas.ExcelWriter(master_file_path, engine='openpyxl')
        master_writer.book = master_book
        master_writer.sheets = dict((ws.title, ws) for ws in master_book.worksheets)
        current_frames = pandas.ExcelFile(current_file_path).parse(pandas.ExcelFile(current_file_path).sheet_names[0],
                                                               header=None,
                                                               index_col=None)
        current_frames.to_excel(master_writer, sheet_name, index=None, header=False)

        master_writer.save()
    except Exception as e:
        raise e

这个工作完全没有问题,唯一的问题是主文件(我们向其添加新表的文件)的格式会丢失。

0

我建议使用xlwings(https://docs.xlwings.org/en/stable/api.html),它非常适用于这个应用程序... 这是我的使用方法:

import xlwings as xw
import pandas as pd
import xlsxwriter

# function to get the active workbook
def getActiveWorkbook():
    try:
        # logic from xlwings to grab the current excel file
        activeWb = xw.books.active
    except:
        # print error message if unable to get the current workbook
        print('Unable to grab the current Workbook')
        pause()
        exitProgram()
    else:
        return activeWb

# function that returns the last row number and last cell of a sheet
def getLastRow(myBook, sheetName):
    lastRow = myBook.sheets[sheetName].range("A1").current_region.last_cell.row
    lastCol = str(xlsxwriter.utility.xl_col_to_name(myBook.sheets[sheetName].range("A1").current_region.last_cell.column))
    return str(lastRow), lastCol + str(lastRow)

activeWb = getActiveWorkbook()
df = pd.DataFrame(data=[1,2,3])

# look at worksheet = Part Number Status
sheetName = "Sheet1"
ws = activeWb.sheets[sheetName]
lastRow, lastCell = getLastRow(activeWb, sheetName)
if int(lastRow) > 1:
    ws.range("A1:" + lastCell).clear()
ws.range("A1").options(index=False, header=False).value = df.fillna('')

这对我的应用程序似乎非常有效,因为 .xlsm 工作簿可能非常棘手。您可以将其作为 Python 脚本执行,或使用 pyinstaller 将其转换为可执行文件,然后通过 Excel 宏运行 .exe。您还可以使用非常有用的 xlwings 从 Python 调用 VBA 宏。


但它是否会在同一张表上写入更多数据,还是创建一个新的表而不删除旧表?我已经处理了一段时间了。尝试了几乎所有应该适用于此的方法,但由于某种原因,在我的数据上无法正常工作。 - vanetoj
1
@vanetoj 你试过这个吗?我用它来写入已存在的工作表,你甚至可以使用getLastRow函数将数据写入到一个列的底部或带有预先存在数据的行的末尾。或者,如果你想要的话,你可以稍微修改它来创建一个新的工作表。 - smichael_44
1
@vanetoj 所以 ws = activeWb.sheets [sheetName] 这行代码将 ws 设置为现有工作表。 我认为,如果您改用 ws = activeWb.sheets.add(name="NameOfNewSheet", before="sheetName", after="sheetName") ,您仍然可以使用 ws.range("A1").options(index=False, header=False).value = df.fillna('') 将数据框发送到该 ws。 在这里查看文档 - smichael_44
1
@vanetoj 所以我从未有过使用它的应用程序,但我非常确定 ws.range("A1").options(index=False, header=False).value = df.fillna('') 可以重写为类似于 ws.range("A1").options(index=False, header=False, chunksize=###).value = df.fillna('')。然后这是 range().options(chunksize=) 的定义——使用一个块大小,例如 10000,以防止读取或写入大量数据时出现超时或内存问题。适用于所有格式,包括 DataFrames、NumPy 数组和列表。 - smichael_44
谢谢 - 我会在尝试后告诉你! - vanetoj
显示剩余2条评论

0
2023年:简短回答(pandas 1.3.0+)
仅更新单元格的值,保持格式和其他单元格不变。
with pd.ExcelWriter('my-existing-file.xlsx', engine='openpyxl', mode="a",
                    if_sheet_exists="overlay"  # => update value only
                    ) as writer:
    df.to_excel(writer, sheet_name="my-existing-sheet", index=None, startcol=2, startrow=3)  # Start at C4 

0
book = load_workbook(xlsFilename)
writer = pd.ExcelWriter(self.xlsFilename)
writer.book = book
writer.sheets = dict((ws.title, ws) for ws in book.worksheets)
df.to_excel(writer, sheet_name=sheetName, index=False)
writer.save()

3
虽然这可能会回答作者的问题,但它缺少一些解释性的文字和/或文档链接。没有一些围绕着原始代码片段的短语是不太有帮助的。您还可以在如何撰写好的答案中找到很有帮助的信息。请编辑您的回答。 - Roy Scheffers

0

@MaxU的解决方案非常好。我只有一个建议:

如果指定truncate_sheet=True,则不应保留现有表中的“startrow”。 我建议:

        if startrow is None and sheet_name in writer.book.sheetnames:
            if not truncate_sheet: # truncate_sheet would use startrow if provided (or zero below)
                startrow = writer.book[sheet_name].max_row


-1

使用pandas,您可以通过使用pandas.DataFrame.to_excel()方法并将模式参数指定为'a'(追加模式),而无需覆盖数据来向现有的Excel文件写入内容。

以下是一个示例:

import pandas as pd

# Create a sample DataFrame
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]})

# Write the DataFrame to an existing Excel file in append mode
df.to_excel('existing_file.xlsx', engine='openpyxl', mode='a', index=False, sheet_name='Sheet1')

类型错误:to_excel()函数收到了一个意外的关键字参数'mode'。 - undefined

-1

方法:

  • 如果不存在,可以创建文件
  • 根据工作表名称追加到现有的 Excel 中
import pandas as pd
from openpyxl import load_workbook

def write_to_excel(df, file):
    try:
        book = load_workbook(file)
        writer = pd.ExcelWriter(file, engine='openpyxl') 
        writer.book = book
        writer.sheets = dict((ws.title, ws) for ws in book.worksheets)
        df.to_excel(writer, **kwds)
        writer.save()
    except FileNotFoundError as e:
        df.to_excel(file, **kwds)

使用方法:

df_a = pd.DataFrame(range(10), columns=["a"])
df_b = pd.DataFrame(range(10, 20), columns=["b"])
write_to_excel(df_a, "test.xlsx", sheet_name="Sheet a", columns=['a'], index=False)
write_to_excel(df_b, "test.xlsx", sheet_name="Sheet b", columns=['b'])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接