-1

According to my understanding, workbook.get_sheet_names() is deprecated and we should use wb.sheetnames instead with openpyxl 2.6.2.

wb.sheetnames returns a list of all the sheets, so why can't we do this?

    import openpyxl
    wb=openpyxl.load_workbook('example.xlsx') #loading the workbook
    wb.sheetnames #getting the sheetnames with the new recomended code
    #output:['Sheet']
    wb.sheetnames[0]='Another name'
    wb.sheetnames[0] # Checking if it were changed or not
    #output:['Sheet']

Why didn't the above code work if wb.sheetnames acts as a list? No error was displayed but I didn't see the expected changes

This is what example.xls looks like:

A                         B             C
1 4/5/2015 13:34  Apples          73
2 4/5/2015 3:41   Cherries        85
3 4/6/2015 12:46  Pears           14
4 4/8/2015 8:59   Oranges         52
5 4/10/2015 2:07  Apples          152
6 4/10/2015 18:10 Bananas         23
7 4/10/2015 2:40  Strawberries    98
gmds
  • 19,325
  • 4
  • 32
  • 58

2 Answers2

4

It's because sheetnames is a property; in other words, it looks like an instance attribute, but when you access it, a function is in fact called. You can see this answer for more details.

Now, if we look at the openpyxl source, we can find the definition of sheetnames:

    @property
    def sheetnames(self):
        return [s.title for s in self._sheets]

sheetnames creates and returns a new list every time it is called, which you can prove with id:

from openpyxl import Workbook

book = Workbook()

a = book.sheetnames
b = book.sheetnames

print(id(a) == id(b))

Output:

False

Due to this, you are in fact just modifying the first element of this new list that is created every time you call sheetnames.

gmds
  • 19,325
  • 4
  • 32
  • 58
1

Link to relevant section of the docs

wb.sheetnames will return list of strings (i.e. just the sheet names), wb.sheetnames[0] is just a string. When you do wb.sheetnames[0]='Another name' you change the first string in the list returned by wb.sheetnames, but this change has no any practical/visible effect, because this list is not assigned to any variable.

there is also wb.worksheets which will return list of sheet objects. You can use this method access the respective sheet and using Worksheet.title property do wb.worksheets[0].title='New Title'

from openpyxl import Workbook
wb = Workbook()
print(wb.sheetnames)
print(type(wb.sheetnames[0]))
print(wb.worksheets) 
print(type(wb.worksheets[0]))
wb.worksheets[0].title='New Title'
print(wb.sheetnames)
print(wb.worksheets)

output

['Sheet']
<class 'str'>
[<Worksheet "Sheet">]
<class 'openpyxl.worksheet.worksheet.Worksheet'>
['New Title']
[<Worksheet "New Title">]

Note - for the example I am using new Workbook instance with just one sheet inside it

buran
  • 13,682
  • 10
  • 36
  • 61