diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index a95f0485abd5f..6b412f5427811 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 :meth:`DataFrame.to_excel` 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..d3ddc13c1497e 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=[0, 1], index_col=[0, 1]) + tm.assert_frame_equal(result, df) + def test_to_excel_float_format(self, tmp_excel): df = DataFrame( [[0.123456, 0.234567, 0.567567], [12.32112, 123123.2, 321321.2]],