Skip to content

Commit f023954

Browse files
author
Joeperdefloep
committed
ENH: add if_sheet_exists='write_to' to ExcelWriter
1 parent 3ce150d commit f023954

File tree

3 files changed

+30
-5
lines changed

3 files changed

+30
-5
lines changed

pandas/io/excel/_base.py

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

940962
self.mode = mode
941963

942-
if if_sheet_exists not in [None, "error", "new", "replace"]:
964+
if if_sheet_exists not in [None, "error", "new", "replace", "write_to"]:
943965
raise ValueError(
944966
f"'{if_sheet_exists}' is not valid for if_sheet_exists. "
945-
"Valid options are 'error', 'new' and 'replace'."
967+
"Valid options are 'error', 'new', 'replace' and 'write_to'."
946968
)
947969
if if_sheet_exists and "r+" not in mode:
948970
raise ValueError("if_sheet_exists is only valid in append mode (mode='a')")

pandas/io/excel/_openpyxl.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -431,10 +431,12 @@ def write_cells(
431431
f"Sheet '{sheet_name}' already exists and "
432432
f"if_sheet_exists is set to 'error'."
433433
)
434+
elif self.if_sheet_exists == "write_to":
435+
wks = self.sheets[sheet_name]
434436
else:
435437
raise ValueError(
436438
f"'{self.if_sheet_exists}' is not valid for if_sheet_exists. "
437-
"Valid options are 'error', 'new' and 'replace'."
439+
"Valid options are 'error', 'new', 'replace' and 'write_to'."
438440
)
439441
else:
440442
wks = self.sheets[sheet_name]

pandas/tests/io/excel/test_openpyxl.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def test_write_append_mode(ext, mode, expected):
115115
[
116116
("new", 2, ["apple", "banana"]),
117117
("replace", 1, ["pear"]),
118+
("write_to", 1, ["pear", "banana"]),
118119
],
119120
)
120121
def test_if_sheet_exists_append_modes(ext, if_sheet_exists, num_sheets, expected):
@@ -146,7 +147,7 @@ def test_if_sheet_exists_append_modes(ext, if_sheet_exists, num_sheets, expected
146147
(
147148
"invalid",
148149
"'invalid' is not valid for if_sheet_exists. Valid options "
149-
"are 'error', 'new' and 'replace'.",
150+
"are 'error', 'new', 'replace' and 'write_to'.",
150151
),
151152
(
152153
"error",

0 commit comments

Comments
 (0)