-
-
Notifications
You must be signed in to change notification settings - Fork 18.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ENH: Allow to assign/create custom body_style and header_style property to an instance of ExcelFormatter used in method df.to_excel() #53973
Conversation
@rhshadrach I'm reading through the linked GitHub issue, as well as @attack68's comments. Do we want to use setter methods to declare values for Or are we letting |
My preferred option as stated in the issues was to remove the formatting added by default when doing However, given that might annoy a number of users I would suggest a compromise.
|
pandas/io/formats/excel.py
Outdated
@@ -577,19 +577,32 @@ def __init__( | |||
self.header = header | |||
self.merge_cells = merge_cells | |||
self.inf_rep = inf_rep | |||
self._header_styledict[str, Any] = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be self._header_style: dict[str, Any] | None = None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between defaulting to None
and {}
here?
pandas/io/formats/excel.py
Outdated
@header_style.setter | ||
def header_style(self, val): | ||
if not isinstance(val, dict): | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setters shouldn't return a value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is overwriting a property on a class, replacing it with (presumably) a Python dictionary. More generally, it is relying on modifying global state but not by any standard approach (e.g. options). I think it is also requiring users to access a class that was previously internal, further confusing the public/private nature of pandas.io
that I think we should be trying to clear up.
For these reasons, I'm -1 on this approach in its current state. Is using an option for this appropriate?
|
||
# Set Excel worksheet header and body style | ||
>>> df = pd.DataFrame([{"A": 1, "B": 2, "C": 3}, {"A": 1, "B": 2, "C": 3}]) | ||
>>> pd.io.formats.excel.ExcelFormatter.header_style = {"font": {"bold": True},} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is doing what you might expect. In particular, this is not using getters/setters, but rather just overwriting a property.
class Foo:
@property
def foo(self):
raise ValueError
@foo.setter
def foo(self, other):
raise ValueError
print(Foo.foo)
# <property object at 0x7f5438093290>
Foo.foo = 5
print(Foo.foo)
# 5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do we think would be the appropriate implementation for this request then? It seems like the initial suggestion is not ideal.
What do we think about setting the default style to None
for both header_style and body_style and have users rely on Styler to format output of to_excel
as mentioned here?
@attack68 (from #53973 (comment))
Is it only the removing of the default style that you feel might annoy users? Or being forced into the Styler in order to add style? Or something else?
Pending a response to the above, I'm +1 on this approach. I think modifying global state should be avoided where ever possible, and this feature seems perfect for the Styler to me. |
Since the Styler uses the underlying implementation of DataFrame.to_excel, it is a shame that an unstyled Styler ends up with bold headers by default because of the status quo.
It does seem unnecessary to add this to the state variables of the excel writer when Styler can already do this by default and with greater flexibility. Perhaps documenting users to use the Styler is the better approach that making the code more complicated. |
@attack68 just to recap, add a parameter to For the formatting of the spreadsheet body, that would be controlled via @rhshadrach Are you good with this? |
@rmhowe425 I just reviewed the current arguments for @rhshadrach - If we remove styling from |
I'm not sure I would even consider this a "breaking" change; I don't believe removing bolding from the cells could ever break any workflow. Even if it is considered breaking, I would lean toward adding this to the list of breaking changes in 3.0 in #44823. |
@rhshadrach I'll plan on updating my implementation so that spreadsheets have no formatting by default, and I'll update documentation so that we're telling users to use This sounds like the changes that we agree on? |
This is what I've suggested, but I think we need to make sure there is a consensus among those involved before saying "we agree". |
I have created an issue to highlight this to move forward: #54154 54154 |
Closing PR as work is continuing on #54154 |
doc/source/whatsnew/vX.X.X.rst
file if fixing a bug or adding a new feature.