Как сохранить новый лист в существующем файле 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()

Этот код сохраняет два DataFrames на двух листах с именами «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»?

Стефано Феделе
источник

Ответы:

117

Спасибо. Я считаю, что полный пример может быть полезен для всех, у кого есть такая же проблема:

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 02
3
Если кто-то читает это и задается вопросом, как перезаписать существующий лист с тем же именем вместо переименования нового: добавьте строку writer.sheets = dict((ws.title, ws) for ws in book.worksheets) после writer.book = book
Harm te Molder
1
@Stefano Fedele, можете ли вы сделать то же обновление существующего Excel, используя xlsxwriter вместо openpyxl?
M
15

В примере, которым вы поделились, вы загружаете существующий файл bookи устанавливаете writer.bookзначение book. В строке writer.sheets = dict((ws.title, ws) for ws in book.worksheets)вы обращаетесь к каждому листу в книге как ws. Заголовок листа таков, wsчто вы создаете словарь {sheet_titles: sheet}пар ключ-значение. Затем этот словарь устанавливается на writer.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()

Это должно сделать то, что вы ищете.

Grr
источник
любая идея, почему, когда я пытаюсь это сделать, я получаю: ValueError: Нет писателя Excel 'Sales Leads Calculations.xlsx'?
bernando_vialli
18
это стирает уже существующие листы.
Nikhil VJ
13

Простой пример записи нескольких данных в Excel за раз. А также, когда вы хотите добавить данные на лист в записанном файле 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'. См. Документацию .

Pulkit Khandelwal
источник
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.
Джис Мэтью
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')
nileshk611
источник
1
Я не понимаю, как это связано с вопросом, за исключением того, что речь идет об Excel.
Artog 06
Я работал, чтобы найти полное решение для чтения и записи в существующую книгу, но не смог найти то же самое. Здесь я нашел подсказку о том, как писать в существующую книгу, поэтому подумал о том, чтобы дать полное решение моей проблемы. Надеюсь, это ясно.
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 как новый лист с Sheet_name . Если книга не существует, она создается. Похоже, что ни openpyxl, ни xlsxwriter не добавляются, поэтому, как в примере @Stefano выше, вам действительно нужно загрузить, а затем переписать, чтобы добавить.

MrMajestyk
источник