Як записатись у існуючий файл excel без перезапису даних (використовуючи панди)?


120

Я використовую панди, щоб записати файл 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
Я думаю, в пандах немає такого поняття, як ExcelReader. Я використовую read_excel для читання даних від excel. Я не думаю, що це дозволило б зберегти дані для досягнення кращих результатів.
BP_

1
@nrathaus, схоже, не будеExcelReader
virtualxtc

Зауважте, що у відповідях є певна плутанина щодо того, що саме задає питання. Деякі відповіді припускають, що "Основне" ще не існує, і ОП просто додає новий аркуш до існуючої робочої книги Excel. Інші припускають, що "Основне" вже існує, і що ОП хоче додати нові дані внизу "Основного".
TC Proctor

Відповіді:


143

Документи Pandas кажуть, що він використовує openpyxl для файлів xlsx. Швидкий перегляд коду ExcelWriterдає зрозуміти, що щось подібне може вийти:

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
Чи можете ви поясніть, для чого це письменник?
BP_

5
ExcelWriter чомусь використовує цю змінну для доступу до аркуша. Якщо ви залишите його порожнім, він не буде знати, що аркуш Main вже є, і створить новий аркуш.
Лижі

2
Це рішення прекрасно працює. Однак у нього є один недолік. Він розбиває формули та з'єднання всередині електронної таблиці. Будь-які ідеї, як змінити таку поведінку?
BP_

1
Що саме ти розбиваєш ..? Ви можете задати це окремим запитанням і позначити його openpyxlта надати достатньо детальних відомостей: які формули у вас є, як оновлюються дані, як вони гальмують формули. Зараз я просто не можу допомогти, занадто багато речей, яких я не знаю.
Лижі

2
чи можна це використовувати замість файлів .xlsm?
dapaz

39

Ось функція помічника:

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()

ПРИМІТКА: для Pandas <0,21,0 замініть sheet_nameна sheetname!

Приклади використання:

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
Це рішення спрацювало для мене ідеально, інші, розміщені тут, не працюють. Дуже дякую! Лише один коментар: коли файл не існує, я отримую помилку "NameError: глобальне ім'я" FileNotFoundError "не визначено"
cholo14,

1
@ cholo14, дякую за вказівку на це! Я перевірив це на Python 3.x, тому я пропустив цю помилку. Я це зафіксував у відповіді ...
MaxU

1
Це працювало для мене, але чи є спосіб підтримати форматування xlsx (з оригінального файлу xlsx)?
одиниці

@ 2one, я точно не знаю - спробуйте або задайте нове питання SO
MaxU

чи є спосіб записати в стовпці замість лише рядків? Наче я хочу автоматично оновлювати аркуш, але не додавати нові рядки, а колонки дякую!
doomdaam

21

З openpyxlверсією 2.4.0та pandasверсією 0.19.2процес @ski придуманий стає трохи простішим:

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
Це не працює для мене. Якщо вже є "Головний" робочий аркуш, він створить новий під назвою "Main1" лише з новими даними та залишить зміст робочого листа "Main" незмінним.
Кулулу

2
@Qululu Я думаю, що в цьому питанні може виникнути плутанина між двома різними цілями. Це дозволяє додавати додаткові аркуші до наявної робочої книги. Він не призначений для додавання додаткових даних до наявного аркуша. Якщо існує конфлікт іменування аркуша, він перейменовує аркуш. Це особливість, а не помилка.
TC Proctor

Як сказав @Qululu, це створює лише більше аркушів з різними назвами. Перше рішення від MaxU працює, і вихід, який ви отримаєте, буде df на першому аркуші стільки разів, скільки ви хотіли (це також із заголовками, помноженими на стільки ж разів.) Один простий текст: кожна ітерація ви додаєте фрейм даних до списку. Врешті-решт вам потрібно лише присісти. Якщо вони слідують тій же структурі, вони будуть працювати як шарм. list_my_dfs = [df1, df2, ...] # Список ваших кадрів даних my_dfs_together = pd.concat (list_my_df) # concat мої рамки даних в одному df
Susana Silva Santos

@SusanaSilvaSantos, погляньте на те, що прокоментував TC Proctor безпосередньо перед вами. ОП хотіла додати неіснуючий робочий лист до існуючої робочої книги. Цей код робить це. Додавання даних до наявного аркуша в робочій книжці не входило до сфери застосування. Якщо це не потрібно, цього буде достатньо.
mvbentes

16

Починаючи з панд 0.24, ви можете спростити це за допомогою modeаргументу ключового слова ExcelWriter:

import pandas as pd

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

3
переписує для мене.
керамат

10
@keramat Я думаю, що в цьому питанні може виникнути плутанина між двома різними цілями. Це дозволяє додавати додаткові аркуші до наявної робочої книги. Він не призначений для додавання додаткових даних до наявного аркуша.
TC Proctor

1
mode = 'a'додає більше аркушів, але що робити, якщо я хочу перезаписати дані на існуючі аркуші?
Збентежений

11

Старе питання, але я здогадуюсь, що деякі люди все ще шукають цього - так ...

Я вважаю цей метод приємним, оскільки всі робочі таблиці завантажуються у словник імен аркушів та пар даних, створених пандами з назвою аркуша = Немає параметра. Додавати, видаляти або змінювати робочі таблиці між елементами читання електронної таблиці у формат диктату просто не можна. Для мене xlsxwriter працює краще, ніж openpyxl для цього конкретного завдання з точки зору швидкості та формату.

Примітка: майбутні версії панд (0.21.0+) змінять параметр "name name" на "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)

Для прикладу у питанні 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)

Цей спосіб працював, однак мої об'єднані клітини, кольори клітин та ширина комірок не збереглися.
virtualxtc

1
Так, при цьому методі такий тип форматування буде втрачено, оскільки кожен робочий аркуш перетворюється в рамку даних панди (без жодного форматного формату excel), а потім перетворюється з фреймів даних у робочі таблиці в новій робочій книзі excel (яка має те саме ім'я, що і оригінал файл). Видається, що може бути новий метод "додавання" за допомогою openpyxl, який може зберегти оригінальне форматування робочого аркуша файлу? github.com/pandas-dev/pandas/pull/21251
b2002

11

Я знаю, що це старіший потік, але це перший елемент, який ви знайдете під час пошуку, і вищезазначені рішення не працюють, якщо вам потрібно зберегти діаграми у створеній вами робочій книжці. У цьому випадку xlwings є кращим варіантом - він дозволяє записувати до книги excel та зберігає дані діаграм / діаграм.

простий приклад:

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()

Чи є спосіб створити файл, якщо він не існує спочатку?
Тінкінк

Так, ви досліджували документи? docs.xlwings.org/en/stable/api.html
flyingmeatball

wb = xw.Book (назва файлу) на їхньому веб-сайті говорить, що це створює книгу. але це не так
Тінкінк

wb = xw.Book () створює нову порожню книгу, коли ви передаєте їй шлях, ви намагаєтеся завантажити існуючу книгу.
літаючий фрикаделька

1
Примітка: xlwings взаємодіє з запущеним екземпляром Excel і тому не працює в Linux.
virtualxtc

5

Є краще рішення в пандах 0,24:

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

перед:

введіть тут опис зображення

після:

введіть тут опис зображення

тож оновіть ваші панди зараз:

pip install --upgrade pandas


1
Лише голова на майбутнє, це не працює з XslxWriterваріантом.
metsentsentk

це також за замовчуванням не працює, engine=openpyxlоскільки він просто додасть новий робочий аркуш під назвоюthe 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

Це прекрасно спрацьовує лише те, що форматування головного файлу (файлу, до якого ми додаємо новий аркуш) втрачається.


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

Сподіваюся, що "Keep_date_col" вам допоможе


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
Хоча це може відповісти на запитання авторів, у ньому відсутні деякі пояснювальні слова та / або посилання на документацію. Фрагменти сирого коду не дуже корисні без певних фраз. Ви також можете знайти, як написати гарну відповідь дуже корисно. Відредагуйте свою відповідь.
Рой Шефферс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.