openpyxl Set Active Sheet

This is a different approach of setting active sheet in workbook by sheetname. There are similar answers (openpyxl get sheet by name for example involves opening a closed file) and others did not have enough detail for me to understand this functionality.

The Manipulating a workbook in memory tutorial is the place to start and under the answer I have used this tutorial to demonstrate there is no active sheet name, it is actually the sheet at the active index. A different sheet will become active if adding or deleting a sheet changes the sheet at the index position.

Initially I thought .create_sheet made the sheet active but then I realised I had only created the sheet at the active sheet index which happened to be 0. The index can be set to a value greater than the number of sheets and the docs also contain a note that "If the sheet set to active is hidden return the next visible sheet or None".

verbose short answer

for s in range(len(wb.sheetnames)):
    if wb.sheetnames[s] == 'charlie':
        break
wb.active = s

Feel free to improve this answer.

Demonstration

(base) C:\Users\User>python
Python 2.7.14 |Anaconda, Inc.| (default, Nov  8 2017, 13:40:45) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> # http://openpyxl.readthedocs.io/en/2.5/tutorial.html#create-a-workbook
...
>>> from openpyxl import Workbook
>>> wb = Workbook()
>>> print(wb.sheetnames)
[u'Sheet']
>>>
>>> print(wb.active)
<Worksheet "Sheet">
>>> ws = wb.active
>>> ws.title = "alpha"
>>>
>>> ws = wb.create_sheet('bravo')
>>> print(wb.sheetnames)
[u'alpha', u'bravo']
>>> print(wb.active)
<Worksheet "alpha">
>>>
>>> ws = wb.create_sheet('charlie',0)  # insert at index 0
>>> print(wb.sheetnames)
[u'charlie', u'alpha', u'bravo']
>>> print(wb.active)
<Worksheet "charlie">
>>>
>>>
>>> wb.active = 1
>>> print(wb.active)
<Worksheet "alpha">
>>>
>>> wb.active = 2
>>> print(wb.active)
<Worksheet "bravo">
>>>
>>> wb.active = 0
>>> print(wb.active)
<Worksheet "charlie">
>>>
>>> wb.active = 3
>>> print(wb.active)
None
>>>
>>> ws = wb.create_sheet(index=0)  # insert at index
>>> print(wb.active)
<Worksheet "bravo">
>>> print(wb.sheetnames)
[u'Sheet', u'charlie', u'alpha', u'bravo']
>>>
>>>
>>> ws_active = wb.get_sheet_by_name('charlie')
__main__:1: DeprecationWarning: Call to deprecated function get_sheet_by_name (Use wb[sheetname]).
>>> ws_active = wb['charlie']
>>> print(wb.active)
<Worksheet "bravo">
>>> ws4 = wb["charlie"] # from https://stackoverflow.com/a/36814135/4539999
>>> print(wb.active)
<Worksheet "bravo">
>>>
>>>
>>> for s in range(len(wb.sheetnames)):
...     if wb.sheetnames[s] == 'charlie':
...         break
...
>>>
>>> wb.active = s
>>>
>>>
>>> print(wb.active)
<Worksheet "charlie">
>>>

I'm unfamiliar with the whole getters and setters thing. However, I figured out the answer. It's horribly confusing to me right now why it works this way - because it doesn't look like a typical function call. In any case, to use the "setter" you would write

wb.active = 1

which uh "eats" the 1 =) and changes the active sheet. Just writing this up thinking at least one other person may ask something similar.