[{"data":1,"prerenderedAt":1808},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter":1772,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter":1781,"children:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter":1786,"related:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter":1787},{"id":4,"title":5,"body":6,"dateModified":1739,"datePublished":1739,"description":1740,"extension":1741,"faq":1742,"keyword":1751,"kind":1752,"meta":1753,"navigation":137,"path":1762,"seo":1763,"slug":1765,"stem":1766,"topics":1767,"type":1770,"__hash__":1771},"docs\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter\u002Findex.md","Fix \"Sheet Already Exists\" Errors in pandas ExcelWriter",{"type":7,"value":8,"toc":1727},"minimark",[9,23,28,49,54,85,91,95,548,569,579,583,586,799,834,990,994,1003,1271,1283,1430,1543,1547,1558,1562,1576,1580,1632,1636,1662,1666,1672,1678,1684,1690,1694,1723],[10,11,12,13,17,18,22],"p",{},"A common reporting job updates one sheet of an existing workbook — refreshes the ",[14,15,16],"em",{},"Summary"," sheet every morning while the rest of the file, with its notes and charts, stays as it is. The first attempt is usually ",[19,20,21],"code",{},"pd.ExcelWriter(path, mode=\"a\")",", and the second run fails with:",[10,24,25],{},[19,26,27],{},"ValueError: Sheet 'Summary' already exists and if_sheet_exists is set to 'error'.",[10,29,30,31,34,35,38,39,42,43,48],{},"The message points at the fix — the ",[19,32,33],{},"if_sheet_exists"," argument — but its four values behave quite differently, and one of them, ",[19,36,37],{},"overlay",", quietly leaves old data in the sheet. There is also a closely related error, ",[19,40,41],{},"Append mode is not supported with xlsxwriter!",", which appears when the engine is not specified. This page reproduces both errors, shows exactly what each option does to a sheet, and settles on a safe way to refresh one sheet in a workbook. It belongs to ",[44,45,47],"a",{"href":46},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002F","Troubleshooting Common Python Excel Errors",".",[50,51,53],"h2",{"id":52},"prerequisites","Prerequisites",[55,56,61],"pre",{"className":57,"code":58,"language":59,"meta":60,"style":60},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl xlsxwriter\n","bash","",[19,62,63],{"__ignoreMap":60},[64,65,68,72,76,79,82],"span",{"class":66,"line":67},"line",1,[64,69,71],{"class":70},"sMTad","pip",[64,73,75],{"class":74},"srMev"," install",[64,77,78],{"class":74}," pandas",[64,80,81],{"class":74}," openpyxl",[64,83,84],{"class":74}," xlsxwriter\n",[10,86,87,88,90],{},"The examples were run with pandas 3. The behaviour described has been the same since pandas 1.4, when ",[19,89,37],{}," was added.",[50,92,94],{"id":93},"step-1-reproduce-the-errors","Step 1 — Reproduce the errors",[55,96,100],{"className":97,"code":98,"language":99,"meta":60,"style":60},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\nfrom openpyxl import load_workbook\n\ndef make_report():\n    with pd.ExcelWriter(\"report.xlsx\", engine=\"openpyxl\") as xw:\n        pd.DataFrame({\"Region\": [\"North\", \"South\", \"East\", \"West\"], \"Sales\": [120, 95, 80, 60]}).to_excel(xw, sheet_name=\"Summary\", index=False)\n        pd.DataFrame({\"Note\": [\"Figures exclude returns.\"]}).to_excel(xw, sheet_name=\"Notes\", index=False)\n    wb = load_workbook(\"report.xlsx\")\n    wb[\"Summary\"][\"D1\"] = \"Checked by: AH\"\n    wb.save(\"report.xlsx\")\n\nnew_summary = pd.DataFrame({\"Region\": [\"North\", \"South\"], \"Sales\": [131, 88]})\n\nmake_report()\nfor kwargs in [{}, {\"engine\": \"openpyxl\"}]:\n    try:\n        with pd.ExcelWriter(\"report.xlsx\", mode=\"a\", **kwargs) as xw:\n            new_summary.to_excel(xw, sheet_name=\"Summary\", index=False)\n    except ValueError as e:\n        print(f\"{str(kwargs):\u003C22} ValueError: {e}\")\n","python",[19,101,102,118,132,139,152,185,266,298,313,335,345,350,388,393,399,425,434,466,488,503],{"__ignoreMap":60},[64,103,104,108,112,115],{"class":66,"line":67},[64,105,107],{"class":106},"s-kum","import",[64,109,111],{"class":110},"skGVy"," pandas ",[64,113,114],{"class":106},"as",[64,116,117],{"class":110}," pd\n",[64,119,121,124,127,129],{"class":66,"line":120},2,[64,122,123],{"class":106},"from",[64,125,126],{"class":110}," openpyxl ",[64,128,107],{"class":106},[64,130,131],{"class":110}," load_workbook\n",[64,133,135],{"class":66,"line":134},3,[64,136,138],{"emptyLinePlaceholder":137},true,"\n",[64,140,142,145,149],{"class":66,"line":141},4,[64,143,144],{"class":106},"def",[64,146,148],{"class":147},"s_Opv"," make_report",[64,150,151],{"class":110},"():\n",[64,153,155,158,161,164,167,171,174,177,180,182],{"class":66,"line":154},5,[64,156,157],{"class":106},"    with",[64,159,160],{"class":110}," pd.ExcelWriter(",[64,162,163],{"class":74},"\"report.xlsx\"",[64,165,166],{"class":110},", ",[64,168,170],{"class":169},"sa561","engine",[64,172,173],{"class":106},"=",[64,175,176],{"class":74},"\"openpyxl\"",[64,178,179],{"class":110},") ",[64,181,114],{"class":106},[64,183,184],{"class":110}," xw:\n",[64,186,188,191,194,197,200,202,205,207,210,212,215,218,221,223,227,229,232,234,237,239,242,245,248,250,253,255,258,260,263],{"class":66,"line":187},6,[64,189,190],{"class":110},"        pd.DataFrame({",[64,192,193],{"class":74},"\"Region\"",[64,195,196],{"class":110},": [",[64,198,199],{"class":74},"\"North\"",[64,201,166],{"class":110},[64,203,204],{"class":74},"\"South\"",[64,206,166],{"class":110},[64,208,209],{"class":74},"\"East\"",[64,211,166],{"class":110},[64,213,214],{"class":74},"\"West\"",[64,216,217],{"class":110},"], ",[64,219,220],{"class":74},"\"Sales\"",[64,222,196],{"class":110},[64,224,226],{"class":225},"sP0c6","120",[64,228,166],{"class":110},[64,230,231],{"class":225},"95",[64,233,166],{"class":110},[64,235,236],{"class":225},"80",[64,238,166],{"class":110},[64,240,241],{"class":225},"60",[64,243,244],{"class":110},"]}).to_excel(xw, ",[64,246,247],{"class":169},"sheet_name",[64,249,173],{"class":106},[64,251,252],{"class":74},"\"Summary\"",[64,254,166],{"class":110},[64,256,257],{"class":169},"index",[64,259,173],{"class":106},[64,261,262],{"class":225},"False",[64,264,265],{"class":110},")\n",[64,267,269,271,274,276,279,281,283,285,288,290,292,294,296],{"class":66,"line":268},7,[64,270,190],{"class":110},[64,272,273],{"class":74},"\"Note\"",[64,275,196],{"class":110},[64,277,278],{"class":74},"\"Figures exclude returns.\"",[64,280,244],{"class":110},[64,282,247],{"class":169},[64,284,173],{"class":106},[64,286,287],{"class":74},"\"Notes\"",[64,289,166],{"class":110},[64,291,257],{"class":169},[64,293,173],{"class":106},[64,295,262],{"class":225},[64,297,265],{"class":110},[64,299,301,304,306,309,311],{"class":66,"line":300},8,[64,302,303],{"class":110},"    wb ",[64,305,173],{"class":106},[64,307,308],{"class":110}," load_workbook(",[64,310,163],{"class":74},[64,312,265],{"class":110},[64,314,316,319,321,324,327,330,332],{"class":66,"line":315},9,[64,317,318],{"class":110},"    wb[",[64,320,252],{"class":74},[64,322,323],{"class":110},"][",[64,325,326],{"class":74},"\"D1\"",[64,328,329],{"class":110},"] ",[64,331,173],{"class":106},[64,333,334],{"class":74}," \"Checked by: AH\"\n",[64,336,338,341,343],{"class":66,"line":337},10,[64,339,340],{"class":110},"    wb.save(",[64,342,163],{"class":74},[64,344,265],{"class":110},[64,346,348],{"class":66,"line":347},11,[64,349,138],{"emptyLinePlaceholder":137},[64,351,353,356,358,361,363,365,367,369,371,373,375,377,380,382,385],{"class":66,"line":352},12,[64,354,355],{"class":110},"new_summary ",[64,357,173],{"class":106},[64,359,360],{"class":110}," pd.DataFrame({",[64,362,193],{"class":74},[64,364,196],{"class":110},[64,366,199],{"class":74},[64,368,166],{"class":110},[64,370,204],{"class":74},[64,372,217],{"class":110},[64,374,220],{"class":74},[64,376,196],{"class":110},[64,378,379],{"class":225},"131",[64,381,166],{"class":110},[64,383,384],{"class":225},"88",[64,386,387],{"class":110},"]})\n",[64,389,391],{"class":66,"line":390},13,[64,392,138],{"emptyLinePlaceholder":137},[64,394,396],{"class":66,"line":395},14,[64,397,398],{"class":110},"make_report()\n",[64,400,402,405,408,411,414,417,420,422],{"class":66,"line":401},15,[64,403,404],{"class":106},"for",[64,406,407],{"class":110}," kwargs ",[64,409,410],{"class":106},"in",[64,412,413],{"class":110}," [{}, {",[64,415,416],{"class":74},"\"engine\"",[64,418,419],{"class":110},": ",[64,421,176],{"class":74},[64,423,424],{"class":110},"}]:\n",[64,426,428,431],{"class":66,"line":427},16,[64,429,430],{"class":106},"    try",[64,432,433],{"class":110},":\n",[64,435,437,440,442,444,446,449,451,454,456,459,462,464],{"class":66,"line":436},17,[64,438,439],{"class":106},"        with",[64,441,160],{"class":110},[64,443,163],{"class":74},[64,445,166],{"class":110},[64,447,448],{"class":169},"mode",[64,450,173],{"class":106},[64,452,453],{"class":74},"\"a\"",[64,455,166],{"class":110},[64,457,458],{"class":106},"**",[64,460,461],{"class":110},"kwargs) ",[64,463,114],{"class":106},[64,465,184],{"class":110},[64,467,469,472,474,476,478,480,482,484,486],{"class":66,"line":468},18,[64,470,471],{"class":110},"            new_summary.to_excel(xw, ",[64,473,247],{"class":169},[64,475,173],{"class":106},[64,477,252],{"class":74},[64,479,166],{"class":110},[64,481,257],{"class":169},[64,483,173],{"class":106},[64,485,262],{"class":225},[64,487,265],{"class":110},[64,489,491,494,497,500],{"class":66,"line":490},19,[64,492,493],{"class":106},"    except",[64,495,496],{"class":225}," ValueError",[64,498,499],{"class":106}," as",[64,501,502],{"class":110}," e:\n",[64,504,506,509,512,515,518,522,525,528,531,534,537,539,542,544,546],{"class":66,"line":505},20,[64,507,508],{"class":225},"        print",[64,510,511],{"class":110},"(",[64,513,514],{"class":106},"f",[64,516,517],{"class":74},"\"",[64,519,521],{"class":520},"sSjpA","{",[64,523,524],{"class":225},"str",[64,526,527],{"class":110},"(kwargs)",[64,529,530],{"class":106},":\u003C22",[64,532,533],{"class":520},"}",[64,535,536],{"class":74}," ValueError: ",[64,538,521],{"class":520},[64,540,541],{"class":110},"e",[64,543,533],{"class":520},[64,545,517],{"class":74},[64,547,265],{"class":110},[10,549,550,551,553,554,557,558,561,562,564,565,568],{},"The first attempt fails before even looking at the sheet: without an ",[19,552,170],{}," argument pandas picks XlsxWriter for ",[19,555,556],{},".xlsx"," files whenever it is installed, and XlsxWriter can only create new files, so append mode is refused. With ",[19,559,560],{},"engine=\"openpyxl\""," the file is opened, and the error is the one in the title: the default for ",[19,563,33],{}," is ",[19,566,567],{},"\"error\"",", which refuses to touch a sheet that is already there. That default is deliberate — pandas will not guess whether you want to keep, replace or merge with the existing sheet.",[10,570,571,572,575,576,578],{},"Notice when the error appears. A job written with ",[19,573,574],{},"mode=\"a\""," often works the first time it runs against a fresh template that has no ",[14,577,16],{}," sheet yet, and fails on the second run, when the sheet it created the day before is in the way. That is why the error tends to surface in production rather than in testing: test the job by running it twice against the same file.",[50,580,582],{"id":581},"step-2-what-each-option-does","Step 2 — What each option does",[10,584,585],{},"Run the same append once for each value and look at the workbook afterwards:",[55,587,589],{"className":97,"code":588,"language":99,"meta":60,"style":60},"for option in [\"new\", \"replace\", \"overlay\"]:\n    make_report()\n    with pd.ExcelWriter(\"report.xlsx\", mode=\"a\", engine=\"openpyxl\", if_sheet_exists=option) as xw:\n        new_summary.to_excel(xw, sheet_name=\"Summary\", index=False)\n    wb = load_workbook(\"report.xlsx\")\n    ws = wb[\"Summary\"]\n    regions = [c.value for c in ws[\"A\"]]\n    print(f\"{option:\u003C8} sheets={wb.sheetnames}  Summary column A={regions}  D1={ws['D1'].value!r}\")\n",[19,590,591,619,624,661,682,694,709,735],{"__ignoreMap":60},[64,592,593,595,598,600,603,606,608,611,613,616],{"class":66,"line":67},[64,594,404],{"class":106},[64,596,597],{"class":110}," option ",[64,599,410],{"class":106},[64,601,602],{"class":110}," [",[64,604,605],{"class":74},"\"new\"",[64,607,166],{"class":110},[64,609,610],{"class":74},"\"replace\"",[64,612,166],{"class":110},[64,614,615],{"class":74},"\"overlay\"",[64,617,618],{"class":110},"]:\n",[64,620,621],{"class":66,"line":120},[64,622,623],{"class":110},"    make_report()\n",[64,625,626,628,630,632,634,636,638,640,642,644,646,648,650,652,654,657,659],{"class":66,"line":134},[64,627,157],{"class":106},[64,629,160],{"class":110},[64,631,163],{"class":74},[64,633,166],{"class":110},[64,635,448],{"class":169},[64,637,173],{"class":106},[64,639,453],{"class":74},[64,641,166],{"class":110},[64,643,170],{"class":169},[64,645,173],{"class":106},[64,647,176],{"class":74},[64,649,166],{"class":110},[64,651,33],{"class":169},[64,653,173],{"class":106},[64,655,656],{"class":110},"option) ",[64,658,114],{"class":106},[64,660,184],{"class":110},[64,662,663,666,668,670,672,674,676,678,680],{"class":66,"line":141},[64,664,665],{"class":110},"        new_summary.to_excel(xw, ",[64,667,247],{"class":169},[64,669,173],{"class":106},[64,671,252],{"class":74},[64,673,166],{"class":110},[64,675,257],{"class":169},[64,677,173],{"class":106},[64,679,262],{"class":225},[64,681,265],{"class":110},[64,683,684,686,688,690,692],{"class":66,"line":154},[64,685,303],{"class":110},[64,687,173],{"class":106},[64,689,308],{"class":110},[64,691,163],{"class":74},[64,693,265],{"class":110},[64,695,696,699,701,704,706],{"class":66,"line":187},[64,697,698],{"class":110},"    ws ",[64,700,173],{"class":106},[64,702,703],{"class":110}," wb[",[64,705,252],{"class":74},[64,707,708],{"class":110},"]\n",[64,710,711,714,716,719,721,724,726,729,732],{"class":66,"line":268},[64,712,713],{"class":110},"    regions ",[64,715,173],{"class":106},[64,717,718],{"class":110}," [c.value ",[64,720,404],{"class":106},[64,722,723],{"class":110}," c ",[64,725,410],{"class":106},[64,727,728],{"class":110}," ws[",[64,730,731],{"class":74},"\"A\"",[64,733,734],{"class":110},"]]\n",[64,736,737,740,742,744,746,748,751,754,756,759,761,764,766,769,771,774,776,779,781,784,787,790,793,795,797],{"class":66,"line":300},[64,738,739],{"class":225},"    print",[64,741,511],{"class":110},[64,743,514],{"class":106},[64,745,517],{"class":74},[64,747,521],{"class":520},[64,749,750],{"class":110},"option",[64,752,753],{"class":106},":\u003C8",[64,755,533],{"class":520},[64,757,758],{"class":74}," sheets=",[64,760,521],{"class":520},[64,762,763],{"class":110},"wb.sheetnames",[64,765,533],{"class":520},[64,767,768],{"class":74},"  Summary column A=",[64,770,521],{"class":520},[64,772,773],{"class":110},"regions",[64,775,533],{"class":520},[64,777,778],{"class":74},"  D1=",[64,780,521],{"class":520},[64,782,783],{"class":110},"ws[",[64,785,786],{"class":74},"'D1'",[64,788,789],{"class":110},"].value",[64,791,792],{"class":106},"!r",[64,794,533],{"class":520},[64,796,517],{"class":74},[64,798,265],{"class":110},[10,800,801,804,805,807,808,811,812,815,816,818,819,822,823,825,826,829,830,833],{},[19,802,803],{},"new"," leaves ",[14,806,16],{}," untouched and writes the data to a new sheet called ",[14,809,810],{},"Summary1"," — rarely what a refresh wants, and each run adds another sheet. ",[19,813,814],{},"replace"," deletes the old ",[14,817,16],{}," sheet and writes a fresh one in the same position: the data is exactly the new DataFrame, but everything else on the sheet is gone too, including the ",[14,820,821],{},"Checked by"," note in D1, any formatting, column widths and charts placed on that sheet. ",[19,824,37],{}," writes the new data into the existing sheet cell by cell, leaving everything it does not overwrite — which keeps the note in D1, but also keeps ",[14,827,828],{},"East"," and ",[14,831,832],{},"West"," with their old figures in rows 4 and 5, because the new data has only two rows. The sheet now mixes this morning's data with yesterday's, with nothing to show which is which.",[835,836,844,845,844,849,844,853,844,861,844,869,844,876,844,883,844,886,844,890,844,893,844,897,844,902,844,908,844,910,844,915,844,917,844,920,844,922,844,925,844,928,844,931,844,933,844,937,844,939,844,941,844,943,844,946,844,949,844,952,844,954,844,958,844,960,844,963,844,965,844,968,844,971,844,974,844,976,844,980,844,982,844,985,844,987],"svg",{"viewBox":837,"role":838,"ariaLabelledBy":839,"xmlns":842,"style":843},"4 0 752 208","img",[840,841],"se-options-t","se-options-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[846,847,848],"title",{"id":840},"The four if_sheet_exists options",[850,851,852],"desc",{"id":841},"error refuses to write. new writes to a new sheet called Summary1 and leaves the old one. replace deletes the sheet and writes a fresh one in the same position, losing other content on it. overlay writes over the existing cells, keeping other content but also any old rows the new data does not reach.",[854,855],"rect",{"x":856,"y":857,"width":858,"height":859,"fill":860},"4","0","752","208","#ffffff",[854,862],{"x":863,"y":864,"width":865,"height":866,"rx":857,"fill":860,"stroke":867,"style":868},"20.0","16.0","76.2","40.0","var(--line,#cdd5e6)","stroke-width:1px",[854,870],{"x":871,"y":864,"width":872,"height":866,"rx":857,"fill":873,"stroke":874,"style":875},"96.2","214.6","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:1.2px",[877,878,882],"text",{"x":879,"y":880,"style":881},"203.5","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","result",[854,884],{"x":885,"y":864,"width":872,"height":866,"rx":857,"fill":873,"stroke":874,"style":875},"310.8",[877,887,889],{"x":888,"y":880,"style":881},"418.1","other content on the sheet",[854,891],{"x":892,"y":864,"width":872,"height":866,"rx":857,"fill":873,"stroke":874,"style":875},"525.4",[877,894,896],{"x":895,"y":880,"style":881},"632.7","risk",[854,898],{"x":863,"y":899,"width":865,"height":900,"rx":857,"fill":901,"stroke":867,"style":868},"56.0","34.0","#e7ebef",[877,903,907],{"x":904,"y":905,"style":906},"32.0","78.0","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start","error",[854,909],{"x":871,"y":899,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,911,914],{"x":879,"y":912,"style":913},"77.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","ValueError",[854,916],{"x":885,"y":899,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,918,919],{"x":888,"y":912,"style":913},"untouched",[854,921],{"x":892,"y":899,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,923,924],{"x":895,"y":912,"style":913},"none — nothing written",[854,926],{"x":863,"y":927,"width":865,"height":900,"rx":857,"fill":901,"stroke":867,"style":868},"90.0",[877,929,803],{"x":904,"y":930,"style":906},"112.0",[854,932],{"x":871,"y":927,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,934,936],{"x":879,"y":935,"style":913},"111.0","new sheet Summary1",[854,938],{"x":885,"y":927,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,940,919],{"x":888,"y":935,"style":913},[854,942],{"x":892,"y":927,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,944,945],{"x":895,"y":935,"style":913},"sheets pile up",[854,947],{"x":863,"y":948,"width":865,"height":900,"rx":857,"fill":901,"stroke":867,"style":868},"124.0",[877,950,814],{"x":904,"y":951,"style":906},"146.0",[854,953],{"x":871,"y":948,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,955,957],{"x":879,"y":956,"style":913},"145.0","fresh sheet",[854,959],{"x":885,"y":948,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,961,962],{"x":888,"y":956,"style":913},"lost (notes, formats)",[854,964],{"x":892,"y":948,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,966,967],{"x":895,"y":956,"style":913},"lost layout",[854,969],{"x":863,"y":970,"width":865,"height":900,"rx":857,"fill":901,"stroke":867,"style":868},"158.0",[877,972,37],{"x":904,"y":973,"style":906},"180.0",[854,975],{"x":871,"y":970,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,977,979],{"x":879,"y":978,"style":913},"179.0","written over old cells",[854,981],{"x":885,"y":970,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,983,984],{"x":888,"y":978,"style":913},"kept",[854,986],{"x":892,"y":970,"width":872,"height":900,"rx":857,"fill":860,"stroke":867,"style":868},[877,988,989],{"x":895,"y":978,"style":913},"stale rows remain",[50,991,993],{"id":992},"step-3-refresh-a-sheet-safely","Step 3 — Refresh a sheet safely",[10,995,996,997,999,1000,1002],{},"Which option is right depends on what else is on the sheet. If the sheet holds only data, ",[19,998,814],{}," is correct and simple. If it holds things you want to keep — notes, formatting, a chart over the data — use ",[19,1001,37],{},", but clear the old data area first so no stale rows survive:",[55,1004,1006],{"className":97,"code":1005,"language":99,"meta":60,"style":60},"def refresh_sheet(path, sheet, df, keep_cols=None):\n    wb = load_workbook(path)\n    ws = wb[sheet]\n    last_col = keep_cols or len(df.columns)\n    for row in ws.iter_rows(min_row=1, max_row=ws.max_row, max_col=last_col):\n        for cell in row:\n            cell.value = None\n    wb.save(path)\n    with pd.ExcelWriter(path, mode=\"a\", engine=\"openpyxl\", if_sheet_exists=\"overlay\") as xw:\n        df.to_excel(xw, sheet_name=sheet, index=False)\n\nmake_report()\nrefresh_sheet(\"report.xlsx\", \"Summary\", new_summary)\nws = load_workbook(\"report.xlsx\")[\"Summary\"]\nprint([c.value for c in ws[\"A\"]], [c.value for c in ws[\"B\"]], \"| D1:\", ws[\"D1\"].value)\n",[19,1007,1008,1026,1035,1044,1063,1102,1115,1125,1130,1165,1185,1189,1193,1207,1225],{"__ignoreMap":60},[64,1009,1010,1012,1015,1018,1020,1023],{"class":66,"line":67},[64,1011,144],{"class":106},[64,1013,1014],{"class":147}," refresh_sheet",[64,1016,1017],{"class":110},"(path, sheet, df, keep_cols",[64,1019,173],{"class":106},[64,1021,1022],{"class":225},"None",[64,1024,1025],{"class":110},"):\n",[64,1027,1028,1030,1032],{"class":66,"line":120},[64,1029,303],{"class":110},[64,1031,173],{"class":106},[64,1033,1034],{"class":110}," load_workbook(path)\n",[64,1036,1037,1039,1041],{"class":66,"line":134},[64,1038,698],{"class":110},[64,1040,173],{"class":106},[64,1042,1043],{"class":110}," wb[sheet]\n",[64,1045,1046,1049,1051,1054,1057,1060],{"class":66,"line":141},[64,1047,1048],{"class":110},"    last_col ",[64,1050,173],{"class":106},[64,1052,1053],{"class":110}," keep_cols ",[64,1055,1056],{"class":106},"or",[64,1058,1059],{"class":225}," len",[64,1061,1062],{"class":110},"(df.columns)\n",[64,1064,1065,1068,1071,1073,1076,1079,1081,1084,1086,1089,1091,1094,1097,1099],{"class":66,"line":154},[64,1066,1067],{"class":106},"    for",[64,1069,1070],{"class":110}," row ",[64,1072,410],{"class":106},[64,1074,1075],{"class":110}," ws.iter_rows(",[64,1077,1078],{"class":169},"min_row",[64,1080,173],{"class":106},[64,1082,1083],{"class":225},"1",[64,1085,166],{"class":110},[64,1087,1088],{"class":169},"max_row",[64,1090,173],{"class":106},[64,1092,1093],{"class":110},"ws.max_row, ",[64,1095,1096],{"class":169},"max_col",[64,1098,173],{"class":106},[64,1100,1101],{"class":110},"last_col):\n",[64,1103,1104,1107,1110,1112],{"class":66,"line":187},[64,1105,1106],{"class":106},"        for",[64,1108,1109],{"class":110}," cell ",[64,1111,410],{"class":106},[64,1113,1114],{"class":110}," row:\n",[64,1116,1117,1120,1122],{"class":66,"line":268},[64,1118,1119],{"class":110},"            cell.value ",[64,1121,173],{"class":106},[64,1123,1124],{"class":225}," None\n",[64,1126,1127],{"class":66,"line":300},[64,1128,1129],{"class":110},"    wb.save(path)\n",[64,1131,1132,1134,1137,1139,1141,1143,1145,1147,1149,1151,1153,1155,1157,1159,1161,1163],{"class":66,"line":315},[64,1133,157],{"class":106},[64,1135,1136],{"class":110}," pd.ExcelWriter(path, ",[64,1138,448],{"class":169},[64,1140,173],{"class":106},[64,1142,453],{"class":74},[64,1144,166],{"class":110},[64,1146,170],{"class":169},[64,1148,173],{"class":106},[64,1150,176],{"class":74},[64,1152,166],{"class":110},[64,1154,33],{"class":169},[64,1156,173],{"class":106},[64,1158,615],{"class":74},[64,1160,179],{"class":110},[64,1162,114],{"class":106},[64,1164,184],{"class":110},[64,1166,1167,1170,1172,1174,1177,1179,1181,1183],{"class":66,"line":337},[64,1168,1169],{"class":110},"        df.to_excel(xw, ",[64,1171,247],{"class":169},[64,1173,173],{"class":106},[64,1175,1176],{"class":110},"sheet, ",[64,1178,257],{"class":169},[64,1180,173],{"class":106},[64,1182,262],{"class":225},[64,1184,265],{"class":110},[64,1186,1187],{"class":66,"line":347},[64,1188,138],{"emptyLinePlaceholder":137},[64,1190,1191],{"class":66,"line":352},[64,1192,398],{"class":110},[64,1194,1195,1198,1200,1202,1204],{"class":66,"line":390},[64,1196,1197],{"class":110},"refresh_sheet(",[64,1199,163],{"class":74},[64,1201,166],{"class":110},[64,1203,252],{"class":74},[64,1205,1206],{"class":110},", new_summary)\n",[64,1208,1209,1212,1214,1216,1218,1221,1223],{"class":66,"line":395},[64,1210,1211],{"class":110},"ws ",[64,1213,173],{"class":106},[64,1215,308],{"class":110},[64,1217,163],{"class":74},[64,1219,1220],{"class":110},")[",[64,1222,252],{"class":74},[64,1224,708],{"class":110},[64,1226,1227,1230,1233,1235,1237,1239,1241,1243,1246,1248,1250,1252,1254,1257,1260,1263,1266,1268],{"class":66,"line":401},[64,1228,1229],{"class":225},"print",[64,1231,1232],{"class":110},"([c.value ",[64,1234,404],{"class":106},[64,1236,723],{"class":110},[64,1238,410],{"class":106},[64,1240,728],{"class":110},[64,1242,731],{"class":74},[64,1244,1245],{"class":110},"]], [c.value ",[64,1247,404],{"class":106},[64,1249,723],{"class":110},[64,1251,410],{"class":106},[64,1253,728],{"class":110},[64,1255,1256],{"class":74},"\"B\"",[64,1258,1259],{"class":110},"]], ",[64,1261,1262],{"class":74},"\"| D1:\"",[64,1264,1265],{"class":110},", ws[",[64,1267,326],{"class":74},[64,1269,1270],{"class":110},"].value)\n",[10,1272,1273,1274,1277,1278,1282],{},"Clearing the ",[14,1275,1276],{},"values"," in the data columns — and only those, here A and B — removes yesterday's rows while leaving the note in D1, cell formatting and anything in other columns in place; overlay then writes the new data on top. The result has exactly the two new rows and keeps the note. If the data has a fixed layout that people format by hand — a header style, number formats — clearing values rather than deleting cells is what preserves it. When the whole report is generated by code, the simplest robust alternative is to regenerate the entire workbook each time rather than patching one sheet; ",[44,1279,1281],{"href":1280},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fappend-a-dataframe-to-an-existing-excel-file-with-pandas\u002F","Append a DataFrame to an Existing Excel File with pandas"," covers the related case of adding rows below existing data.",[835,1284,844,1289,844,1292,844,1295,844,1298,844,1305,844,1316,844,1321,844,1325,844,1329,844,1332,844,1337,844,1344,844,1349,844,1356,844,1363,844,1368,844,1372,844,1374,844,1377,844,1381,844,1384,844,1387,844,1393,844,1396,844,1399,844,1401,844,1404,844,1408,844,1411,844,1416,844,1423,844,1427],{"viewBox":1285,"role":838,"ariaLabelledBy":1286,"xmlns":842,"style":843},"4 0 752 272",[1287,1288],"se-choose-t","se-choose-d",[846,1290,1291],{"id":1287},"Which option for a refresh",[850,1293,1294],{"id":1288},"If the sheet holds only data that the script writes, use replace. If it also holds notes, formatting or charts that must survive, clear the old data values and then write with overlay. If the old sheet must be kept as history, write to a new, dated sheet name instead of using new.",[854,1296],{"x":856,"y":857,"width":858,"height":1297,"fill":860},"272",[854,1299],{"x":1300,"y":864,"width":1301,"height":1302,"rx":1303,"fill":873,"stroke":874,"style":1304},"240.0","280.0","75.5","12","stroke-width:2px",[1306,1307,1309],"g",{"transform":1308},"translate(368.0,29.0) scale(1.000)",[1310,1311],"path",{"d":1312,"fill":1313,"stroke":1314,"style":1315},"M6 3h9l4 4v14H6z M15 3v4h4 M9.5 11.5l4.5 6 M14 11.5l-4.5 6","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[877,1317,1320],{"x":1318,"y":1302,"style":1319},"380.0","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","What else is on the sheet?",[66,1322],{"x1":1318,"y1":1323,"x2":1318,"y2":1324,"stroke":874,"style":1304},"91.5","111.5",[66,1326],{"x1":1327,"y1":1324,"x2":1328,"y2":1324,"stroke":874,"style":1304},"134.7","625.3",[66,1330],{"x1":1327,"y1":1324,"x2":1327,"y2":1331,"stroke":874,"style":1304},"157.5",[1333,1334],"polygon",{"points":1335,"fill":1336},"134.7,161.5 129.7,152.5 139.7,152.5","#5b5cf0",[854,1338],{"x":1339,"y":1340,"width":1341,"height":1342,"rx":1343,"fill":860,"stroke":867,"style":875},"87.5","121.5","94.4","21.0","10",[877,1345,1348],{"x":1327,"y":1346,"style":1347},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","only the data",[854,1350],{"x":863,"y":1351,"width":1352,"height":1353,"rx":1303,"fill":1354,"stroke":1355,"style":1304},"163.5","229.3","93.0","#d9f4f1","var(--teal,#0f9488)",[1306,1357,1359],{"transform":1358},"translate(122.7,176.5) scale(1.000)",[1310,1360],{"d":1361,"fill":1313,"stroke":1362,"style":1315},"M20 11a8 8 0 1 0-2.3 5.7 M20 4v7h-7","var(--teal-ink,#0b6157)",[877,1364,1367],{"x":1327,"y":1365,"style":1366},"223.0","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","if_sheet_exists='replace'",[877,1369,1371],{"x":1327,"y":1370,"style":913},"242.5","simple and clean",[66,1373],{"x1":1318,"y1":1324,"x2":1318,"y2":1331,"stroke":874,"style":1304},[1333,1375],{"points":1376,"fill":1336},"380.0,161.5 375.0,152.5 385.0,152.5",[854,1378],{"x":1379,"y":1340,"width":1380,"height":1342,"rx":1343,"fill":860,"stroke":867,"style":875},"305.4","149.2",[877,1382,1383],{"x":1318,"y":1346,"style":1347},"notes, formats, charts",[854,1385],{"x":1386,"y":1351,"width":1352,"height":1353,"rx":1303,"fill":873,"stroke":874,"style":1304},"265.3",[1306,1388,1390],{"transform":1389},"translate(368.0,176.5) scale(1.000)",[1310,1391],{"d":1392,"fill":1313,"stroke":1314,"style":1315},"M12 3l9 5-9 5-9-5z M3 13l9 5 9-5 M3 17l9 5 9-5",[877,1394,1395],{"x":1318,"y":1365,"style":1319},"clear values + 'overlay'",[877,1397,1398],{"x":1318,"y":1370,"style":913},"no stale rows",[66,1400],{"x1":1328,"y1":1324,"x2":1328,"y2":1331,"stroke":874,"style":1304},[1333,1402],{"points":1403,"fill":1336},"625.3,161.5 620.3,152.5 630.3,152.5",[854,1405],{"x":1406,"y":1340,"width":1407,"height":1342,"rx":1343,"fill":860,"stroke":867,"style":875},"579.6","91.4",[877,1409,1410],{"x":1328,"y":1346,"style":1347},"keep history",[854,1412],{"x":1413,"y":1351,"width":1352,"height":1353,"rx":1303,"fill":1414,"stroke":1415,"style":1304},"510.7","#fdefd8","var(--gold,#b4740a)",[1306,1417,1419],{"transform":1418},"translate(613.3,176.5) scale(1.000)",[1310,1420],{"d":1421,"fill":1313,"stroke":1422,"style":1315},"M4 5h16v15H4z M4 10h16 M8 3v4 M16 3v4","var(--gold-ink,#7a4e06)",[877,1424,1426],{"x":1328,"y":1365,"style":1425},"font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","dated sheet name",[877,1428,1429],{"x":1328,"y":1370,"style":913},"e.g. Summary 2026-10-02",[835,1431,844,1436,844,1439,844,1442,844,1445,844,1449,844,1455,844,1460,844,1463,844,1467,844,1472,844,1475,844,1478,844,1484,844,1489,844,1493,844,1497,844,1500,844,1503,844,1509,844,1513,844,1516,844,1520,844,1523,844,1526,844,1532,844,1536,844,1540],{"viewBox":1432,"role":838,"ariaLabelledBy":1433,"xmlns":842,"style":843},"4 0 752 142",[1434,1435],"se-refresh-t","se-refresh-d",[846,1437,1438],{"id":1434},"Refreshing one sheet without losing its layout",[850,1440,1441],{"id":1435},"Open the workbook with openpyxl, set the values in the data columns to empty while leaving formats, notes and other columns alone, save, then append the new DataFrame with mode a, the openpyxl engine and if_sheet_exists overlay. The sheet then holds exactly the new rows and keeps its layout.",[854,1443],{"x":856,"y":857,"width":858,"height":1444,"fill":860},"142",[854,1446],{"x":863,"y":864,"width":1447,"height":1448,"rx":1303,"fill":901,"stroke":867,"style":1304},"153.0","110.5",[1306,1450,1452],{"transform":1451},"translate(84.5,29.0) scale(1.000)",[1310,1453],{"d":1312,"fill":1313,"stroke":1454,"style":1315},"var(--text,#172033)",[877,1456,1459],{"x":1457,"y":1302,"style":1458},"96.5","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Open with",[877,1461,1462],{"x":1457,"y":1353,"style":1458},"openpyxl",[877,1464,1466],{"x":1457,"y":1465,"style":913},"112.5","existing workbook",[66,1468],{"x1":1469,"y1":1470,"x2":1471,"y2":1470,"stroke":874,"style":1304},"178.0","71.2","200.0",[1333,1473],{"points":1474,"fill":1336},"204.0,71.2 195.0,76.2 195.0,66.2",[854,1476],{"x":1477,"y":864,"width":1447,"height":1448,"rx":1303,"fill":1414,"stroke":1415,"style":1304},"209.0",[1306,1479,1481],{"transform":1480},"translate(273.5,37.8) scale(1.000)",[1310,1482],{"d":1483,"fill":1313,"stroke":1422,"style":1315},"M4 7h16 M10 11v6 M14 11v6 M6 7l1 13h10l1-13 M9 7V4h6v3",[877,1485,1488],{"x":1486,"y":1487,"style":1425},"285.5","84.2","Clear data values",[877,1490,1492],{"x":1486,"y":1491,"style":913},"103.8","columns A:B only",[66,1494],{"x1":1495,"y1":1470,"x2":1496,"y2":1470,"stroke":874,"style":1304},"367.0","389.0",[1333,1498],{"points":1499,"fill":1336},"393.0,71.2 384.0,76.2 384.0,66.2",[854,1501],{"x":1502,"y":864,"width":1447,"height":1448,"rx":1303,"fill":901,"stroke":867,"style":1304},"398.0",[1306,1504,1506],{"transform":1505},"translate(462.5,37.8) scale(1.000)",[1310,1507],{"d":1508,"fill":1313,"stroke":1454,"style":1315},"M5 12.5l4.5 4.5L19 7",[877,1510,1512],{"x":1511,"y":1487,"style":1458},"474.5","Save",[877,1514,1515],{"x":1511,"y":1491,"style":913},"layout untouched",[66,1517],{"x1":1518,"y1":1470,"x2":1519,"y2":1470,"stroke":874,"style":1304},"556.0","578.0",[1333,1521],{"points":1522,"fill":1336},"582.0,71.2 573.0,76.2 573.0,66.2",[854,1524],{"x":1525,"y":864,"width":1447,"height":1448,"rx":1303,"fill":1354,"stroke":1355,"style":1304},"587.0",[1306,1527,1529],{"transform":1528},"translate(651.5,29.0) scale(1.000)",[1310,1530],{"d":1531,"fill":1313,"stroke":1362,"style":1315},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14",[877,1533,1535],{"x":1534,"y":1302,"style":1366},"663.5","overlay write",[877,1537,1539],{"x":1534,"y":1538,"style":913},"95.0","mode='a',",[877,1541,1542],{"x":1534,"y":1465,"style":913},"engine='openpyxl'",[50,1544,1546],{"id":1545},"what-append-mode-keeps-and-what-it-cannot","What append mode keeps — and what it cannot",[10,1548,1549,1550,1553,1554,1557],{},"Append mode with openpyxl loads the whole workbook, changes the sheet you write to, and saves everything again. Most content survives the round trip: other sheets, their values and formatting, defined names, data validation and conditional formatting. Some does not, because openpyxl does not model it fully: charts and images are read back but can lose formatting details, shapes and text boxes are dropped, pivot tables are kept only partially, slicers and form controls are lost, and a macro-enabled ",[19,1551,1552],{},".xlsm"," loses its VBA unless loaded with ",[19,1555,1556],{},"keep_vba=True",", which pandas does not do. If the workbook contains such things, append mode is the wrong tool; either keep the generated data in a separate workbook that the main one links to, or drive Excel itself with xlwings. A quick test is to append to a copy of the real workbook and open both side by side before putting the job into production.",[50,1559,1561],{"id":1560},"checking-before-you-write","Checking before you write",[10,1563,1564,1565,1568,1569,1571,1572,1575],{},"Two further habits make append-mode jobs predictable. First, look before writing: ",[19,1566,1567],{},"load_workbook(path, read_only=True).sheetnames"," lists the sheets cheaply, so the job can decide between creating a sheet and refreshing it, or refuse with a clear message if the workbook is not the one it expects. Second, remember that ",[19,1570,574],{}," requires the file to exist; a job that must work on its first ever run should create the workbook with ",[19,1573,1574],{},"mode=\"w\""," when the file is missing and switch to append mode afterwards, rather than catching the exception. And because openpyxl rewrites the whole file when it saves, an append is not cheaper than regenerating the file for small workbooks — it is the right tool when the workbook contains things your code did not create and should not lose.",[50,1577,1579],{"id":1578},"common-pitfalls","Common pitfalls",[1581,1582,1583,1593,1601,1609,1623],"ul",{},[1584,1585,1586,1592],"li",{},[1587,1588,1589,1590,48],"strong",{},"Leaving out ",[19,1591,560],{}," pandas picks XlsxWriter, which cannot append.",[1584,1594,1595,1600],{},[1587,1596,1597,1599],{},[19,1598,37],{}," with fewer rows than before."," Old rows remain; clear the data area first.",[1584,1602,1603,1608],{},[1587,1604,1605,1607],{},[19,1606,814],{}," on a formatted sheet."," It deletes notes, formats and charts on that sheet.",[1584,1610,1611,1616,1617,166,1619,1622],{},[1587,1612,1613,1615],{},[19,1614,803],{}," in a scheduled job."," Each run adds ",[14,1618,810],{},[14,1620,1621],{},"Summary2",", …",[1584,1624,1625,1628,1629,1631],{},[1587,1626,1627],{},"A file that does not exist yet."," Append mode needs an existing file; create it with ",[19,1630,1574],{}," first.",[50,1633,1635],{"id":1634},"conclusion","Conclusion",[10,1637,1638,1639,1641,1642,1644,1645,829,1647,1649,1650,1652,1653,1655,1656,1658,1659,1661],{},"The \"Sheet already exists\" error comes from ",[19,1640,33],{}," defaulting to ",[19,1643,567],{}," in append mode. Open the writer with ",[19,1646,574],{},[19,1648,560],{},", then choose deliberately: ",[19,1651,814],{}," when the sheet holds only data, or clear the old data values and use ",[19,1654,37],{}," when the sheet holds content worth keeping. Avoid ",[19,1657,803],{}," in recurring jobs, and remember that ",[19,1660,37],{}," alone leaves old rows behind whenever the new data is shorter.",[50,1663,1665],{"id":1664},"frequently-asked-questions","Frequently asked questions",[10,1667,1668,1671],{},[1587,1669,1670],{},"How do I fix \"Sheet already exists and if_sheet_exists is set to 'error'\"?","\nPass if_sheet_exists=\"replace\" or \"overlay\" to pd.ExcelWriter together with mode=\"a\" and engine=\"openpyxl\", choosing based on what else is on the sheet.",[10,1673,1674,1677],{},[1587,1675,1676],{},"What is the difference between replace and overlay in pandas ExcelWriter?","\nreplace deletes the sheet and writes a new one; overlay writes over the existing cells and leaves anything it does not overwrite, including old rows.",[10,1679,1680,1683],{},[1587,1681,1682],{},"Why do I get \"Append mode is not supported with xlsxwriter\"?","\npandas chose the XlsxWriter engine, which only creates new files; pass engine=\"openpyxl\" when using mode=\"a\".",[10,1685,1686,1689],{},[1587,1687,1688],{},"Why does my refreshed sheet still contain old rows?","\noverlay only writes the cells covered by the new data; clear the old data area first or use replace.",[50,1691,1693],{"id":1692},"related","Related",[1581,1695,1696,1702,1709,1716],{},[1584,1697,1698,1699,1701],{},"Up one level: ",[44,1700,47],{"href":46}," — fixes for common errors.",[1584,1703,1704,1708],{},[44,1705,1707],{"href":1706},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fwrite-multiple-dataframes-to-one-excel-file\u002F","Write Multiple DataFrames to One Excel File"," — several sheets in one workbook.",[1584,1710,1711,1715],{},[44,1712,1714],{"href":1713},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-excelwriter-has-no-attribute-save\u002F","Fix \"ExcelWriter Object Has No Attribute save\""," — another ExcelWriter error.",[1584,1717,1718,1722],{},[44,1719,1721],{"href":1720},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-xlsxwriter-overwriting-an-existing-workbook\u002F","Fix XlsxWriter Overwriting an Existing Workbook"," — the other side of the engine choice.",[1724,1725,1726],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":60,"searchDepth":120,"depth":120,"links":1728},[1729,1730,1731,1732,1733,1734,1735,1736,1737,1738],{"id":52,"depth":120,"text":53},{"id":93,"depth":120,"text":94},{"id":581,"depth":120,"text":582},{"id":992,"depth":120,"text":993},{"id":1545,"depth":120,"text":1546},{"id":1560,"depth":120,"text":1561},{"id":1578,"depth":120,"text":1579},{"id":1634,"depth":120,"text":1635},{"id":1664,"depth":120,"text":1665},{"id":1692,"depth":120,"text":1693},"2026-10-02","Fix ValueError: Sheet 'Summary' already exists and if_sheet_exists is set to 'error' when writing to an existing workbook with pandas: what each if_sheet_exists option really does — error, new, replace and overlay — why overlay leaves old rows behind, the related \"Append mode is not supported with xlsxwriter\" error, and a safe way to refresh one sheet of a workbook.","md",[1743,1745,1747,1749],{"q":1670,"a":1744},"Pass if_sheet_exists=\"replace\" or \"overlay\" to pd.ExcelWriter together with mode=\"a\" and engine=\"openpyxl\", choosing based on what else is on the sheet.",{"q":1676,"a":1746},"replace deletes the sheet and writes a new one; overlay writes over the existing cells and leaves anything it does not overwrite, including old rows.",{"q":1682,"a":1748},"pandas chose the XlsxWriter engine, which only creates new files; pass engine=\"openpyxl\" when using mode=\"a\".",{"q":1688,"a":1750},"overlay only writes the cells covered by the new data; clear the old data area first or use replace.","fix sheet already exists error pandas excelwriter",null,{"breadcrumb":1754},[1755,1758,1761],{"name":1756,"item":1757},"Home","\u002F",{"name":1759,"item":1760},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":47,"item":46},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter",{"title":5,"description":1764},"Solve pandas ExcelWriter if_sheet_exists errors: mode=\"a\" with engine=\"openpyxl\", error vs new vs replace vs overlay, stale rows left by overlay, the xlsxwriter append error, and refreshing a sheet safely.","fix-sheet-already-exists-errors-in-pandas-excelwriter","getting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter\u002Findex",[1768,1769],"troubleshooting","writing-excel","how-to","Qd1-j9kXtT3DP65jw-h8fUt5PdCOQzKBJQqSZdZ86is",[1773,1777],{"title":1774,"path":1775,"stem":1776,"children":-1},"Fix ReadOnlyWorksheet Has No Attribute Errors in openpyxl","\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-readonlyworksheet-has-no-attribute-errors-in-openpyxl","getting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-readonlyworksheet-has-no-attribute-errors-in-openpyxl\u002Findex",{"title":1778,"path":1779,"stem":1780,"children":-1},"Fix Text Truncated at 32,767 Characters in Excel Output","\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel","getting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel\u002Findex",[1782,1784],{"path":1783,"title":1759},"\u002Fgetting-started-with-python-excel-automation",{"path":1785,"title":47},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors",[],[1788,1792,1795,1798,1801,1804],{"path":1789,"title":1790,"kind":1791},"\u002Fautomating-reporting-workflows\u002Ferror-handling-and-logging-in-excel-automation\u002Fhandle-permission-denied-when-writing-excel-in-python","Handle Permission Denied When Writing Excel in Python","fix",{"path":1793,"title":1794,"kind":1770},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fwhat-openpyxl-loses-when-saving-an-existing-workbook","What openpyxl Loses When You Save an Existing Workbook",{"path":1796,"title":1797,"kind":1791},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates","Fix Excel Serial Numbers Showing Instead of Dates",{"path":1799,"title":1800,"kind":1770},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fhandle-daylight-saving-time-in-excel-timestamps","Handle Daylight Saving Time in Excel Timestamps",{"path":1802,"title":1803,"kind":1770},"\u002Fautomating-reporting-workflows\u002Fautomating-excel-online-with-microsoft-graph\u002Fhandle-microsoft-graph-throttling-for-excel","Handle Microsoft Graph Throttling in Excel Automation",{"path":1805,"title":1806,"kind":1807},"\u002Fautomating-reporting-workflows\u002Ferror-handling-and-logging-in-excel-automation","Error Handling and Logging in Excel Automation","guide",1790972067455]