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