检查工作簿中的工作表,如果缺少则添加

时间:2019-04-30 13:36:52

标签: python pandas openpyxl

我试图简单地检查.xlsx文件中是否存在工作表,如果不存在,我想添加它。

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

if 'testSheet' in book.sheetnames:
    pass
else:
    book.add_sheet(book['testSheet'])

关于为什么这样不起作用的任何想法?

6 个答案:

答案 0 :(得分:8)

如果仅使用扩展名为*.xlsx的Excel文件,则openpyxl具有有用的功能,可让您在Excel工作表中创建,访问,重命名,添加数据或从中删除数据。虽然使用openpyxl访问工作簿的工作表似乎很简单,但是当工作表最初不存在时,利用Python的异常处理可以帮助捕获错误。考虑下面的示例,如果对于工作簿“ test.xlsx”不存在名为“ invalidSheet”的工作表,则会引发KeyError。如果工作表不存在,则try / except块的工作是引发异常。这个简单示例的目的是仅识别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 / except块,以捕获不存在的工作表。稍后,我们将改进此示例,但首先让我们在此Excel电子表格中查找工作表名称。我们使用之前创建的工作簿对象sheetnames的{​​{1}}属性:

book

这将返回一个工作表名称列表。我们稍后将使用此信息来验证工作表名称。回到上面的示例,以下改进的版本捕获不存在的工作表的In [15]: book.sheetnames Out[15]: ['testSheet1', 'testSheet2'] In [16]: type(book.sheetnames) Out[16]: list 并创建一个新工作表(如果不存在)。但是,除非我们KeyError,否则工作表将不会出现在实际的Excel电子表格中。另一方面,该工作表的名称仍将更新。您可以在执行代码段后对此进行验证:

save()

因此,现在我们添加了工作表“ invalidSheet”,让我们添加一些数据并使用更有意义的名称进行保存。 Openpyxl还提供Pandas dataframe support。我们将首先创建一个数据框,然后使用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'] 方法将该数据框中的每一行(包括标题)附加到工作表中,然后重命名工作表并最后保存它。

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

准备好此功能后,让我们测试所有条件。首先,让我们添加一些新数据,为我们的老朋友John,Val和Katie说“收藏夹”。

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***")

我们的工作簿将是相同的“ test.xlsx”,新的工作表将被称为“ favAlbumSheet”。在现有和不存在的工作表的所有条件下进行测试:

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

我们利用Openpyxl的易于使用的功能访问有效的Excel工作簿中的工作表,并将数据框中的数据添加到工作表中。使用Python的异常处理,我们能够清楚地识别出一个工作表(对于有效的工作簿)的存在,并在必要时添加一个工作表。可以进一步扩展该功能,以捕获其他错误,例如无效的文件名(#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*** ),无效的dataframe对象等。如果您不想每次都添加数据,而仅检查工作表的存在,则使{{ 1}}的可选参数:FileNotFoundError,并且仅保存工作簿,而不在df块中添加任何数据到工作表。

答案 1 :(得分:5)

仅使用openpyxl条命令即可添加工作表(即也无需使用pandas条命令):

import openpyxl

# Load existing excel file into a openpyxl Workbook object
book = openpyxl.load_workbook('test.xlsx')

# If sheet 'testSheet' does not exist yet, then add it in the openpyxl Workbook object
if not 'testSheet' in book.sheetnames:
    book.create_sheet('testSheet')

# Save the openpyxl Workbook object to file
book.save('test.xlsx')

答案 2 :(得分:2)

对于openpyxl引擎,请使用 book.create_sheet("testSheet")

来源:https://openpyxl.readthedocs.io/en/stable/tutorial.html

答案 3 :(得分:0)

  1. 安装openpyxl
  2. 将openpyxl导入为pxl
  3. my_excel_wb = pxl.load_workbook(“ excel.xlsx”)
  4. 如果不是my_excel_wb.sheetnames中的“ sheetname”:  my_excel_wb.create_sheet('sheetname')
  5. 最后保存书。

答案 4 :(得分:0)

我使用的功能显然可以完成您还需要的工作。我使用 xlwings ,我不知道openpyxl。 它可以处理3种严重情况:

  • 没有工作簿打开
  • 找不到所需的工作表(在不引发异常的情况下创建一个新的工作表)
  • 试图找到工作表失败(这是用于搜索工作表并且对用户不可见)

该函数返回(如果成功)xlwings.Sheet对象(与Excel Sheet对象的xlwings等效)。 记住,您可以使用xlwings.sheet.api属性返回本机COM“ Sheet”对象

import xlwings as xw

def load_xlsh(SheetName):
    foundBK = False
    iBK = 0
    try:
        while (not foundBK) and iBK < len(xw.books):
            srcBK = xw.books[iBK]
            try:
                srcSH = srcBK.sheets[SheetName]
                foundBK = True
            except:
                iBK += 1
        if foundBK == False:
            srcBK.sheets.add(SheetName)
        else:
            return srcSH
    except AttributeError:
        print('No Workbooks open')

答案 5 :(得分:0)

如果使用xlwings,则还有另一种方法。

wb = xw.Book(FileName)
sNamList = [sh.name for sh in Wb.sheets]
if 'sheetName' in sNamList: print('sheetName exists!')