Skip to content

ENH: Make ExcelFormatter.header_style a class attribute instead of a property #50336

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

Closed
1 of 3 tasks
terazus opened this issue Dec 18, 2022 · 9 comments
Closed
1 of 3 tasks
Assignees
Labels
Enhancement IO Excel read_excel, to_excel

Comments

@terazus
Copy link

terazus commented Dec 18, 2022

Feature Type

  • Adding new functionality to pandas

  • Changing existing functionality in pandas

  • Removing existing functionality in pandas

Problem Description

When I'm trying to remove the default ExcelFormatter header style, my IDE complains that the property cannot be set.
Pycharm suggest adding a setter but I don't think it's the correct behaviour.
image

This is very minor improvement as code runs perfectly well.

Feature Description

Change the ExcelFormatter header_style to be a class attribute instead of a property:

class ExcelFormatter:
    """
    Class for formatting a DataFrame to a list of ExcelCells,

    Parameters
    ----------
    ...
    """

    max_rows = 2 ** 20
    max_cols = 2 ** 14
    header_style: dict[str, dict[str, str | bool]] = {
        "font": {"bold": True},
        "borders": {
            "top": "thin",
            "right": "thin",
            "bottom": "thin",
            "left": "thin",
        },
        "alignment": {"horizontal": "center", "vertical": "top"},
    }

    def __init__(
            self,
            df,
            na_rep: str = "",
            float_format: str | None = None,
            cols: Sequence[Hashable] | None = None,
            header: Sequence[Hashable] | bool = True,
            index: bool = True,
            index_label: IndexLabel | None = None,
            merge_cells: bool = False,
            inf_rep: str = "inf",
            style_converter: Callable | None = None,
    ) -> None:...

Alternative Solutions

Pycharm setter suggestion (which i find less relevant):

class ExcelFormatter:
    """
    Class for formatting a DataFrame to a list of ExcelCells,

    Parameters
    ----------
    ...
    """

    max_rows = 2 ** 20
    max_cols = 2 ** 14

    def __init__(
            self,
            df,
            na_rep: str = "",
            float_format: str | None = None,
            cols: Sequence[Hashable] | None = None,
            header: Sequence[Hashable] | bool = True,
            index: bool = True,
            index_label: IndexLabel | None = None,
            merge_cells: bool = False,
            inf_rep: str = "inf",
            style_converter: Callable | None = None,
    ) -> None:...

    @property
    def header_style(self) -> dict[str, dict[str, str | bool]]:
        return {
            "font": {"bold": True},
            "borders": {
                "top": "thin",
                "right": "thin",
                "bottom": "thin",
                "left": "thin",
            },
            "alignment": {"horizontal": "center", "vertical": "top"},
        }

    @header_style.setter
    def header_style(self, value):
        self._header_style = value

Additional Context

Just thanks for your hard work. 🐼

@terazus terazus added Enhancement Needs Triage Issue that has not been reviewed by a pandas team member labels Dec 18, 2022
@rhshadrach
Copy link
Member

Thanks for the request; can you shorten the code posted? I'm guessing you do not need the entire code of the class.

@rhshadrach rhshadrach added the IO Excel read_excel, to_excel label Dec 18, 2022
@terazus
Copy link
Author

terazus commented Dec 18, 2022

Thanks for the request; can you shorten the code posted? I'm guessing you do not need the entire code of the class.

Hello. Thx for the quick reply. It's done. Let me know if I shorthened too much.

@rhshadrach
Copy link
Member

Thanks - some relevant issues: #22758, #22773

cc @WillAyd @attack68

@rhshadrach rhshadrach changed the title ENH: Make pandas.io.formats.excel.ExcelFormatter.header_style a class attribute instead of a property ENH: Make ExcelFormatter.header_style a class attribute instead of a property Dec 18, 2022
@WillAyd
Copy link
Member

WillAyd commented Dec 20, 2022

Would it suffice to make a setter for the property instead? The advantage of a property is we could theoretically control the assignment and raise if for example particular expectations are not met as to what the header_style needs to provide

@terazus
Copy link
Author

terazus commented Dec 21, 2022

Hello,
I'm personally fine with both. It just feels weird to call a property setter over an object that hasn't been instantianted yet. My suggestion came from the logic that we are modifying the class before we instantiate the object so it would made more sense to use a class attribute than an object property.
I do agree that using a setter would provide extra validation the attribute doesn't.
Thankx :)

@rhshadrach
Copy link
Member

In either case, is there a risk of errors due to the changing of this property while an ExcelWriter is open? I think the answer is no, but we should be certain before entertaining the idea.

@attack68
Copy link
Contributor

df = pd.DataFrame([[1,2],[3,4]], index=["one", "two"], columns=["A", "B"])
df.to_excel("file.xlsx")

image

The above is the default. Using Styler with no styles applied also yields the same, but when adding styles you can control this.

df.style \
  .applymap_index(lambda v: "color:red; text-align:center;", axis=0) \
  .applymap_index(lambda v: "color:blue;", axis=1) \
  .to_excel("df_styler.xlsx")

image

There is a bug that was fixed for v1.5.0 that corrected adding borders as well.

Personally, I would prefer df.to_excel to produce a completely un-styled excel sheet, and let Styler be used to add and define all the custom styles, without setting properties directly on the ExcelFormatter, which are not generally consistent with the way the rest of the API works and is documented for users.

@rmhowe425
Copy link
Contributor

take

@rmhowe425
Copy link
Contributor

@attack68 I'm thinking we can close this issue too due to the same reasons as #52369. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement IO Excel read_excel, to_excel
Projects
None yet
Development

No branches or pull requests

6 participants