データを上書きせずに既存のExcelファイルに書き込む方法(パンダを使用)?


120

私はパンダを使用して次の方法でExcelファイルに書き込みます:

import pandas

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

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

writer.save()

Masterfile.xlsxはすでにさまざまなタブで構成されています。ただし、「メイン」はまだ含まれていません。

パンダは「メイン」シートに正しく書き込みますが、残念ながら他のすべてのタブも削除されます。


1
あなたは例またはExcelReaderを与えることができますか?ドキュメントにこのようなものは見つかりませんでした。
BP_ 2013年

1
パンダにはExcelReaderのようなものはないと思います。read_excelを使用して、Excelからデータを読み取ります。私はそれが優れたデータを保存することはないと思います。
BP_ 2013年

1
@nrathausはないようですExcelReader
virtualxtc

質問が正確に何を求めているかについての回答には、いくつかの混乱があることに注意してください。「メイン」がまだ存在せず、OPが単に既存のExcelワークブックに新しいシートを追加することを前提とする回答もあります。他の人たちは、「メイン」がすでに存在し、OPが「メイン」の下部に新しいデータを追加したいと想定しています。
TCプロクター

回答:


143

Pandas docsは、xlsxファイルにopenpyxlを使用すると言っています。のコードをざっと見てみると、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
writer.sheetsとは何ですか?
BP_ 2013年

5
何らかの理由でExcelWriterはこの変数を使用してシートにアクセスします。空のままにしておくと、メインのシートが既に存在することがわからず、新しいシートが作成されます。
2013年

2
このソリューションは正常に動作します。ただし、欠点が1つあります。スプレッドシート内の数式と接続を解除します。この動作を変更する方法はありますか?
BP_ 2013年

1
正確に何が壊れますか?これを別の質問として質問し、タグを付けて、openpyxl十分な詳細を提供することができます。どのような種類の数式があり、データがどのように更新されるか、どのように数式をブレーキするのですか。今、私は手伝うことができません。知らないことが多すぎます。
スキー

2
代わりに.xlsmファイルで使用できますか?
dapaz 2017年

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_namesheetname

使用例:

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
このソリューションは私にとって完璧に機能しましたが、ここに掲載されている他のソリューションは機能しません。どうもありがとう!コメントが1つだけ:ファイルが存在しない場合、「NameError:グローバル名 'FileNotFoundError'が定義されていません」というエラーが表示されます
cholo14

1
@ cholo14、これを指摘してくれてありがとう!Python 3.xでテストしたので、そのバグを見逃しました。私は答えでそれを修正しました...
MaxU

1
これは私にとってはうまくいきましたが、(元のxlsxファイルから)xlsxフォーマットを維持する方法はありますか?
-2-オン

@ 2one、私は正確にはわかりません-試してみるか、新しいSOの質問をしてください
MaxU

行だけでなく列に書き込む方法はありますか?シートを自動的に更新したいのですが、新しい行を追加するのではなく、列に感謝します!
doomdaam

21

openpyxlバージョン2.4.0pandasバージョン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
これは私にはうまくいきません。「メイン」ワークシートがすでにある場合は、新しいデータのみを使用して「メイン1」という名前の新しいワークシートが作成され、「メイン」ワークシートの内容は変更されません。
Qululu 2017

2
@Qululu 2つの異なる目標の間でこの質問に混乱があるかもしれないと思います。これにより、既存のワークブックにシートを追加できます。既存のシートに追加のデータを追加することは意図されていません。シートの名前が競合している場合は、シートの名前が変更されます。これはバグではなく機能です。
TCプロクター

@Qululuが言ったように、これは異なる名前でより多くのシートを作成するだけです。MaxUからの最初のソリューションが機能し、得られる出力は、最初のシートのdfです。これは、必要な回数だけ行われます(つまり、ヘッダーも何倍にも乗算されます)。1つの単純な手法:各反復データフレームをリストに追加します。最終的には、連結する必要があるだけです。彼らが同じ構造に従うならば、魅力として働きます。list_my_dfs = [df1、df2、...]#データフレームのリストmy_dfs_together = pd.concat(list_my_df)#1つのdfにデータフレームを連結
Susana Silva Santos

@SusanaSilvaSantos、あなたの直前にTC Proctorがコメントしたことを見てください。OPは、既存のワークブックに存在しないワークシートを追加したいと考えていました。このコードはそれを行います。ブック内の既存のシートにデータを追加することは範囲の一部ではありませんでした。それが必要ない場合は、これで十分です。
mvbentes

16

pandas 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
私のために上書きします。
keramat

10
@keramatこの質問については、2つの異なる目標の間に混乱があるかもしれません。これにより、既存のワークブックにシートを追加できます。既存のシートに追加のデータを追加することは意図されていません
TCプロクター

1
mode = 'a'シートを追加しますが、既存のシートのデータを上書きしたい場合はどうすればよいですか?
交絡

11

古い質問ですが、まだこれを検索している人もいると思います-だから...

すべてのワークシートがシート名とデータフレームのペアのディクショナリに読み込まれ、pandasがsheetname = Noneオプションを使用して作成したので、この方法は素晴らしいと思います。スプレッドシートをdict形式に読み込んでから、dictから書き戻すまでの間に、ワークシートを追加、削除、または変更するのは簡単です。私にとって、xlsxwriterは、速度と形式の点で、openpyxlよりもこの特定のタスクに適しています。

注:pandasの将来のバージョン(0.21.0以降)では、「sheetname」パラメーターが「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
はい、この方法では、各ワークシートがpandasデータフレームに変換され(その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()

最初に存在しないファイルを作成する方法はありますか?
Tinkinc 2018年

はい、ドキュメントを調べましたか?docs.xlwings.org/en/stable/api.html
flyingmeatball

彼らのウェブサイトのwb = xw.Book(filename)は本を作成すると言っています。しかし、そうではあり
ません

wb = xw.Book()は新しい空の本を作成します。既存の本をロードしようとしているパスをそれに渡すと、
flyingmeatball

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
これは、重複のあるこの以前の答え
TCプロクター

1
将来に向けての準備であり、これはXslxWriterオプションでは機能しません。
metinsenturk

それはまた、デフォルトでは動作しませんengine=openpyxl、それはちょうどと呼ばれる新しいワークシートを追加しますとthe only worksheet1
ビョルン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
これは著者の質問に答えるかもしれませんが、説明的な単語やドキュメントへのリンクが不足しています。生のコードスニペットは、周りにフレーズがないとあまり役に立ちません。また、良い答えの書き方も非常に役立ちます。回答を編集してください。
Roy Scheffers
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.