Если вы работаете только с файлами Excel с расширением *.xlsx
, то openpyxl имеет полезные функции, которые позволяют создавать, получать доступ, переименовывать, добавлять / удалять данные в / из рабочих таблиц Excel.Хотя доступ к рабочему листу рабочей книги с помощью openpyxl может показаться довольно простым, использование обработки исключений в Python может помочь отловить ошибки, когда рабочий лист не существует в первую очередь.Рассмотрим приведенный ниже пример, где KeyError вызывается, если для рабочей книги «test.xlsx» не существует листа с именем invalidSheet.Задача блока try / Кроме того, чтобы вызвать исключение, если лист не существует.Цель этого простого примера - определить только тип исключения, которое вызывает openpyxl.
In [1]: import openpyxl
In [2]: book = openpyxl.load_workbook("test.xlsx")
In [3]: try:
...: ws = book["invalidSheet"] #try to access a non-existent worksheet
...: except:
...: raise
...:
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-3-4f4ac71a4f19> in <module>
1 try:
----> 2 ws = book["invalidSheet"]
3 except:
4 raise
5
~\Anaconda3\lib\site-packages\openpyxl\workbook\workbook.py in __getitem__(self, key)
275 if sheet.title == key:
276 return sheet
--> 277 raise KeyError("Worksheet {0} does not exist.".format(key))
278
279 def __delitem__(self, key):
KeyError: 'Worksheet invalidSheet does not exist.'
Это помогает нам сформировать более явный блок try / Кроме того, чтобы ловить несуществующие листы.Вскоре мы улучшим этот пример, но сначала давайте выясним имена листов в этой электронной таблице Excel.Мы используем атрибут sheetnames
объекта Workbook book
, который мы создали ранее:
In [15]: book.sheetnames
Out[15]: ['testSheet1', 'testSheet2']
In [16]: type(book.sheetnames)
Out[16]: list
Возвращает список имен листов.Мы будем использовать эту информацию для проверки имен листов позже.Возвращаясь к приведенному выше примеру, следующая улучшенная версия перехватывает KeyError
для несуществующих листов и создает новый лист, если он не существует.Однако листы не появятся в реальной электронной таблице Excel, если мы не save()
ее.Имена листов с другой стороны все еще будут обновляться для объекта.Вы можете проверить это после выполнения фрагмента:
In [20]: try:
...: filename = "test.xlsx"
...: sheet_name = "invalidSheet"
...: ws = book[sheet_name]
...: except KeyError:
...: print("The worksheet '{}' does not exist for workbook '{}'. Creating one...".format(
...: sheet_name,
...: filename))
...: book.create_sheet(sheet_name)
...: print("Worksheet '{}' created successfully for workbook '{}'.".format(sheet_name, filename))
...:
The worksheet 'invalidSheet' does not exist for workbook 'test.xlsx'. Creating one...
Worksheet 'invalidSheet' created successfully for workbook 'test.xlsx'.
In [21]: book.sheetnames
Out[21]: ['testSheet1', 'testSheet2', 'invalidSheet']
Итак, теперь, когда у нас добавлен лист «invalidSheet», давайте добавим некоторые данные и сохраним их под более осмысленным именем.Openpyxl также обеспечивает поддержку Pandas dataframe .Сначала мы создадим фрейм данных, а затем добавим каждую строку в фрейме данных (включая заголовок) на лист, используя метод dataframe_to_rows()
, затем переименуем лист и, наконец, сохраним его.
In [23]: import pandas as pd
In [24]: df = pd.DataFrame({"Name": ["John", "Val", "Katie"],
"Favorite Pet":["dog", "cat", "guinea pig"]}) #create dataframe
In [25]: df
Out[25]:
Name Favorite Pet
0 John dog
1 Val cat
2 Katie guinea pig
In [26]: from openpyxl.utils.dataframe import dataframe_to_rows #import method
In [27]: ws = book["invalidSheet"] #create a worksheet object for the existing sheet "invalidSheet"
In [29]: for r in dataframe_to_rows(df, index=False, header=True):
...: ws.append(r) #append each df row to the worksheet
...:
In [31]: ws['A2'].value #verify value at cell 'A2'. Remember, the first row will be the header
Out[31]: 'John'
In [32]: ws.title = "favPetSheet" #rename the worksheet
In [33]: book.sheetnames #verify whether the sheet was added & renamed
Out[33]: ['testSheet1', 'testSheet2', 'favPetSheet']
In [35]: book.save("test.xlsx") #save the workbook
В идеалеВ этом случае одна функция должна выполнять все эти задачи для определенной рабочей книги и рабочего листа рабочей книги и кадра данных.
In [45]: def check_sheet_add_data(filename, sheetname, df):
...: """Check if sheet exists for an xlsx spreadsheet and add data from dataframe to the sheet
...: :param: filename - The filename of the xlsx spreadsheet
...: :param: sheetname - Name of the worksheet to search for
...: :param: df - A Pandas dataframe object"""
...:
...: wb = openpyxl.load_workbook(filename)
...: try:
...: ws = wb[sheetname]
...: print("Sheet '{}' found in workbook '{}'".format(sheetname, filename))
...: except KeyError:
...: print("Worksheet '{}' not found for workbook '{}'.Adding...".format(sheetname, filename))
...: wb.create_sheet(sheetname)
...: ws = wb[sheetname]
...: print()
...: print("Current sheetnames: {}".format(wb.sheetnames))
...: print()
...: print("Worksheet '{}' added successfully for workbook '{}'".format(sheetname, filename))
...: finally:
...: print()
...: print("Adding data to worksheet '{}'...".format(sheetname))
...: print()
...: for r in dataframe_to_rows(df, index=False, header=True):
...: ws.append(r)
...: wb.save(filename)
...: print("Workbook '{}' saved successfully.".format(filename))
...: print()
...: print("***End***")
Когда эта функция готова, давайте протестируем все условия.Сначала давайте добавим некоторые новые данные, скажем, «Любимые альбомы» для наших старых друзей Джона, Вэл и Кэти.
In [39]: df2 = pd.DataFrame({"Name":["John", "Val", "Katie"],
"Favorite Album": ["Thriller", "Stairway to Heaven", "Abbey Road"]})
In [40]: df2
Out[40]:
Name Favorite Album
0 John Thriller
1 Val Stairway to Heaven
2 Katie Abbey Road
Наша рабочая книга будет называться «test.xlsx», а наша новая рабочая таблица будет называться «favAlbumSheet».Тестирование на всех условиях для существующих и несуществующих рабочих листов:
#Condition 1: Worksheet does not exist
In [44]: check_sheet_add_data(filename="test.xlsx", sheetname="favAlbumSheet", df=df2)
Worksheet 'favAlbumSheet' not found for workbook 'test.xlsx'.Adding...
Current sheetnames: ['testSheet1', 'testSheet2', 'favPetSheet', 'favAlbumSheet']
Worksheet 'favAlbumSheet' added successfully for workbook 'test.xlsx'
Adding data to worksheet 'favAlbumSheet'...
Workbook 'test.xlsx' saved successfully.
***End***
#Condition 2: Worksheet exists
In [46]: check_sheet_add_data(filename="test.xlsx", sheetname="favAlbumSheet", df=df2)
Sheet 'favAlbumSheet' found in workbook 'test.xlsx'
Adding data to worksheet 'favAlbumSheet'...
Workbook 'test.xlsx' saved successfully.
***End***
Мы использовали простые в использовании функции Openpyxl для доступа к рабочим листам в действующей рабочей книге Excel и добавления данных из информационных фреймов в рабочие листы.Благодаря обработке исключений в Python мы смогли четко определить наличие рабочего листа (для действительной рабочей книги) и добавить его при необходимости.Эта функция может быть расширена для обнаружения других ошибок, таких как недопустимое имя файла (FileNotFoundError
), недопустимый объект фрейма данных и т. Д. Если вы не хотите добавлять данные каждый раз и проверять только наличие листа, сделайте df
anнеобязательный аргумент: df=None
и сохраняйте книгу только без добавления каких-либо данных на лист в блоке finally
.