web-dev-qa-db-fra.com

Comment écrire dans un fichier Excel existant sans écraser les données (avec des pandas)?

J'utilise des pandas pour écrire dans un fichier Excel de la manière suivante:

import pandas

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

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

writer.save()

Masterfile.xlsx se compose déjà d'un nombre d'onglets différents.

Les pandas écrivent correctement dans la feuille "principale". Malheureusement, tous les autres onglets sont également supprimés.

84
BP_

Pandas docs dit qu'il utilise openpyxl pour les fichiers xlsx. Un coup d’œil rapide dans le code dans ExcelWriter donne une idée que quelque chose comme cela pourrait marcher:

import pandas
from openpyxl import load_workbook

book = load_workbook('Masterfile.xlsx')
writer = pandas.ExcelWriter('Masterfile.xlsx', engine='openpyxl') 
writer.book = book
writer.sheets = dict((ws.title, ws) for ws in book.worksheets)

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

writer.save()
105
Ski

Voici une fonction d'assistance:

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

    import pandas as pd

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

NOTE: pour les pandas <0.21.0, remplacez sheet_name par sheetname!

Exemples d'utilisation:

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)
18
MaxU

Avec openpyxlversion 2.4.0 et pandasversion 0.19.2, le processus créé par @ski devient un peu plus simple:

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!
12
mvbentes

Vieille question, mais je suppose que certaines personnes cherchent encore cela - alors ...

Je trouve cette méthode intéressante car toutes les feuilles de calcul sont chargées dans un dictionnaire de paires nom-feuille et image-données, créées par des pandas avec l'option nom-feuille = Aucune. Il est simple d’ajouter, de supprimer ou de modifier des feuilles de calcul entre la lecture de la feuille de calcul au format dict et sa réécriture à partir du dict. Pour moi, xlsxwriter fonctionne mieux que openpyxl pour cette tâche particulière en termes de vitesse et de format.

Note: les futures versions de pandas (0.21.0+) changeront le paramètre "sheetname" en "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)

Pour l'exemple de la question de 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)
8
b2002

Je sais que c'est un fil plus ancien, mais c'est le premier élément trouvé lors de la recherche et les solutions ci-dessus ne fonctionnent pas si vous devez conserver les graphiques dans un classeur que vous avez déjà créé. Dans ce cas, xlwings est une meilleure option - elle vous permet d’écrire dans le livre Excel et de conserver les graphiques/données de graphique.

exemple simple:

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

À partir de pandas 0.24, vous pouvez simplifier ceci avec l’argument mode de ExcelWriter:

import pandas as pd

with pd.ExcelWriter('the_file.xlsx', engine='openpyxl', mode='a') as writer: 
     data_filtered.to_Excel(writer) 
2
Will Ayd
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

Cela fonctionne parfaitement bien, la seule chose à faire est que le formatage du fichier maître (fichier dans lequel nous ajoutons une nouvelle feuille) est perdu.

1
Manish Mehra
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()
0
Pedro Machado

Il y a une meilleure solution dans les pandas 0.24:

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

avant:

 enter image description here 

après:

 enter image description here 

alors améliorez vos pandas maintenant:

pip install --upgrade pandas
0
blacksheep
writer = pd.ExcelWriter('prueba1.xlsx'engine='openpyxl',keep_date_col=True)

"Keep_date_col" espère vous aider

0
Edward