Skip to content

Commit e552845

Browse files
committed
mitosheet: update formatting export to better preserve mito default formatting
1 parent ba17ec6 commit e552845

File tree

1 file changed

+150
-83
lines changed

1 file changed

+150
-83
lines changed

mitosheet/mitosheet/public/v3/formatting.py

+150-83
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Optional, Dict
1+
from typing import Any, List, Optional, Dict
22

33
from openpyxl.styles import Font, PatternFill
44
from openpyxl.styles import NamedStyle
@@ -7,6 +7,7 @@
77
from pandas import DataFrame, ExcelWriter
88

99
from mitosheet.excel_utils import get_column_from_column_index
10+
from mitosheet.is_type_utils import is_float_dtype
1011
from mitosheet.types import (
1112
FC_BOOLEAN_IS_FALSE, FC_BOOLEAN_IS_TRUE, FC_DATETIME_EXACTLY,
1213
FC_DATETIME_GREATER, FC_DATETIME_GREATER_THAN_OR_EQUAL, FC_DATETIME_LESS,
@@ -89,10 +90,13 @@ def get_conditional_format_rule(
8990
return FormulaRule(fill=fill, font=font, formula=formula)
9091

9192
def add_conditional_formats(
92-
conditional_formats: list,
93+
conditional_formats: Optional[List[Any]],
9394
sheet: Worksheet,
9495
df: DataFrame
9596
) -> None:
97+
if conditional_formats is None:
98+
return
99+
96100
for conditional_format in conditional_formats:
97101
for filter in conditional_format.get('filters', []):
98102
# Create the conditional formatting color objects
@@ -127,90 +131,153 @@ def add_number_formatting(
127131
sheet: Worksheet,
128132
df: DataFrame
129133
) -> None:
130-
if number_formats is None:
131-
return
132-
for column_header, number_format in number_formats.items():
133-
column_index = df.columns.tolist().index(column_header)
134+
default_number_format_column_indexes = set(range(len(df.columns)))
135+
136+
# For all the columns that have user defined number formats
137+
# apply those
138+
if number_formats is not None:
139+
for column_header, number_format in number_formats.items():
140+
column_index = df.columns.tolist().index(column_header)
141+
column = get_column_from_column_index(column_index)
142+
cell_range = f'{column}2:{column}{sheet.max_row}'
143+
for cell in sheet[cell_range]:
144+
cell[0].number_format = number_format
145+
146+
default_number_format_column_indexes.remove(column_index)
147+
148+
# For all the float columns that have default number formats
149+
# and contain numbers, apply the default number format
150+
# which has comma separators and 2 decimal places
151+
column_headers = df.columns.tolist()
152+
for column_index in default_number_format_column_indexes:
153+
column_header = column_headers[column_index]
154+
dtype = str(df[column_header].dtype)
155+
if not is_float_dtype(dtype):
156+
continue
157+
134158
column = get_column_from_column_index(column_index)
135159
cell_range = f'{column}2:{column}{sheet.max_row}'
136160
for cell in sheet[cell_range]:
137-
cell[0].number_format = number_format
161+
cell[0].number_format = '#,##0.00'
162+
163+
def add_header_formatting_to_excel_sheet(
164+
writer: ExcelWriter,
165+
sheet_name: str,
166+
header_background_color: Optional[str]=None,
167+
header_font_color: Optional[str]=None
168+
) -> None:
169+
"""
170+
Adds formatting to the header row of the sheet_name, based on the formatting the user
171+
currently has applied in the frontend.
172+
"""
173+
workbook = writer.book
174+
sheet = workbook.get_sheet_by_name(sheet_name)
175+
176+
# Add formatting to the header row
177+
header_name = f"{sheet_name}_Header"
178+
header_format = NamedStyle(name=header_name)
179+
if header_font_color:
180+
# Remove the # from the color
181+
header_format.font = Font(color=header_font_color[1:])
182+
if header_background_color:
183+
# Remove the # from the color
184+
header_format.fill = PatternFill(start_color=header_background_color[1:], end_color=header_background_color[1:], fill_type="solid")
185+
186+
# Only add format if there is a header color or background color
187+
has_header_formatting = header_background_color or header_font_color
188+
if has_header_formatting:
189+
# Add named styles for the header rows to improve performance
190+
workbook.add_named_style(header_format)
191+
192+
# Write the formatting to the sheet
193+
for col in range(1, sheet.max_column + 1):
194+
sheet.cell(row=1, column=col).style = header_name
195+
196+
def add_row_formatting_to_excel_sheet(
197+
writer: ExcelWriter,
198+
sheet_name: str,
199+
even_background_color: Optional[str]=None,
200+
even_font_color: Optional[str]=None,
201+
odd_background_color: Optional[str]=None,
202+
odd_font_color: Optional[str]=None
203+
) -> None:
204+
"""
205+
Adds formatting to the rows of the sheet_name, based on the formatting the user
206+
currently has applied in the frontend.
207+
"""
208+
workbook = writer.book
209+
sheet = workbook.get_sheet_by_name(sheet_name)
210+
211+
# Add formatting to the rows
212+
even_name = f"{sheet_name}_Even"
213+
odd_name = f"{sheet_name}_Odd"
214+
even_format = NamedStyle(name=even_name)
215+
odd_format = NamedStyle(name=odd_name)
216+
217+
# Remove the # from the colors and define the formatting objects
218+
if even_background_color:
219+
even_format.fill = PatternFill(start_color=even_background_color[1:], end_color=even_background_color[1:], fill_type="solid")
220+
if even_font_color:
221+
even_format.font = Font(color=even_font_color[1:])
222+
if odd_background_color:
223+
odd_format.fill = PatternFill(start_color=odd_background_color[1:], end_color=odd_background_color[1:], fill_type="solid")
224+
if odd_font_color:
225+
odd_format.font = Font(color=odd_font_color[1:])
226+
227+
# Only add format if there is a background color or font color
228+
has_row_formatting = even_background_color or even_font_color or odd_background_color or odd_font_color
229+
if not has_row_formatting:
230+
return
231+
232+
workbook.add_named_style(even_format)
233+
workbook.add_named_style(odd_format)
234+
235+
for row in range(2, sheet.max_row + 1):
236+
for col in range(1, sheet.max_column + 1):
237+
if row % 2 == 0:
238+
sheet.cell(row=row, column=col).style = even_name
239+
else:
240+
sheet.cell(row=row, column=col).style = odd_name
138241

139242

140243
def add_formatting_to_excel_sheet(
141-
writer: ExcelWriter,
142-
sheet_name: str,
143-
df: DataFrame,
144-
header_background_color: Optional[str]=None,
145-
header_font_color: Optional[str]=None,
146-
even_background_color: Optional[str]=None,
147-
even_font_color: Optional[str]=None,
148-
odd_background_color: Optional[str]=None,
149-
odd_font_color: Optional[str]=None,
150-
conditional_formats: Optional[list]=None,
151-
number_formats: Optional[Dict[str, Any]]=None
152-
) -> None:
153-
"""
154-
Adds formatting to the sheet_name, based on the formatting the user
155-
currently has applied in the frontend.
156-
157-
NOTE: this is a Mito Pro feature.
158-
"""
159-
workbook = writer.book
160-
sheet = workbook.get_sheet_by_name(sheet_name)
161-
162-
# Add formatting to the header row
163-
header_name = f"{sheet_name}_Header"
164-
header_format = NamedStyle(name=header_name)
165-
if header_font_color:
166-
# Remove the # from the color
167-
header_format.font = Font(color=header_font_color[1:])
168-
if header_background_color:
169-
# Remove the # from the color
170-
header_format.fill = PatternFill(start_color=header_background_color[1:], end_color=header_background_color[1:], fill_type="solid")
171-
172-
# Only add format if there is a header color or background color
173-
has_header_formatting = header_background_color or header_font_color
174-
if has_header_formatting:
175-
# Add named styles for the header rows to improve performance
176-
workbook.add_named_style(header_format)
177-
178-
# Write the formatting to the sheet
179-
for col in range(1, sheet.max_column + 1):
180-
sheet.cell(row=1, column=col).style = header_name
181-
182-
# Add formatting to the rows
183-
even_name = f"{sheet_name}_Even"
184-
odd_name = f"{sheet_name}_Odd"
185-
even_format = NamedStyle(name=even_name)
186-
odd_format = NamedStyle(name=odd_name)
187-
188-
# Remove the # from the colors and define the formatting objects
189-
if even_background_color:
190-
even_format.fill = PatternFill(start_color=even_background_color[1:], end_color=even_background_color[1:], fill_type="solid")
191-
if even_font_color:
192-
even_format.font = Font(color=even_font_color[1:])
193-
if odd_background_color:
194-
odd_format.fill = PatternFill(start_color=odd_background_color[1:], end_color=odd_background_color[1:], fill_type="solid")
195-
if odd_font_color:
196-
odd_format.font = Font(color=odd_font_color[1:])
197-
198-
# Only add format if there is a background color or font color
199-
has_row_formatting = even_background_color or even_font_color or odd_background_color or odd_font_color
200-
if has_row_formatting:
201-
workbook.add_named_style(even_format)
202-
workbook.add_named_style(odd_format)
203-
204-
for row in range(2, sheet.max_row + 1):
205-
for col in range(1, sheet.max_column + 1):
206-
if row % 2 == 0:
207-
sheet.cell(row=row, column=col).style = even_name
208-
else:
209-
sheet.cell(row=row, column=col).style = odd_name
210-
211-
# Add conditional formatting
212-
if conditional_formats is not None:
213-
add_conditional_formats(conditional_formats, sheet, df)
214-
215-
if number_formats is not None:
216-
add_number_formatting(number_formats, sheet, df)
244+
writer: ExcelWriter,
245+
sheet_name: str,
246+
df: DataFrame,
247+
header_background_color: Optional[str]=None,
248+
header_font_color: Optional[str]=None,
249+
even_background_color: Optional[str]=None,
250+
even_font_color: Optional[str]=None,
251+
odd_background_color: Optional[str]=None,
252+
odd_font_color: Optional[str]=None,
253+
conditional_formats: Optional[list]=None,
254+
number_formats: Optional[Dict[str, Any]]=None
255+
) -> None:
256+
"""
257+
Adds formatting to the sheet_name, based on the formatting the user
258+
currently has applied in the frontend.
259+
260+
NOTE: this is a Mito Pro feature.
261+
"""
262+
workbook = writer.book
263+
sheet = workbook.get_sheet_by_name(sheet_name)
264+
265+
add_header_formatting_to_excel_sheet(
266+
writer=writer,
267+
sheet_name=sheet_name,
268+
header_background_color=header_background_color,
269+
header_font_color=header_font_color
270+
)
271+
272+
add_row_formatting_to_excel_sheet(
273+
writer=writer,
274+
sheet_name=sheet_name,
275+
even_background_color=even_background_color,
276+
even_font_color=even_font_color,
277+
odd_background_color=odd_background_color,
278+
odd_font_color=odd_font_color
279+
)
280+
281+
add_conditional_formats(conditional_formats, sheet, df)
282+
283+
add_number_formatting(number_formats, sheet, df)

0 commit comments

Comments
 (0)