[{"data":1,"prerenderedAt":1501},["ShallowReactive",2],{"doc:\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fwrite-multiple-dataframes-to-one-excel-file":3,"surround:\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fwrite-multiple-dataframes-to-one-excel-file":1493},{"id":4,"title":5,"body":6,"dateModified":1472,"datePublished":1472,"description":1473,"extension":1474,"faq":1475,"meta":1485,"navigation":281,"path":1486,"seo":1487,"slug":1489,"stem":1490,"type":1491,"__hash__":1492},"docs\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fwrite-multiple-dataframes-to-one-excel-file\u002Findex.md","Write Multiple DataFrames to One Excel File",{"type":7,"value":8,"toc":1460},"minimark",[9,29,175,180,191,221,230,234,253,597,607,611,631,893,910,914,932,1075,1099,1103,1173,1183,1187,1318,1322,1335,1339,1355,1370,1379,1396,1400,1426,1430,1456],[10,11,12,13,17,18,22,23,28],"p",{},"You have several DataFrames and want them in one workbook — one sheet each, or stacked on a single sheet, or appended to a file that already exists. The mechanism for all three is ",[14,15,16],"code",{},"pandas.ExcelWriter",", and the single rule that prevents the most common failure is: ",[19,20,21],"strong",{},"one writer per file, opened once",". This page is part of ",[24,25,27],"a",{"href":26},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002F","Building Multi-Sheet Excel Dashboards","; it covers the writer mechanics that the dashboard build depends on.",[30,31,39,40,39,44,39,48,39,58,39,65,39,68,39,72,39,75,39,79,39,84,39,93,39,96,39,100,39,104,39,112,39,118,39,123,39,127,39,130,39,136,39,141,39,147,39,151,39,154,39,158,39,161,39,165,39,169],"svg",{"viewBox":32,"role":33,"ariaLabelledBy":34,"xmlns":37,"style":38},"0 0 760 280","img",[35,36],"wm-df-title","wm-df-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:760px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[41,42,43],"title",{"id":35},"Three DataFrames through one ExcelWriter into three named sheets",[45,46,47],"desc",{"id":36},"Three pandas DataFrames pass through a single ExcelWriter and land as three named sheets in one workbook; a note shows that stacking on one sheet uses the startrow argument.",[49,50],"rect",{"x":51,"y":52,"width":53,"height":54,"rx":55,"fill":56,"stroke":57},"20","34","150","40","8","var(--brand-soft,rgba(91,92,240,0.12))","var(--line,#cdd5e6)",[59,60,64],"text",{"x":61,"y":62,"style":63},"95","59","font-size:13px;font-weight:600;fill:var(--text,#172033);text-anchor:middle","regions_df",[49,66],{"x":51,"y":67,"width":53,"height":54,"rx":55,"fill":56,"stroke":57},"98",[59,69,71],{"x":61,"y":70,"style":63},"123","months_df",[49,73],{"x":51,"y":74,"width":53,"height":54,"rx":55,"fill":56,"stroke":57},"162",[59,76,78],{"x":61,"y":77,"style":63},"187","products_df",[59,80,83],{"x":61,"y":81,"style":82},"24","font-size:12px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","DataFrames",[85,86],"line",{"x1":87,"y1":88,"x2":89,"y2":90,"stroke":91,"style":92},"172","54","296","108","var(--brand,#5b5cf0)","stroke-width:2px",[85,94],{"x1":87,"y1":95,"x2":89,"y2":95,"stroke":91,"style":92},"118",[85,97],{"x1":87,"y1":98,"x2":89,"y2":99,"stroke":91,"style":92},"182","128",[101,102],"polygon",{"points":103,"fill":91},"300,118 288,112 288,124",[49,105],{"x":106,"y":107,"width":108,"height":109,"rx":110,"fill":111,"stroke":91,"style":92},"300","80","156","76","12","var(--surface-muted,#eef2ff)",[59,113,117],{"x":114,"y":115,"style":116},"378","112","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","ExcelWriter",[59,119,122],{"x":114,"y":120,"style":121},"134","font-size:11.5px;fill:var(--muted,#5b6780);text-anchor:middle","one writer, one file",[85,124],{"x1":125,"y1":95,"x2":126,"y2":95,"stroke":91,"style":92},"458","556",[101,128],{"points":129,"fill":91},"560,118 548,112 548,124",[49,131],{"x":132,"y":54,"width":133,"height":108,"rx":110,"fill":134,"stroke":135,"style":92},"560","180","#ffffff","var(--brand-strong,#4338ca)",[59,137,140],{"x":138,"y":139,"style":82},"650","30","one workbook",[49,142],{"x":143,"y":144,"width":145,"height":52,"rx":146,"fill":91},"578","58","144","6",[59,148,150],{"x":138,"y":107,"style":149},"font-size:12.5px;font-weight:600;fill:#ffffff;text-anchor:middle","\"Regions\"",[49,152],{"x":143,"y":153,"width":145,"height":52,"rx":146,"fill":91},"100",[59,155,157],{"x":138,"y":156,"style":149},"122","\"Months\"",[49,159],{"x":143,"y":160,"width":145,"height":52,"rx":146,"fill":91},"142",[59,162,164],{"x":138,"y":163,"style":149},"164","\"Products\"",[49,166],{"x":51,"y":167,"width":168,"height":52,"rx":55,"fill":56},"232","720",[59,170,174],{"x":171,"y":172,"style":173},"380","254","font-size:12.5px;fill:var(--text,#172033);text-anchor:middle","Same sheet instead? Stack with startrow= so the blocks do not overwrite each other.",[176,177,179],"h2",{"id":178},"prerequisites","Prerequisites",[10,181,182,183,186,187,190],{},"You need pandas and at least one Excel engine. ",[14,184,185],{},"openpyxl"," reads and writes ",[14,188,189],{},".xlsx"," and supports append mode, so install it:",[192,193,198],"pre",{"className":194,"code":195,"language":196,"meta":197,"style":197},"language-bash shiki shiki-themes github-light github-dark","pip install pandas openpyxl xlsxwriter\n","bash","",[14,199,200],{"__ignoreMap":197},[201,202,204,208,212,215,218],"span",{"class":85,"line":203},1,[201,205,207],{"class":206},"sScJk","pip",[201,209,211],{"class":210},"sZZnC"," install",[201,213,214],{"class":210}," pandas",[201,216,217],{"class":210}," openpyxl",[201,219,220],{"class":210}," xlsxwriter\n",[10,222,223,226,227,229],{},[14,224,225],{},"xlsxwriter"," is optional — it is a fast write-only engine, useful when you never need to reopen the file. For multi-sheet dashboards you reopen later, prefer ",[14,228,185],{},".",[176,231,233],{"id":232},"one-sheet-per-dataframe","One sheet per DataFrame",[10,235,236,237,240,241,244,245,248,249,252],{},"Open a single ",[14,238,239],{},"pd.ExcelWriter"," as a context manager and call ",[14,242,243],{},"to_excel()"," once per DataFrame, each with a distinct ",[14,246,247],{},"sheet_name",". The ",[14,250,251],{},"with"," block writes and closes the file exactly once when it exits:",[192,254,258],{"className":255,"code":256,"language":257,"meta":197,"style":197},"language-python shiki shiki-themes github-light github-dark","import pandas as pd\n\nregion = pd.DataFrame({\n    \"region\": [\"North\", \"South\", \"West\"],\n    \"revenue\": [26700, 20900, 7600],\n})\nmonth = pd.DataFrame({\n    \"month\": [\"Jan\", \"Feb\", \"Mar\"],\n    \"revenue\": [22300, 21800, 11100],\n})\nproduct = pd.DataFrame({\n    \"product\": [\"Widget\", \"Gadget\", \"Gizmo\"],\n    \"units\": [350, 209, 76],\n})\n\nwith pd.ExcelWriter(\"report.xlsx\", engine=\"openpyxl\") as writer:\n    region.to_excel(writer, sheet_name=\"By Region\", index=False)\n    month.to_excel(writer, sheet_name=\"By Month\", index=False)\n    product.to_excel(writer, sheet_name=\"By Product\", index=False)\n\nprint(\"Wrote 3 sheets to report.xlsx\")\n","python",[14,259,260,276,283,295,321,345,351,361,384,406,411,421,444,466,471,476,506,532,555,578,583],{"__ignoreMap":197},[201,261,262,266,270,273],{"class":85,"line":203},[201,263,265],{"class":264},"szBVR","import",[201,267,269],{"class":268},"sVt8B"," pandas ",[201,271,272],{"class":264},"as",[201,274,275],{"class":268}," pd\n",[201,277,279],{"class":85,"line":278},2,[201,280,282],{"emptyLinePlaceholder":281},true,"\n",[201,284,286,289,292],{"class":85,"line":285},3,[201,287,288],{"class":268},"region ",[201,290,291],{"class":264},"=",[201,293,294],{"class":268}," pd.DataFrame({\n",[201,296,298,301,304,307,310,313,315,318],{"class":85,"line":297},4,[201,299,300],{"class":210},"    \"region\"",[201,302,303],{"class":268},": [",[201,305,306],{"class":210},"\"North\"",[201,308,309],{"class":268},", ",[201,311,312],{"class":210},"\"South\"",[201,314,309],{"class":268},[201,316,317],{"class":210},"\"West\"",[201,319,320],{"class":268},"],\n",[201,322,324,327,329,333,335,338,340,343],{"class":85,"line":323},5,[201,325,326],{"class":210},"    \"revenue\"",[201,328,303],{"class":268},[201,330,332],{"class":331},"sj4cs","26700",[201,334,309],{"class":268},[201,336,337],{"class":331},"20900",[201,339,309],{"class":268},[201,341,342],{"class":331},"7600",[201,344,320],{"class":268},[201,346,348],{"class":85,"line":347},6,[201,349,350],{"class":268},"})\n",[201,352,354,357,359],{"class":85,"line":353},7,[201,355,356],{"class":268},"month ",[201,358,291],{"class":264},[201,360,294],{"class":268},[201,362,364,367,369,372,374,377,379,382],{"class":85,"line":363},8,[201,365,366],{"class":210},"    \"month\"",[201,368,303],{"class":268},[201,370,371],{"class":210},"\"Jan\"",[201,373,309],{"class":268},[201,375,376],{"class":210},"\"Feb\"",[201,378,309],{"class":268},[201,380,381],{"class":210},"\"Mar\"",[201,383,320],{"class":268},[201,385,387,389,391,394,396,399,401,404],{"class":85,"line":386},9,[201,388,326],{"class":210},[201,390,303],{"class":268},[201,392,393],{"class":331},"22300",[201,395,309],{"class":268},[201,397,398],{"class":331},"21800",[201,400,309],{"class":268},[201,402,403],{"class":331},"11100",[201,405,320],{"class":268},[201,407,409],{"class":85,"line":408},10,[201,410,350],{"class":268},[201,412,414,417,419],{"class":85,"line":413},11,[201,415,416],{"class":268},"product ",[201,418,291],{"class":264},[201,420,294],{"class":268},[201,422,424,427,429,432,434,437,439,442],{"class":85,"line":423},12,[201,425,426],{"class":210},"    \"product\"",[201,428,303],{"class":268},[201,430,431],{"class":210},"\"Widget\"",[201,433,309],{"class":268},[201,435,436],{"class":210},"\"Gadget\"",[201,438,309],{"class":268},[201,440,441],{"class":210},"\"Gizmo\"",[201,443,320],{"class":268},[201,445,447,450,452,455,457,460,462,464],{"class":85,"line":446},13,[201,448,449],{"class":210},"    \"units\"",[201,451,303],{"class":268},[201,453,454],{"class":331},"350",[201,456,309],{"class":268},[201,458,459],{"class":331},"209",[201,461,309],{"class":268},[201,463,109],{"class":331},[201,465,320],{"class":268},[201,467,469],{"class":85,"line":468},14,[201,470,350],{"class":268},[201,472,474],{"class":85,"line":473},15,[201,475,282],{"emptyLinePlaceholder":281},[201,477,479,481,484,487,489,493,495,498,501,503],{"class":85,"line":478},16,[201,480,251],{"class":264},[201,482,483],{"class":268}," pd.ExcelWriter(",[201,485,486],{"class":210},"\"report.xlsx\"",[201,488,309],{"class":268},[201,490,492],{"class":491},"s4XuR","engine",[201,494,291],{"class":264},[201,496,497],{"class":210},"\"openpyxl\"",[201,499,500],{"class":268},") ",[201,502,272],{"class":264},[201,504,505],{"class":268}," writer:\n",[201,507,509,512,514,516,519,521,524,526,529],{"class":85,"line":508},17,[201,510,511],{"class":268},"    region.to_excel(writer, ",[201,513,247],{"class":491},[201,515,291],{"class":264},[201,517,518],{"class":210},"\"By Region\"",[201,520,309],{"class":268},[201,522,523],{"class":491},"index",[201,525,291],{"class":264},[201,527,528],{"class":331},"False",[201,530,531],{"class":268},")\n",[201,533,535,538,540,542,545,547,549,551,553],{"class":85,"line":534},18,[201,536,537],{"class":268},"    month.to_excel(writer, ",[201,539,247],{"class":491},[201,541,291],{"class":264},[201,543,544],{"class":210},"\"By Month\"",[201,546,309],{"class":268},[201,548,523],{"class":491},[201,550,291],{"class":264},[201,552,528],{"class":331},[201,554,531],{"class":268},[201,556,558,561,563,565,568,570,572,574,576],{"class":85,"line":557},19,[201,559,560],{"class":268},"    product.to_excel(writer, ",[201,562,247],{"class":491},[201,564,291],{"class":264},[201,566,567],{"class":210},"\"By Product\"",[201,569,309],{"class":268},[201,571,523],{"class":491},[201,573,291],{"class":264},[201,575,528],{"class":331},[201,577,531],{"class":268},[201,579,581],{"class":85,"line":580},20,[201,582,282],{"emptyLinePlaceholder":281},[201,584,586,589,592,595],{"class":85,"line":585},21,[201,587,588],{"class":331},"print",[201,590,591],{"class":268},"(",[201,593,594],{"class":210},"\"Wrote 3 sheets to report.xlsx\"",[201,596,531],{"class":268},[10,598,599,600,602,603,606],{},"The order of the ",[14,601,243],{}," calls sets the left-to-right tab order. ",[14,604,605],{},"index=False"," drops the pandas row-number column — pass it on every call, because it is not remembered between writes.",[176,608,610],{"id":609},"several-dataframes-on-the-same-sheet","Several DataFrames on the same sheet",[10,612,613,614,616,617,620,621,624,625,627,628,630],{},"To place tables side by side or stacked on one sheet, pass the same ",[14,615,247],{}," with different ",[14,618,619],{},"startrow"," \u002F ",[14,622,623],{},"startcol"," offsets. ",[14,626,619],{}," and ",[14,629,623],{}," are zero-based and count from the top-left. Leave a blank row between stacked tables so they read as separate blocks:",[192,632,634],{"className":255,"code":633,"language":257,"meta":197,"style":197},"import pandas as pd\n\nsummary = pd.DataFrame({\n    \"Metric\": [\"Total Revenue\", \"Total Units\"],\n    \"Value\": [55200, 635],\n})\ndetail = pd.DataFrame({\n    \"region\": [\"North\", \"South\", \"West\"],\n    \"revenue\": [26700, 20900, 7600],\n})\n\nwith pd.ExcelWriter(\"stacked.xlsx\", engine=\"openpyxl\") as writer:\n    summary.to_excel(writer, sheet_name=\"Overview\", index=False, startrow=0)\n    # leave one blank row after summary (len + header + gap)\n    next_row = len(summary) + 2\n    detail.to_excel(writer, sheet_name=\"Overview\",\n                    index=False, startrow=next_row)\n\nprint(f\"Stacked detail starting at row {next_row + 1} on the Overview sheet\")\n",[14,635,636,646,650,659,676,693,697,706,724,742,746,750,773,804,810,829,843,861,865],{"__ignoreMap":197},[201,637,638,640,642,644],{"class":85,"line":203},[201,639,265],{"class":264},[201,641,269],{"class":268},[201,643,272],{"class":264},[201,645,275],{"class":268},[201,647,648],{"class":85,"line":278},[201,649,282],{"emptyLinePlaceholder":281},[201,651,652,655,657],{"class":85,"line":285},[201,653,654],{"class":268},"summary ",[201,656,291],{"class":264},[201,658,294],{"class":268},[201,660,661,664,666,669,671,674],{"class":85,"line":297},[201,662,663],{"class":210},"    \"Metric\"",[201,665,303],{"class":268},[201,667,668],{"class":210},"\"Total Revenue\"",[201,670,309],{"class":268},[201,672,673],{"class":210},"\"Total Units\"",[201,675,320],{"class":268},[201,677,678,681,683,686,688,691],{"class":85,"line":323},[201,679,680],{"class":210},"    \"Value\"",[201,682,303],{"class":268},[201,684,685],{"class":331},"55200",[201,687,309],{"class":268},[201,689,690],{"class":331},"635",[201,692,320],{"class":268},[201,694,695],{"class":85,"line":347},[201,696,350],{"class":268},[201,698,699,702,704],{"class":85,"line":353},[201,700,701],{"class":268},"detail ",[201,703,291],{"class":264},[201,705,294],{"class":268},[201,707,708,710,712,714,716,718,720,722],{"class":85,"line":363},[201,709,300],{"class":210},[201,711,303],{"class":268},[201,713,306],{"class":210},[201,715,309],{"class":268},[201,717,312],{"class":210},[201,719,309],{"class":268},[201,721,317],{"class":210},[201,723,320],{"class":268},[201,725,726,728,730,732,734,736,738,740],{"class":85,"line":386},[201,727,326],{"class":210},[201,729,303],{"class":268},[201,731,332],{"class":331},[201,733,309],{"class":268},[201,735,337],{"class":331},[201,737,309],{"class":268},[201,739,342],{"class":331},[201,741,320],{"class":268},[201,743,744],{"class":85,"line":408},[201,745,350],{"class":268},[201,747,748],{"class":85,"line":413},[201,749,282],{"emptyLinePlaceholder":281},[201,751,752,754,756,759,761,763,765,767,769,771],{"class":85,"line":423},[201,753,251],{"class":264},[201,755,483],{"class":268},[201,757,758],{"class":210},"\"stacked.xlsx\"",[201,760,309],{"class":268},[201,762,492],{"class":491},[201,764,291],{"class":264},[201,766,497],{"class":210},[201,768,500],{"class":268},[201,770,272],{"class":264},[201,772,505],{"class":268},[201,774,775,778,780,782,785,787,789,791,793,795,797,799,802],{"class":85,"line":446},[201,776,777],{"class":268},"    summary.to_excel(writer, ",[201,779,247],{"class":491},[201,781,291],{"class":264},[201,783,784],{"class":210},"\"Overview\"",[201,786,309],{"class":268},[201,788,523],{"class":491},[201,790,291],{"class":264},[201,792,528],{"class":331},[201,794,309],{"class":268},[201,796,619],{"class":491},[201,798,291],{"class":264},[201,800,801],{"class":331},"0",[201,803,531],{"class":268},[201,805,806],{"class":85,"line":468},[201,807,809],{"class":808},"sJ8bj","    # leave one blank row after summary (len + header + gap)\n",[201,811,812,815,817,820,823,826],{"class":85,"line":473},[201,813,814],{"class":268},"    next_row ",[201,816,291],{"class":264},[201,818,819],{"class":331}," len",[201,821,822],{"class":268},"(summary) ",[201,824,825],{"class":264},"+",[201,827,828],{"class":331}," 2\n",[201,830,831,834,836,838,840],{"class":85,"line":478},[201,832,833],{"class":268},"    detail.to_excel(writer, ",[201,835,247],{"class":491},[201,837,291],{"class":264},[201,839,784],{"class":210},[201,841,842],{"class":268},",\n",[201,844,845,848,850,852,854,856,858],{"class":85,"line":508},[201,846,847],{"class":491},"                    index",[201,849,291],{"class":264},[201,851,528],{"class":331},[201,853,309],{"class":268},[201,855,619],{"class":491},[201,857,291],{"class":264},[201,859,860],{"class":268},"next_row)\n",[201,862,863],{"class":85,"line":534},[201,864,282],{"emptyLinePlaceholder":281},[201,866,867,869,871,874,877,880,883,885,888,891],{"class":85,"line":557},[201,868,588],{"class":331},[201,870,591],{"class":268},[201,872,873],{"class":264},"f",[201,875,876],{"class":210},"\"Stacked detail starting at row ",[201,878,879],{"class":331},"{",[201,881,882],{"class":268},"next_row ",[201,884,825],{"class":264},[201,886,887],{"class":331}," 1}",[201,889,890],{"class":210}," on the Overview sheet\"",[201,892,531],{"class":268},[10,894,895,896,898,899,901,902,905,906,909],{},"For side-by-side blocks, keep ",[14,897,619],{}," fixed and vary ",[14,900,623],{}," instead — for example ",[14,903,904],{},"startcol=0"," for the first table and ",[14,907,908],{},"startcol=4"," for the second.",[176,911,913],{"id":912},"append-a-sheet-to-an-existing-workbook","Append a sheet to an existing workbook",[10,915,916,917,920,921,924,925,928,929,931],{},"To add a sheet to a file you already wrote — without rewriting the whole thing — open the writer with ",[14,918,919],{},"mode=\"a\""," (append) and an ",[14,922,923],{},"if_sheet_exists"," policy. Append mode requires ",[14,926,927],{},"engine=\"openpyxl\"","; xlsxwriter cannot append. ",[14,930,923],{}," controls what happens when the sheet name is already present:",[192,933,935],{"className":255,"code":934,"language":257,"meta":197,"style":197},"import pandas as pd\n\n# Assume report.xlsx already exists from the first example.\nlate = pd.DataFrame({\n    \"region\": [\"East\"],\n    \"revenue\": [4100],\n})\n\nwith pd.ExcelWriter(\"report.xlsx\", engine=\"openpyxl\",\n                    mode=\"a\", if_sheet_exists=\"replace\") as writer:\n    late.to_excel(writer, sheet_name=\"By Region East\", index=False)\n\nprint(\"Appended a sheet to the existing report.xlsx\")\n",[14,936,937,947,951,956,965,976,987,991,995,1013,1038,1060,1064],{"__ignoreMap":197},[201,938,939,941,943,945],{"class":85,"line":203},[201,940,265],{"class":264},[201,942,269],{"class":268},[201,944,272],{"class":264},[201,946,275],{"class":268},[201,948,949],{"class":85,"line":278},[201,950,282],{"emptyLinePlaceholder":281},[201,952,953],{"class":85,"line":285},[201,954,955],{"class":808},"# Assume report.xlsx already exists from the first example.\n",[201,957,958,961,963],{"class":85,"line":297},[201,959,960],{"class":268},"late ",[201,962,291],{"class":264},[201,964,294],{"class":268},[201,966,967,969,971,974],{"class":85,"line":323},[201,968,300],{"class":210},[201,970,303],{"class":268},[201,972,973],{"class":210},"\"East\"",[201,975,320],{"class":268},[201,977,978,980,982,985],{"class":85,"line":347},[201,979,326],{"class":210},[201,981,303],{"class":268},[201,983,984],{"class":331},"4100",[201,986,320],{"class":268},[201,988,989],{"class":85,"line":353},[201,990,350],{"class":268},[201,992,993],{"class":85,"line":363},[201,994,282],{"emptyLinePlaceholder":281},[201,996,997,999,1001,1003,1005,1007,1009,1011],{"class":85,"line":386},[201,998,251],{"class":264},[201,1000,483],{"class":268},[201,1002,486],{"class":210},[201,1004,309],{"class":268},[201,1006,492],{"class":491},[201,1008,291],{"class":264},[201,1010,497],{"class":210},[201,1012,842],{"class":268},[201,1014,1015,1018,1020,1023,1025,1027,1029,1032,1034,1036],{"class":85,"line":408},[201,1016,1017],{"class":491},"                    mode",[201,1019,291],{"class":264},[201,1021,1022],{"class":210},"\"a\"",[201,1024,309],{"class":268},[201,1026,923],{"class":491},[201,1028,291],{"class":264},[201,1030,1031],{"class":210},"\"replace\"",[201,1033,500],{"class":268},[201,1035,272],{"class":264},[201,1037,505],{"class":268},[201,1039,1040,1043,1045,1047,1050,1052,1054,1056,1058],{"class":85,"line":413},[201,1041,1042],{"class":268},"    late.to_excel(writer, ",[201,1044,247],{"class":491},[201,1046,291],{"class":264},[201,1048,1049],{"class":210},"\"By Region East\"",[201,1051,309],{"class":268},[201,1053,523],{"class":491},[201,1055,291],{"class":264},[201,1057,528],{"class":331},[201,1059,531],{"class":268},[201,1061,1062],{"class":85,"line":423},[201,1063,282],{"emptyLinePlaceholder":281},[201,1065,1066,1068,1070,1073],{"class":85,"line":446},[201,1067,588],{"class":331},[201,1069,591],{"class":268},[201,1071,1072],{"class":210},"\"Appended a sheet to the existing report.xlsx\"",[201,1074,531],{"class":268},[10,1076,1077,1078,1080,1081,1084,1085,1087,1088,1091,1092,1095,1096,1098],{},"The ",[14,1079,923],{}," values are: ",[14,1082,1083],{},"\"error\""," (default — raise if the name exists), ",[14,1086,1031],{}," (drop and rewrite the sheet), ",[14,1089,1090],{},"\"overlay\""," (write on top of existing cells, keeping the rest), and ",[14,1093,1094],{},"\"new\""," (create a uniquely renamed sheet). Use ",[14,1097,1031],{}," for idempotent jobs that rerun the same report.",[176,1100,1102],{"id":1101},"choosing-an-engine","Choosing an engine",[1104,1105,1106,1128],"table",{},[1107,1108,1109],"thead",{},[1110,1111,1112,1116,1119,1122,1125],"tr",{},[1113,1114,1115],"th",{},"Engine",[1113,1117,1118],{},"Read existing file",[1113,1120,1121],{},"Append mode",[1113,1123,1124],{},"Charts",[1113,1126,1127],{},"When to use",[1129,1130,1131,1153],"tbody",{},[1110,1132,1133,1138,1141,1143,1150],{},[1134,1135,1136],"td",{},[14,1137,185],{},[1134,1139,1140],{},"Yes",[1134,1142,1140],{},[1134,1144,1145,1146,1149],{},"Yes (",[14,1147,1148],{},"openpyxl.chart",")",[1134,1151,1152],{},"Multi-sheet dashboards you reopen to add charts, links, or sheets.",[1110,1154,1155,1159,1162,1165,1170],{},[1134,1156,1157],{},[14,1158,225],{},[1134,1160,1161],{},"No (write-only)",[1134,1163,1164],{},"No",[1134,1166,1145,1167,1149],{},[14,1168,1169],{},"workbook.add_chart",[1134,1171,1172],{},"One-shot writes where speed matters and you never reopen the file.",[10,1174,1175,1176,1178,1179,1182],{},"For everything in the dashboard build, use ",[14,1177,185],{}," — append and ",[14,1180,1181],{},"load_workbook()"," are what make it work.",[176,1184,1186],{"id":1185},"common-pitfalls","Common pitfalls",[1104,1188,1189,1202],{},[1107,1190,1191],{},[1110,1192,1193,1196,1199],{},[1113,1194,1195],{},"Symptom",[1113,1197,1198],{},"Cause",[1113,1200,1201],{},"Fix",[1129,1203,1204,1228,1251,1265,1282,1300],{},[1110,1205,1206,1209,1219],{},[1134,1207,1208],{},"Only the last sheet survives",[1134,1210,1211,1212,1214,1215,1218],{},"A second ",[14,1213,239],{}," opened on the same path in default ",[14,1216,1217],{},"mode=\"w\""," truncated the file",[1134,1220,1221,1222,1224,1225,1227],{},"Keep all writes in one ",[14,1223,251],{}," block, or use ",[14,1226,919],{}," to add to an existing file.",[1110,1229,1230,1237,1242],{},[1134,1231,1232,1233,1236],{},"A stray ",[14,1234,1235],{},"0, 1, 2"," column appears",[1134,1238,1239,1241],{},[14,1240,605],{}," missing — it is per-call, not global",[1134,1243,1244,1245,1247,1248,1250],{},"Pass ",[14,1246,605],{}," on every ",[14,1249,243],{}," call.",[1110,1252,1253,1259,1262],{},[1134,1254,1255,1258],{},[14,1256,1257],{},"InvalidWorksheetName"," or silent truncation",[1134,1260,1261],{},"Sheet name over 31 characters",[1134,1263,1264],{},"Keep names ≤ 31 chars; truncate long names before writing.",[1110,1266,1267,1273,1279],{},[1134,1268,1269,1272],{},[14,1270,1271],{},"ValueError"," on the sheet name",[1134,1274,1275,1276],{},"Name contains ",[14,1277,1278],{},"\\ \u002F * ? : [ ]",[1134,1280,1281],{},"Strip those characters; Excel forbids them in tab names.",[1110,1283,1284,1289,1294],{},[1134,1285,1286],{},[14,1287,1288],{},"ValueError: Append mode is not supported with xlsxwriter",[1134,1290,1291,1293],{},[14,1292,919],{}," with the wrong engine",[1134,1295,1296,1297,1299],{},"Use ",[14,1298,927],{}," for append.",[1110,1301,1302,1305,1312],{},[1134,1303,1304],{},"Appended sheet raises on rerun",[1134,1306,1307,1308,1311],{},"Default ",[14,1309,1310],{},"if_sheet_exists=\"error\""," and the name already exists",[1134,1313,1244,1314,1317],{},[14,1315,1316],{},"if_sheet_exists=\"replace\""," for idempotent reruns.",[176,1319,1321],{"id":1320},"scale-note","Scale note",[10,1323,1324,1325,1327,1328,1330,1331,1334],{},"For workbooks with many large sheets, ",[14,1326,225],{}," writes faster and uses less memory than ",[14,1329,185],{},", and its ",[14,1332,1333],{},"constant_memory"," mode streams rows to disk — but it cannot reopen or append, so you must write every sheet in one pass. If a job grows beyond comfortable memory, write each DataFrame to its own file and combine them in a final openpyxl pass, or switch the whole job to a single streaming xlsxwriter write.",[176,1336,1338],{"id":1337},"frequently-asked-questions","Frequently asked questions",[10,1340,1341,1344,1345,1347,1348,1350,1351,1354],{},[19,1342,1343],{},"Why does my file only contain the last DataFrame?","\nYou opened more than one ",[14,1346,117],{}," on the same path. The second one opens in write mode and truncates the file. Put every ",[14,1349,243],{}," call inside a single ",[14,1352,1353],{},"with pd.ExcelWriter(...)"," block.",[10,1356,1357,1363,1364,1366,1367,1369],{},[19,1358,1359,1360,1362],{},"Do I need ",[14,1361,605],{}," on every call?","\nYes. ",[14,1365,605],{}," is an argument to each ",[14,1368,243],{}," call and is not carried over from a previous write. Omit it once and that sheet gets a row-number column.",[10,1371,1372,1375,1376,1378],{},[19,1373,1374],{},"What is the maximum sheet name length?","\nExcel caps tab names at 31 characters and forbids ",[14,1377,1278],{},". Names over the limit or with those characters raise an error or get mangled — sanitize names you build from data.",[10,1380,1381,1384,1385,627,1387,1389,1390,1392,1393,1395],{},[19,1382,1383],{},"How do I add a sheet without rewriting the file?","\nOpen the writer with ",[14,1386,919],{},[14,1388,927],{},", and set ",[14,1391,923],{}," to control collisions. Use ",[14,1394,1031],{}," so a rerun overwrites the sheet cleanly.",[176,1397,1399],{"id":1398},"conclusion","Conclusion",[10,1401,1402,1403,1405,1406,1408,1409,1411,1412,1414,1415,1417,1418,1411,1420,1422,1423,1425],{},"Writing multiple DataFrames to one file comes down to one ",[14,1404,117],{},": distinct ",[14,1407,247],{}," values for separate tabs, matching ",[14,1410,247],{}," with ",[14,1413,619],{},"\u002F",[14,1416,623],{}," offsets to stack tables on one sheet, and ",[14,1419,919],{},[14,1421,923],{}," to append to an existing workbook. Open the writer once, pass ",[14,1424,605],{}," every time, and keep sheet names short and clean — and the three failure modes above never occur.",[176,1427,1429],{"id":1428},"where-to-go-next","Where to go next",[1431,1432,1433,1439,1446],"ul",{},[1434,1435,1436,1438],"li",{},[24,1437,27],{"href":26}," — assemble these sheets into a Summary-plus-detail dashboard with a chart.",[1434,1440,1441,1445],{},[24,1442,1444],{"href":1443},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-summary-sheet-to-excel-report-python\u002F","Add a Summary Sheet to an Excel Report with Python"," — compute KPIs and write a front-page Summary tab.",[1434,1447,1448,1452,1453,1455],{},[24,1449,1451],{"href":1450},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002F","Writing DataFrames to Excel with Pandas"," — the core ",[14,1454,243],{}," options these examples build on.",[1457,1458,1459],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":197,"searchDepth":278,"depth":278,"links":1461},[1462,1463,1464,1465,1466,1467,1468,1469,1470,1471],{"id":178,"depth":278,"text":179},{"id":232,"depth":278,"text":233},{"id":609,"depth":278,"text":610},{"id":912,"depth":278,"text":913},{"id":1101,"depth":278,"text":1102},{"id":1185,"depth":278,"text":1186},{"id":1320,"depth":278,"text":1321},{"id":1337,"depth":278,"text":1338},{"id":1398,"depth":278,"text":1399},{"id":1428,"depth":278,"text":1429},"2026-06-18","Write several pandas DataFrames into one .xlsx: separate sheets via one ExcelWriter, stacking on a single sheet with startrow, and appending with mode='a'.","md",[1476,1478,1481,1483],{"q":1343,"a":1477},"You opened more than one ExcelWriter on the same path. The second one opens in write mode and truncates the file. Put every to_excel() call inside a single with pd.ExcelWriter(...) block.",{"q":1479,"a":1480},"Do I need index=False on every call?","Yes. index=False is an argument to each to_excel() call and is not carried over from a previous write. Omit it once and that sheet gets a row-number column.",{"q":1374,"a":1482},"Excel caps tab names at 31 characters and forbids \\ \u002F * ? : [ ]. Names over the limit or with those characters raise an error or get mangled — sanitize names you build from data.",{"q":1383,"a":1484},"Open the writer with mode=\"a\" and engine=\"openpyxl\", and set if_sheet_exists to control collisions. Use \"replace\" so a rerun overwrites the sheet cleanly.",{},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fwrite-multiple-dataframes-to-one-excel-file",{"title":5,"description":1488},"Save multiple pandas DataFrames to a single Excel workbook: one ExcelWriter for separate sheets, startrow\u002Fstartcol stacking, and mode='a' append with if_sheet_exists.","write-multiple-dataframes-to-one-excel-file","automating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fwrite-multiple-dataframes-to-one-excel-file\u002Findex","long_tail","3pF5LIagJ846aR0-obqyqv_9KtEA-zqQmpJYw4xCl_w",[1494,1497],{"title":1444,"path":1495,"stem":1496,"children":-1},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-summary-sheet-to-excel-report-python","automating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-summary-sheet-to-excel-report-python\u002Findex",{"title":1498,"path":1499,"stem":1500,"children":-1},"Emailing Excel Reports with smtplib","\u002Fautomating-reporting-workflows\u002Femailing-excel-reports-with-smtplib","automating-reporting-workflows\u002Femailing-excel-reports-with-smtplib\u002Findex",1781795518678]