[{"data":1,"prerenderedAt":2058},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fread-all-sheets-from-an-excel-file-into-dataframes":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fread-all-sheets-from-an-excel-file-into-dataframes":2050},{"id":4,"title":5,"body":6,"dateModified":2017,"datePublished":2017,"description":2018,"extension":2019,"faq":2020,"meta":2031,"navigation":249,"path":2042,"seo":2043,"slug":2046,"stem":2047,"type":2048,"__hash__":2049},"docs\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fread-all-sheets-from-an-excel-file-into-dataframes\u002Findex.md","Read All Sheets from an Excel File into DataFrames",{"type":7,"value":8,"toc":2003},"minimark",[9,18,27,163,168,196,217,221,512,519,523,614,634,638,643,785,795,890,894,897,966,977,1030,1037,1103,1107,1124,1254,1278,1351,1363,1367,1370,1673,1676,1680,1839,1843,1849,1860,1864,1875,1879,1893,1915,1938,1947,1951,1954,1963,1966,1999],[10,11,12,13,17],"p",{},"A workbook with one sheet per month, per region or per site is one of the most common shapes in reporting, and pandas reads all of it in a single call — ",[14,15,16],"code",{},"sheet_name=None"," returns a dictionary keyed by sheet name rather than a single DataFrame.",[10,19,20,21,26],{},"The call is easy. What is worth knowing is when it is the wrong tool (a hundred-sheet workbook you only need two sheets from), how to avoid re-parsing the file on every read, and how to combine the sheets without losing track of which row came from where. This guide is part of ",[22,23,25],"a",{"href":24},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002F","Working with Multiple Excel Sheets in Python",".",[28,29,37,38,37,42,37,46,37,53,37,60,37,70,37,76,37,85,37,90,37,95,37,99,37,104,37,108,37,112,37,117,37,120,37,124,37,127,37,130,37,135,37,139,37,142,37,145,37,148,37,150,37,153,37,157,37,160],"svg",{"viewBox":30,"role":31,"ariaLabelledBy":32,"xmlns":35,"style":36},"0 0 740 236","img",[33,34],"ras-shape-t","ras-shape-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:740px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[39,40,41],"title",{"id":33},"What each sheet_name value returns",[43,44,45],"desc",{"id":34},"Passing a name or an index returns one DataFrame. Passing a list returns a dictionary containing only those sheets. Passing None returns a dictionary of every sheet in the workbook, keyed by sheet name in workbook order.",[47,48],"rect",{"x":49,"y":49,"width":50,"height":51,"fill":52},"0","740","236","#ffffff",[54,55,59],"text",{"x":56,"y":57,"style":58},"370","30","font-size:12.5px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","One argument decides the shape of what you get back",[47,61],{"x":62,"y":63,"width":64,"height":65,"rx":66,"fill":67,"stroke":68,"style":69},"16","50","228","160","14","#f0f2f5","var(--line,#cdd5e6)","stroke-width:2px",[54,71,75],{"x":72,"y":73,"style":74},"130","80","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","sheet_name=\"Jan\"",[47,77],{"x":78,"y":79,"width":80,"height":81,"rx":82,"fill":83,"stroke":84,"style":69},"52","98","156","42","8","#ebebfd","var(--brand,#5b5cf0)",[54,86,89],{"x":72,"y":87,"style":88},"124","font-size:11.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","one DataFrame",[54,91,94],{"x":72,"y":92,"style":93},"168","font-size:11px;fill:var(--muted,#5b6780);text-anchor:middle","an index works too:",[54,96,98],{"x":72,"y":97,"style":93},"186","sheet_name=0 is the first sheet",[47,100],{"x":101,"y":63,"width":64,"height":65,"rx":66,"fill":102,"stroke":103,"style":69},"256","#fdefd8","var(--gold,#b4740a)",[54,105,107],{"x":56,"y":73,"style":106},"font-size:12.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","sheet_name=[\"Jan\",\"Feb\"]",[47,109],{"x":110,"y":79,"width":111,"height":81,"rx":82,"fill":52,"stroke":103},"292","72",[54,113,116],{"x":114,"y":87,"style":115},"328","font-size:11px;fill:var(--text,#172033);text-anchor:middle","\"Jan\"",[47,118],{"x":119,"y":79,"width":111,"height":81,"rx":82,"fill":52,"stroke":103},"376",[54,121,123],{"x":122,"y":87,"style":115},"412","\"Feb\"",[54,125,126],{"x":56,"y":92,"style":93},"a dictionary with just",[54,128,129],{"x":56,"y":97,"style":93},"the sheets you named",[47,131],{"x":132,"y":63,"width":64,"height":65,"rx":66,"fill":133,"stroke":134,"style":69},"496","#d9f4f1","var(--teal,#0f9488)",[54,136,16],{"x":137,"y":73,"style":138},"610","font-size:12.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle",[47,140],{"x":141,"y":79,"width":78,"height":81,"rx":82,"fill":52,"stroke":134},"524",[54,143,116],{"x":144,"y":87,"style":115},"550",[47,146],{"x":147,"y":79,"width":78,"height":81,"rx":82,"fill":52,"stroke":134},"584",[54,149,123],{"x":137,"y":87,"style":115},[47,151],{"x":152,"y":79,"width":78,"height":81,"rx":82,"fill":52,"stroke":134},"644",[54,154,156],{"x":155,"y":87,"style":115},"670","\"Mar\"",[54,158,159],{"x":137,"y":92,"style":93},"every sheet, in workbook",[54,161,162],{"x":137,"y":97,"style":93},"order, keyed by name",[164,165,167],"h2",{"id":166},"prerequisites","Prerequisites",[169,170,175],"pre",{"className":171,"code":172,"language":173,"meta":174,"style":174},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl\n","bash","",[14,176,177],{"__ignoreMap":174},[178,179,182,186,190,193],"span",{"class":180,"line":181},"line",1,[178,183,185],{"class":184},"sMTad","pip",[178,187,189],{"class":188},"srMev"," install",[178,191,192],{"class":188}," pandas",[178,194,195],{"class":188}," openpyxl\n",[10,197,198,199,202,203,206,207,210,211,213,214,216],{},"openpyxl is the engine pandas uses for ",[14,200,201],{},".xlsx",". Legacy ",[14,204,205],{},".xls"," files need ",[14,208,209],{},"xlrd"," instead, and the modern ",[14,212,209],{}," no longer reads ",[14,215,201],{}," at all — if you are on a mixed pile of files, convert the old ones first.",[164,218,220],{"id":219},"step-1-build-a-multi-sheet-workbook-to-read","Step 1: Build a multi-sheet workbook to read",[169,222,226],{"className":223,"code":224,"language":225,"meta":174,"style":174},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\nmonths = {\n    \"Jan\": pd.DataFrame({\"region\": [\"North\", \"South\"], \"amount\": [120.0, 180.5]}),\n    \"Feb\": pd.DataFrame({\"region\": [\"North\", \"South\"], \"amount\": [131.25, 175.0]}),\n    \"Mar\": pd.DataFrame({\"region\": [\"North\", \"South\", \"East\"],\n                         \"amount\": [140.0, 190.75, 60.0]}),\n}\n\nwith pd.ExcelWriter(\"year.xlsx\", engine=\"openpyxl\") as writer:\n    for name, frame in months.items():\n        frame.to_excel(writer, sheet_name=name, index=False)\n    pd.DataFrame({\"note\": [\"internal working sheet\"]}).to_excel(\n        writer, sheet_name=\"_scratch\", index=False)\n","python",[14,227,228,244,251,263,307,341,367,390,396,401,432,447,472,489],{"__ignoreMap":174},[178,229,230,234,238,241],{"class":180,"line":181},[178,231,233],{"class":232},"s-kum","import",[178,235,237],{"class":236},"skGVy"," pandas ",[178,239,240],{"class":232},"as",[178,242,243],{"class":236}," pd\n",[178,245,247],{"class":180,"line":246},2,[178,248,250],{"emptyLinePlaceholder":249},true,"\n",[178,252,254,257,260],{"class":180,"line":253},3,[178,255,256],{"class":236},"months ",[178,258,259],{"class":232},"=",[178,261,262],{"class":236}," {\n",[178,264,266,269,272,275,278,281,284,287,290,293,295,299,301,304],{"class":180,"line":265},4,[178,267,268],{"class":188},"    \"Jan\"",[178,270,271],{"class":236},": pd.DataFrame({",[178,273,274],{"class":188},"\"region\"",[178,276,277],{"class":236},": [",[178,279,280],{"class":188},"\"North\"",[178,282,283],{"class":236},", ",[178,285,286],{"class":188},"\"South\"",[178,288,289],{"class":236},"], ",[178,291,292],{"class":188},"\"amount\"",[178,294,277],{"class":236},[178,296,298],{"class":297},"sP0c6","120.0",[178,300,283],{"class":236},[178,302,303],{"class":297},"180.5",[178,305,306],{"class":236},"]}),\n",[178,308,310,313,315,317,319,321,323,325,327,329,331,334,336,339],{"class":180,"line":309},5,[178,311,312],{"class":188},"    \"Feb\"",[178,314,271],{"class":236},[178,316,274],{"class":188},[178,318,277],{"class":236},[178,320,280],{"class":188},[178,322,283],{"class":236},[178,324,286],{"class":188},[178,326,289],{"class":236},[178,328,292],{"class":188},[178,330,277],{"class":236},[178,332,333],{"class":297},"131.25",[178,335,283],{"class":236},[178,337,338],{"class":297},"175.0",[178,340,306],{"class":236},[178,342,344,347,349,351,353,355,357,359,361,364],{"class":180,"line":343},6,[178,345,346],{"class":188},"    \"Mar\"",[178,348,271],{"class":236},[178,350,274],{"class":188},[178,352,277],{"class":236},[178,354,280],{"class":188},[178,356,283],{"class":236},[178,358,286],{"class":188},[178,360,283],{"class":236},[178,362,363],{"class":188},"\"East\"",[178,365,366],{"class":236},"],\n",[178,368,370,373,375,378,380,383,385,388],{"class":180,"line":369},7,[178,371,372],{"class":188},"                         \"amount\"",[178,374,277],{"class":236},[178,376,377],{"class":297},"140.0",[178,379,283],{"class":236},[178,381,382],{"class":297},"190.75",[178,384,283],{"class":236},[178,386,387],{"class":297},"60.0",[178,389,306],{"class":236},[178,391,393],{"class":180,"line":392},8,[178,394,395],{"class":236},"}\n",[178,397,399],{"class":180,"line":398},9,[178,400,250],{"emptyLinePlaceholder":249},[178,402,404,407,410,413,415,419,421,424,427,429],{"class":180,"line":403},10,[178,405,406],{"class":232},"with",[178,408,409],{"class":236}," pd.ExcelWriter(",[178,411,412],{"class":188},"\"year.xlsx\"",[178,414,283],{"class":236},[178,416,418],{"class":417},"sa561","engine",[178,420,259],{"class":232},[178,422,423],{"class":188},"\"openpyxl\"",[178,425,426],{"class":236},") ",[178,428,240],{"class":232},[178,430,431],{"class":236}," writer:\n",[178,433,435,438,441,444],{"class":180,"line":434},11,[178,436,437],{"class":232},"    for",[178,439,440],{"class":236}," name, frame ",[178,442,443],{"class":232},"in",[178,445,446],{"class":236}," months.items():\n",[178,448,450,453,456,458,461,464,466,469],{"class":180,"line":449},12,[178,451,452],{"class":236},"        frame.to_excel(writer, ",[178,454,455],{"class":417},"sheet_name",[178,457,259],{"class":232},[178,459,460],{"class":236},"name, ",[178,462,463],{"class":417},"index",[178,465,259],{"class":232},[178,467,468],{"class":297},"False",[178,470,471],{"class":236},")\n",[178,473,475,478,481,483,486],{"class":180,"line":474},13,[178,476,477],{"class":236},"    pd.DataFrame({",[178,479,480],{"class":188},"\"note\"",[178,482,277],{"class":236},[178,484,485],{"class":188},"\"internal working sheet\"",[178,487,488],{"class":236},"]}).to_excel(\n",[178,490,492,495,497,499,502,504,506,508,510],{"class":180,"line":491},14,[178,493,494],{"class":236},"        writer, ",[178,496,455],{"class":417},[178,498,259],{"class":232},[178,500,501],{"class":188},"\"_scratch\"",[178,503,283],{"class":236},[178,505,463],{"class":417},[178,507,259],{"class":232},[178,509,468],{"class":297},[178,511,471],{"class":236},[10,513,514,515,518],{},"The ",[14,516,517],{},"_scratch"," sheet is deliberate — real workbooks always have one, and it is the reason \"read every sheet\" is rarely the whole answer.",[164,520,522],{"id":521},"step-2-read-every-sheet-at-once","Step 2: Read every sheet at once",[169,524,526],{"className":223,"code":525,"language":225,"meta":174,"style":174},"sheets = pd.read_excel(\"year.xlsx\", sheet_name=None)\n\nprint(type(sheets))                 # \u003Cclass 'dict'>\nprint(list(sheets))                 # ['Jan', 'Feb', 'Mar', '_scratch']\nprint(sheets[\"Feb\"])\n#   region  amount\n# 0  North  131.25\n# 1  South  175.00\n",[14,527,528,551,555,573,587,599,604,609],{"__ignoreMap":174},[178,529,530,533,535,538,540,542,544,546,549],{"class":180,"line":181},[178,531,532],{"class":236},"sheets ",[178,534,259],{"class":232},[178,536,537],{"class":236}," pd.read_excel(",[178,539,412],{"class":188},[178,541,283],{"class":236},[178,543,455],{"class":417},[178,545,259],{"class":232},[178,547,548],{"class":297},"None",[178,550,471],{"class":236},[178,552,553],{"class":180,"line":246},[178,554,250],{"emptyLinePlaceholder":249},[178,556,557,560,563,566,569],{"class":180,"line":253},[178,558,559],{"class":297},"print",[178,561,562],{"class":236},"(",[178,564,565],{"class":297},"type",[178,567,568],{"class":236},"(sheets))                 ",[178,570,572],{"class":571},"s-wDw","# \u003Cclass 'dict'>\n",[178,574,575,577,579,582,584],{"class":180,"line":265},[178,576,559],{"class":297},[178,578,562],{"class":236},[178,580,581],{"class":297},"list",[178,583,568],{"class":236},[178,585,586],{"class":571},"# ['Jan', 'Feb', 'Mar', '_scratch']\n",[178,588,589,591,594,596],{"class":180,"line":309},[178,590,559],{"class":297},[178,592,593],{"class":236},"(sheets[",[178,595,123],{"class":188},[178,597,598],{"class":236},"])\n",[178,600,601],{"class":180,"line":343},[178,602,603],{"class":571},"#   region  amount\n",[178,605,606],{"class":180,"line":369},[178,607,608],{"class":571},"# 0  North  131.25\n",[178,610,611],{"class":180,"line":392},[178,612,613],{"class":571},"# 1  South  175.00\n",[10,615,616,617,620,621,283,624,283,627,283,630,633],{},"The dictionary preserves workbook order, and each value is an ordinary DataFrame. Every other ",[14,618,619],{},"read_excel"," argument still applies and is passed to each sheet — ",[14,622,623],{},"dtype",[14,625,626],{},"skiprows",[14,628,629],{},"usecols",[14,631,632],{},"na_values"," — which is useful when the sheets share a layout and unhelpful when they do not.",[164,635,637],{"id":636},"step-3-open-the-file-once-parse-many-times","Step 3: Open the file once, parse many times",[10,639,640,642],{},[14,641,619],{}," parses the whole file on every call. Calling it in a loop over sheet names re-reads the workbook once per sheet, which on a large file is the difference between one second and thirty:",[169,644,646],{"className":223,"code":645,"language":225,"meta":174,"style":174},"with pd.ExcelFile(\"year.xlsx\") as xls:\n    print(xls.sheet_names)                       # cheap: no data parsed yet\n\n    wanted = [s for s in xls.sheet_names if not s.startswith(\"_\")]\n    frames = {name: xls.parse(name, dtype={\"region\": str}) for name in wanted}\n\nprint({name: len(f) for name, f in frames.items()})\n# {'Jan': 2, 'Feb': 2, 'Mar': 3}\n",[14,647,648,664,675,679,715,753,757,780],{"__ignoreMap":174},[178,649,650,652,655,657,659,661],{"class":180,"line":181},[178,651,406],{"class":232},[178,653,654],{"class":236}," pd.ExcelFile(",[178,656,412],{"class":188},[178,658,426],{"class":236},[178,660,240],{"class":232},[178,662,663],{"class":236}," xls:\n",[178,665,666,669,672],{"class":180,"line":246},[178,667,668],{"class":297},"    print",[178,670,671],{"class":236},"(xls.sheet_names)                       ",[178,673,674],{"class":571},"# cheap: no data parsed yet\n",[178,676,677],{"class":180,"line":253},[178,678,250],{"emptyLinePlaceholder":249},[178,680,681,684,686,689,692,695,697,700,703,706,709,712],{"class":180,"line":265},[178,682,683],{"class":236},"    wanted ",[178,685,259],{"class":232},[178,687,688],{"class":236}," [s ",[178,690,691],{"class":232},"for",[178,693,694],{"class":236}," s ",[178,696,443],{"class":232},[178,698,699],{"class":236}," xls.sheet_names ",[178,701,702],{"class":232},"if",[178,704,705],{"class":232}," not",[178,707,708],{"class":236}," s.startswith(",[178,710,711],{"class":188},"\"_\"",[178,713,714],{"class":236},")]\n",[178,716,717,720,722,725,727,729,732,734,737,740,743,745,748,750],{"class":180,"line":309},[178,718,719],{"class":236},"    frames ",[178,721,259],{"class":232},[178,723,724],{"class":236}," {name: xls.parse(name, ",[178,726,623],{"class":417},[178,728,259],{"class":232},[178,730,731],{"class":236},"{",[178,733,274],{"class":188},[178,735,736],{"class":236},": ",[178,738,739],{"class":297},"str",[178,741,742],{"class":236},"}) ",[178,744,691],{"class":232},[178,746,747],{"class":236}," name ",[178,749,443],{"class":232},[178,751,752],{"class":236}," wanted}\n",[178,754,755],{"class":180,"line":343},[178,756,250],{"emptyLinePlaceholder":249},[178,758,759,761,764,767,770,772,775,777],{"class":180,"line":369},[178,760,559],{"class":297},[178,762,763],{"class":236},"({name: ",[178,765,766],{"class":297},"len",[178,768,769],{"class":236},"(f) ",[178,771,691],{"class":232},[178,773,774],{"class":236}," name, f ",[178,776,443],{"class":232},[178,778,779],{"class":236}," frames.items()})\n",[178,781,782],{"class":180,"line":392},[178,783,784],{"class":571},"# {'Jan': 2, 'Feb': 2, 'Mar': 3}\n",[10,786,787,790,791,794],{},[14,788,789],{},"pd.ExcelFile"," also gives you ",[14,792,793],{},"sheet_names"," without reading any data, which is what makes the filtering above possible — you can decide which sheets are worth parsing before paying for them. Using it as a context manager closes the underlying file handle, which matters on Windows where an open handle blocks anything else from writing the file.",[28,796,37,801,37,804,37,807,37,810,37,816,37,823,37,826,37,829,37,833,37,835,37,839,37,844,37,848,37,852,37,855,37,859,37,862,37,866,37,869,37,873,37,875,37,878,37,880,37,883,37,887],{"viewBox":797,"role":31,"ariaLabelledBy":798,"xmlns":35,"style":36},"0 0 740 238",[799,800],"ras-parse-t","ras-parse-d",[39,802,803],{"id":799},"Repeated read_excel calls versus one ExcelFile",[43,805,806],{"id":800},"Calling read_excel once per sheet opens and parses the entire workbook each time, so the cost multiplies by the number of sheets. Opening one ExcelFile parses the workbook once and each parse call only reads the sheet you asked for.",[47,808],{"x":49,"y":49,"width":50,"height":809,"fill":52},"238",[54,811,815],{"x":812,"y":813,"style":814},"184","32","font-size:12.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","read_excel in a loop",[47,817],{"x":818,"y":78,"width":819,"height":57,"rx":820,"fill":821,"stroke":822,"style":69},"24","320","6","#fce9e9","var(--accent-ink,#be185d)",[54,824,825],{"x":812,"y":111,"style":115},"parse whole workbook → take \"Jan\"",[47,827],{"x":818,"y":828,"width":819,"height":57,"rx":820,"fill":821,"stroke":822,"style":69},"88",[54,830,832],{"x":812,"y":831,"style":115},"108","parse whole workbook → take \"Feb\"",[47,834],{"x":818,"y":87,"width":819,"height":57,"rx":820,"fill":821,"stroke":822,"style":69},[54,836,838],{"x":812,"y":837,"style":115},"144","parse whole workbook → take \"Mar\"",[54,840,843],{"x":812,"y":841,"style":842},"180","font-size:11.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","cost × number of sheets",[54,845,847],{"x":812,"y":846,"style":93},"204","on a 40-sheet workbook this is the whole runtime",[54,849,851],{"x":850,"y":813,"style":138},"556","one pd.ExcelFile",[47,853],{"x":854,"y":78,"width":819,"height":57,"rx":820,"fill":133,"stroke":134,"style":69},"396",[54,856,858],{"x":850,"y":111,"style":857},"font-size:11px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","open + parse the workbook once",[47,860],{"x":854,"y":828,"width":861,"height":57,"rx":820,"fill":52,"stroke":134},"150",[54,863,865],{"x":864,"y":831,"style":115},"471","parse(\"Jan\")",[47,867],{"x":868,"y":828,"width":861,"height":57,"rx":820,"fill":52,"stroke":134},"566",[54,870,872],{"x":871,"y":831,"style":115},"641","parse(\"Feb\")",[47,874],{"x":854,"y":87,"width":861,"height":57,"rx":820,"fill":52,"stroke":134},[54,876,877],{"x":864,"y":837,"style":115},"parse(\"Mar\")",[47,879],{"x":868,"y":87,"width":861,"height":57,"rx":820,"fill":67,"stroke":68},[54,881,882],{"x":871,"y":837,"style":93},"skip \"_scratch\"",[54,884,886],{"x":850,"y":841,"style":885},"font-size:11.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","one parse, then cheap reads",[54,888,889],{"x":850,"y":846,"style":93},"and sheet_names is available before any data is read",[164,891,893],{"id":892},"step-4-combine-the-sheets-keeping-the-source","Step 4: Combine the sheets, keeping the source",[10,895,896],{},"Stacking the sheets is one call, and the only decision is how to record which sheet each row came from:",[169,898,900],{"className":223,"code":899,"language":225,"meta":174,"style":174},"combined = pd.concat(frames, names=[\"month\", None]).reset_index(level=0)\nprint(combined.head())\n#   month region  amount\n# 0   Jan  North  120.00\n# 1   Jan  South  180.50\n# 2   Feb  North  131.25\n",[14,901,902,939,946,951,956,961],{"__ignoreMap":174},[178,903,904,907,909,912,915,917,920,923,925,927,930,933,935,937],{"class":180,"line":181},[178,905,906],{"class":236},"combined ",[178,908,259],{"class":232},[178,910,911],{"class":236}," pd.concat(frames, ",[178,913,914],{"class":417},"names",[178,916,259],{"class":232},[178,918,919],{"class":236},"[",[178,921,922],{"class":188},"\"month\"",[178,924,283],{"class":236},[178,926,548],{"class":297},[178,928,929],{"class":236},"]).reset_index(",[178,931,932],{"class":417},"level",[178,934,259],{"class":232},[178,936,49],{"class":297},[178,938,471],{"class":236},[178,940,941,943],{"class":180,"line":246},[178,942,559],{"class":297},[178,944,945],{"class":236},"(combined.head())\n",[178,947,948],{"class":180,"line":253},[178,949,950],{"class":571},"#   month region  amount\n",[178,952,953],{"class":180,"line":265},[178,954,955],{"class":571},"# 0   Jan  North  120.00\n",[178,957,958],{"class":180,"line":309},[178,959,960],{"class":571},"# 1   Jan  South  180.50\n",[178,962,963],{"class":180,"line":343},[178,964,965],{"class":571},"# 2   Feb  North  131.25\n",[10,967,968,969,972,973,976],{},"Passing the dictionary straight to ",[14,970,971],{},"concat"," uses its keys as an outer index level, which ",[14,974,975],{},"reset_index(level=0)"," then turns into an ordinary column. The alternative — assigning the column inside a loop — is equivalent and sometimes clearer:",[169,978,980],{"className":223,"code":979,"language":225,"meta":174,"style":174},"combined = pd.concat(\n    [frame.assign(month=name) for name, frame in frames.items()],\n    ignore_index=True,\n)\n",[14,981,982,991,1013,1026],{"__ignoreMap":174},[178,983,984,986,988],{"class":180,"line":181},[178,985,906],{"class":236},[178,987,259],{"class":232},[178,989,990],{"class":236}," pd.concat(\n",[178,992,993,996,999,1001,1004,1006,1008,1010],{"class":180,"line":246},[178,994,995],{"class":236},"    [frame.assign(",[178,997,998],{"class":417},"month",[178,1000,259],{"class":232},[178,1002,1003],{"class":236},"name) ",[178,1005,691],{"class":232},[178,1007,440],{"class":236},[178,1009,443],{"class":232},[178,1011,1012],{"class":236}," frames.items()],\n",[178,1014,1015,1018,1020,1023],{"class":180,"line":253},[178,1016,1017],{"class":417},"    ignore_index",[178,1019,259],{"class":232},[178,1021,1022],{"class":297},"True",[178,1024,1025],{"class":236},",\n",[178,1027,1028],{"class":180,"line":265},[178,1029,471],{"class":236},[10,1031,1032,1033,1036],{},"Either way, add the source column. A combined table with no record of which sheet a row came from cannot be checked against the original, and the first time a total looks wrong that is exactly what someone will want to do. Sheets whose columns differ align by name and fill ",[14,1034,1035],{},"NaN"," elsewhere, which is usually right — but check the column set first if the sheets were maintained by different people:",[169,1038,1040],{"className":223,"code":1039,"language":225,"meta":174,"style":174},"column_sets = {name: tuple(f.columns) for name, f in frames.items()}\nif len(set(column_sets.values())) > 1:\n    print(\"sheets disagree on columns:\", column_sets)\n",[14,1041,1042,1067,1091],{"__ignoreMap":174},[178,1043,1044,1047,1049,1052,1055,1058,1060,1062,1064],{"class":180,"line":181},[178,1045,1046],{"class":236},"column_sets ",[178,1048,259],{"class":232},[178,1050,1051],{"class":236}," {name: ",[178,1053,1054],{"class":297},"tuple",[178,1056,1057],{"class":236},"(f.columns) ",[178,1059,691],{"class":232},[178,1061,774],{"class":236},[178,1063,443],{"class":232},[178,1065,1066],{"class":236}," frames.items()}\n",[178,1068,1069,1071,1074,1076,1079,1082,1085,1088],{"class":180,"line":246},[178,1070,702],{"class":232},[178,1072,1073],{"class":297}," len",[178,1075,562],{"class":236},[178,1077,1078],{"class":297},"set",[178,1080,1081],{"class":236},"(column_sets.values())) ",[178,1083,1084],{"class":232},">",[178,1086,1087],{"class":297}," 1",[178,1089,1090],{"class":236},":\n",[178,1092,1093,1095,1097,1100],{"class":180,"line":253},[178,1094,668],{"class":297},[178,1096,562],{"class":236},[178,1098,1099],{"class":188},"\"sheets disagree on columns:\"",[178,1101,1102],{"class":236},", column_sets)\n",[164,1104,1106],{"id":1105},"step-4b-check-the-sheets-agree-before-you-trust-the-total","Step 4b: Check the sheets agree before you trust the total",[10,1108,1109,1110,1113,1114,1117,1118,1120,1121,1123],{},"Sheets that look alike rarely are. A month maintained by a different person acquires an extra column, loses one, or renames ",[14,1111,1112],{},"Amount"," to ",[14,1115,1116],{},"Net",". ",[14,1119,971],{}," aligns by name and fills the gaps with ",[14,1122,1035],{},", which is the right default and also the reason a quiet mismatch survives all the way to a total:",[28,1125,37,1130,37,1133,37,1136,37,1139,37,1142,37,1148,37,1154,37,1156,37,1159,37,1163,37,1167,37,1173,37,1178,37,1183,37,1186,37,1192,37,1195,37,1199,37,1202,37,1207,37,1209,37,1212,37,1214,37,1217,37,1219,37,1221,37,1224,37,1227,37,1229,37,1232,37,1236,37,1239,37,1243,37,1246,37,1250],{"viewBox":1126,"role":31,"ariaLabelledBy":1127,"xmlns":35,"style":36},"0 0 740 224",[1128,1129],"ras-align-t","ras-align-d",[39,1131,1132],{"id":1128},"What concat does when one sheet renamed a column",[43,1134,1135],{"id":1129},"January and February both have region and amount. March calls the same field net. Concatenating produces three columns, with amount empty for March's rows and net empty for the others, so a total over amount silently omits March entirely.",[47,1137],{"x":49,"y":49,"width":50,"height":1138,"fill":52},"224",[54,1140,1141],{"x":56,"y":57,"style":58},"March renamed one column, and nothing raised",[47,1143],{"x":818,"y":63,"width":1144,"height":1145,"rx":1146,"fill":1147},"136","26","4","#1f4e78",[54,1149,1153],{"x":1150,"y":1151,"style":1152},"92","68","font-size:10.5px;font-weight:700;fill:#ffffff;text-anchor:middle","Jan · region, amount",[47,1155],{"x":818,"y":73,"width":1144,"height":1145,"rx":1146,"fill":1147},[54,1157,1158],{"x":1150,"y":79,"style":1152},"Feb · region, amount",[47,1160],{"x":818,"y":1161,"width":1144,"height":1145,"rx":1146,"fill":1162},"110","#8a5808",[54,1164,1166],{"x":1150,"y":1165,"style":1152},"128","Mar · region, net",[180,1168],{"x1":1169,"y1":1170,"x2":1171,"y2":1170,"stroke":1172,"style":69},"166","93","200","var(--muted,#5b6780)",[1174,1175],"polygon",{"points":1176,"fill":1177},"204,93 194,88 194,98","#5b6780",[54,1179,971],{"x":1180,"y":1181,"style":1182},"178","82","font-size:10px;fill:var(--muted,#5b6780);text-anchor:middle",[47,1184],{"x":1185,"y":63,"width":72,"height":818,"fill":67,"stroke":68},"212",[54,1187,1191],{"x":1188,"y":1189,"style":1190},"277","67","font-size:10.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","amount",[47,1193],{"x":1194,"y":63,"width":72,"height":818,"fill":67,"stroke":68},"342",[54,1196,1198],{"x":1197,"y":1189,"style":1190},"407","net",[47,1200],{"x":1185,"y":1201,"width":72,"height":818,"fill":133,"stroke":68},"74",[54,1203,1206],{"x":1188,"y":1204,"style":1205},"91","font-size:10.5px;fill:var(--text,#172033);text-anchor:middle","120.00",[47,1208],{"x":1194,"y":1201,"width":72,"height":818,"fill":52,"stroke":68},[54,1210,1035],{"x":1197,"y":1204,"style":1211},"font-size:10.5px;fill:var(--muted,#5b6780);text-anchor:middle",[47,1213],{"x":1185,"y":79,"width":72,"height":818,"fill":133,"stroke":68},[54,1215,333],{"x":1188,"y":1216,"style":1205},"115",[47,1218],{"x":1194,"y":79,"width":72,"height":818,"fill":52,"stroke":68},[54,1220,1035],{"x":1197,"y":1216,"style":1211},[47,1222],{"x":1185,"y":1223,"width":72,"height":818,"fill":52,"stroke":68},"122",[54,1225,1035],{"x":1188,"y":1226,"style":1211},"139",[47,1228],{"x":1194,"y":1223,"width":72,"height":818,"fill":102,"stroke":68},[54,1230,1231],{"x":1197,"y":1226,"style":1205},"140.00",[47,1233],{"x":132,"y":63,"width":64,"height":1234,"rx":1235,"fill":821,"stroke":822,"style":69},"96","12",[54,1237,1238],{"x":137,"y":73,"style":842},"df[\"amount\"].sum()",[54,1240,1242],{"x":137,"y":1241,"style":115},"106","251.25, not 391.25",[54,1244,1245],{"x":137,"y":72,"style":93},"March is simply absent",[54,1247,1249],{"x":56,"y":841,"style":1248},"font-size:11.5px;fill:var(--text,#172033);text-anchor:middle","Comparing the column sets before concatenating turns this into an error message",[54,1251,1253],{"x":56,"y":1252,"style":93},"202","rather than a total that is quietly a third too low",[10,1255,1256,1257,1260,1261,1264,1265,1268,1269,1271,1272,1274,1275,1277],{},"The same care applies to dtypes rather than names. A column read as ",[14,1258,1259],{},"float64"," in eleven sheets and as ",[14,1262,1263],{},"object"," in the twelfth — because one cell holds ",[14,1266,1267],{},"\"n\u002Fa\""," — concatenates without complaint into an ",[14,1270,1263],{}," column, and every later numeric operation on it either fails or silently produces a string. Passing ",[14,1273,623],{}," and ",[14,1276,632],{}," to the read is the fix, and it costs nothing to apply to every sheet at once:",[169,1279,1281],{"className":223,"code":1280,"language":225,"meta":174,"style":174},"frames = {name: xls.parse(name, dtype={\"region\": str},\n                          na_values=[\"\", \"-\", \"n\u002Fa\", \"N\u002FA\", \"TBC\"])\n          for name in wanted}\n",[14,1282,1283,1307,1340],{"__ignoreMap":174},[178,1284,1285,1288,1290,1292,1294,1296,1298,1300,1302,1304],{"class":180,"line":181},[178,1286,1287],{"class":236},"frames ",[178,1289,259],{"class":232},[178,1291,724],{"class":236},[178,1293,623],{"class":417},[178,1295,259],{"class":232},[178,1297,731],{"class":236},[178,1299,274],{"class":188},[178,1301,736],{"class":236},[178,1303,739],{"class":297},[178,1305,1306],{"class":236},"},\n",[178,1308,1309,1312,1314,1316,1319,1321,1324,1326,1328,1330,1333,1335,1338],{"class":180,"line":246},[178,1310,1311],{"class":417},"                          na_values",[178,1313,259],{"class":232},[178,1315,919],{"class":236},[178,1317,1318],{"class":188},"\"\"",[178,1320,283],{"class":236},[178,1322,1323],{"class":188},"\"-\"",[178,1325,283],{"class":236},[178,1327,1267],{"class":188},[178,1329,283],{"class":236},[178,1331,1332],{"class":188},"\"N\u002FA\"",[178,1334,283],{"class":236},[178,1336,1337],{"class":188},"\"TBC\"",[178,1339,598],{"class":236},[178,1341,1342,1345,1347,1349],{"class":180,"line":253},[178,1343,1344],{"class":232},"          for",[178,1346,747],{"class":236},[178,1348,443],{"class":232},[178,1350,752],{"class":236},[10,1352,1353,1354,1356,1357,1359,1360,1362],{},"The check costs three lines and belongs in any job that reads sheets it does not control. Whether a mismatch should stop the run or be normalised — mapping ",[14,1355,1198],{}," onto ",[14,1358,1191],{}," through a rename dictionary — depends on how the workbook is maintained, but the choice should be explicit. A silent ",[14,1361,1035],{}," column is the one outcome nobody chose.",[164,1364,1366],{"id":1365},"step-5-skip-the-sheets-that-are-not-data","Step 5: Skip the sheets that are not data",[10,1368,1369],{},"Real workbooks carry cover sheets, notes, lookup tables and working areas. Filter by name pattern, and check the shape before trusting anything:",[169,1371,1373],{"className":223,"code":1372,"language":225,"meta":174,"style":174},"import re\n\nMONTH = re.compile(r\"^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)$\")\nREQUIRED = {\"region\", \"amount\"}\n\nwith pd.ExcelFile(\"year.xlsx\") as xls:\n    usable = {}\n    for name in xls.sheet_names:\n        if not MONTH.match(name):\n            continue\n        frame = xls.parse(name)\n        missing = REQUIRED - set(frame.columns)\n        if missing:\n            print(f\"skipping {name}: missing {sorted(missing)}\")\n            continue\n        usable[name] = frame\n\nprint(f\"{len(usable)} data sheet(s):\", list(usable))\n",[14,1374,1375,1382,1386,1472,1490,1494,1508,1518,1529,1542,1547,1557,1576,1583,1622,1627,1638,1643],{"__ignoreMap":174},[178,1376,1377,1379],{"class":180,"line":181},[178,1378,233],{"class":232},[178,1380,1381],{"class":236}," re\n",[178,1383,1384],{"class":180,"line":246},[178,1385,250],{"emptyLinePlaceholder":249},[178,1387,1388,1391,1394,1397,1400,1403,1406,1409,1412,1415,1417,1420,1422,1425,1427,1430,1432,1435,1437,1440,1442,1445,1447,1450,1452,1455,1457,1460,1462,1465,1468,1470],{"class":180,"line":253},[178,1389,1390],{"class":297},"MONTH",[178,1392,1393],{"class":232}," =",[178,1395,1396],{"class":236}," re.compile(",[178,1398,1399],{"class":232},"r",[178,1401,1402],{"class":188},"\"",[178,1404,1405],{"class":297},"^(",[178,1407,1408],{"class":188},"Jan",[178,1410,1411],{"class":232},"|",[178,1413,1414],{"class":188},"Feb",[178,1416,1411],{"class":232},[178,1418,1419],{"class":188},"Mar",[178,1421,1411],{"class":232},[178,1423,1424],{"class":188},"Apr",[178,1426,1411],{"class":232},[178,1428,1429],{"class":188},"May",[178,1431,1411],{"class":232},[178,1433,1434],{"class":188},"Jun",[178,1436,1411],{"class":232},[178,1438,1439],{"class":188},"Jul",[178,1441,1411],{"class":232},[178,1443,1444],{"class":188},"Aug",[178,1446,1411],{"class":232},[178,1448,1449],{"class":188},"Sep",[178,1451,1411],{"class":232},[178,1453,1454],{"class":188},"Oct",[178,1456,1411],{"class":232},[178,1458,1459],{"class":188},"Nov",[178,1461,1411],{"class":232},[178,1463,1464],{"class":188},"Dec",[178,1466,1467],{"class":297},")$",[178,1469,1402],{"class":188},[178,1471,471],{"class":236},[178,1473,1474,1477,1479,1482,1484,1486,1488],{"class":180,"line":265},[178,1475,1476],{"class":297},"REQUIRED",[178,1478,1393],{"class":232},[178,1480,1481],{"class":236}," {",[178,1483,274],{"class":188},[178,1485,283],{"class":236},[178,1487,292],{"class":188},[178,1489,395],{"class":236},[178,1491,1492],{"class":180,"line":309},[178,1493,250],{"emptyLinePlaceholder":249},[178,1495,1496,1498,1500,1502,1504,1506],{"class":180,"line":343},[178,1497,406],{"class":232},[178,1499,654],{"class":236},[178,1501,412],{"class":188},[178,1503,426],{"class":236},[178,1505,240],{"class":232},[178,1507,663],{"class":236},[178,1509,1510,1513,1515],{"class":180,"line":369},[178,1511,1512],{"class":236},"    usable ",[178,1514,259],{"class":232},[178,1516,1517],{"class":236}," {}\n",[178,1519,1520,1522,1524,1526],{"class":180,"line":392},[178,1521,437],{"class":232},[178,1523,747],{"class":236},[178,1525,443],{"class":232},[178,1527,1528],{"class":236}," xls.sheet_names:\n",[178,1530,1531,1534,1536,1539],{"class":180,"line":398},[178,1532,1533],{"class":232},"        if",[178,1535,705],{"class":232},[178,1537,1538],{"class":297}," MONTH",[178,1540,1541],{"class":236},".match(name):\n",[178,1543,1544],{"class":180,"line":403},[178,1545,1546],{"class":232},"            continue\n",[178,1548,1549,1552,1554],{"class":180,"line":434},[178,1550,1551],{"class":236},"        frame ",[178,1553,259],{"class":232},[178,1555,1556],{"class":236}," xls.parse(name)\n",[178,1558,1559,1562,1564,1567,1570,1573],{"class":180,"line":449},[178,1560,1561],{"class":236},"        missing ",[178,1563,259],{"class":232},[178,1565,1566],{"class":297}," REQUIRED",[178,1568,1569],{"class":232}," -",[178,1571,1572],{"class":297}," set",[178,1574,1575],{"class":236},"(frame.columns)\n",[178,1577,1578,1580],{"class":180,"line":474},[178,1579,1533],{"class":232},[178,1581,1582],{"class":236}," missing:\n",[178,1584,1585,1588,1590,1593,1596,1599,1602,1605,1608,1610,1613,1616,1618,1620],{"class":180,"line":491},[178,1586,1587],{"class":297},"            print",[178,1589,562],{"class":236},[178,1591,1592],{"class":232},"f",[178,1594,1595],{"class":188},"\"skipping ",[178,1597,731],{"class":1598},"sSjpA",[178,1600,1601],{"class":236},"name",[178,1603,1604],{"class":1598},"}",[178,1606,1607],{"class":188},": missing ",[178,1609,731],{"class":1598},[178,1611,1612],{"class":297},"sorted",[178,1614,1615],{"class":236},"(missing)",[178,1617,1604],{"class":1598},[178,1619,1402],{"class":188},[178,1621,471],{"class":236},[178,1623,1625],{"class":180,"line":1624},15,[178,1626,1546],{"class":232},[178,1628,1630,1633,1635],{"class":180,"line":1629},16,[178,1631,1632],{"class":236},"        usable[name] ",[178,1634,259],{"class":232},[178,1636,1637],{"class":236}," frame\n",[178,1639,1641],{"class":180,"line":1640},17,[178,1642,250],{"emptyLinePlaceholder":249},[178,1644,1646,1648,1650,1652,1654,1656,1658,1661,1663,1666,1668,1670],{"class":180,"line":1645},18,[178,1647,559],{"class":297},[178,1649,562],{"class":236},[178,1651,1592],{"class":232},[178,1653,1402],{"class":188},[178,1655,731],{"class":1598},[178,1657,766],{"class":297},[178,1659,1660],{"class":236},"(usable)",[178,1662,1604],{"class":1598},[178,1664,1665],{"class":188}," data sheet(s):\"",[178,1667,283],{"class":236},[178,1669,581],{"class":297},[178,1671,1672],{"class":236},"(usable))\n",[10,1674,1675],{},"Reporting the skipped sheets rather than dropping them silently is the part that matters. A month that quietly failed the column check is a month missing from the total, and nothing downstream will notice.",[164,1677,1679],{"id":1678},"common-pitfalls-and-gotchas","Common pitfalls and gotchas",[1681,1682,1683,1699],"table",{},[1684,1685,1686],"thead",{},[1687,1688,1689,1693,1696],"tr",{},[1690,1691,1692],"th",{},"Symptom",[1690,1694,1695],{},"Cause",[1690,1697,1698],{},"Fix",[1700,1701,1702,1721,1741,1756,1770,1787,1798,1812],"tbody",{},[1687,1703,1704,1711,1716],{},[1705,1706,1707,1710],"td",{},[14,1708,1709],{},"AttributeError"," on the result",[1705,1712,1713,1715],{},[14,1714,16],{}," returns a dict, not a DataFrame",[1705,1717,1718,1719],{},"Index it by name, or ",[14,1720,971],{},[1687,1722,1723,1726,1731],{},[1705,1724,1725],{},"Very slow on a big workbook",[1705,1727,1728,1730],{},[14,1729,619],{}," called once per sheet",[1705,1732,1733,1734,1736,1737,1740],{},"One ",[14,1735,789],{},", many ",[14,1738,1739],{},"parse"," calls",[1687,1742,1743,1746,1749],{},[1705,1744,1745],{},"A sheet is missing from the result",[1705,1747,1748],{},"Name filter or a typo in the list",[1705,1750,1751,1752,1755],{},"Print ",[14,1753,1754],{},"xls.sheet_names"," first",[1687,1757,1758,1764,1767],{},[1705,1759,1760,1761,1763],{},"Combined frame has surprise ",[14,1762,1035],{}," columns",[1705,1765,1766],{},"Sheets disagree on columns",[1705,1768,1769],{},"Compare column sets before concatenating",[1687,1771,1772,1775,1778],{},[1705,1773,1774],{},"Cannot tell which sheet a row came from",[1705,1776,1777],{},"Concatenated without keys",[1705,1779,1780,1783,1784],{},[14,1781,1782],{},"concat(dict)"," or ",[14,1785,1786],{},"assign(month=name)",[1687,1788,1789,1792,1795],{},[1705,1790,1791],{},"Sheet order differs from the tabs",[1705,1793,1794],{},"Sorted somewhere along the way",[1705,1796,1797],{},"Dictionaries preserve workbook order; keep it",[1687,1799,1800,1803,1809],{},[1705,1801,1802],{},"File locked on Windows afterwards",[1705,1804,1805,1808],{},[14,1806,1807],{},"ExcelFile"," never closed",[1705,1810,1811],{},"Use it as a context manager",[1687,1813,1814,1819,1828],{},[1705,1815,1816,1818],{},[14,1817,205],{}," file will not read",[1705,1820,1821,1822,1824,1825,1827],{},"Modern ",[14,1823,209],{}," dropped ",[14,1826,201],{},", old files need it",[1705,1829,1830,1831,1833,1834,1836,1837],{},"Install ",[14,1832,209],{}," for ",[14,1835,205],{},", or convert to ",[14,1838,201],{},[164,1840,1842],{"id":1841},"performance-and-scale-notes","Performance and scale notes",[10,1844,1845,1846,1848],{},"Reading every sheet means parsing every sheet, so the cost scales with total cells, not sheet count — a 40-sheet workbook of small tables is quick; three sheets of 200,000 rows is not. When you need a subset, filter the names first and parse only those; ",[14,1847,793],{}," is free.",[10,1850,1851,1852,1854,1855,1859],{},"If the workbook is large and you only need a few columns, pass ",[14,1853,629],{}," so pandas discards the rest during parsing rather than after. And if the same workbook is read repeatedly by a scheduled job, convert it once to CSV or Parquet per sheet and read from that — ",[22,1856,1858],{"href":1857},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-large-excel-files-in-python\u002Fread-large-excel-file-in-chunks-with-pandas\u002F","Read Large Excel Files in Chunks with pandas"," covers the trade-offs when a single sheet is the problem.",[164,1861,1863],{"id":1862},"conclusion","Conclusion",[10,1865,1866,1868,1869,1871,1872,1874],{},[14,1867,16],{}," gives you every sheet as a dictionary of DataFrames, which is the right call when the workbook is small and every tab is data. Once it is neither, open one ",[14,1870,789],{},", use ",[14,1873,793],{}," to decide what is worth parsing, parse only those, and combine with the sheet name preserved as a column. Report the sheets you skipped, because a silently dropped month is the failure this pattern actually produces.",[164,1876,1878],{"id":1877},"frequently-asked-questions","Frequently asked questions",[10,1880,1881,1888,1889,1892],{},[1882,1883,1884,1885,1887],"strong",{},"What does ",[14,1886,16],{}," return?","\nA dictionary keyed by sheet name, with a DataFrame for each sheet, in workbook order. ",[14,1890,1891],{},"sheet_name=0"," returns one DataFrame, and a list returns a dictionary containing only those sheets.",[10,1894,1895,1904,1905,1907,1908,1910,1911,1914],{},[1882,1896,1897,1898,1900,1901,1903],{},"Why use ",[14,1899,789],{}," instead of calling ",[14,1902,619],{}," repeatedly?","\nEach ",[14,1906,619],{}," call parses the whole file again. ",[14,1909,789],{}," opens and parses it once, then every ",[14,1912,1913],{},"parse()"," call reads from that. On a large workbook the difference is several times faster.",[10,1916,1917,1920,1921,1923,1924,1926,1927,1930,1931,1934,1935,26],{},[1882,1918,1919],{},"How do I know the sheet names without loading the data?","\nOpen the file with ",[14,1922,789],{}," and read its ",[14,1925,793],{}," attribute, or use openpyxl's ",[14,1928,1929],{},"load_workbook"," with ",[14,1932,1933],{},"read_only=True"," and read ",[14,1936,1937],{},"wb.sheetnames",[10,1939,1940,1943,1946],{},[1882,1941,1942],{},"How do I combine every sheet into one DataFrame?",[14,1944,1945],{},"pd.concat"," over the dictionary's values, with keys or an added column so each row still says which sheet it came from.",[164,1948,1950],{"id":1949},"related","Related",[10,1952,1953],{},"Up to the parent guide:",[1955,1956,1957],"ul",{},[1958,1959,1960,1962],"li",{},[22,1961,25],{"href":24}," — the sheet-level operations this reading pattern feeds.",[10,1964,1965],{},"Related guides:",[1955,1967,1968,1975,1982,1992],{},[1958,1969,1970,1974],{},[22,1971,1973],{"href":1972},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fcombine-multiple-excel-files-into-one-python\u002F","Combine Multiple Excel Files into One with Python"," — the same stacking problem across files rather than tabs.",[1958,1976,1977,1981],{},[22,1978,1980],{"href":1979},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Frename-reorder-and-delete-excel-sheets-with-openpyxl\u002F","Rename, Reorder and Delete Excel Sheets with openpyxl"," — tidying the workbook before or after reading it.",[1958,1983,1984,1988,1989,1991],{},[22,1985,1987],{"href":1986},"\u002Fgetting-started-with-python-excel-automation\u002Freading-excel-files-with-pandas\u002Fread-specific-columns-from-excel-with-pandas\u002F","Read Specific Columns from Excel with pandas"," — ",[14,1990,629],{}," in detail.",[1958,1993,1994,1998],{},[22,1995,1997],{"href":1996},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fwrite-multiple-dataframes-to-one-excel-file\u002F","Write Multiple DataFrames to One Excel File"," — the reverse operation.",[2000,2001,2002],"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 .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":174,"searchDepth":246,"depth":246,"links":2004},[2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016],{"id":166,"depth":246,"text":167},{"id":219,"depth":246,"text":220},{"id":521,"depth":246,"text":522},{"id":636,"depth":246,"text":637},{"id":892,"depth":246,"text":893},{"id":1105,"depth":246,"text":1106},{"id":1365,"depth":246,"text":1366},{"id":1678,"depth":246,"text":1679},{"id":1841,"depth":246,"text":1842},{"id":1862,"depth":246,"text":1863},{"id":1877,"depth":246,"text":1878},{"id":1949,"depth":246,"text":1950},"2026-08-10","sheet_name=None returns a dictionary of every sheet — how to use it, why one ExcelFile beats repeated read_excel calls, how to filter and concatenate sheets, and what it costs on a large workbook.","md",[2021,2024,2027,2029],{"q":2022,"a":2023},"What does sheet_name=None return?","A dictionary keyed by sheet name, with a DataFrame for each sheet, in workbook order. sheet_name=0 returns one DataFrame, and a list returns a dictionary containing only those sheets.",{"q":2025,"a":2026},"Why use pd.ExcelFile instead of calling read_excel repeatedly?","Each read_excel call parses the whole file again. pd.ExcelFile opens and parses it once, then every parse() call reads from that. On a large workbook the difference is several times faster.",{"q":1919,"a":2028},"Open the file with pd.ExcelFile and read its sheet_names attribute, or use openpyxl's load_workbook with read_only=True and read wb.sheetnames.",{"q":1942,"a":2030},"pd.concat over the dictionary's values, with keys or an added column so each row still says which sheet it came from.",{"breadcrumb":2032},[2033,2036,2039,2040],{"name":2034,"item":2035},"Home","\u002F",{"name":2037,"item":2038},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":25,"item":24},{"name":5,"item":2041},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fread-all-sheets-from-an-excel-file-into-dataframes\u002F","\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fread-all-sheets-from-an-excel-file-into-dataframes",{"title":2044,"description":2045},"Read All Sheets from Excel into pandas DataFrames","Load every worksheet with pandas: sheet_name=None, reusing pd.ExcelFile, selecting sheets by pattern, concatenating with a source column, and memory notes for large workbooks.","read-all-sheets-from-an-excel-file-into-dataframes","getting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fread-all-sheets-from-an-excel-file-into-dataframes\u002Findex","how-to","29pzWRy1bbC4Ntmq4P3_xrxqzC94ge4iicUXA69OkO8",[2051,2055],{"title":2052,"path":2053,"stem":2054,"children":-1},"Copy a Sheet Between Excel Workbooks with Python","\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fcopy-a-sheet-between-excel-workbooks-with-python","getting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fcopy-a-sheet-between-excel-workbooks-with-python\u002Findex",{"title":1980,"path":2056,"stem":2057,"children":-1},"\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",1786800028712]