[{"data":1,"prerenderedAt":2084},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsave-each-sheet-of-a-workbook-as-a-separate-file":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsave-each-sheet-of-a-workbook-as-a-separate-file":2050,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsave-each-sheet-of-a-workbook-as-a-separate-file":2059,"children:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsave-each-sheet-of-a-workbook-as-a-separate-file":2064,"related:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsave-each-sheet-of-a-workbook-as-a-separate-file":2065},{"id":4,"title":5,"body":6,"dateModified":2017,"datePublished":2017,"description":2018,"extension":2019,"faq":2020,"keyword":2029,"kind":2030,"meta":2031,"navigation":122,"path":2039,"seo":2040,"slug":2043,"stem":2044,"topics":2045,"type":2048,"__hash__":2049},"docs\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsave-each-sheet-of-a-workbook-as-a-separate-file\u002Findex.md","Save Each Sheet of a Workbook as a Separate File",{"type":7,"value":8,"toc":2004},"minimark",[9,19,24,53,87,91,94,233,257,404,408,415,676,687,720,724,747,939,942,946,949,1265,1275,1437,1441,1444,1591,1695,1702,1706,1721,1857,1884,1888,1932,1936,1939,1943,1949,1955,1961,1967,1971,2000],[10,11,12,13,18],"p",{},"A regional workbook has one tab per region, and each regional manager should receive only their own tab. Copy-and-paste into new workbooks works for three tabs and becomes a chore at thirty, and Excel's \"Move or Copy\" keeps every cross-sheet formula pointing back at the original file. In Python the split takes a short loop — but a correct split has to deal with formulas that reference sheets that will not be in the new file, defined names that point at deleted sheets, hidden helper tabs, and sheet names that are not valid file names. This page goes through a split that keeps formatting and produces files that open cleanly. It belongs to ",[14,15,17],"a",{"href":16},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002F","Working with Multiple Excel Sheets in Python",".",[20,21,23],"h2",{"id":22},"prerequisites","Prerequisites",[25,26,31],"pre",{"className":27,"code":28,"language":29,"meta":30,"style":30},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install openpyxl pandas\n","bash","",[32,33,34],"code",{"__ignoreMap":30},[35,36,39,43,47,50],"span",{"class":37,"line":38},"line",1,[35,40,42],{"class":41},"sMTad","pip",[35,44,46],{"class":45},"srMev"," install",[35,48,49],{"class":45}," openpyxl",[35,51,52],{"class":45}," pandas\n",[10,54,55,58,59,62,63,66,67,70,71,74,75,78,79,82,83,86],{},[32,56,57],{},"regions.xlsx"," has three regional sheets — ",[32,60,61],{},"North | East",", ",[32,64,65],{},"South"," and ",[32,68,69],{},"West \u003Cpilot>"," — plus a hidden ",[32,72,73],{},"Settings"," sheet holding a VAT rate, a ",[32,76,77],{},"Lists"," sheet, and a defined name ",[32,80,81],{},"VatRate",". Each regional sheet calculates gross amounts with ",[32,84,85],{},"=B2*(1+Settings!$B$1)",", a formula that reaches into another sheet. The file was last saved by a spreadsheet application, so every formula cell also carries its calculated result.",[20,88,90],{"id":89},"step-1-the-naive-split-and-why-it-breaks","Step 1 — The naive split and why it breaks",[10,92,93],{},"The obvious approach is: load the workbook, remove every sheet except one, save under a new name. It produces files — but look inside one:",[25,95,99],{"className":96,"code":97,"language":98,"meta":30,"style":30},"language-python shiki shiki-themes github-light github-dark-high-contrast","from openpyxl import load_workbook\n\nwb = load_workbook(\"regions.xlsx\")\nfor name in wb.sheetnames:\n    if name != \"South\":\n        wb.remove(wb[name])\nwb.save(\"naive_south.xlsx\")\ncheck = load_workbook(\"naive_south.xlsx\")\nprint(check.sheetnames, check[\"South\"][\"C2\"].value, check.defined_names[\"VatRate\"].attr_text)\n","python",[32,100,101,117,124,142,157,174,180,191,205],{"__ignoreMap":30},[35,102,103,107,111,114],{"class":37,"line":38},[35,104,106],{"class":105},"s-kum","from",[35,108,110],{"class":109},"skGVy"," openpyxl ",[35,112,113],{"class":105},"import",[35,115,116],{"class":109}," load_workbook\n",[35,118,120],{"class":37,"line":119},2,[35,121,123],{"emptyLinePlaceholder":122},true,"\n",[35,125,127,130,133,136,139],{"class":37,"line":126},3,[35,128,129],{"class":109},"wb ",[35,131,132],{"class":105},"=",[35,134,135],{"class":109}," load_workbook(",[35,137,138],{"class":45},"\"regions.xlsx\"",[35,140,141],{"class":109},")\n",[35,143,145,148,151,154],{"class":37,"line":144},4,[35,146,147],{"class":105},"for",[35,149,150],{"class":109}," name ",[35,152,153],{"class":105},"in",[35,155,156],{"class":109}," wb.sheetnames:\n",[35,158,160,163,165,168,171],{"class":37,"line":159},5,[35,161,162],{"class":105},"    if",[35,164,150],{"class":109},[35,166,167],{"class":105},"!=",[35,169,170],{"class":45}," \"South\"",[35,172,173],{"class":109},":\n",[35,175,177],{"class":37,"line":176},6,[35,178,179],{"class":109},"        wb.remove(wb[name])\n",[35,181,183,186,189],{"class":37,"line":182},7,[35,184,185],{"class":109},"wb.save(",[35,187,188],{"class":45},"\"naive_south.xlsx\"",[35,190,141],{"class":109},[35,192,194,197,199,201,203],{"class":37,"line":193},8,[35,195,196],{"class":109},"check ",[35,198,132],{"class":105},[35,200,135],{"class":109},[35,202,188],{"class":45},[35,204,141],{"class":109},[35,206,208,212,215,218,221,224,227,230],{"class":37,"line":207},9,[35,209,211],{"class":210},"sP0c6","print",[35,213,214],{"class":109},"(check.sheetnames, check[",[35,216,217],{"class":45},"\"South\"",[35,219,220],{"class":109},"][",[35,222,223],{"class":45},"\"C2\"",[35,225,226],{"class":109},"].value, check.defined_names[",[35,228,229],{"class":45},"\"VatRate\"",[35,231,232],{"class":109},"].attr_text)\n",[10,234,235,236,238,239,242,243,245,246,249,250,252,253,256],{},"The new file has only the ",[32,237,65],{}," sheet, but ",[32,240,241],{},"C2"," still says ",[32,244,85],{}," and the defined name still points at ",[32,247,248],{},"Settings!$B$1",". There is no ",[32,251,73],{}," sheet any more, so Excel shows ",[32,254,255],{},"#REF!"," in every gross amount and may report a problem with the defined name. openpyxl does not rewrite or remove references when a sheet is deleted; that is up to the script.",[258,259,267,268,267,272,267,276,267,284,267,294,267,305,267,312,267,318,267,324,267,330,267,334,267,339,267,343,267,348,267,352,267,357,267,362,267,369,267,374,267,378,267,381,267,388,267,391,267,396,267,399],"svg",{"viewBox":260,"role":261,"ariaLabelledBy":262,"xmlns":265,"style":266},"4 0 752 233","img",[263,264],"ss-naive-t","ss-naive-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  ",[269,270,271],"title",{"id":263},"What removing sheets leaves behind",[273,274,275],"desc",{"id":264},"Removing every sheet except South keeps its values, styles and widths. Formulas that refer to the deleted Settings sheet and the defined name that points at it are left dangling and show errors in the new file.",[277,278],"rect",{"x":279,"y":280,"width":281,"height":282,"fill":283},"4","0","752","233","#ffffff",[277,285],{"x":286,"y":287,"width":288,"height":289,"rx":290,"fill":291,"stroke":292,"style":293},"20.0","16.0","351.0","201.0","14","#d9f4f1","var(--teal,#0f9488)","stroke-width:2px",[295,296,298],"g",{"transform":297},"translate(182.5,29.0) scale(1.083)",[299,300],"path",{"d":301,"fill":302,"stroke":303,"style":304},"M5 12.5l4.5 4.5L19 7","none","var(--teal-ink,#0b6157)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[306,307,311],"text",{"x":308,"y":309,"style":310},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Comes through intact",[37,313],{"x1":314,"y1":315,"x2":316,"y2":315,"stroke":292,"style":317},"36.0","91.0","355.0","stroke-width:1px",[306,319,323],{"x":320,"y":321,"style":322},"60.0","111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","values on the kept sheet",[295,325,327],{"transform":326},"translate(38.5,99.5) scale(0.625)",[299,328],{"d":301,"fill":302,"stroke":292,"style":329},"stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[306,331,333],{"x":320,"y":332,"style":322},"137.0","fonts, fills, number formats",[295,335,337],{"transform":336},"translate(38.5,125.5) scale(0.625)",[299,338],{"d":301,"fill":302,"stroke":292,"style":329},[306,340,342],{"x":320,"y":341,"style":322},"163.0","column widths and merges",[295,344,346],{"transform":345},"translate(38.5,151.5) scale(0.625)",[299,347],{"d":301,"fill":302,"stroke":292,"style":329},[306,349,351],{"x":320,"y":350,"style":322},"189.0","formulas within the sheet",[295,353,355],{"transform":354},"translate(38.5,177.5) scale(0.625)",[299,356],{"d":301,"fill":302,"stroke":292,"style":329},[277,358],{"x":359,"y":287,"width":288,"height":289,"rx":290,"fill":360,"stroke":361,"style":293},"389.0","#fce9e9","var(--danger,#dc2626)",[295,363,365],{"transform":364},"translate(551.5,29.0) scale(1.083)",[299,366],{"d":367,"fill":302,"stroke":368,"style":304},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","var(--accent-ink,#be185d)",[306,370,373],{"x":371,"y":309,"style":372},"564.5","font-size:14px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","Left dangling",[37,375],{"x1":376,"y1":315,"x2":377,"y2":315,"stroke":361,"style":317},"405.0","724.0",[306,379,85],{"x":380,"y":321,"style":322},"429.0",[295,382,384],{"transform":383},"translate(407.5,99.5) scale(0.625)",[299,385],{"d":386,"fill":302,"stroke":387,"style":329},"M6 6l12 12 M18 6L6 18","var(--accent,#f43f8f)",[306,389,390],{"x":380,"y":332,"style":322},"defined name VatRate",[295,392,394],{"transform":393},"translate(407.5,125.5) scale(0.625)",[299,395],{"d":386,"fill":302,"stroke":387,"style":329},[306,397,398],{"x":380,"y":341,"style":322},"hidden-sheet state if only one remains",[295,400,402],{"transform":401},"translate(407.5,151.5) scale(0.625)",[299,403],{"d":386,"fill":302,"stroke":387,"style":329},[20,405,407],{"id":406},"step-2-freeze-cross-sheet-formulas-as-values","Step 2 — Freeze cross-sheet formulas as values",[10,409,410,411,414],{},"A regional manager does not need a live link to a settings sheet they will never see; they need the numbers. Load the workbook a second time with ",[32,412,413],{},"data_only=True"," to get the cached results, and replace every formula that mentions another sheet with its value:",[25,416,418],{"className":96,"code":417,"language":98,"meta":30,"style":30},"import re\n\nCROSS_SHEET = re.compile(r\"!|\\[\\d+\\]\")      # Sheet!A1, 'My sheet'!A1 or an external [1] link\n\ndef freeze_cross_sheet(ws, ws_values):\n    frozen = 0\n    for row in ws.iter_rows():\n        for cell in row:\n            if isinstance(cell.value, str) and cell.value.startswith(\"=\") and CROSS_SHEET.search(cell.value):\n                cell.value = ws_values[cell.coordinate].value\n                frozen += 1\n    return frozen\n\nwb = load_workbook(\"regions.xlsx\")\nvalues = load_workbook(\"regions.xlsx\", data_only=True)\nprint(\"frozen:\", freeze_cross_sheet(wb[\"South\"], values[\"South\"]), \"->\", wb[\"South\"][\"C2\"].value)\n",[32,419,420,427,431,474,478,490,500,513,526,562,573,585,594,599,612,637],{"__ignoreMap":30},[35,421,422,424],{"class":37,"line":38},[35,423,113],{"class":105},[35,425,426],{"class":109}," re\n",[35,428,429],{"class":37,"line":119},[35,430,123],{"emptyLinePlaceholder":122},[35,432,433,436,439,442,445,448,451,455,458,461,464,467,470],{"class":37,"line":126},[35,434,435],{"class":210},"CROSS_SHEET",[35,437,438],{"class":105}," =",[35,440,441],{"class":109}," re.compile(",[35,443,444],{"class":105},"r",[35,446,447],{"class":45},"\"!",[35,449,450],{"class":105},"|",[35,452,454],{"class":453},"s_b0D","\\[",[35,456,457],{"class":210},"\\d",[35,459,460],{"class":105},"+",[35,462,463],{"class":453},"\\]",[35,465,466],{"class":45},"\"",[35,468,469],{"class":109},")      ",[35,471,473],{"class":472},"s-wDw","# Sheet!A1, 'My sheet'!A1 or an external [1] link\n",[35,475,476],{"class":37,"line":144},[35,477,123],{"emptyLinePlaceholder":122},[35,479,480,483,487],{"class":37,"line":159},[35,481,482],{"class":105},"def",[35,484,486],{"class":485},"s_Opv"," freeze_cross_sheet",[35,488,489],{"class":109},"(ws, ws_values):\n",[35,491,492,495,497],{"class":37,"line":176},[35,493,494],{"class":109},"    frozen ",[35,496,132],{"class":105},[35,498,499],{"class":210}," 0\n",[35,501,502,505,508,510],{"class":37,"line":182},[35,503,504],{"class":105},"    for",[35,506,507],{"class":109}," row ",[35,509,153],{"class":105},[35,511,512],{"class":109}," ws.iter_rows():\n",[35,514,515,518,521,523],{"class":37,"line":193},[35,516,517],{"class":105},"        for",[35,519,520],{"class":109}," cell ",[35,522,153],{"class":105},[35,524,525],{"class":109}," row:\n",[35,527,528,531,534,537,540,543,546,549,552,554,556,559],{"class":37,"line":207},[35,529,530],{"class":105},"            if",[35,532,533],{"class":210}," isinstance",[35,535,536],{"class":109},"(cell.value, ",[35,538,539],{"class":210},"str",[35,541,542],{"class":109},") ",[35,544,545],{"class":105},"and",[35,547,548],{"class":109}," cell.value.startswith(",[35,550,551],{"class":45},"\"=\"",[35,553,542],{"class":109},[35,555,545],{"class":105},[35,557,558],{"class":210}," CROSS_SHEET",[35,560,561],{"class":109},".search(cell.value):\n",[35,563,565,568,570],{"class":37,"line":564},10,[35,566,567],{"class":109},"                cell.value ",[35,569,132],{"class":105},[35,571,572],{"class":109}," ws_values[cell.coordinate].value\n",[35,574,576,579,582],{"class":37,"line":575},11,[35,577,578],{"class":109},"                frozen ",[35,580,581],{"class":105},"+=",[35,583,584],{"class":210}," 1\n",[35,586,588,591],{"class":37,"line":587},12,[35,589,590],{"class":105},"    return",[35,592,593],{"class":109}," frozen\n",[35,595,597],{"class":37,"line":596},13,[35,598,123],{"emptyLinePlaceholder":122},[35,600,602,604,606,608,610],{"class":37,"line":601},14,[35,603,129],{"class":109},[35,605,132],{"class":105},[35,607,135],{"class":109},[35,609,138],{"class":45},[35,611,141],{"class":109},[35,613,615,618,620,622,624,626,630,632,635],{"class":37,"line":614},15,[35,616,617],{"class":109},"values ",[35,619,132],{"class":105},[35,621,135],{"class":109},[35,623,138],{"class":45},[35,625,62],{"class":109},[35,627,629],{"class":628},"sa561","data_only",[35,631,132],{"class":105},[35,633,634],{"class":210},"True",[35,636,141],{"class":109},[35,638,640,642,645,648,651,653,656,658,661,664,667,669,671,673],{"class":37,"line":639},16,[35,641,211],{"class":210},[35,643,644],{"class":109},"(",[35,646,647],{"class":45},"\"frozen:\"",[35,649,650],{"class":109},", freeze_cross_sheet(wb[",[35,652,217],{"class":45},[35,654,655],{"class":109},"], values[",[35,657,217],{"class":45},[35,659,660],{"class":109},"]), ",[35,662,663],{"class":45},"\"->\"",[35,665,666],{"class":109},", wb[",[35,668,217],{"class":45},[35,670,220],{"class":109},[35,672,223],{"class":45},[35,674,675],{"class":109},"].value)\n",[10,677,678,679,682,683,18],{},"Formulas that stay within the sheet — a ",[32,680,681],{},"SUM"," of its own column, say — are left alone and keep working. Only references that would dangle are frozen. The value comes from the copy saved by the last spreadsheet application; if the workbook was written by a script and never opened, there is no cached value and the cell would become empty, so recalculate it first as described in ",[14,684,686],{"href":685},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Frecalculate-excel-formulas-without-excel-in-python\u002F","Recalculate Excel Formulas Without Excel in Python",[10,688,689,690,692,693,696,697,700,701,704,705,708,709,712,713,716,717,18],{},"The regular expression catches the usual shapes: ",[32,691,248],{},", quoted names such as ",[32,694,695],{},"'Price list'!A1",", three-dimensional ranges like ",[32,698,699],{},"Jan:Mar!B2",", and the ",[32,702,703],{},"[1]"," prefix that marks a link to another workbook. It cannot see references hidden inside text, such as ",[32,706,707],{},"INDIRECT(\"Settings!B1\")",", or formulas that use a defined name — ",[32,710,711],{},"=B2*(1+VatRate)"," contains no ",[32,714,715],{},"!"," at all. If the source uses names in formulas, add a second test that looks for each name defined at workbook level and freeze those cells too; the list of names is in ",[32,718,719],{},"wb.defined_names",[20,721,723],{"id":722},"step-3-make-file-names-from-sheet-names","Step 3 — Make file names from sheet names",[10,725,726,727,730,731,62,733,62,736,66,739,741,742,66,744,746],{},"Excel already bans ",[32,728,729],{},"\u002F \\ ? * [ ] :"," in sheet names, but it allows ",[32,732,450],{},[32,734,735],{},"\u003C",[32,737,738],{},">",[32,740,466],{},", which Windows forbids in file names — ",[32,743,61],{},[32,745,69],{}," are valid tabs and invalid files. Replace the characters Windows rejects, the strictest common rule set, so the same script works on every system:",[25,748,750],{"className":96,"code":749,"language":98,"meta":30,"style":30},"from pathlib import Path\n\ndef file_name(sheet, prefix=\"regions\"):\n    safe = re.sub(r'[\u003C>:\"\u002F\\\\|?*]', \"-\", sheet)\n    safe = re.sub(r\"\\s+\", \" \", safe).strip(\" .\")\n    return f\"{prefix} - {safe}.xlsx\"\n\nfor s in [\"North | East\", \"South\", \"West \u003Cpilot>\"]:\n    print(repr(s), \"->\", file_name(s))\n",[32,751,752,764,768,786,827,859,890,894,921],{"__ignoreMap":30},[35,753,754,756,759,761],{"class":37,"line":38},[35,755,106],{"class":105},[35,757,758],{"class":109}," pathlib ",[35,760,113],{"class":105},[35,762,763],{"class":109}," Path\n",[35,765,766],{"class":37,"line":119},[35,767,123],{"emptyLinePlaceholder":122},[35,769,770,772,775,778,780,783],{"class":37,"line":126},[35,771,482],{"class":105},[35,773,774],{"class":485}," file_name",[35,776,777],{"class":109},"(sheet, prefix",[35,779,132],{"class":105},[35,781,782],{"class":45},"\"regions\"",[35,784,785],{"class":109},"):\n",[35,787,788,791,793,796,798,801,804,808,811,814,817,819,821,824],{"class":37,"line":144},[35,789,790],{"class":109},"    safe ",[35,792,132],{"class":105},[35,794,795],{"class":109}," re.sub(",[35,797,444],{"class":105},[35,799,800],{"class":45},"'",[35,802,803],{"class":210},"[",[35,805,807],{"class":806},"sSjpA","\u003C>:\"\u002F",[35,809,810],{"class":453},"\\\\",[35,812,813],{"class":806},"|?*",[35,815,816],{"class":210},"]",[35,818,800],{"class":45},[35,820,62],{"class":109},[35,822,823],{"class":45},"\"-\"",[35,825,826],{"class":109},", sheet)\n",[35,828,829,831,833,835,837,839,842,844,846,848,851,854,857],{"class":37,"line":159},[35,830,790],{"class":109},[35,832,132],{"class":105},[35,834,795],{"class":109},[35,836,444],{"class":105},[35,838,466],{"class":45},[35,840,841],{"class":210},"\\s",[35,843,460],{"class":105},[35,845,466],{"class":45},[35,847,62],{"class":109},[35,849,850],{"class":45},"\" \"",[35,852,853],{"class":109},", safe).strip(",[35,855,856],{"class":45},"\" .\"",[35,858,141],{"class":109},[35,860,861,863,866,868,871,874,877,880,882,885,887],{"class":37,"line":176},[35,862,590],{"class":105},[35,864,865],{"class":105}," f",[35,867,466],{"class":45},[35,869,870],{"class":806},"{",[35,872,873],{"class":109},"prefix",[35,875,876],{"class":806},"}",[35,878,879],{"class":45}," - ",[35,881,870],{"class":806},[35,883,884],{"class":109},"safe",[35,886,876],{"class":806},[35,888,889],{"class":45},".xlsx\"\n",[35,891,892],{"class":37,"line":182},[35,893,123],{"emptyLinePlaceholder":122},[35,895,896,898,901,903,906,909,911,913,915,918],{"class":37,"line":193},[35,897,147],{"class":105},[35,899,900],{"class":109}," s ",[35,902,153],{"class":105},[35,904,905],{"class":109}," [",[35,907,908],{"class":45},"\"North | East\"",[35,910,62],{"class":109},[35,912,217],{"class":45},[35,914,62],{"class":109},[35,916,917],{"class":45},"\"West \u003Cpilot>\"",[35,919,920],{"class":109},"]:\n",[35,922,923,926,928,931,934,936],{"class":37,"line":207},[35,924,925],{"class":210},"    print",[35,927,644],{"class":109},[35,929,930],{"class":210},"repr",[35,932,933],{"class":109},"(s), ",[35,935,663],{"class":45},[35,937,938],{"class":109},", file_name(s))\n",[10,940,941],{},"Trailing dots and spaces are stripped because Windows silently drops them, which would make two different sheet names map to the same file. Prefixing the source file name keeps the outputs recognisable when they are attached to emails or uploaded together.",[20,943,945],{"id":944},"step-4-the-complete-split","Step 4 — The complete split",[10,947,948],{},"Put the pieces together: for each sheet to export, load the workbook fresh, freeze cross-sheet formulas, delete the other sheets, remove defined names that now point nowhere, make sure the remaining sheet is visible, and save:",[25,950,952],{"className":96,"code":951,"language":98,"meta":30,"style":30},"def split_workbook(path, out_dir=\"split\", skip=(\"Settings\", \"Lists\")):\n    out = Path(out_dir)\n    out.mkdir(exist_ok=True)\n    values = load_workbook(path, data_only=True)\n    written = []\n    for name in load_workbook(path, read_only=True).sheetnames:\n        if name in skip:\n            continue\n        wb = load_workbook(path)\n        freeze_cross_sheet(wb[name], values[name])\n        for other in wb.sheetnames:\n            if other != name:\n                wb.remove(wb[other])\n        for dn in list(wb.defined_names):\n            if \"!\" in wb.defined_names[dn].attr_text and name not in wb.defined_names[dn].attr_text:\n                del wb.defined_names[dn]\n        ws = wb[name]\n        ws.sheet_state = \"visible\"\n        wb.active = 0\n        target = out \u002F file_name(name)\n        wb.save(target)\n        written.append(target.name)\n    return written\n\nfor f in split_workbook(\"regions.xlsx\"):\n    print(f)\n",[32,953,954,987,997,1011,1029,1039,1059,1071,1076,1086,1091,1102,1113,1118,1133,1158,1166,1177,1188,1198,1215,1221,1227,1235,1240,1257],{"__ignoreMap":30},[35,955,956,958,961,964,966,969,972,974,976,979,981,984],{"class":37,"line":38},[35,957,482],{"class":105},[35,959,960],{"class":485}," split_workbook",[35,962,963],{"class":109},"(path, out_dir",[35,965,132],{"class":105},[35,967,968],{"class":45},"\"split\"",[35,970,971],{"class":109},", skip",[35,973,132],{"class":105},[35,975,644],{"class":109},[35,977,978],{"class":45},"\"Settings\"",[35,980,62],{"class":109},[35,982,983],{"class":45},"\"Lists\"",[35,985,986],{"class":109},")):\n",[35,988,989,992,994],{"class":37,"line":119},[35,990,991],{"class":109},"    out ",[35,993,132],{"class":105},[35,995,996],{"class":109}," Path(out_dir)\n",[35,998,999,1002,1005,1007,1009],{"class":37,"line":126},[35,1000,1001],{"class":109},"    out.mkdir(",[35,1003,1004],{"class":628},"exist_ok",[35,1006,132],{"class":105},[35,1008,634],{"class":210},[35,1010,141],{"class":109},[35,1012,1013,1016,1018,1021,1023,1025,1027],{"class":37,"line":144},[35,1014,1015],{"class":109},"    values ",[35,1017,132],{"class":105},[35,1019,1020],{"class":109}," load_workbook(path, ",[35,1022,629],{"class":628},[35,1024,132],{"class":105},[35,1026,634],{"class":210},[35,1028,141],{"class":109},[35,1030,1031,1034,1036],{"class":37,"line":159},[35,1032,1033],{"class":109},"    written ",[35,1035,132],{"class":105},[35,1037,1038],{"class":109}," []\n",[35,1040,1041,1043,1045,1047,1049,1052,1054,1056],{"class":37,"line":176},[35,1042,504],{"class":105},[35,1044,150],{"class":109},[35,1046,153],{"class":105},[35,1048,1020],{"class":109},[35,1050,1051],{"class":628},"read_only",[35,1053,132],{"class":105},[35,1055,634],{"class":210},[35,1057,1058],{"class":109},").sheetnames:\n",[35,1060,1061,1064,1066,1068],{"class":37,"line":182},[35,1062,1063],{"class":105},"        if",[35,1065,150],{"class":109},[35,1067,153],{"class":105},[35,1069,1070],{"class":109}," skip:\n",[35,1072,1073],{"class":37,"line":193},[35,1074,1075],{"class":105},"            continue\n",[35,1077,1078,1081,1083],{"class":37,"line":207},[35,1079,1080],{"class":109},"        wb ",[35,1082,132],{"class":105},[35,1084,1085],{"class":109}," load_workbook(path)\n",[35,1087,1088],{"class":37,"line":564},[35,1089,1090],{"class":109},"        freeze_cross_sheet(wb[name], values[name])\n",[35,1092,1093,1095,1098,1100],{"class":37,"line":575},[35,1094,517],{"class":105},[35,1096,1097],{"class":109}," other ",[35,1099,153],{"class":105},[35,1101,156],{"class":109},[35,1103,1104,1106,1108,1110],{"class":37,"line":587},[35,1105,530],{"class":105},[35,1107,1097],{"class":109},[35,1109,167],{"class":105},[35,1111,1112],{"class":109}," name:\n",[35,1114,1115],{"class":37,"line":596},[35,1116,1117],{"class":109},"                wb.remove(wb[other])\n",[35,1119,1120,1122,1125,1127,1130],{"class":37,"line":601},[35,1121,517],{"class":105},[35,1123,1124],{"class":109}," dn ",[35,1126,153],{"class":105},[35,1128,1129],{"class":210}," list",[35,1131,1132],{"class":109},"(wb.defined_names):\n",[35,1134,1135,1137,1140,1143,1146,1148,1150,1153,1155],{"class":37,"line":614},[35,1136,530],{"class":105},[35,1138,1139],{"class":45}," \"!\"",[35,1141,1142],{"class":105}," in",[35,1144,1145],{"class":109}," wb.defined_names[dn].attr_text ",[35,1147,545],{"class":105},[35,1149,150],{"class":109},[35,1151,1152],{"class":105},"not",[35,1154,1142],{"class":105},[35,1156,1157],{"class":109}," wb.defined_names[dn].attr_text:\n",[35,1159,1160,1163],{"class":37,"line":639},[35,1161,1162],{"class":105},"                del",[35,1164,1165],{"class":109}," wb.defined_names[dn]\n",[35,1167,1169,1172,1174],{"class":37,"line":1168},17,[35,1170,1171],{"class":109},"        ws ",[35,1173,132],{"class":105},[35,1175,1176],{"class":109}," wb[name]\n",[35,1178,1180,1183,1185],{"class":37,"line":1179},18,[35,1181,1182],{"class":109},"        ws.sheet_state ",[35,1184,132],{"class":105},[35,1186,1187],{"class":45}," \"visible\"\n",[35,1189,1191,1194,1196],{"class":37,"line":1190},19,[35,1192,1193],{"class":109},"        wb.active ",[35,1195,132],{"class":105},[35,1197,499],{"class":210},[35,1199,1201,1204,1206,1209,1212],{"class":37,"line":1200},20,[35,1202,1203],{"class":109},"        target ",[35,1205,132],{"class":105},[35,1207,1208],{"class":109}," out ",[35,1210,1211],{"class":105},"\u002F",[35,1213,1214],{"class":109}," file_name(name)\n",[35,1216,1218],{"class":37,"line":1217},21,[35,1219,1220],{"class":109},"        wb.save(target)\n",[35,1222,1224],{"class":37,"line":1223},22,[35,1225,1226],{"class":109},"        written.append(target.name)\n",[35,1228,1230,1232],{"class":37,"line":1229},23,[35,1231,590],{"class":105},[35,1233,1234],{"class":109}," written\n",[35,1236,1238],{"class":37,"line":1237},24,[35,1239,123],{"emptyLinePlaceholder":122},[35,1241,1243,1245,1248,1250,1253,1255],{"class":37,"line":1242},25,[35,1244,147],{"class":105},[35,1246,1247],{"class":109}," f ",[35,1249,153],{"class":105},[35,1251,1252],{"class":109}," split_workbook(",[35,1254,138],{"class":45},[35,1256,785],{"class":109},[35,1258,1260,1262],{"class":37,"line":1259},26,[35,1261,925],{"class":210},[35,1263,1264],{"class":109},"(f)\n",[10,1266,1267,1268,1271,1272,18],{},"Loading the source once per output is the simplest way to start each file from an untouched copy; the alternative — deleting sheets from one loaded workbook and \"undoing\" it — is error-prone. The ",[32,1269,1270],{},"skip"," tuple keeps helper sheets out of the output. Setting the sheet visible matters when the sheet you export was hidden: a workbook whose only sheet is hidden cannot be saved, and openpyxl raises ",[32,1273,1274],{},"ValueError: The only worksheet of a workbook cannot be hidden",[258,1276,267,1281,267,1284,267,1287,267,1290,267,1297,267,1305,267,1311,267,1316,267,1323,267,1328,267,1334,267,1339,267,1343,267,1350,267,1356,267,1360,267,1364,267,1368,267,1371,267,1374,267,1377,267,1382,267,1389,267,1394,267,1397,267,1400,267,1404,267,1407,267,1411,267,1414,267,1417,267,1423,267,1428,267,1431,267,1435],{"viewBox":1277,"role":261,"ariaLabelledBy":1278,"xmlns":265,"style":266},"4 0 752 150",[1279,1280],"ss-loop-t","ss-loop-d",[269,1282,1283],{"id":1279},"One pass of the split loop, per sheet",[273,1285,1286],{"id":1280},"For each sheet the loop loads a fresh copy of the workbook, freezes formulas that point at other sheets using the cached values, removes the other sheets, drops dangling defined names, makes the sheet visible and saves it under a safe file name.",[277,1288],{"x":279,"y":280,"width":281,"height":1289,"fill":283},"150",[277,1291],{"x":286,"y":287,"width":1292,"height":1293,"rx":1294,"fill":1295,"stroke":1296,"style":293},"153.0","118.5","12","#e7ebef","var(--line,#cdd5e6)",[295,1298,1300],{"transform":1299},"translate(84.5,41.8) scale(1.000)",[299,1301],{"d":1302,"fill":302,"stroke":1303,"style":1304},"M6 3h9l4 4v14H6z M15 3v4h4 M9.5 11.5l4.5 6 M14 11.5l-4.5 6","var(--text,#172033)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[306,1306,1310],{"x":1307,"y":1308,"style":1309},"96.5","88.2","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Load fresh copy",[306,1312,1315],{"x":1307,"y":1313,"style":1314},"107.8","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","load_workbook(path)",[1317,1318],"circle",{"cx":314,"cy":1319,"r":1320,"fill":1321,"stroke":302,"style":1322},"32.0","11.0","#5b6780","stroke-width:0px",[306,1324,1327],{"x":314,"y":1325,"style":1326},"36.5","font-size:12px;font-weight:700;fill:#ffffff;text-anchor:middle","1",[37,1329],{"x1":1330,"y1":1331,"x2":1332,"y2":1331,"stroke":1333,"style":293},"178.0","75.2","200.0","var(--brand,#5b5cf0)",[1335,1336],"polygon",{"points":1337,"fill":1338},"204.0,75.2 195.0,80.2 195.0,70.2","#5b5cf0",[277,1340],{"x":1341,"y":287,"width":1292,"height":1293,"rx":1294,"fill":1342,"stroke":1333,"style":293},"209.0","#f0f4ff",[295,1344,1346],{"transform":1345},"translate(273.5,33.0) scale(1.000)",[299,1347],{"d":1348,"fill":302,"stroke":1349,"style":1304},"M9 8l-4 4 4 4 M15 8l4 4-4 4","var(--brand-strong,#4338ca)",[306,1351,1355],{"x":1352,"y":1353,"style":1354},"285.5","79.5","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Freeze",[306,1357,1359],{"x":1352,"y":1358,"style":1314},"99.0","cross-sheet formulas",[306,1361,1363],{"x":1352,"y":1362,"style":1314},"116.5","to values",[1317,1365],{"cx":1366,"cy":1319,"r":1320,"fill":1367,"stroke":302,"style":1322},"225.0","#4338ca",[306,1369,1370],{"x":1366,"y":1325,"style":1326},"2",[37,1372],{"x1":1373,"y1":1331,"x2":359,"y2":1331,"stroke":1333,"style":293},"367.0",[1335,1375],{"points":1376,"fill":1338},"393.0,75.2 384.0,80.2 384.0,70.2",[277,1378],{"x":1379,"y":287,"width":1292,"height":1293,"rx":1294,"fill":1380,"stroke":1381,"style":293},"398.0","#fdefd8","var(--gold,#b4740a)",[295,1383,1385],{"transform":1384},"translate(462.5,33.0) scale(1.000)",[299,1386],{"d":1387,"fill":302,"stroke":1388,"style":1304},"M4 7h16 M10 11v6 M14 11v6 M6 7l1 13h10l1-13 M9 7V4h6v3","var(--gold-ink,#7a4e06)",[306,1390,1393],{"x":1391,"y":1353,"style":1392},"474.5","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Remove",[306,1395,1396],{"x":1391,"y":1358,"style":1314},"other sheets and",[306,1398,1399],{"x":1391,"y":1362,"style":1314},"dangling names",[1317,1401],{"cx":1402,"cy":1319,"r":1320,"fill":1403,"stroke":302,"style":1322},"414.0","#8a5808",[306,1405,1406],{"x":1402,"y":1325,"style":1326},"3",[37,1408],{"x1":1409,"y1":1331,"x2":1410,"y2":1331,"stroke":1333,"style":293},"556.0","578.0",[1335,1412],{"points":1413,"fill":1338},"582.0,75.2 573.0,80.2 573.0,70.2",[277,1415],{"x":1416,"y":287,"width":1292,"height":1293,"rx":1294,"fill":291,"stroke":292,"style":293},"587.0",[295,1418,1420],{"transform":1419},"translate(651.5,41.8) scale(1.000)",[299,1421],{"d":1422,"fill":302,"stroke":303,"style":1304},"M6 3h9l4 4v14H6z M15 3v4h4",[306,1424,1427],{"x":1425,"y":1308,"style":1426},"663.5","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Save",[306,1429,1430],{"x":1425,"y":1313,"style":1314},"regions - South.xlsx",[1317,1432],{"cx":1433,"cy":1319,"r":1320,"fill":1434,"stroke":302,"style":1322},"603.0","#0b6157",[306,1436,279],{"x":1433,"y":1325,"style":1326},[20,1438,1440],{"id":1439},"step-5-check-the-outputs","Step 5 — Check the outputs",[10,1442,1443],{},"Open each file and confirm it has one sheet, no formulas that reach outside it, and no defined names that point at missing sheets:",[25,1445,1447],{"className":96,"code":1446,"language":98,"meta":30,"style":30},"for f in sorted(Path(\"split\").glob(\"*.xlsx\")):\n    wb = load_workbook(f)\n    ws = wb.active\n    leftovers = [c.coordinate for row in ws.iter_rows() for c in row\n                 if isinstance(c.value, str) and c.value.startswith(\"=\") and \"!\" in c.value]\n    print(f.name, wb.sheetnames, \"gross C2 =\", ws[\"C2\"].value, \"| cross-sheet formulas:\", leftovers,\n          \"| names:\", list(wb.defined_names))\n",[32,1448,1449,1473,1483,1493,1522,1554,1578],{"__ignoreMap":30},[35,1450,1451,1453,1455,1457,1460,1463,1465,1468,1471],{"class":37,"line":38},[35,1452,147],{"class":105},[35,1454,1247],{"class":109},[35,1456,153],{"class":105},[35,1458,1459],{"class":210}," sorted",[35,1461,1462],{"class":109},"(Path(",[35,1464,968],{"class":45},[35,1466,1467],{"class":109},").glob(",[35,1469,1470],{"class":45},"\"*.xlsx\"",[35,1472,986],{"class":109},[35,1474,1475,1478,1480],{"class":37,"line":119},[35,1476,1477],{"class":109},"    wb ",[35,1479,132],{"class":105},[35,1481,1482],{"class":109}," load_workbook(f)\n",[35,1484,1485,1488,1490],{"class":37,"line":126},[35,1486,1487],{"class":109},"    ws ",[35,1489,132],{"class":105},[35,1491,1492],{"class":109}," wb.active\n",[35,1494,1495,1498,1500,1503,1505,1507,1509,1512,1514,1517,1519],{"class":37,"line":144},[35,1496,1497],{"class":109},"    leftovers ",[35,1499,132],{"class":105},[35,1501,1502],{"class":109}," [c.coordinate ",[35,1504,147],{"class":105},[35,1506,507],{"class":109},[35,1508,153],{"class":105},[35,1510,1511],{"class":109}," ws.iter_rows() ",[35,1513,147],{"class":105},[35,1515,1516],{"class":109}," c ",[35,1518,153],{"class":105},[35,1520,1521],{"class":109}," row\n",[35,1523,1524,1527,1529,1532,1534,1536,1538,1541,1543,1545,1547,1549,1551],{"class":37,"line":159},[35,1525,1526],{"class":105},"                 if",[35,1528,533],{"class":210},[35,1530,1531],{"class":109},"(c.value, ",[35,1533,539],{"class":210},[35,1535,542],{"class":109},[35,1537,545],{"class":105},[35,1539,1540],{"class":109}," c.value.startswith(",[35,1542,551],{"class":45},[35,1544,542],{"class":109},[35,1546,545],{"class":105},[35,1548,1139],{"class":45},[35,1550,1142],{"class":105},[35,1552,1553],{"class":109}," c.value]\n",[35,1555,1556,1558,1561,1564,1567,1569,1572,1575],{"class":37,"line":176},[35,1557,925],{"class":210},[35,1559,1560],{"class":109},"(f.name, wb.sheetnames, ",[35,1562,1563],{"class":45},"\"gross C2 =\"",[35,1565,1566],{"class":109},", ws[",[35,1568,223],{"class":45},[35,1570,1571],{"class":109},"].value, ",[35,1573,1574],{"class":45},"\"| cross-sheet formulas:\"",[35,1576,1577],{"class":109},", leftovers,\n",[35,1579,1580,1583,1585,1588],{"class":37,"line":182},[35,1581,1582],{"class":45},"          \"| names:\"",[35,1584,62],{"class":109},[35,1586,1587],{"class":210},"list",[35,1589,1590],{"class":109},"(wb.defined_names))\n",[258,1592,267,1597,267,1600,267,1603,267,1606,267,1611,267,1616,267,1620,267,1624,267,1627,267,1632,267,1637,267,1643,267,1648,267,1651,267,1654,267,1657,267,1662,267,1665,267,1668,267,1671,267,1674,267,1677,267,1682,267,1686,267,1689,267,1692],{"viewBox":1593,"role":261,"ariaLabelledBy":1594,"xmlns":265,"style":266},"4 0 752 332",[1595,1596],"ss-out-t","ss-out-d",[269,1598,1599],{"id":1595},"One source workbook, three regional files",[273,1601,1602],{"id":1596},"regions.xlsx on the left fans out to three files, regions - North - East.xlsx, regions - South.xlsx and regions - West -pilot-.xlsx. The hidden Settings sheet and the Lists sheet are not exported.",[277,1604],{"x":279,"y":280,"width":281,"height":1605,"fill":283},"332",[277,1607],{"x":286,"y":1608,"width":1609,"height":1610,"rx":1294,"fill":1342,"stroke":1333,"style":293},"110.8","220.0","110.5",[295,1612,1614],{"transform":1613},"translate(118.0,123.8) scale(1.000)",[299,1615],{"d":1302,"fill":302,"stroke":1349,"style":1304},[306,1617,57],{"x":1618,"y":1619,"style":1354},"130.0","170.2",[306,1621,1623],{"x":1618,"y":1622,"style":1314},"189.8","3 regional sheets + Settings +",[306,1625,77],{"x":1618,"y":1626,"style":1314},"207.2",[277,1628],{"x":1629,"y":287,"width":1630,"height":1631,"rx":1294,"fill":291,"stroke":292,"style":293},"490.0","250.0","92.0",[295,1633,1635],{"transform":1634},"translate(603.0,29.0) scale(1.000)",[299,1636],{"d":1422,"fill":302,"stroke":303,"style":1304},[306,1638,1642],{"x":1639,"y":1640,"style":1641},"615.0","75.0","font-size:13px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","regions - North - East.xlsx",[306,1644,1647],{"x":1639,"y":1645,"style":1646},"94.0","font-size:11px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","gross values frozen",[299,1649],{"d":1650,"fill":302,"stroke":1333,"style":293},"M244.0,166.0 C364.0,166.0 364.0,62.0 480.0,62.0",[1335,1652],{"points":1653,"fill":1338},"484.0,62.0 475.0,67.0 475.0,57.0",[277,1655],{"x":1629,"y":1656,"width":1630,"height":1631,"rx":1294,"fill":291,"stroke":292,"style":293},"120.0",[295,1658,1660],{"transform":1659},"translate(603.0,133.0) scale(1.000)",[299,1661],{"d":1422,"fill":302,"stroke":303,"style":1304},[306,1663,1430],{"x":1639,"y":1664,"style":1641},"179.0",[306,1666,1647],{"x":1639,"y":1667,"style":1646},"198.0",[299,1669],{"d":1670,"fill":302,"stroke":1333,"style":293},"M244.0,166.0 C364.0,166.0 364.0,166.0 480.0,166.0",[1335,1672],{"points":1673,"fill":1338},"484.0,166.0 475.0,171.0 475.0,161.0",[277,1675],{"x":1629,"y":1676,"width":1630,"height":1631,"rx":1294,"fill":291,"stroke":292,"style":293},"224.0",[295,1678,1680],{"transform":1679},"translate(603.0,237.0) scale(1.000)",[299,1681],{"d":1422,"fill":302,"stroke":303,"style":1304},[306,1683,1685],{"x":1639,"y":1684,"style":1641},"283.0","regions - West -pilot-.xlsx",[306,1687,1647],{"x":1639,"y":1688,"style":1646},"302.0",[299,1690],{"d":1691,"fill":302,"stroke":1333,"style":293},"M244.0,166.0 C364.0,166.0 364.0,270.0 480.0,270.0",[1335,1693],{"points":1694,"fill":1338},"484.0,270.0 475.0,275.0 475.0,265.0",[10,1696,1697,1698,1701],{},"Each file holds one visible sheet with its formatting — the header fill and the ",[32,1699,1700],{},"#,##0.00"," format on the gross column came through untouched — gross amounts as numbers, and no dangling names. A check like this is worth keeping in the script itself: it costs milliseconds and catches the day someone adds a new cross-sheet lookup to the template.",[20,1703,1705],{"id":1704},"step-6-other-ways-to-split","Step 6 — Other ways to split",[10,1707,1708,1712,1713,1716,1717,1720],{},[1709,1710,1711],"strong",{},"Values only, with pandas."," If formatting does not matter, ",[32,1714,1715],{},"pd.read_excel(path, sheet_name=None)"," returns every sheet as a DataFrame, and each can be written with ",[32,1718,1719],{},"to_excel",". The output has no styles, no widths and no formulas at all — every formula becomes its cached value automatically, which sidesteps Step 2.",[25,1722,1724],{"className":96,"code":1723,"language":98,"meta":30,"style":30},"import pandas as pd\n\nfor name, df in pd.read_excel(\"regions.xlsx\", sheet_name=None).items():\n    if name not in (\"Settings\", \"Lists\"):\n        df.to_excel(Path(\"split\") \u002F file_name(name, prefix=\"values\"), index=False)\nprint(sorted(p.name for p in Path(\"split\").glob(\"values*\")))\n",[32,1725,1726,1739,1743,1770,1791,1825],{"__ignoreMap":30},[35,1727,1728,1730,1733,1736],{"class":37,"line":38},[35,1729,113],{"class":105},[35,1731,1732],{"class":109}," pandas ",[35,1734,1735],{"class":105},"as",[35,1737,1738],{"class":109}," pd\n",[35,1740,1741],{"class":37,"line":119},[35,1742,123],{"emptyLinePlaceholder":122},[35,1744,1745,1747,1750,1752,1755,1757,1759,1762,1764,1767],{"class":37,"line":126},[35,1746,147],{"class":105},[35,1748,1749],{"class":109}," name, df ",[35,1751,153],{"class":105},[35,1753,1754],{"class":109}," pd.read_excel(",[35,1756,138],{"class":45},[35,1758,62],{"class":109},[35,1760,1761],{"class":628},"sheet_name",[35,1763,132],{"class":105},[35,1765,1766],{"class":210},"None",[35,1768,1769],{"class":109},").items():\n",[35,1771,1772,1774,1776,1778,1780,1783,1785,1787,1789],{"class":37,"line":144},[35,1773,162],{"class":105},[35,1775,150],{"class":109},[35,1777,1152],{"class":105},[35,1779,1142],{"class":105},[35,1781,1782],{"class":109}," (",[35,1784,978],{"class":45},[35,1786,62],{"class":109},[35,1788,983],{"class":45},[35,1790,785],{"class":109},[35,1792,1793,1796,1798,1800,1802,1805,1807,1809,1812,1815,1818,1820,1823],{"class":37,"line":159},[35,1794,1795],{"class":109},"        df.to_excel(Path(",[35,1797,968],{"class":45},[35,1799,542],{"class":109},[35,1801,1211],{"class":105},[35,1803,1804],{"class":109}," file_name(name, ",[35,1806,873],{"class":628},[35,1808,132],{"class":105},[35,1810,1811],{"class":45},"\"values\"",[35,1813,1814],{"class":109},"), ",[35,1816,1817],{"class":628},"index",[35,1819,132],{"class":105},[35,1821,1822],{"class":210},"False",[35,1824,141],{"class":109},[35,1826,1827,1829,1831,1834,1837,1839,1842,1844,1847,1849,1851,1854],{"class":37,"line":176},[35,1828,211],{"class":210},[35,1830,644],{"class":109},[35,1832,1833],{"class":210},"sorted",[35,1835,1836],{"class":109},"(p.name ",[35,1838,147],{"class":105},[35,1840,1841],{"class":109}," p ",[35,1843,153],{"class":105},[35,1845,1846],{"class":109}," Path(",[35,1848,968],{"class":45},[35,1850,1467],{"class":109},[35,1852,1853],{"class":45},"\"values*\"",[35,1855,1856],{"class":109},")))\n",[10,1858,1859,1862,1863,1867,1868,1871,1872,1875,1876,1879,1880,18],{},[1709,1860,1861],{},"Full fidelity, through Excel."," openpyxl does not carry charts, images or form controls across a load-and-save, as listed in ",[14,1864,1866],{"href":1865},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fwhat-openpyxl-loses-when-saving-an-existing-workbook\u002F","What openpyxl Loses When Saving an Existing Workbook",". On Windows with Excel installed, ",[32,1869,1870],{},"sheet.Copy()"," through win32com creates a new workbook containing an exact copy of the sheet, charts included, and ",[32,1873,1874],{},"SaveAs"," writes it; cross-sheet formulas then point back at the source file as external links, so break them with ",[32,1877,1878],{},"wb.BreakLink"," or paste values afterwards. See ",[14,1881,1883],{"href":1882},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002F","Automating Excel with COM and pywin32",[20,1885,1887],{"id":1886},"common-pitfalls","Common pitfalls",[1889,1890,1891,1898,1910,1916,1926],"ul",{},[1892,1893,1894,1897],"li",{},[1709,1895,1896],{},"Dangling references."," Deleting sheets does not update formulas or defined names; freeze or remove them.",[1892,1899,1900,1903,1904,1906,1907,1909],{},[1709,1901,1902],{},"No cached values."," ",[32,1905,413],{}," returns ",[32,1908,1766],{}," for formulas in files that no application has calculated; recalculate first.",[1892,1911,1912,1915],{},[1709,1913,1914],{},"Hidden sheets."," The only sheet in a workbook must be visible.",[1892,1917,1918,1921,1922,1925],{},[1709,1919,1920],{},"Illegal file names."," Replace ",[32,1923,1924],{},"\u003C > : \" \u002F \\ | ? *"," and strip trailing dots and spaces.",[1892,1927,1928,1931],{},[1709,1929,1930],{},"Charts and images."," openpyxl drops them on save; use the COM route when they matter.",[20,1933,1935],{"id":1934},"conclusion","Conclusion",[10,1937,1938],{},"To save each sheet as its own file, load a fresh copy of the workbook per sheet, replace formulas that reach into other sheets with their cached values, delete the other sheets, remove defined names that would dangle, make the sheet visible and save it under a cleaned file name — then check each output. Use pandas when only the values matter, and Excel through COM when charts and images must come along.",[20,1940,1942],{"id":1941},"frequently-asked-questions","Frequently asked questions",[10,1944,1945,1948],{},[1709,1946,1947],{},"How do I split an Excel workbook into separate files per sheet with Python?","\nFor each sheet, load the workbook with openpyxl, remove every other sheet with wb.remove(), and save the result under a new name. Fix cross-sheet formulas and defined names first so the new files do not show #REF! errors.",[10,1950,1951,1954],{},[1709,1952,1953],{},"Why do my split files show #REF! errors?","\nFormulas such as =B2*Settings!B1 still refer to sheets that were removed. openpyxl does not rewrite them. Replace those formulas with their cached values, loaded with data_only=True, before removing the other sheets.",[10,1956,1957,1960],{},[1709,1958,1959],{},"Why does openpyxl say the only worksheet cannot be hidden?","\nThe sheet you kept was hidden in the source workbook. A workbook needs at least one visible sheet, so set ws.sheet_state = \"visible\" before saving.",[10,1962,1963,1966],{},[1709,1964,1965],{},"Does splitting with openpyxl keep charts?","\nNo. openpyxl does not preserve charts and images when it loads and saves an existing workbook. Use Excel through win32com (sheet.Copy and SaveAs) when charts must be kept.",[20,1968,1970],{"id":1969},"related","Related",[1889,1972,1973,1979,1986,1993],{},[1892,1974,1975,1976,1978],{},"Up one level: ",[14,1977,17],{"href":16}," — reading, combining and splitting sheets.",[1892,1980,1981,1985],{},[14,1982,1984],{"href":1983},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsplit-one-excel-sheet-into-multiple-files-by-value\u002F","Split One Excel Sheet into Multiple Files by Value"," — splitting rows rather than sheets.",[1892,1987,1988,1992],{},[14,1989,1991],{"href":1990},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fmerge-workbooks-into-one-file-with-a-sheet-per-source\u002F","Merge Workbooks into One File with a Sheet per Source"," — the reverse operation.",[1892,1994,1995,1999],{},[14,1996,1998],{"href":1997},"\u002Fautomating-reporting-workflows\u002Femailing-excel-reports-with-smtplib\u002Fsend-each-recipient-their-own-excel-report\u002F","Send Each Recipient Their Own Excel Report"," — delivering the split files.",[2001,2002,2003],"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 .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .s_b0D, html code.shiki .s_b0D{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":30,"searchDepth":119,"depth":119,"links":2005},[2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016],{"id":22,"depth":119,"text":23},{"id":89,"depth":119,"text":90},{"id":406,"depth":119,"text":407},{"id":722,"depth":119,"text":723},{"id":944,"depth":119,"text":945},{"id":1439,"depth":119,"text":1440},{"id":1704,"depth":119,"text":1705},{"id":1886,"depth":119,"text":1887},{"id":1934,"depth":119,"text":1935},{"id":1941,"depth":119,"text":1942},{"id":1969,"depth":119,"text":1970},"2026-10-02","Split a workbook into one .xlsx file per sheet while keeping each sheet's formatting: remove the other sheets with openpyxl, freeze formulas that point at sheets that will no longer exist, drop defined names that would dangle, make hidden sheets visible, build safe file names, and know when a values-only split with pandas or a full-fidelity split through Excel is the better tool.","md",[2021,2023,2025,2027],{"q":1947,"a":2022},"For each sheet, load the workbook with openpyxl, remove every other sheet with wb.remove(), and save the result under a new name. Fix cross-sheet formulas and defined names first so the new files do not show #REF! errors.",{"q":1953,"a":2024},"Formulas such as =B2*Settings!B1 still refer to sheets that were removed. openpyxl does not rewrite them. Replace those formulas with their cached values, loaded with data_only=True, before removing the other sheets.",{"q":1959,"a":2026},"The sheet you kept was hidden in the source workbook. A workbook needs at least one visible sheet, so set ws.sheet_state = \"visible\" before saving.",{"q":1965,"a":2028},"No. openpyxl does not preserve charts and images when it loads and saves an existing workbook. Use Excel through win32com (sheet.Copy and SaveAs) when charts must be kept.","save each sheet of a workbook as a separate file",null,{"breadcrumb":2032},[2033,2035,2038],{"name":2034,"item":1211},"Home",{"name":2036,"item":2037},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":17,"item":16},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsave-each-sheet-of-a-workbook-as-a-separate-file",{"title":2041,"description":2042},"Save Each Excel Sheet as a Separate File with Python","Split a workbook into one file per sheet with openpyxl, keeping formatting: delete the other sheets, replace cross-sheet formulas with their values, remove dangling defined names, handle hidden sheets and file names, plus pandas and win32com options.","save-each-sheet-of-a-workbook-as-a-separate-file","getting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsave-each-sheet-of-a-workbook-as-a-separate-file\u002Findex",[2046,2047],"sheets-and-files","openpyxl","how-to","QNe0WWJurKHoWHGgWs1CYVtVP3wl6ozS0ktFef2baiU",[2051,2055],{"title":2052,"path":2053,"stem":2054,"children":-1},"Rename, Reorder and Delete Excel Sheets with openpyxl","\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Frename-reorder-and-delete-excel-sheets-with-openpyxl","getting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Frename-reorder-and-delete-excel-sheets-with-openpyxl\u002Findex",{"title":2056,"path":2057,"stem":2058,"children":-1},"Search Every Sheet and Workbook in a Folder for a Value","\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsearch-every-sheet-and-workbook-for-a-value","getting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fsearch-every-sheet-and-workbook-for-a-value\u002Findex",[2060,2062],{"path":2061,"title":2036},"\u002Fgetting-started-with-python-excel-automation",{"path":2063,"title":17},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python",[],[2066,2069,2072,2075,2078,2081],{"path":2067,"title":2068,"kind":2048},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fconsolidate-timesheets-from-many-workbooks","Consolidate Timesheets from Many Workbooks with Python",{"path":2070,"title":2071,"kind":2048},"\u002Fadvanced-data-transformation-and-cleaning\u002Fextracting-data-from-messy-excel-sheets\u002Fcombine-sheets-with-different-layouts-into-one-table","Combine Sheets with Different Layouts into One Table",{"path":2073,"title":2074,"kind":2048},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmerging-and-joining-excel-dataframes\u002Fappend-new-rows-to-a-master-excel-file-without-duplicates","Append New Rows to a Master Excel File Without Duplicates",{"path":2076,"title":2077,"kind":2048},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmerging-and-joining-excel-dataframes\u002Fconcatenate-excel-sheets-with-different-columns","Concatenate Excel Sheets with Different Columns",{"path":2079,"title":2080,"kind":2048},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmerging-and-joining-excel-dataframes\u002Fmerge-excel-files-with-different-column-names","Merge Excel Files with Different Column Names in pandas",{"path":2082,"title":2083,"kind":2048},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmerging-and-joining-excel-dataframes\u002Fmerge-more-than-two-excel-files-on-a-key-column","Merge More Than Two Excel Files on a Key Column",1790972076250]