Skip to content
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: Number formatting support for excel styles #22015

Merged
merged 2 commits into from
Jul 24, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion doc/source/style.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,10 @@
"- `vertical-align`\n",
"- `white-space: nowrap`\n",
"\n",
"Only CSS2 named colors and hex colors of the form `#rgb` or `#rrggbb` are currently supported."
"Only CSS2 named colors and hex colors of the form `#rgb` or `#rrggbb` are currently supported.\n",
"\n",
"The following pseudo CSS properties are also available to set excel specific style properties:\n",
"- `number-format`\n"
]
},
{
Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.24.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ Other API Changes
- Trying to reindex a ``DataFrame`` with a non unique ``MultiIndex`` now raises a ``ValueError`` instead of an ``Exception`` (:issue:`21770`)
- :meth:`PeriodIndex.tz_convert` and :meth:`PeriodIndex.tz_localize` have been removed (:issue:`21781`)
- :class:`Index` subtraction will attempt to operate element-wise instead of raising ``TypeError`` (:issue:`19369`)
- :class:`pandas.io.formats.style.Styler` supports a ``number-format`` property when using :meth:`~pandas.io.formats.style.Styler.to_excel`

.. _whatsnew_0240.deprecations:

Expand Down
5 changes: 4 additions & 1 deletion pandas/io/formats/excel.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ def build_xlstyle(self, props):
'border': self.build_border(props),
'fill': self.build_fill(props),
'font': self.build_font(props),
'number_format': self.build_number_format(props),
}
# TODO: support number format
# TODO: handle cell width and height: needs support in pandas.io.excel

def remove_none(d):
Expand Down Expand Up @@ -314,6 +314,9 @@ def color_to_excel(self, val):
warnings.warn('Unhandled color format: {val!r}'.format(val=val),
CSSWarning)

def build_number_format(self, props):
return {'format_code': props.get('number-format')}


class ExcelFormatter(object):
"""
Expand Down
3 changes: 3 additions & 0 deletions pandas/tests/io/formats/test_to_excel.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@
{'alignment': {'wrap_text': False}}),
('white-space: normal',
{'alignment': {'wrap_text': True}}),
# NUMBER FORMAT
('number-format: 0%',
{'number_format': {'format_code': '0%'}}),
])
def test_css_to_excel(css, expected):
convert = CSSToExcelConverter()
Expand Down
14 changes: 9 additions & 5 deletions pandas/tests/io/test_excel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2241,6 +2241,7 @@ def style(df):
['', 'font-style: italic', ''],
['', '', 'text-align: right'],
['background-color: red', '', ''],
['number-format: 0%', '', ''],
['', '', ''],
['', '', ''],
['', '', '']],
Expand All @@ -2266,7 +2267,7 @@ def custom_converter(css):

# Prepare spreadsheets

df = DataFrame(np.random.randn(10, 3))
df = DataFrame(np.random.randn(11, 3))
with ensure_clean('.xlsx' if engine != 'xlwt' else '.xls') as path:
writer = ExcelWriter(path, engine=engine)
df.to_excel(writer, sheet_name='frame')
Expand Down Expand Up @@ -2294,7 +2295,7 @@ def custom_converter(css):
n_cells += 1

# ensure iteration actually happened:
assert n_cells == (10 + 1) * (3 + 1)
assert n_cells == (11 + 1) * (3 + 1)

# (2) check styling with default converter

Expand Down Expand Up @@ -2344,13 +2345,16 @@ def custom_converter(css):
assert cell1.fill.patternType != cell2.fill.patternType
assert cell2.fill.fgColor.rgb == alpha + 'FF0000'
assert cell2.fill.patternType == 'solid'
elif ref == 'B9':
assert cell1.number_format == 'General'
assert cell2.number_format == '0%'
else:
assert_equal_style(cell1, cell2)

assert cell1.value == cell2.value
n_cells += 1

assert n_cells == (10 + 1) * (3 + 1)
assert n_cells == (11 + 1) * (3 + 1)

# (3) check styling with custom converter
n_cells = 0
Expand All @@ -2359,7 +2363,7 @@ def custom_converter(css):
assert len(col1) == len(col2)
for cell1, cell2 in zip(col1, col2):
ref = '%s%d' % (cell2.column, cell2.row)
if ref in ('B2', 'C3', 'D4', 'B5', 'C6', 'D7', 'B8'):
if ref in ('B2', 'C3', 'D4', 'B5', 'C6', 'D7', 'B8', 'B9'):
assert not cell1.font.bold
assert cell2.font.bold
else:
Expand All @@ -2368,7 +2372,7 @@ def custom_converter(css):
assert cell1.value == cell2.value
n_cells += 1

assert n_cells == (10 + 1) * (3 + 1)
assert n_cells == (11 + 1) * (3 + 1)


@td.skip_if_no('openpyxl')
Expand Down