I got the same issue and the answer of @Julius was part of the solution, but this only works provided that the columns you want to remove are located at the end of your DataFrame
.
Note: The new API documentation https://pandas.pydata.org/docs/reference/api/pandas.io.formats.style.Styler.hide.html mentions clearly that hide
will not work with to_excel
.
In the below example, we have a table with some columns that are not styled, and others (columns_to_style
) for which there exists a "{name}_style"
column containing which background color to apply.
Here is an example styling function, working row by row. Note that we get the entire row (both data and styling, to be styled and not to be styled). We need to specify a None
or ""
style for those cells. Mind this when you'll be writing your own function.
# Example styling function: get background color from the "*_style" column
def apply_style(row: pd.Series) -> list[str | None]:
styles = []
for col, val in row.items():
if col in columns_to_style:
# Get style from the corresponding column
bg_color = row[f"{col}_style"]
styles.append(f"background-color: {bg_color};")
else:
# Since we get _all_ the columns, and not only the data columns,
# we need to specify a `None` style so the size of the returned list
# and the position of styles match the columns passed to the function
styles.append(None)
return styles
Now, onto the more generic part. Your own is_style
condition to separate the columns may be adjusted to your use case.
# Separate the columns used for styling from the columns of data
is_style = lambda col: col.endswith("_style") # For example
data_cols, style_cols = [], []
for col in df.columns:
style_cols.append(col) if is_style(col) else data_cols.append(col)
dfstyled = (
df
# Place style columns at the end of the dataframe
.reindex(data_cols + style_cols, axis="columns")
# Apply the style to the data columns
.style.apply(apply_style, axis="columns")
# Eventually, hide the styling columns now (but only works for to_html, ...)
.hide(style_cols, axis="columns")
)
dfstyled.to_excel(
filepath,
sheet_name=sheet_name,
index=False,
# Take only the first columns, remove the last ones which are the style columns
columns=data_cols,
)