From 5bcfef0357a88740567c5bbb78ea588773e84fc4 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Fri, 1 Mar 2024 20:07:54 +0100 Subject: [PATCH 1/2] BUG: Fix empty MultiIndex DataFrame xlsx export (#57696) MultiIndex on both axes, with zero rows. --- doc/source/whatsnew/v3.0.0.rst | 1 + pandas/io/formats/excel.py | 2 +- pandas/tests/io/excel/test_writers.py | 11 +++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index a95f0485abd5f..b22355ecc28b5 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -324,6 +324,7 @@ MultiIndex I/O ^^^ +- Bug in :class:`io.formats.excel.ExcelFormatter` when writing empty :class:`DataFrame` with :class:`MultiIndex` on both axes (:issue:`57696`) - - diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index 504b5aa560670..ee7739df49389 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -620,7 +620,7 @@ def _format_header_mi(self) -> Iterable[ExcelCell]: lnum = 0 if self.index and isinstance(self.df.index, MultiIndex): - coloffset = len(self.df.index[0]) - 1 + coloffset = self.df.index.nlevels - 1 if self.merge_cells: # Format multi-index as a merged cells. diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 6637b4f931102..0858f26b610e0 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -936,6 +936,17 @@ def test_to_excel_empty_multiindex(self, tmp_excel): result, expected, check_index_type=False, check_dtype=False ) + def test_to_excel_empty_multiindex_both_axes(self, tmp_excel): + # GH 57696 + df = DataFrame( + [], + index=MultiIndex.from_tuples([], names=[0, 1]), + columns=MultiIndex.from_tuples([("A", "B")]), + ) + df.to_excel(tmp_excel) + result = pd.read_excel(tmp_excel, header=None) + assert result.iloc[:2, -1].to_list() == ["A", "B"] + def test_to_excel_float_format(self, tmp_excel): df = DataFrame( [[0.123456, 0.234567, 0.567567], [12.32112, 123123.2, 321321.2]], From 94fb1840e96bd382fecd0ef01b14f940515ac905 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Sat, 2 Mar 2024 07:55:07 +0100 Subject: [PATCH 2/2] Address @rhshadrach review comments --- doc/source/whatsnew/v3.0.0.rst | 2 +- pandas/tests/io/excel/test_writers.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index b22355ecc28b5..6b412f5427811 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -324,7 +324,7 @@ MultiIndex I/O ^^^ -- Bug in :class:`io.formats.excel.ExcelFormatter` when writing empty :class:`DataFrame` with :class:`MultiIndex` on both axes (:issue:`57696`) +- Bug in :meth:`DataFrame.to_excel` when writing empty :class:`DataFrame` with :class:`MultiIndex` on both axes (:issue:`57696`) - - diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 0858f26b610e0..d3ddc13c1497e 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -944,8 +944,8 @@ def test_to_excel_empty_multiindex_both_axes(self, tmp_excel): columns=MultiIndex.from_tuples([("A", "B")]), ) df.to_excel(tmp_excel) - result = pd.read_excel(tmp_excel, header=None) - assert result.iloc[:2, -1].to_list() == ["A", "B"] + result = pd.read_excel(tmp_excel, header=[0, 1], index_col=[0, 1]) + tm.assert_frame_equal(result, df) def test_to_excel_float_format(self, tmp_excel): df = DataFrame(