3
votes

Vérifiez le classeur pour la feuille et ajoutez s'il manque

J'essaie simplement de vérifier si une feuille existe dans un fichier .xlsx et sinon je veux l'ajouter.

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'])

Des idées pour expliquer pourquoi cela ne fonctionne pas?


5 commentaires

Le si vérifie si testSheet est dans book.sheetnames , alors vous essayez d'y accéder à l'intérieur du bloc else , là où il est évidemment n'existe pas, il est donc logique que book ['testSheet'] lève une KeyError .


Le bloc else est ma tentative d'ajouter la feuille car elle n'existe pas. Êtes-vous en mesure de préciser où je vais mal?


Comme vous dites qu'il n'existe pas, vous ne pouvez pas obtenir 'testSheet' à partir de book via book ['testSheet'] . Donc, c'est clair où vous vous trompez, sans rien savoir sur la manière correcte de openpyxl de réaliser ce que vous voulez. ;)


@Jeronimo la ligne book.add_sheet (book ['testSheet']) ne créerait-elle pas simplement une nouvelle feuille dans le classeur avec ce nom? Il ne tente pas d'y accéder.


@MaxB Non. La partie de la ligne qui est évaluée en premier est book ['testSheet'] , et cela revient à "récupérer la feuille de calcul nommée testSheet".


6 Réponses :


8
votes

L'ajout d'une feuille de calcul peut être effectué en utilisant uniquement des commandes openpyxl (c'est-à-dire qu'il n'y a pas doivent également impliquer les commandes 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')


0 commentaires

10
votes

Si vous travaillez uniquement avec des fichiers Excel avec l'extension * .xlsx , alors openpyxl a des fonctionnalités utiles qui vous permettent de créer, accéder, renommer, ajouter / supprimer des données dans / depuis des feuilles de calcul Excel. Bien qu'il puisse sembler assez simple d'accéder à la feuille de calcul d'un classeur avec openpyxl, l'utilisation de la gestion des exceptions de Python peut aider à détecter les erreurs lorsque la feuille de calcul n'existe pas en premier lieu. Considérez l'exemple ci-dessous où une KeyError est déclenchée si une feuille de calcul appelée "invalidSheet" n'existe pas pour le classeur "test.xlsx". Le travail du bloc try / except consiste à déclencher une exception si la feuille de calcul n'existe pas. Le but de cet exemple simple est d'identifier uniquement le type d'exception soulevé par openpyxl.

#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***

Cela nous aide à former un bloc try / except plus explicite pour attraper les feuilles inexistantes. Dans peu de temps, nous améliorerons cet exemple, mais découvrons d'abord les noms de feuille dans cette feuille de calcul Excel. Nous utilisons l'attribut sheetnames de l'objet Workbook book que nous avons créé précédemment:

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

Ceci renvoie une liste de noms de feuilles . Nous utiliserons ces informations pour vérifier les noms des feuilles ultérieurement. Revenant à l'exemple ci-dessus, la version améliorée suivante intercepte le KeyError pour les feuilles inexistantes et crée une nouvelle feuille si elle n'existe pas. Cependant, les feuilles n'apparaîtront pas dans la feuille de calcul Excel réelle à moins que nous ne la sauvegardions () . Les noms de feuille, par contre, seront toujours mis à jour pour l'objet. Vous pouvez le vérifier après avoir exécuté l'extrait de code:

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

Alors maintenant que nous avons ajouté la feuille "invalidSheet", ajoutons quelques données et sauvegardons-les avec un nom plus significatif. Openpyxl fournit également prise en charge des cadres de données Pandas . Nous allons d'abord créer un dataframe, puis ajouter chaque ligne du dataframe (y compris l'en-tête) à la feuille de calcul en utilisant la méthode dataframe_to_rows () , puis renommer la feuille de calcul et enfin l'enregistrer.

XXX

Dans une situation idéale, une seule fonction devrait effectuer toutes ces tâches pour un certain classeur et feuille de calcul du classeur et du dataframe.

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

Avec cette fonction prête, testons toutes les conditions. Ajoutons d'abord de nouvelles données, disons "Albums favoris" pour nos anciens amis John, Val et Katie.

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']

Notre classeur sera le même "test.xlsx" et notre nouvelle feuille de travail s'appellera "favAlbumSheet". Test sur toutes les conditions pour les feuilles de calcul existantes et inexistantes:

In [15]: book.sheetnames
Out[15]: ['testSheet1', 'testSheet2']

In [16]: type(book.sheetnames)
Out[16]: list

Nous avons utilisé les fonctionnalités faciles à utiliser d'Openpyxl pour accéder aux feuilles de calcul dans un classeur Excel valide et ajouter des données de dataframes à des feuilles de calcul. Avec la gestion des exceptions de Python, nous avons pu identifier clairement la présence d'une feuille de calcul (pour un classeur valide) et en ajouter une si nécessaire. La fonction peut être étendue pour attraper d'autres erreurs comme un nom de fichier invalide ( FileNotFoundError ), un objet dataframe invalide, etc. Si vous ne voulez pas ajouter de données à chaque fois et ne vérifier que l'existence de la feuille, faites de df un argument facultatif: df = None et enregistrez uniquement le classeur sans ajouter de données à la feuille de calcul, dans le bloc enfin . p>


2 commentaires

C'est très cool, bravo pour la réponse très détaillée, cela aidera sûrement les autres.


Merci, j'espère que c'est le cas.



2
votes

Pour le moteur openpyxl, utilisez book.create_sheet("testSheet")

Source: https://openpyxl.readthedocs.io/en/stable/tutorial .html


0 commentaires

0
votes
  1. installer openpyxl
  2. importer openpyxl au format pxl
  3. mon_excel_wb = pxl.load_workbook ("excel.xlsx")
  4. sinon 'sheetname' dans my_excel_wb.sheetnames: my_excel_wb.create_sheet ('nom de la feuille')
  5. à la fin, enregistrez le livre.

1 commentaires

Vous ne parlez pas de openpxyl à l'étape 1? pyxl est un package python (qui n'est plus maintenu) pour étendre Python à la prise en charge HTML en ligne.



0
votes

J'ai utilisé une fonction qui fait apparemment le travail dont vous avez également besoin. J'utilise xlwings , je ne connais pas openpyxl. Il peut traiter 3 cas critiques:

  • Aucun classeur ouvert
  • Feuille souhaitée introuvable (créez-en une nouvelle sans lever d'exception)
  • La tentative de localisation de la feuille a échoué (ceci est utilisé pour rechercher la feuille et n'est pas visible pour l'utilisateur)

La fonction renvoie (en cas de succès) un objet xlwings.Sheet (qui est l'équivalent xlwings de l'objet Excel Sheet. N'oubliez pas que vous pouvez revenir à l'objet COM natif "Sheet" en utilisant la propriété xlwings.sheet.api

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


0 commentaires

0
votes

Si vous utilisez xlwings , il existe une autre méthode comme suit.

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


0 commentaires