Làm thế nào để ghi vào một tệp excel hiện có mà không ghi đè dữ liệu (sử dụng gấu trúc)?


120

Tôi sử dụng pandas để ghi vào tệp excel theo kiểu sau:

import pandas

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

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

writer.save()

Masterfile.xlsx đã bao gồm một số tab khác nhau. Tuy nhiên, nó vẫn chưa chứa "Main".

Pandas ghi đúng vào trang "Chính", tiếc là nó cũng xóa tất cả các tab khác.


1
bạn có thể cho một ví dụ hoặc ExcelReader không? Tôi không tìm thấy bất cứ điều gì như thế này trong tài liệu.
BP_

1
Tôi nghĩ rằng không có thứ gì giống như ExcelReader ở gấu trúc. Tôi sử dụng read_excel để đọc dữ liệu từ excel. Tôi không nghĩ rằng nó sẽ lưu dữ liệu để vượt trội.
BP_

1
@nrathaus có vẻ không phải là mộtExcelReader
virtualxtc

Lưu ý rằng có một số nhầm lẫn trong các câu trả lời về những gì chính xác câu hỏi đang hỏi. Một số câu trả lời giả định rằng "Main" chưa tồn tại và OP chỉ đơn giản là thêm một trang tính mới vào sổ làm việc excel hiện có. Những người khác cho rằng "Main" đã tồn tại và OP muốn nối thêm dữ liệu mới vào cuối "Main".
TC Proctor

Câu trả lời:


143

Pandas docs cho biết nó sử dụng openpyxl cho các tệp xlsx. Xem nhanh qua mã trong ExcelWritercung cấp manh mối rằng một cái gì đó như thế này có thể hoạt động:

import pandas
from openpyxl import load_workbook

book = load_workbook('Masterfile.xlsx')
writer = pandas.ExcelWriter('Masterfile.xlsx', engine='openpyxl') 
writer.book = book

## ExcelWriter for some reason uses writer.sheets to access the sheet.
## If you leave it empty it will not know that sheet Main is already there
## and will create a new sheet.

writer.sheets = dict((ws.title, ws) for ws in book.worksheets)

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

writer.save()

2
Bạn có thể vui lòng giải thích writer.sheets là gì không?
BP_

5
ExcelWriter vì một số lý do sử dụng biến này để truy cập trang tính. Nếu bạn để trống nó sẽ không biết rằng trang tính Chính đã ở đó và sẽ tạo một trang tính mới.
Trượt tuyết vào

2
Giải pháp này hoạt động tốt. Nó có một nhược điểm. Nó phá vỡ các công thức và kết nối trong bảng tính. Bất kỳ ý tưởng làm thế nào để thay đổi hành vi này?
BP_

1
Chính xác thì bạn bị hỏng cái gì ..? Bạn có thể hỏi đây là một câu hỏi riêng biệt và gắn thẻ nó openpyxlvà cung cấp đủ thông tin chi tiết: bạn có loại công thức nào, dữ liệu được cập nhật như thế nào, nó hãm các công thức như thế nào. Bây giờ tôi chỉ không thể giúp đỡ, quá nhiều điều tôi không biết.
Trượt tuyết vào

2
nó có thể được sử dụng với các tệp .xlsm thay thế không?
dapaz

39

Đây là một chức năng trợ giúp:

def append_df_to_excel(filename, df, sheet_name='Sheet1', startrow=None,
                       truncate_sheet=False, 
                       **to_excel_kwargs):
    """
    Append a DataFrame [df] to existing Excel file [filename]
    into [sheet_name] Sheet.
    If [filename] doesn't exist, then this function will create it.

    Parameters:
      filename : File path or existing ExcelWriter
                 (Example: '/path/to/file.xlsx')
      df : dataframe to save to workbook
      sheet_name : Name of sheet which will contain DataFrame.
                   (default: 'Sheet1')
      startrow : upper left cell row to dump data frame.
                 Per default (startrow=None) calculate the last row
                 in the existing DF and write to the next row...
      truncate_sheet : truncate (remove and recreate) [sheet_name]
                       before writing DataFrame to Excel file
      to_excel_kwargs : arguments which will be passed to `DataFrame.to_excel()`
                        [can be dictionary]

    Returns: None
    """
    from openpyxl import load_workbook

    # ignore [engine] parameter if it was passed
    if 'engine' in to_excel_kwargs:
        to_excel_kwargs.pop('engine')

    writer = pd.ExcelWriter(filename, engine='openpyxl')

    # Python 2.x: define [FileNotFoundError] exception if it doesn't exist 
    try:
        FileNotFoundError
    except NameError:
        FileNotFoundError = IOError


    try:
        # try to open an existing workbook
        writer.book = load_workbook(filename)

        # get the last row in the existing Excel sheet
        # if it was not specified explicitly
        if startrow is None and sheet_name in writer.book.sheetnames:
            startrow = writer.book[sheet_name].max_row

        # truncate sheet
        if truncate_sheet and sheet_name in writer.book.sheetnames:
            # index of [sheet_name] sheet
            idx = writer.book.sheetnames.index(sheet_name)
            # remove [sheet_name]
            writer.book.remove(writer.book.worksheets[idx])
            # create an empty sheet [sheet_name] using old index
            writer.book.create_sheet(sheet_name, idx)

        # copy existing sheets
        writer.sheets = {ws.title:ws for ws in writer.book.worksheets}
    except FileNotFoundError:
        # file does not exist yet, we will create it
        pass

    if startrow is None:
        startrow = 0

    # write out the new sheet
    df.to_excel(writer, sheet_name, startrow=startrow, **to_excel_kwargs)

    # save the workbook
    writer.save()

LƯU Ý: đối với Gấu trúc <0.21.0, hãy thay thế sheet_namebằng sheetname!

Các ví dụ sử dụng:

append_df_to_excel('d:/temp/test.xlsx', df)

append_df_to_excel('d:/temp/test.xlsx', df, header=None, index=False)

append_df_to_excel('d:/temp/test.xlsx', df, sheet_name='Sheet2', index=False)

append_df_to_excel('d:/temp/test.xlsx', df, sheet_name='Sheet2', index=False, startrow=25)

1
Giải pháp này hoạt động hoàn hảo đối với tôi, những giải pháp khác được đăng ở đây không hoạt động. Cảm ơn rất nhiều! Chỉ một nhận xét: khi tệp không tồn tại, tôi gặp lỗi "NameError: global name 'FileNotFoundError' không được xác định"
cholo14

1
@ cholo14, cảm ơn bạn đã chỉ ra điều này! Tôi đã thử nghiệm nó trên Python 3.x, vì vậy tôi đã bỏ sót lỗi đó. Tôi đã sửa nó trong câu trả lời ...
MaxU

1
Điều này làm việc cho tôi nhưng có cách nào để duy trì định dạng xlsx (từ tệp xlsx gốc) không?
2one 11/09/19

@ 2one, tôi không biết chính xác - hãy thử hoặc đặt một câu hỏi SO mới
MaxU 11/09/19

có cách nào để ghi vào cột thay vì chỉ hàng? Giống như tôi muốn cập nhật một trang tính tự động, nhưng không thêm các hàng mới, nhưng các cột, cảm ơn!
doomdaam

21

Với openpyxlphiên bản 2.4.0pandasphiên bản 0.19.2, quy trình mà @ski đưa ra đơn giản hơn một chút:

import pandas
from openpyxl import load_workbook

with pandas.ExcelWriter('Masterfile.xlsx', engine='openpyxl') as writer:
    writer.book = load_workbook('Masterfile.xlsx')
    data_filtered.to_excel(writer, "Main", cols=['Diff1', 'Diff2'])
#That's it!

11
Điều này không hiệu quả với tôi. Nếu đã có trang tính "Chính", nó sẽ tạo một trang tính mới có tên "Main1" chỉ với dữ liệu mới và giữ nguyên nội dung trang tính "Chính".
Qululu

2
@Qululu Tôi nghĩ rằng có thể có sự nhầm lẫn về câu hỏi này giữa hai mục tiêu khác nhau. Điều này cho phép bạn thêm trang tính bổ sung vào sổ làm việc hiện có. Nó không nhằm mục đích nối thêm dữ liệu vào một trang tính hiện có. Nếu có xung đột đặt tên trang tính, nó sẽ đổi tên trang tính. Đây là một tính năng, không phải là một lỗi.
Giám đốc TC

Như @Qululu đã nói, điều này chỉ tạo ra nhiều trang tính hơn, với các tên khác nhau. Giải pháp đầu tiên, từ MaxU hoạt động và đầu ra bạn sẽ nhận được, sẽ là df trong trang tính đầu tiên, bao nhiêu lần tùy thích (điều này có nghĩa là với các tiêu đề được nhân lên nhiều lần.) Một thuật toán đơn giản: mỗi lần lặp bạn nối khung dữ liệu vào một danh sách. Cuối cùng, bạn chỉ cần nối. Nếu chúng theo cùng một cấu trúc sẽ có tác dụng như một chiếc bùa. list_my_dfs = [df1, df2, ...] # Danh sách các khung dữ liệu của bạn my_dfs_together = pd.concat (list_my_df) # ghép các khung dữ liệu của tôi trong một df
Susana Silva Santos

@SusanaSilvaSantos, hãy xem những gì TC Proctor đã nhận xét ngay trước bạn. OP muốn thêm một trang tính Không tồn tại vào một sổ làm việc hiện có. Mã này thực hiện điều đó. Việc thêm dữ liệu vào một trang tính hiện có trong sổ làm việc không phải là một phần của phạm vi. Nếu điều đó là không cần thiết, điều này là đủ.
mvbentes

16

Bắt đầu bằng pandas 0,24, bạn có thể đơn giản hóa điều này với modeđối số từ khóa là ExcelWriter:

import pandas as pd

with pd.ExcelWriter('the_file.xlsx', engine='openpyxl', mode='a') as writer: 
     data_filtered.to_excel(writer) 

3
ghi đè cho tôi.
keramat

10
@keramat Tôi nghĩ có thể có sự nhầm lẫn về câu hỏi này giữa hai mục tiêu khác nhau. Điều này cho phép bạn thêm trang tính bổ sung vào sổ làm việc hiện có. Nó không nhằm mục đích nối thêm dữ liệu vào một trang tính hiện có.
Giám đốc TC

1
mode = 'a'thêm nhiều trang tính hơn, nhưng nếu tôi muốn ghi đè dữ liệu trên các trang tính hiện có thì sao?
Nhầm lẫn

11

Câu hỏi cũ, nhưng tôi đoán một số người vẫn tìm kiếm điều này - vì vậy ...

Tôi thấy phương pháp này hay vì tất cả các trang tính đều được tải vào một từ điển gồm tên trang tính và các cặp khung dữ liệu, được tạo bởi gấu trúc với tùy chọn sheetname = None. Thật đơn giản để thêm, xóa hoặc sửa đổi trang tính giữa việc đọc bảng tính sang định dạng dict và viết lại từ dict. Đối với tôi, xlsxwriter hoạt động tốt hơn openpyxl cho tác vụ cụ thể này về tốc độ và định dạng.

Lưu ý: các phiên bản gấu trúc trong tương lai (0.21.0+) sẽ thay đổi tham số "sheetname" thành "sheet_name".

# read a single or multi-sheet excel file
# (returns dict of sheetname(s), dataframe(s))
ws_dict = pd.read_excel(excel_file_path,
                        sheetname=None)

# all worksheets are accessible as dataframes.

# easy to change a worksheet as a dataframe:
mod_df = ws_dict['existing_worksheet']

# do work on mod_df...then reassign
ws_dict['existing_worksheet'] = mod_df

# add a dataframe to the workbook as a new worksheet with
# ws name, df as dict key, value:
ws_dict['new_worksheet'] = some_other_dataframe

# when done, write dictionary back to excel...
# xlsxwriter honors datetime and date formats
# (only included as example)...
with pd.ExcelWriter(excel_file_path,
                    engine='xlsxwriter',
                    datetime_format='yyyy-mm-dd',
                    date_format='yyyy-mm-dd') as writer:

    for ws_name, df_sheet in ws_dict.items():
        df_sheet.to_excel(writer, sheet_name=ws_name)

Ví dụ trong câu hỏi năm 2013:

ws_dict = pd.read_excel('Masterfile.xlsx',
                        sheetname=None)

ws_dict['Main'] = data_filtered[['Diff1', 'Diff2']]

with pd.ExcelWriter('Masterfile.xlsx',
                    engine='xlsxwriter') as writer:

    for ws_name, df_sheet in ws_dict.items():
        df_sheet.to_excel(writer, sheet_name=ws_name)

Loại này hoạt động, tuy nhiên, các ô đã hợp nhất, màu ô và độ rộng ô của tôi không được giữ nguyên.
virtualxtc

1
Có, với phương pháp này, kiểu định dạng sẽ bị mất vì mỗi trang tính được chuyển đổi thành khung dữ liệu gấu trúc (không có định dạng excel nào trong số đó), sau đó được chuyển đổi từ khung dữ liệu sang trang tính trong một sổ làm việc excel mới (có cùng tên với bản gốc tập tin). Có vẻ như một phương pháp "chắp thêm" mới sử dụng openpyxl có thể sắp ra mắt, có thể bảo toàn định dạng trang tính tệp gốc? github.com/pandas-dev/pandas/pull/21251
b2002

11

Tôi biết đây là một chuỗi cũ hơn, nhưng đây là mục đầu tiên bạn tìm thấy khi tìm kiếm và các giải pháp trên không hoạt động nếu bạn cần giữ lại biểu đồ trong sổ làm việc mà bạn đã tạo. Trong trường hợp đó, xlwings là một lựa chọn tốt hơn - nó cho phép bạn ghi vào sổ excel và giữ các biểu đồ / dữ liệu biểu đồ.

ví dụ đơn giản:

import xlwings as xw
import pandas as pd

#create DF
months = ['2017-01','2017-02','2017-03','2017-04','2017-05','2017-06','2017-07','2017-08','2017-09','2017-10','2017-11','2017-12']
value1 = [x * 5+5 for x in range(len(months))]
df = pd.DataFrame(value1, index = months, columns = ['value1'])
df['value2'] = df['value1']+5
df['value3'] = df['value2']+5

#load workbook that has a chart in it
wb = xw.Book('C:\\data\\bookwithChart.xlsx')

ws = wb.sheets['chartData']

ws.range('A1').options(index=False).value = df

wb = xw.Book('C:\\data\\bookwithChart_updated.xlsx')

xw.apps[0].quit()

Có cách nào để tạo tệp nếu nó không tồn tại trước không?
Tinkinc

Có, bạn đã khám phá các tài liệu? docs.xlwings.org/en/stable/api.html
flymeatball

wb = xw.Book (tên tệp) trên trang web của họ cho biết nó tạo ra một cuốn sách. nhưng nó không
Tinkinc

wb = xw.Book () tạo một cuốn sách trống mới, khi bạn chuyển nó một đường dẫn, bạn đang cố tải một cuốn sách hiện có.
flymeatball

1
Lưu ý: xlwings tương tác với phiên bản Excel đang chạy và do đó không chạy trên Linux.
virtualxtc

5

Có một giải pháp tốt hơn ở gấu trúc 0,24:

with pd.ExcelWriter(path, mode='a') as writer:
    s.to_excel(writer, sheet_name='another sheet', index=False)

trước:

nhập mô tả hình ảnh ở đây

sau:

nhập mô tả hình ảnh ở đây

vì vậy hãy nâng cấp gấu trúc của bạn ngay bây giờ:

pip install --upgrade pandas

1
Đây là một bản sao của một câu trả lời sớm này
TC Proctor

1
Chỉ là cảnh báo cho tương lai, điều này không hoạt động với XslxWritertùy chọn.
metinsenturk

nó cũng không hoạt động theo mặc định engine=openpyxlvì nó sẽ chỉ thêm một trang tính mới có tênthe only worksheet1
Björn B

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

Điều này hoạt động hoàn toàn tốt chỉ có điều là định dạng của tệp chính (tệp mà chúng tôi thêm trang tính mới) bị mất.


0
writer = pd.ExcelWriter('prueba1.xlsx'engine='openpyxl',keep_date_col=True)

"Keep_date_col" hy vọng sẽ giúp bạn


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
Mặc dù điều này có thể trả lời câu hỏi của tác giả, nhưng nó thiếu một số từ giải thích và / hoặc liên kết đến tài liệu. Các đoạn mã thô không hữu ích lắm nếu không có một số cụm từ xung quanh chúng. Bạn cũng có thể thấy cách viết một câu trả lời hay rất hữu ích. Vui lòng chỉnh sửa câu trả lời của bạn.
Roy Scheffers

0

Phương pháp:

  • Có thể tạo tệp nếu không có
  • Nối vào excel hiện có theo tên trang tính
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)

Sử dụng:

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'])
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.