diff --git a/py-polars/polars/dataframe/frame.py b/py-polars/polars/dataframe/frame.py index 30fe3691635e..372d98036f16 100644 --- a/py-polars/polars/dataframe/frame.py +++ b/py-polars/polars/dataframe/frame.py @@ -98,6 +98,7 @@ from polars.dependencies import pyarrow as pa from polars.exceptions import ( ColumnNotFoundError, + InvalidOperationError, ModuleUpgradeRequiredError, NoRowsReturnedError, TooManyRowsReturnedError, @@ -3506,6 +3507,16 @@ def write_excel( table_start[1] + len(df.columns) - 1, ) + excel_max_valid_rows = 1048575 + excel_max_valid_cols = 16384 + + if ( + table_finish[0] > excel_max_valid_rows + or table_finish[1] > excel_max_valid_cols + ): + msg = f"writing {df.height}x{df.width} frame at {position!r} does not fit worksheet dimensions of {excel_max_valid_rows} rows and {excel_max_valid_cols} columns" + raise InvalidOperationError(msg) + # write table structure and formats into the target sheet if not is_empty or include_header: ws.add_table( diff --git a/py-polars/tests/unit/io/test_spreadsheet.py b/py-polars/tests/unit/io/test_spreadsheet.py index a5ac7a568d99..f0d03caf00fd 100644 --- a/py-polars/tests/unit/io/test_spreadsheet.py +++ b/py-polars/tests/unit/io/test_spreadsheet.py @@ -12,7 +12,10 @@ import polars as pl import polars.selectors as cs -from polars.exceptions import NoDataError, ParameterCollisionError +from polars.exceptions import ( + NoDataError, + ParameterCollisionError, +) from polars.testing import assert_frame_equal, assert_series_equal from tests.unit.conftest import FLOAT_DTYPES, NUMERIC_DTYPES @@ -1184,6 +1187,16 @@ def test_excel_write_worksheet_object() -> None: df.write_excel(None, worksheet=ws) +def test_excel_write_beyond_max_rows_cols() -> None: + path = "/tmp/test.xlsx" + sheet = "mysheet" + + df = pl.DataFrame({"col1": range(10), "col2": range(10, 20)}) + + with pytest.raises(pl.exceptions.InvalidOperationError): + df.write_excel(workbook=path, worksheet=sheet, position="A1048570") + + def test_excel_freeze_panes() -> None: from xlsxwriter import Workbook