Repository: pandas-dev/pandas

Issue:
No way to control display format when exporting to excel
#### Code Sample, a copy-pastable example if possible

```python
# format call does nothing
df.style.format("{:.2%}").to_excel('styled.xlsx')

```
#### Problem description

The current excel styler doesn't implement anything for the styler format method. To get number format there are two possible options. First is to connect this method to something. Second is to allow some way to set the number_format attribute on excel cells. The second option is a bit cleaner IMHO since data conversion like truncating decimal places can result in loss of information and number_format is also sort of how excel declares data types eg. displaying a number as a time. 


Discussion:

Resolving patch:
diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py
--- a/pandas/io/formats/excel.py
+++ b/pandas/io/formats/excel.py
@@ -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):
@@ -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):
     """


Test patch:
diff --git a/pandas/tests/io/formats/test_to_excel.py b/pandas/tests/io/formats/test_to_excel.py
--- a/pandas/tests/io/formats/test_to_excel.py
+++ b/pandas/tests/io/formats/test_to_excel.py
@@ -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()
diff --git a/pandas/tests/io/test_excel.py b/pandas/tests/io/test_excel.py
--- a/pandas/tests/io/test_excel.py
+++ b/pandas/tests/io/test_excel.py
@@ -2241,6 +2241,7 @@ def style(df):
                           ['', 'font-style: italic', ''],
                           ['', '', 'text-align: right'],
                           ['background-color: red', '', ''],
+                          ['number-format: 0%', '', ''],
                           ['', '', ''],
                           ['', '', ''],
                           ['', '', '']],
@@ -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')
@@ -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
 
@@ -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
@@ -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:
@@ -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')