Як зберегти новий аркуш у існуючому файлі Excel за допомогою Pandas?


86

Я хочу використовувати файли Excel для зберігання даних, розроблених за допомогою python. Моя проблема полягає в тому, що я не можу додавати аркуші до існуючого файлу Excel. Тут я пропоную зразок коду для роботи, щоб вирішити цю проблему

import pandas as pd
import numpy as np

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

x1 = np.random.randn(100, 2)
df1 = pd.DataFrame(x1)

x2 = np.random.randn(100, 2)
df2 = pd.DataFrame(x2)

writer = pd.ExcelWriter(path, engine = 'xlsxwriter')
df1.to_excel(writer, sheet_name = 'x1')
df2.to_excel(writer, sheet_name = 'x2')
writer.save()
writer.close()

Цей код зберігає два кадри даних на двох аркушах із іменами "x1" та "x2" відповідно. Якщо я створюю два нових DataFrames і намагаюся використовувати один і той же код для додавання двох нових аркушів, 'x3' і 'x4', вихідні дані втрачаються.

import pandas as pd
import numpy as np

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

x3 = np.random.randn(100, 2)
df3 = pd.DataFrame(x3)

x4 = np.random.randn(100, 2)
df4 = pd.DataFrame(x4)

writer = pd.ExcelWriter(path, engine = 'xlsxwriter')
df3.to_excel(writer, sheet_name = 'x3')
df4.to_excel(writer, sheet_name = 'x4')
writer.save()
writer.close()

Я хочу файл Excel із чотирма аркушами: 'x1', 'x2', 'x3', 'x4'. Я знаю, що 'xlsxwriter' - не єдиний "движок", існує "openpyxl". Я також бачив, що вже є інші люди, які писали про це питання, але все ще не можу зрозуміти, як це зробити.

Ось код, взятий за цим посиланням

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

Кажуть, що це працює, але важко зрозуміти, як. Я не розумію, що таке "ws.title", "ws" та "dict" у цьому контексті.

Який найкращий спосіб зберегти "x1" та "x2", а потім закрити файл, знову відкрити його та додати "x3" та "x4"?

Відповіді:


116

Дякую. Я вважаю, що повний приклад може бути корисним для всіх, хто має таку ж проблему:

import pandas as pd
import numpy as np

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

x1 = np.random.randn(100, 2)
df1 = pd.DataFrame(x1)

x2 = np.random.randn(100, 2)
df2 = pd.DataFrame(x2)

writer = pd.ExcelWriter(path, engine = 'xlsxwriter')
df1.to_excel(writer, sheet_name = 'x1')
df2.to_excel(writer, sheet_name = 'x2')
writer.save()
writer.close()

Тут я генерую файл Excel, наскільки я розумію, насправді не має значення, чи генерується він за допомогою механізму "xslxwriter" чи "openpyxl".

Коли я хочу писати, не втрачаючи вихідних даних, тоді

import pandas as pd
import numpy as np
from openpyxl import load_workbook

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

book = load_workbook(path)
writer = pd.ExcelWriter(path, engine = 'openpyxl')
writer.book = book

x3 = np.random.randn(100, 2)
df3 = pd.DataFrame(x3)

x4 = np.random.randn(100, 2)
df4 = pd.DataFrame(x4)

df3.to_excel(writer, sheet_name = 'x3')
df4.to_excel(writer, sheet_name = 'x4')
writer.save()
writer.close()

цей код робить роботу!


будь-яка ідея, чому, коли я спробую це, я отримую: ValueError: Немає редактора Excel "Sales Leads Calculations.xlsx"?
bernando_vialli

1
так, це додавання аркуша до Excel без знищення вже існуючих аркушів. Дякую!
Nikhil VJ

2
Зберігаючи файл Excel, як зберегти існуючі формати аркушів Excel?
Vineesh TP

3
Якщо хтось читає це і задається питанням, як замінити існуючий аркуш з тим самим іменем замість того, щоб перейменовувати новий: Додайте рядок writer.sheets = dict((ws.title, ws) for ws in book.worksheets) після writer.book = book
Harm te

1
@Stefano Fedele, чи можете ви зробити те саме оновлення існуючого Excel, використовуючи 'xlsxwriter' замість 'openpyxl'?
М Нікеш,

15

У наведеному вами прикладі ви завантажуєте існуючий файл bookі встановлюєте writer.bookзначення book. У рядку writer.sheets = dict((ws.title, ws) for ws in book.worksheets)ви отримуєте доступ до кожного аркуша книги як ws. Тоді заголовок аркуша wsтаким чином ви створюєте словник {sheet_titles: sheet}пар ключів, значень. Потім для цього словника встановлюється Writ.sheets. По суті, ці кроки просто завантажують наявні дані 'Masterfile.xlsx'та заповнюють ними ваш автор.

Тепер припустимо, у вас вже є файл із аркушами x1та x2як. Ви можете використовувати приклад коду для завантаження файлу, а потім можете зробити щось подібне, щоб додати x3та x4.

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"
writer = pd.ExcelWriter(path, engine='openpyxl')
df3.to_excel(writer, 'x3', index=False)
df4.to_excel(writer, 'x4', index=False)
writer.save()

Це повинно робити те, що ви шукаєте.


будь-яка ідея, чому, коли я спробую це, я отримую: ValueError: Немає редактора Excel "Sales Leads Calculations.xlsx"?
bernando_vialli

18
це стирання вже існуючих аркушів.
Nikhil VJ

13

Простий приклад написання кількох даних, щоб досягти успіху одночасно. А також, коли ви хочете додати дані на аркуш письмового файлу Excel (закритий файл Excel).

Коли ви вперше пишете в Excel. (Запис "df1" і "df2" в "1st_sheet" і "2nd_sheet")

import pandas as pd 
from openpyxl import load_workbook

df1 = pd.DataFrame([[1],[1]], columns=['a'])
df2 = pd.DataFrame([[2],[2]], columns=['b'])
df3 = pd.DataFrame([[3],[3]], columns=['c'])

excel_dir = "my/excel/dir"

with pd.ExcelWriter(excel_dir, engine='xlsxwriter') as writer:    
    df1.to_excel(writer, '1st_sheet')   
    df2.to_excel(writer, '2nd_sheet')   
    writer.save()    

Після закриття Excel, але ви хочете "додати" дані до того самого файлу Excel, але іншого аркуша, скажімо "df3" до імені аркуша "3rd_sheet".

book = load_workbook(excel_dir)
with pd.ExcelWriter(excel_dir, engine='openpyxl') as writer:
    writer.book = book
    writer.sheets = dict((ws.title, ws) for ws in book.worksheets)    

    ## Your dataframe to append. 
    df3.to_excel(writer, '3rd_sheet')  

    writer.save()     

Зауважте, що формат Excel не повинен бути xls, ви можете використовувати xlsx.


1
Не бачу, що додає ця відповідь. Насправді, неодноразове використання такого менеджера контекстів буде включати набагато більше вводу-виводу.
Чарлі Кларк

8

Я настійно рекомендую вам працювати безпосередньо з openpyxl, оскільки зараз він підтримує Pandas DataFrames .

Це дозволяє зосередитись на відповідному коді Excel та Pandas.


3
Було б дуже корисно, якщо б ви могли додати трохи більше прикладів "панд", подібних до цього
MaxU

Я сам багато не працюю з Pandas, тому я не можу навести стільки прикладів, але вітаю вдосконалення документації.
Чарлі Кларк,

4

Для створення нового файлу

x1 = np.random.randn(100, 2)
df1 = pd.DataFrame(x1)
with pd.ExcelWriter('sample.xlsx') as writer:  
    df1.to_excel(writer, sheet_name='x1')

Для додавання до файлу використовуйте аргумент mode='a'у pd.ExcelWriter.

x2 = np.random.randn(100, 2)
df2 = pd.DataFrame(x2)
with pd.ExcelWriter('sample.xlsx', engine='openpyxl', mode='a') as writer:  
    df2.to_excel(writer, sheet_name='x2')

За замовчуванням mode ='w'. Див. Документацію .


3

Це можна зробити без використання ExcelWriter, за допомогою інструментів у openpyxl Це може значно полегшити додавання шрифтів до нового аркуша openpyxl.styles

import pandas as pd
from openpyxl import load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows

#Location of original excel sheet
fileLocation =r'C:\workspace\data.xlsx'

#Location of new file which can be the same as original file
writeLocation=r'C:\workspace\dataNew.xlsx'

data = {'Name':['Tom','Paul','Jeremy'],'Age':[32,43,34],'Salary':[20000,34000,32000]}

#The dataframe you want to add
df = pd.DataFrame(data)

#Load existing sheet as it is
book = load_workbook(fileLocation)
#create a new sheet
sheet = book.create_sheet("Sheet Name")

#Load dataframe into new sheet
for row in dataframe_to_rows(df, index=False, header=True):
    sheet.append(row)

#Save the modified excel at desired location    
book.save(writeLocation)

Це гарне рішення, однак я не впевнений, що це також має значення. Ви маєте на увазі, що ви не можете цього робити ExcelWriterабо вам просто не потрібно?
MattSom

Ви можете зробити це за допомогою Excelwriter, але мені стає простіше, просто використовуючи openpyxl.
Jis Mathew

2

Ви можете прочитати наявні аркуші, які вас цікавлять, наприклад, "x1", "x2", в пам'ять і "записати" їх назад перед додаванням нових аркушів (майте на увазі, що аркуші у файлі та аркуші в пам'яті є двома різними речі, якщо ви їх не прочитаєте, вони будуть загублені). Цей підхід використовує лише 'xlsxwriter', без участі у openpyxl.

import pandas as pd
import numpy as np

path = r"C:\Users\fedel\Desktop\excelData\PhD_data.xlsx"

# begin <== read selected sheets and write them back
df1 = pd.read_excel(path, sheet_name='x1', index_col=0) # or sheet_name=0
df2 = pd.read_excel(path, sheet_name='x2', index_col=0) # or sheet_name=1
writer = pd.ExcelWriter(path, engine='xlsxwriter')
df1.to_excel(writer, sheet_name='x1')
df2.to_excel(writer, sheet_name='x2')
# end ==>

# now create more new sheets
x3 = np.random.randn(100, 2)
df3 = pd.DataFrame(x3)

x4 = np.random.randn(100, 2)
df4 = pd.DataFrame(x4)

df3.to_excel(writer, sheet_name='x3')
df4.to_excel(writer, sheet_name='x4')
writer.save()
writer.close()

Якщо ви хочете зберегти всі існуючі аркуші, ви можете замінити наведений вище код між початком і кінцем на:

# read all existing sheets and write them back
writer = pd.ExcelWriter(path, engine='xlsxwriter')
xlsx = pd.ExcelFile(path)
for sheet in xlsx.sheet_names:
    df = xlsx.parse(sheet_name=sheet, index_col=0)
    df.to_excel(writer, sheet_name=sheet)

1
#This program is to read from excel workbook to fetch only the URL domain names and write to the existing excel workbook in a different sheet..
#Developer - Nilesh K
import pandas as pd
from openpyxl import load_workbook #for writting to the existing workbook

df = pd.read_excel("urlsearch_test.xlsx")

#You can use the below for the relative path.
# r"C:\Users\xyz\Desktop\Python\

l = [] #To make a list in for loop

#begin
#loop starts here for fetching http from a string and iterate thru the entire sheet. You can have your own logic here.
for index, row in df.iterrows():
    try: 
        str = (row['TEXT']) #string to read and iterate
        y = (index)
        str_pos = str.index('http') #fetched the index position for http
        str_pos1 = str.index('/', str.index('/')+2) #fetched the second 3rd position of / starting from http
        str_op = str[str_pos:str_pos1] #Substring the domain name
        l.append(str_op) #append the list with domain names

    #Error handling to skip the error rows and continue.
    except ValueError:
            print('Error!')
print(l)
l = list(dict.fromkeys(l)) #Keep distinct values, you can comment this line to get all the values
df1 = pd.DataFrame(l,columns=['URL']) #Create dataframe using the list
#end

#Write using openpyxl so it can be written to same workbook
book = load_workbook('urlsearch_test.xlsx')
writer = pd.ExcelWriter('urlsearch_test.xlsx',engine = 'openpyxl')
writer.book = book
df1.to_excel(writer,sheet_name = 'Sheet3')
writer.save()
writer.close()

#The below can be used to write to a different workbook without using openpyxl
#df1.to_excel(r"C:\Users\xyz\Desktop\Python\urlsearch1_test.xlsx",index='false',sheet_name='sheet1')

1
Я не стежу, як це пов'язано з питанням, за винятком того, що це про excel.
Artog

Я працював над пошуком повного рішення для читання та запису до існуючої книги, але не зміг знайти те саме. Тут я знайшов підказку про те, як писати до існуючої книги, тому я подумав дати повне рішення для своєї проблеми. Сподіваюся, це ясно.
nileshk611

0

Інший досить простий спосіб зробити це - зробити такий метод:

def _write_frame_to_new_sheet(path_to_file=None, sheet_name='sheet', data_frame=None):
    book = None
    try:
        book = load_workbook(path_to_file)
    except Exception:
        logging.debug('Creating new workbook at %s', path_to_file)
    with pd.ExcelWriter(path_to_file, engine='openpyxl') as writer:
        if book is not None:
            writer.book = book
        data_frame.to_excel(writer, sheet_name, index=False)

Ідея тут полягає в тому, щоб завантажити книгу в path_to_file, якщо вона існує, а потім додати data_frame як новий аркуш з іменем аркуша . Якщо робочої книги не існує, вона створюється. Здається , що ні openpyxl або xlsxwriter Append, так як в прикладі з @Stefano вище, ви дійсно повинні навантаження , а потім переписати додавання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.