Python for Excel

Errata for Python for Excel

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
Page Chapter 9
Chapter 9

Very small typo:

# First, let's import the packages that we"ll use in this chapter


Note from the Author or Editor:
This is correct. Replace double-quote with single-quote.

Anonymous  May 05, 2021  Jan 14, 2022
Appendix A
Create a New Conda Environment

In the Conda environment, there is the NumPy package missing. "numpy=1.19.2" should be included in the command.

Felix Zumstein
Sep 13, 2023 
Chapter 1, Why Python for Excel, Python For Excel, Modern Language Features, 2nd to last sentence of 1st paragraph

The sentence 'As an example, error handling in VBA has come of age.' exhibits a sentiment that I think was unintended. From the surrounding context it sounds like the author intended to disparage VBA error handling, but 'come of age' means 'the attainment of prominence, respectability, recognition, or maturity' (Merriam Webster). It's a generally positive phrase, with the result being that the meaning of this sentence is something like 'We've been waiting for good error handling in VBA, and at last it's here!' which I don't think was the intention.

I believe a phrase more like 'showing its age' carries the negative connotation intended, along with the meaning of old and past its prime. The revised sentence would be 'As an example, error handling in VBA is really showing its age.'

Note from the Author or Editor:
Thanks for pointing this out! I'll make sure to let the copy editor know so this will be fixed in the final version of the book.

Anonymous  Jan 18, 2021  Mar 04, 2021
Page 16

My point is it's NOT an error but rather I think the code as it is paints an unfair picture of VBA's error handling.

For the example, error handling is not even required.

Instead, the code could be written as follows:

Sub ModifiedRecip(num As Variant)

Select Case IsNumeric(num)

Case True

Select Case num

Case 0

Debug.Print "Value is 0"

Case Else

Debug.Print 1 / num

End Select

Case False

Debug.Print "Value is not numeric"

End Select

End Sub

Note from the Author or Editor:
Thanks for your feedback and you're definitely right, if the code sample would be about how to write an algorithm to return the reciprocal, there would be better ways to solve it. However, the sample was explicitly constructed to present the error handling capabilities of VBA and calculating the reciprocal was just an excuse to have something easy to follow along with. I will add a note about this to clarify.

Anonymous  Nov 10, 2021  Jan 14, 2022
Page 26
1st paragraph

Using wrong term in the following section (correct: "Darstellungsschicht" instead of used "Geschäftsschicht"):
Excel wird die Darstellungsschicht sein, während die Geschäfts- und Datenschichten ...

Note from the Author or Editor:
Thanks! This is an error in the German translation only.

Anonymous  Feb 23, 2023 
Page 57
Open the Command Palette and type default shell. Select the entry that reads “Terminal: Select Default Shell” and hit Enter.

When I type as default shell, the entry "Terminal: Select Default Shell" is not found. Request to check and update. I think this is not available in latest version of VS code.

Note from the Author or Editor:
[p32 rather than p57] Correct, VS Code changed the Command Palette entry from Terminal: Select Default Shell to Terminal: Select Default Profile, accordingly, when you search for default shell, you won’t find the entry. Instead, type default profile.

I had this pointed out on the book's homepage ( but forgot to open an official errata here.

Gowtham  Nov 09, 2021  Jan 14, 2022
Page 59
2nd paragraph

Just for clarity it should be mentioned that the comment in

If condition Then
' Do nothing
End If

is *optional*. Thus, this is equivalent to

If condition Then
End If

Note from the Author or Editor:
I agree, but would rather mention again explicitly that "Do Nothing" is a comment in both versions.

Stefan Pinnow  Nov 06, 2021  Jan 14, 2022
Page 61
Second to last paragraph

The last sentence before `In [94]` it states "You can enumArate in a loop like this:"

Note from the Author or Editor:
Correct: should be "enumerate" instead of "enumarate".

IvenBach  May 27, 2021  Jan 14, 2022
Page 62
2nd to last paragraph

***Even though you state on xii the book is intended for those that "have a basic understanding of programming" there will be those like my past self who use your book to grow beyond what they presently know.

Language change: "You skip the remainder of a loop with the `continue` statement, which means that execution continues with a new loop and the next element:" feels off. Wording "skip the remainder of a loop" and "new loop" may lead some to understand when the condition is fulfilled execution no longer continues and a separate loop is started.
Modified wording from the documentation ( "The continue statement ---, also borrowed from C,--- continues with the next iteration of the loop:"

Also on pg63 Augmented Assignment - the inclusion of a note about creating an infinite loop if someone edits `n += 1` to `n -= 1` would prevent some users from creating one.

Note from the Author or Editor:
Agreed with respect to both remarks!

IvenBach  May 29, 2021  Jan 14, 2022
Page 87
1st paragraph example code `In [3]`

Consider changing the variable name from `data` to `source`, or any other non-identical name, to have distinct names. Having the variable/argument name the same as the parameter name may look strange and possibly confuse some readers. With non identical names `pd.DataFrame(data=source, ...)` it is clearer that `source` is the argument for `data`.

Since it is common to use the same names and you already defined keyword arguments on pg 66 is defined, you can refer the reader back back to this section. Sample explanation:
"You may find instances when a variable is named the same as the parameter. When this occurs `data` on the right of the equals sign is the variable we just defined. It is argument that is assigned to the parameter on the left side of the equals sign."

*A rose by any other name: Python calls them keyword arguments, VBA calls them [named argument](

Note from the Author or Editor:
Agreed that these suggestions will improve the content.

IvenBach  Jun 01, 2021  Jan 14, 2022
Page 113
2nd code block

df.groupby(["continent"]).agg(lambda x: x.max() - x.min())

returns result properly, but Jupyter Notebook shows this warning:

/opt/anaconda3/lib/python3.9/site-packages/pandas/core/groupby/ FutureWarning: Dropping invalid columns in SeriesGroupBy.agg is deprecated. In a future version, a TypeError will be raised. Before calling .agg, select only columns which should be valid for the aggregating function.
results[key] = self.aggregate(func)

so I think a more future-proof version of this command is required.

Note from the Author or Editor:
Correct, this is caused by a newer version of pandas and the code sample should be changed to:

df.loc[:, ["age", "score", "continent"]].groupby(["continent"]).agg(lambda x: x.max() - x.min())

HAN SUN YONG  Nov 25, 2021  Jan 14, 2022
Page 127-128
Beginning on In[6]

The second line of output for `` displays "RangeIndex: 8622 entries, 0 to 8621", while In [10] displays "DatetimeIndex: 8622 entries, 1986-03-13 to 2020-05-27". I initially only saw the difference in columns and missed the importance in the difference of indexes until it was mentioned on page 128 1st paragraph. Explicitly stating line 2 of the output for `` and calling attention to the start and end values of the index should help readers make this connection: "As ++the second line of output for `info` reveals, what was an index of 0 to 8621 is now 1986-03-13 to 2020-05-27++, you are now ..."

Note from the Author or Editor:
Agreed that this makes it clearer.

IvenBach  Jun 02, 2021  Jan 14, 2022
Page 146
3rd paragraph

Problem on page 146
I’m getting an error on page 146 when I try running the script in VS Code.
The error message (traceback) to the terminal is quite long, it ends with “Missing optional dependency ‘xlrd’ ”.
I changed the filter “rglob("*.xls*")” to try to isolate the problem:
• “rglob("*.xlsx")” ran successfully;
• “rglob("*.xls")” failed, with the same message about xlrd as above.
It looks like the problem is with the .xls files only, not the .xlsx files.
Could you give me any advice on solving this? Up to this page, all the examples have worked perfectly for me.
My version of Python is 3.11.4
My version of pandas is 1.5.3
Thanks for any help you can give me.

Note from the Author or Editor:
Thanks for your message! It looks like the most recent versions of Anaconda don't have xlrd installed by default anymore. You can manually install it by running "pip install xlrd" on the Anaconda Prompt.

Anonymous  Nov 13, 2023 
Page 171
first paragraph and following example

The first paragraph in page 171 reads like this:

"Since OpenPyXL doesn’t support the with statement, you will need to make sure to close the file again when you’re done."

If this is true, you should *always* close file manually.

But the second comment in following example states:

"# Required with read_only=True"

This sounds like if you don't use read_only option, OpenPyXL *automatically* closes the file. Confusing, I need your clarification.

Note from the Author or Editor:
You're right. It isn't pointed out clear enough that you only need to manually close the file with "read_only=True". For your reference, without "read_only=True", it is closed automatically as per comment on p.159.

HAN SUN YONG  Dec 02, 2021  Jan 14, 2022
Page 187

"For example, "Sheet1" is called "Feuille1" in French." Should be Feuil1 instead of Feuille1.

Felix Zumstein
Sep 15, 2021  Jan 14, 2022
Page 197
table at the top

The table option should be "numbers" instead of "number"

Felix Zumstein
Oct 15, 2021  Jan 14, 2022
Page 206
code In[66]

In the printed book and the source notebook, it says:

# This makes just two cross-application calls
values = sheet2["A1:E30"].options(np.array).value
sheet2["A1"].value = values + 1

This works just fine. But I was wondering if that last line should be:

sheet2["A1:E30"].value = values + 1

to show that you can update all the values in the range with a single cross-application call.


Note from the Author or Editor:
Hi Sean. I agree, this will make the example easier to read. On top of that, I think it's possibly confusing that I am writing out the values first before manipulating them. I should be able to simplify the sample by turning it into "write by looping" vs. "write as array".

Sean McCoy  Sep 01, 2021  Jan 14, 2022
Page 207
second row on last bullet point

and an on --> and on

Stefan Pinnow  Sep 16, 2021  Jan 14, 2022
Page 214
last paragraph, 8th line from bottom

`File` in `File > Options` has a wrong format/style. Should be the same as `Options`.

Stefan Pinnow  Nov 06, 2021  Jan 14, 2022
Page 258
Figure 12-4

The screenshot shows JSON instead of JavaScript.

Felix Zumstein
Oct 17, 2021  Jan 14, 2022