Skip to content

BUG: XlsxWriter ignoring formats on numpy types if merged cells #27006

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

Merged
merged 11 commits into from
Jun 28, 2019
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.25.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,7 @@ I/O
- Fixed bug in :func:`pandas.read_csv` where a BOM would result in incorrect parsing using engine='python' (:issue:`26545`)
- :func:`read_excel` now raises a ``ValueError`` when input is of type :class:`pandas.io.excel.ExcelFile` and ``engine`` param is passed since :class:`pandas.io.excel.ExcelFile` has an engine defined (:issue:`26566`)
- Bug while selecting from :class:`HDFStore` with ``where=''`` specified (:issue:`26610`).
- Fixed bug in :func:`DataFrame.to_excel()` where custom objects (i.e. `PeriodIndex`) inside merged cells were not being converted into types safe for the Excel writer (:issue:`27006`)

Plotting
^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion pandas/io/excel/_xlsxwriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0,
startcol + cell.col,
startrow + cell.mergestart,
startcol + cell.mergeend,
cell.val, style)
val, style)
else:
wks.write(startrow + cell.row,
startcol + cell.col,
Expand Down
14 changes: 14 additions & 0 deletions pandas/tests/io/excel/test_writers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,20 @@ def test_path_local_path(self, engine, ext):
path="foo.{ext}".format(ext=ext))
tm.assert_frame_equal(result, df)

def test_merged_cell_custom_objects(self, engine, ext):
# see GH-27006
mi = MultiIndex.from_tuples([(pd.Period('2018'), pd.Period('2018Q1')),
(pd.Period('2018'), pd.Period('2018Q2'))])
expected = DataFrame(np.random.rand(2, len(mi)), columns=mi)
expected.to_excel(self.path)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you add the merge_cells fixture do merge_cells=merge_cells as part of the call here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if I do this, won't this always fail the assert comparison? When this is False, it creates a single cell that contains both levels in the excel file (for instance '2018.2018Q2'). When I read this back in, it's read in as a single column Index and fails comparing against the original MultiIndex.

result = pd.read_excel(self.path, header=[0, 1], index_col=0)
# need to convert PeriodIndexes to standard Indexes for assert equal
expected.columns.set_levels([[str(i) for i in mi.levels[0]],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can just simplify this as expected.columns = expected.columns.astype(object) - Period won't be lossless to / from Excel so makes sense

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplify this as stated

Copy link
Contributor Author

@riptusk331 riptusk331 Jun 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This simplication doesn't seem to work. Comparison fails - the Index read back in isn't preserved as a Period.

E  MultiIndex level [0] classes are not equivalent
E  [left]:  PeriodIndex(['2018', '2018'], dtype='period[A-DEC]', freq='A-DEC')
E  [right]: Index(['2018', '2018'], dtype='object')

[str(i) for i in mi.levels[1]]],
level=[0, 1],
inplace=True)
tm.assert_frame_equal(expected, result)


class TestExcelWriterEngineTests:

Expand Down