Skip to content

Commit bc6534a

Browse files
author
Joeperdefloep
committed
ENH: add if_sheet_exists='write_to' to ExcelWriter
1 parent 73c473d commit bc6534a

File tree

3 files changed

+30
-5
lines changed

3 files changed

+30
-5
lines changed

pandas/io/excel/_base.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -681,13 +681,14 @@ class ExcelWriter(metaclass=abc.ABCMeta):
681681
be parsed by ``fsspec``, e.g., starting "s3://", "gcs://".
682682
683683
.. versionadded:: 1.2.0
684-
if_sheet_exists : {'error', 'new', 'replace'}, default 'error'
684+
: {'error', 'new', 'replace', 'write_to'}, default 'error'
685685
How to behave when trying to write to a sheet that already
686686
exists (append mode only).
687687
688688
* error: raise a ValueError.
689689
* new: Create a new sheet, with a name determined by the engine.
690690
* replace: Delete the contents of the sheet before writing to it.
691+
* write_to: Write contents to the existing sheet.
691692
692693
.. versionadded:: 1.3.0
693694
engine_kwargs : dict, optional
@@ -755,6 +756,27 @@ class ExcelWriter(metaclass=abc.ABCMeta):
755756
>>> with ExcelWriter("path_to_file.xlsx", mode="a", engine="openpyxl") as writer:
756757
... df.to_excel(writer, sheet_name="Sheet3")
757758
759+
Here, the `if_sheet_exists` parameter can be set to replace a sheet if it
760+
already exists:
761+
762+
>>> with ExcelWriter(
763+
... "path_to_file.xlsx",
764+
... mode="a",
765+
... engine="openpyxl",
766+
... if_sheet_exists="replace"
767+
... ) as writer:
768+
... df.to_excel(writer, sheet_name="Sheet1")
769+
770+
You can specify arguments to the underlying engine. For example to not
771+
calculate the result of a formula:
772+
773+
>>> df = pd.DataFrame(["=1+1"])
774+
... with ExcelWriter(
775+
... "path_to_file.xlsx",
776+
... engine_kwargs={"strings_to_formulas":False}
777+
... ) as writer:
778+
... df.to_excel(writer)
779+
758780
You can store Excel file in RAM:
759781
760782
>>> import io
@@ -940,10 +962,10 @@ def __init__(
940962

941963
self.mode = mode
942964

943-
if if_sheet_exists not in [None, "error", "new", "replace"]:
965+
if if_sheet_exists not in [None, "error", "new", "replace", "write_to"]:
944966
raise ValueError(
945967
f"'{if_sheet_exists}' is not valid for if_sheet_exists. "
946-
"Valid options are 'error', 'new' and 'replace'."
968+
"Valid options are 'error', 'new', 'replace' and 'write_to'."
947969
)
948970
if if_sheet_exists and "r+" not in mode:
949971
raise ValueError("if_sheet_exists is only valid in append mode (mode='a')")

pandas/io/excel/_openpyxl.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,10 +437,12 @@ def write_cells(
437437
f"Sheet '{sheet_name}' already exists and "
438438
f"if_sheet_exists is set to 'error'."
439439
)
440+
elif self.if_sheet_exists == "write_to":
441+
wks = self.sheets[sheet_name]
440442
else:
441443
raise ValueError(
442444
f"'{self.if_sheet_exists}' is not valid for if_sheet_exists. "
443-
"Valid options are 'error', 'new' and 'replace'."
445+
"Valid options are 'error', 'new', 'replace' and 'write_to'."
444446
)
445447
else:
446448
wks = self.sheets[sheet_name]

pandas/tests/io/excel/test_openpyxl.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ def test_write_append_mode(ext, mode, expected):
139139
[
140140
("new", 2, ["apple", "banana"]),
141141
("replace", 1, ["pear"]),
142+
("write_to", 1, ["pear", "banana"]),
142143
],
143144
)
144145
def test_if_sheet_exists_append_modes(ext, if_sheet_exists, num_sheets, expected):
@@ -170,7 +171,7 @@ def test_if_sheet_exists_append_modes(ext, if_sheet_exists, num_sheets, expected
170171
(
171172
"invalid",
172173
"'invalid' is not valid for if_sheet_exists. Valid options "
173-
"are 'error', 'new' and 'replace'.",
174+
"are 'error', 'new', 'replace' and 'write_to'.",
174175
),
175176
(
176177
"error",

0 commit comments

Comments
 (0)