[{"data":1,"prerenderedAt":1593},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-missing-optional-dependency-openpyxl":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-missing-optional-dependency-openpyxl":1557,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-missing-optional-dependency-openpyxl":1566,"children:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-missing-optional-dependency-openpyxl":1571,"related:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-missing-optional-dependency-openpyxl":1572},{"id":4,"title":5,"body":6,"dateModified":1522,"datePublished":1522,"description":1523,"extension":1524,"faq":1525,"keyword":1534,"kind":1535,"meta":1536,"navigation":331,"path":1545,"seo":1546,"slug":1549,"stem":1550,"topics":1551,"type":1555,"__hash__":1556},"docs\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-missing-optional-dependency-openpyxl\u002Findex.md","Fix \"Missing optional dependency 'openpyxl'\" in pandas",{"type":7,"value":8,"toc":1508},"minimark",[9,18,28,54,213,218,221,263,278,282,295,352,367,371,382,388,400,560,564,575,579,582,588,591,611,614,872,878,882,892,1009,1029,1033,1036,1042,1056,1060,1063,1350,1357,1361,1419,1423,1443,1447,1453,1459,1465,1471,1475,1504],[10,11,12,13,17],"p",{},"The first ",[14,15,16],"code",{},"pd.read_excel()"," in a fresh environment often ends like this:",[19,20,26],"pre",{"className":21,"code":23,"language":24,"meta":25},[22],"language-text","ImportError: Missing optional dependency 'openpyxl'.  Use pip or conda to install openpyxl.\n","text","",[14,27,23],{"__ignoreMap":25},[10,29,30,31,34,35,38,39,43,44,47,48,53],{},"In pandas 3 the wording is slightly different — ",[14,32,33],{},"ImportError: `Import openpyxl` failed.  Use pip or conda to install the openpyxl package."," — but the meaning is the same. pandas does not read or write ",[14,36,37],{},".xlsx"," files itself; it hands them to an ",[40,41,42],"em",{},"engine"," package, and that package could not be imported by the Python process running your code. The fix is almost always a one-line install, but ",[40,45,46],{},"where"," you install it is the part that goes wrong. This guide, part of ",[49,50,52],"a",{"href":51},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002F","Troubleshooting Common Python Excel Errors",", finds the right interpreter and fixes each variant of the error.",[55,56,64,65,64,69,64,73,64,81,64,91,64,102,64,108,64,113,64,120,64,125,64,129,64,136,64,141,64,144,64,148,64,151,64,156,64,163,64,169,64,173,64,177,64,181,64,184,64,189,64,196,64,201,64,204,64,207],"svg",{"viewBox":57,"role":58,"ariaLabelledBy":59,"xmlns":62,"style":63},"4 0 752 168","img",[60,61],"dep-flow-t","dep-flow-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  ",[66,67,68],"title",{"id":60},"How pandas finds an Excel engine",[70,71,72],"desc",{"id":61},"read_excel picks an engine from the file extension, openpyxl for xlsx, then tries to import that package in the running Python. If the package is not installed in that interpreter, pandas raises the missing optional dependency ImportError; if it is installed but too old, it raises a minimum-version error.",[74,75],"rect",{"x":76,"y":77,"width":78,"height":79,"fill":80},"4","0","752","168","#ffffff",[74,82],{"x":83,"y":84,"width":85,"height":86,"rx":87,"fill":88,"stroke":89,"style":90},"20.0","16.0","153.0","110.5","12","#e7ebef","var(--line,#cdd5e6)","stroke-width:2px",[92,93,95],"g",{"transform":94},"translate(84.5,37.8) scale(1.000)",[96,97],"path",{"d":98,"fill":99,"stroke":100,"style":101},"M9 8l-4 4 4 4 M15 8l4 4-4 4","none","var(--text,#172033)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[24,103,107],{"x":104,"y":105,"style":106},"96.5","84.2","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","read_excel(\"x.xlsx\")",[24,109,112],{"x":104,"y":110,"style":111},"103.8","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","engine from extension",[114,115],"line",{"x1":116,"y1":117,"x2":118,"y2":117,"stroke":119,"style":90},"178.0","71.2","200.0","var(--brand,#5b5cf0)",[121,122],"polygon",{"points":123,"fill":124},"204.0,71.2 195.0,76.2 195.0,66.2","#5b5cf0",[74,126],{"x":127,"y":84,"width":85,"height":86,"rx":87,"fill":128,"stroke":119,"style":90},"209.0","#f0f4ff",[92,130,132],{"transform":131},"translate(273.5,37.8) scale(1.000)",[96,133],{"d":134,"fill":99,"stroke":135,"style":101},"M12 3c-4 0-4 1.6-4 3v2h4.2v1H6c-2 0-3 1.4-3 4s1 4 3 4h2v-2.6c0-1.6 1.3-2.9 2.9-2.9h4.2c1.3 0 2.4-1.1 2.4-2.4V6c0-1.6-1.8-3-5.5-3z M10 5.5h.01 M12 21c4 0 4-1.6 4-3v-2h-4.2v-1H18c2 0 3-1.4 3-4s-1-4-3-4h-2v2.6c0 1.6-1.3 2.9-2.9 2.9H8.9c-1.3 0-2.4 1.1-2.4 2.4V18c0 1.6 1.8 3 5.5 3z M14 18.5h.01","var(--brand-strong,#4338ca)",[24,137,140],{"x":138,"y":105,"style":139},"285.5","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","import openpyxl",[24,142,143],{"x":138,"y":110,"style":111},"in this interpreter",[114,145],{"x1":146,"y1":117,"x2":147,"y2":117,"stroke":119,"style":90},"367.0","389.0",[121,149],{"points":150,"fill":124},"393.0,71.2 384.0,76.2 384.0,66.2",[74,152],{"x":153,"y":84,"width":85,"height":86,"rx":87,"fill":154,"stroke":155,"style":90},"398.0","#fee8f2","var(--accent,#f43f8f)",[92,157,159],{"transform":158},"translate(462.5,29.0) scale(1.000)",[96,160],{"d":161,"fill":99,"stroke":162,"style":101},"M6 6l12 12 M18 6L6 18","var(--accent-ink,#be185d)",[24,164,168],{"x":165,"y":166,"style":167},"474.5","75.5","font-size:13.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","Not found",[24,170,172],{"x":165,"y":171,"style":111},"95.0","Missing optional",[24,174,176],{"x":165,"y":175,"style":111},"112.5","dependency",[114,178],{"x1":179,"y1":117,"x2":180,"y2":117,"stroke":119,"style":90},"556.0","578.0",[121,182],{"points":183,"fill":124},"582.0,71.2 573.0,76.2 573.0,66.2",[74,185],{"x":186,"y":84,"width":85,"height":86,"rx":87,"fill":187,"stroke":188,"style":90},"587.0","#fdefd8","var(--gold,#b4740a)",[92,190,192],{"transform":191},"translate(651.5,29.0) scale(1.000)",[96,193],{"d":194,"fill":99,"stroke":195,"style":101},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","var(--gold-ink,#7a4e06)",[24,197,200],{"x":198,"y":166,"style":199},"663.5","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Too old",[24,202,203],{"x":198,"y":171,"style":111},"requires version 3.1.5",[24,205,206],{"x":198,"y":175,"style":111},"or newer",[24,208,212],{"x":209,"y":210,"style":211},"380.0","148.5","font-size:12.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","the error is about the interpreter running your code, not about your machine as a whole",[214,215,217],"h2",{"id":216},"step-1-find-out-which-python-is-running","Step 1 — Find out which Python is running",[10,219,220],{},"Before installing anything, ask the failing code which interpreter it is running under. Put these lines at the top of the script or in a notebook cell:",[19,222,226],{"className":223,"code":224,"language":225,"meta":25,"style":25},"language-python shiki shiki-themes github-light github-dark-high-contrast","import sys\nprint(sys.executable)\nprint(sys.version.split()[0])\n","python",[14,227,228,240,250],{"__ignoreMap":25},[229,230,232,236],"span",{"class":114,"line":231},1,[229,233,235],{"class":234},"s-kum","import",[229,237,239],{"class":238},"skGVy"," sys\n",[229,241,243,247],{"class":114,"line":242},2,[229,244,246],{"class":245},"sP0c6","print",[229,248,249],{"class":238},"(sys.executable)\n",[229,251,253,255,258,260],{"class":114,"line":252},3,[229,254,246],{"class":245},[229,256,257],{"class":238},"(sys.version.split()[",[229,259,77],{"class":245},[229,261,262],{"class":238},"])\n",[10,264,265,266,269,270,273,274,277],{},"The path is the truth. It might be a project's ",[14,267,268],{},".venv",", a conda environment, the Python that shipped with an IDE, or the system Python — and it is often not the one your terminal's ",[14,271,272],{},"pip"," belongs to. Every fix below installs into ",[40,275,276],{},"that"," path.",[214,279,281],{"id":280},"step-2-install-with-that-interpreter","Step 2 — Install with that interpreter",[10,283,284,285,287,288,290,291,294],{},"Running ",[14,286,272],{}," by name uses whichever ",[14,289,272],{}," comes first on your PATH, which may belong to another Python. Run pip ",[40,292,293],{},"through"," the interpreter instead, so the package lands where the code will look for it:",[19,296,300],{"className":297,"code":298,"language":299,"meta":25,"style":25},"language-bash shiki shiki-themes github-light github-dark-high-contrast","# use the exact path printed by sys.executable\n\u002Fpath\u002Fto\u002Fpython -m pip install openpyxl\n\n# or, in an activated virtual environment\npython -m pip install openpyxl\n","bash",[14,301,302,308,327,333,339],{"__ignoreMap":25},[229,303,304],{"class":114,"line":231},[229,305,307],{"class":306},"s-wDw","# use the exact path printed by sys.executable\n",[229,309,310,314,317,321,324],{"class":114,"line":242},[229,311,313],{"class":312},"sMTad","\u002Fpath\u002Fto\u002Fpython",[229,315,316],{"class":245}," -m",[229,318,320],{"class":319},"srMev"," pip",[229,322,323],{"class":319}," install",[229,325,326],{"class":319}," openpyxl\n",[229,328,329],{"class":114,"line":252},[229,330,332],{"emptyLinePlaceholder":331},true,"\n",[229,334,336],{"class":114,"line":335},4,[229,337,338],{"class":306},"# or, in an activated virtual environment\n",[229,340,342,344,346,348,350],{"class":114,"line":341},5,[229,343,225],{"class":312},[229,345,316],{"class":245},[229,347,320],{"class":319},[229,349,323],{"class":319},[229,351,326],{"class":319},[10,353,354,355,358,359,362,363,366],{},"On Windows the equivalent is ",[14,356,357],{},"py -m pip install openpyxl"," for the default launcher Python, or the full path to ",[14,360,361],{},"python.exe"," inside the virtual environment. If you use conda, ",[14,364,365],{},"conda install openpyxl"," in the activated environment works too — but do not mix conda and pip for the same package in one environment.",[214,368,370],{"id":369},"step-3-jupyter-notebooks-install-into-the-kernel","Step 3 — Jupyter notebooks: install into the kernel",[10,372,373,374,377,378,381],{},"Notebooks add a layer: the notebook server and the kernel can be different Pythons, so ",[14,375,376],{},"!pip install openpyxl"," in a cell may install into the wrong one. The ",[14,379,380],{},"%pip"," magic always targets the running kernel:",[19,383,386],{"className":384,"code":385,"language":24,"meta":25},[22],"%pip install openpyxl\n",[14,387,385],{"__ignoreMap":25},[10,389,390,391,395,396,399],{},"Then ",[392,393,394],"strong",{},"restart the kernel"," — a running Python process does not pick up packages installed after it started importing. If the error persists, the notebook is using a kernel from another environment; choose the right one from the kernel menu, or register your environment as a kernel with ",[14,397,398],{},"python -m ipykernel install --user --name myproject",".",[55,401,64,406,64,409,64,412,64,415,64,419,64,425,64,428,64,432,64,436,64,439,64,442,64,450,64,455,64,462,64,469,64,474,64,478,64,481,64,484,64,488,64,491,64,494,64,499,64,502,64,505,64,508,64,511,64,515,64,518,64,521,64,527,64,530,64,533,64,535,64,538,64,542,64,545,64,548,64,554,64,557],{"viewBox":402,"role":58,"ariaLabelledBy":403,"xmlns":62,"style":63},"4 0 752 272",[404,405],"dep-where-t","dep-where-d",[66,407,408],{"id":404},"Where to install the missing engine",[70,410,411],{"id":405},"If the code runs as a script in a virtual environment, activate it and use python -m pip. If it runs in Jupyter, use percent pip in a cell and restart the kernel. If it runs inside an IDE, check which interpreter the IDE uses and install into that one. If it runs on a server or in Docker, add the package to requirements and rebuild.",[74,413],{"x":76,"y":77,"width":78,"height":414,"fill":80},"272",[74,416],{"x":417,"y":84,"width":418,"height":166,"rx":87,"fill":128,"stroke":119,"style":90},"235.8","288.4",[92,420,422],{"transform":421},"translate(368.0,29.0) scale(1.000)",[96,423],{"d":424,"fill":99,"stroke":135,"style":101},"M11 4a7 7 0 1 0 .01 0z M16 16l5 5",[24,426,427],{"x":209,"y":166,"style":139},"Where does the failing code run?",[114,429],{"x1":209,"y1":430,"x2":209,"y2":431,"stroke":119,"style":90},"91.5","111.5",[114,433],{"x1":434,"y1":431,"x2":435,"y2":431,"stroke":119,"style":90},"104.0","656.0",[114,437],{"x1":434,"y1":431,"x2":434,"y2":438,"stroke":119,"style":90},"157.5",[121,440],{"points":441,"fill":124},"104.0,161.5 99.0,152.5 109.0,152.5",[74,443],{"x":444,"y":445,"width":446,"height":447,"rx":448,"fill":80,"stroke":89,"style":449},"47.3","121.5","113.5","21.0","10","stroke-width:1.2px",[24,451,454],{"x":434,"y":452,"style":453},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","a terminal script",[74,456],{"x":83,"y":457,"width":458,"height":459,"rx":87,"fill":460,"stroke":461,"style":90},"163.5","168.0","93.0","#d9f4f1","var(--teal,#0f9488)",[92,463,465],{"transform":464},"translate(92.0,176.5) scale(1.000)",[96,466],{"d":467,"fill":99,"stroke":468,"style":101},"M4 5h16v14H4z M7 9l3 3-3 3 M12 15h5","var(--teal-ink,#0b6157)",[24,470,473],{"x":434,"y":471,"style":472},"223.0","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","python -m pip",[24,475,477],{"x":434,"y":476,"style":111},"242.5","in the active venv",[114,479],{"x1":480,"y1":431,"x2":480,"y2":438,"stroke":119,"style":90},"288.0",[121,482],{"points":483,"fill":124},"288.0,161.5 283.0,152.5 293.0,152.5",[74,485],{"x":486,"y":445,"width":487,"height":447,"rx":448,"fill":80,"stroke":89,"style":449},"256.0","64.0",[24,489,490],{"x":480,"y":452,"style":453},"Jupyter",[74,492],{"x":493,"y":457,"width":458,"height":459,"rx":87,"fill":128,"stroke":119,"style":90},"204.0",[92,495,497],{"transform":496},"translate(276.0,176.5) scale(1.000)",[96,498],{"d":98,"fill":99,"stroke":135,"style":101},[24,500,501],{"x":480,"y":471,"style":139},"%pip install",[24,503,504],{"x":480,"y":476,"style":111},"then restart the kernel",[114,506],{"x1":507,"y1":431,"x2":507,"y2":438,"stroke":119,"style":90},"472.0",[121,509],{"points":510,"fill":124},"472.0,161.5 467.0,152.5 477.0,152.5",[74,512],{"x":513,"y":445,"width":514,"height":447,"rx":448,"fill":80,"stroke":89,"style":449},"444.6","54.8",[24,516,517],{"x":507,"y":452,"style":453},"an IDE",[74,519],{"x":520,"y":457,"width":458,"height":459,"rx":87,"fill":187,"stroke":188,"style":90},"388.0",[92,522,524],{"transform":523},"translate(460.0,176.5) scale(1.000)",[96,525],{"d":526,"fill":99,"stroke":195,"style":101},"M12 9a3 3 0 1 0 .01 0z M12 2.5v3 M12 18.5v3 M2.5 12h3 M18.5 12h3 M5.3 5.3l2.1 2.1 M16.6 16.6l2.1 2.1 M5.3 18.7l2.1-2.1 M16.6 7.4l2.1-2.1",[24,528,529],{"x":507,"y":471,"style":199},"IDE interpreter",[24,531,532],{"x":507,"y":476,"style":111},"install into that path",[114,534],{"x1":435,"y1":431,"x2":435,"y2":438,"stroke":119,"style":90},[121,536],{"points":537,"fill":124},"656.0,161.5 651.0,152.5 661.0,152.5",[74,539],{"x":540,"y":445,"width":541,"height":447,"rx":448,"fill":80,"stroke":89,"style":449},"597.7","116.6",[24,543,544],{"x":435,"y":452,"style":453},"server or Docker",[74,546],{"x":547,"y":457,"width":458,"height":459,"rx":87,"fill":154,"stroke":155,"style":90},"572.0",[92,549,551],{"transform":550},"translate(644.0,176.5) scale(1.000)",[96,552],{"d":553,"fill":99,"stroke":162,"style":101},"M12 2.5l8.5 4.7v9.6L12 21.5l-8.5-4.7V7.2z M3.5 7.2l8.5 4.7 8.5-4.7 M12 11.9v9.6",[24,555,556],{"x":435,"y":471,"style":167},"requirements file",[24,558,559],{"x":435,"y":476,"style":111},"rebuild the image",[214,561,563],{"id":562},"step-4-ides-pick-their-own-interpreter","Step 4 — IDEs pick their own interpreter",[10,565,566,567,570,571,574],{},"VS Code, PyCharm and other editors run code with the interpreter selected in the project settings, which may differ from the one in your terminal. The status bar (VS Code) or ",[40,568,569],{},"Settings → Project → Python Interpreter"," (PyCharm) shows which. Either select the environment where openpyxl is installed, or install openpyxl into the selected one using its own package manager panel. The ",[14,572,573],{},"sys.executable"," check from Step 1 settles any doubt in seconds.",[214,576,578],{"id":577},"step-5-the-version-is-too-old","Step 5 — The version is too old",[10,580,581],{},"A different message means openpyxl is present but older than your pandas supports:",[19,583,586],{"className":584,"code":585,"language":24,"meta":25},[22],"ImportError: Pandas requires version '3.1.5' or newer of 'openpyxl' (version '3.0.10' currently installed).\n",[14,587,585],{"__ignoreMap":25},[10,589,590],{},"Upgrade in the same interpreter:",[19,592,594],{"className":297,"code":593,"language":299,"meta":25,"style":25},"python -m pip install --upgrade openpyxl\n",[14,595,596],{"__ignoreMap":25},[229,597,598,600,602,604,606,609],{"class":114,"line":231},[229,599,225],{"class":312},[229,601,316],{"class":245},[229,603,320],{"class":319},[229,605,323],{"class":319},[229,607,608],{"class":245}," --upgrade",[229,610,326],{"class":319},[10,612,613],{},"pandas keeps a table of minimum versions for every optional dependency, and each pandas release raises some of them. You can see what the installed pandas expects, and what you have, without triggering the error:",[19,615,617],{"className":223,"code":616,"language":225,"meta":25,"style":25},"import importlib.metadata as md\n\nimport pandas as pd\nfrom pandas.compat._optional import VERSIONS\n\nprint(\"pandas\", pd.__version__)\nfor package, module in [(\"openpyxl\", \"openpyxl\"), (\"xlsxwriter\", \"xlsxwriter\"),\n                        (\"xlrd\", \"xlrd\"), (\"pyxlsb\", \"pyxlsb\"),\n                        (\"odfpy\", \"odfpy\"), (\"python-calamine\", \"python-calamine\")]:\n    try:\n        installed = md.version(package)\n    except md.PackageNotFoundError:\n        installed = \"not installed\"\n    print(f\"{package:16} needs >= {VERSIONS.get(module, '?'):8} installed: {installed}\")\n",[14,618,619,632,636,648,661,665,685,721,745,769,778,790,799,809],{"__ignoreMap":25},[229,620,621,623,626,629],{"class":114,"line":231},[229,622,235],{"class":234},[229,624,625],{"class":238}," importlib.metadata ",[229,627,628],{"class":234},"as",[229,630,631],{"class":238}," md\n",[229,633,634],{"class":114,"line":242},[229,635,332],{"emptyLinePlaceholder":331},[229,637,638,640,643,645],{"class":114,"line":252},[229,639,235],{"class":234},[229,641,642],{"class":238}," pandas ",[229,644,628],{"class":234},[229,646,647],{"class":238}," pd\n",[229,649,650,653,656,658],{"class":114,"line":335},[229,651,652],{"class":234},"from",[229,654,655],{"class":238}," pandas.compat._optional ",[229,657,235],{"class":234},[229,659,660],{"class":245}," VERSIONS\n",[229,662,663],{"class":114,"line":341},[229,664,332],{"emptyLinePlaceholder":331},[229,666,668,670,673,676,679,682],{"class":114,"line":667},6,[229,669,246],{"class":245},[229,671,672],{"class":238},"(",[229,674,675],{"class":319},"\"pandas\"",[229,677,678],{"class":238},", pd.",[229,680,681],{"class":245},"__version__",[229,683,684],{"class":238},")\n",[229,686,688,691,694,697,700,703,706,708,711,714,716,718],{"class":114,"line":687},7,[229,689,690],{"class":234},"for",[229,692,693],{"class":238}," package, module ",[229,695,696],{"class":234},"in",[229,698,699],{"class":238}," [(",[229,701,702],{"class":319},"\"openpyxl\"",[229,704,705],{"class":238},", ",[229,707,702],{"class":319},[229,709,710],{"class":238},"), (",[229,712,713],{"class":319},"\"xlsxwriter\"",[229,715,705],{"class":238},[229,717,713],{"class":319},[229,719,720],{"class":238},"),\n",[229,722,724,727,730,732,734,736,739,741,743],{"class":114,"line":723},8,[229,725,726],{"class":238},"                        (",[229,728,729],{"class":319},"\"xlrd\"",[229,731,705],{"class":238},[229,733,729],{"class":319},[229,735,710],{"class":238},[229,737,738],{"class":319},"\"pyxlsb\"",[229,740,705],{"class":238},[229,742,738],{"class":319},[229,744,720],{"class":238},[229,746,748,750,753,755,757,759,762,764,766],{"class":114,"line":747},9,[229,749,726],{"class":238},[229,751,752],{"class":319},"\"odfpy\"",[229,754,705],{"class":238},[229,756,752],{"class":319},[229,758,710],{"class":238},[229,760,761],{"class":319},"\"python-calamine\"",[229,763,705],{"class":238},[229,765,761],{"class":319},[229,767,768],{"class":238},")]:\n",[229,770,772,775],{"class":114,"line":771},10,[229,773,774],{"class":234},"    try",[229,776,777],{"class":238},":\n",[229,779,781,784,787],{"class":114,"line":780},11,[229,782,783],{"class":238},"        installed ",[229,785,786],{"class":234},"=",[229,788,789],{"class":238}," md.version(package)\n",[229,791,793,796],{"class":114,"line":792},12,[229,794,795],{"class":234},"    except",[229,797,798],{"class":238}," md.PackageNotFoundError:\n",[229,800,802,804,806],{"class":114,"line":801},13,[229,803,783],{"class":238},[229,805,786],{"class":234},[229,807,808],{"class":319}," \"not installed\"\n",[229,810,812,815,817,820,823,827,830,833,836,839,841,844,847,850,853,856,858,861,863,866,868,870],{"class":114,"line":811},14,[229,813,814],{"class":245},"    print",[229,816,672],{"class":238},[229,818,819],{"class":234},"f",[229,821,822],{"class":319},"\"",[229,824,826],{"class":825},"sSjpA","{",[229,828,829],{"class":238},"package",[229,831,832],{"class":234},":16",[229,834,835],{"class":825},"}",[229,837,838],{"class":319}," needs >= ",[229,840,826],{"class":825},[229,842,843],{"class":245},"VERSIONS",[229,845,846],{"class":238},".get(module, ",[229,848,849],{"class":319},"'?'",[229,851,852],{"class":238},")",[229,854,855],{"class":234},":8",[229,857,835],{"class":825},[229,859,860],{"class":319}," installed: ",[229,862,826],{"class":825},[229,864,865],{"class":238},"installed",[229,867,835],{"class":825},[229,869,822],{"class":319},[229,871,684],{"class":238},[10,873,874,877],{},[14,875,876],{},"pandas.compat._optional"," is an internal module, so treat the listing as a diagnostic rather than something to build on — but it answers \"which version do I need?\" exactly for the pandas you have.",[214,879,881],{"id":880},"step-6-other-formats-need-other-engines","Step 6 — Other formats need other engines",[10,883,884,885,887,888,891],{},"openpyxl covers ",[14,886,37],{}," and ",[14,889,890],{},".xlsm",". Other formats have their own engines, each with its own version of this error:",[55,893,64,898,64,901,64,904,64,907,64,912,64,916,64,922,64,925,64,929,64,933,64,939,64,941,64,945,64,947,64,950,64,953,64,957,64,959,64,963,64,965,64,971,64,974,64,978,64,980,64,984,64,986,64,991,64,994,64,998,64,1000,64,1004,64,1006],{"viewBox":894,"role":58,"ariaLabelledBy":895,"xmlns":62,"style":63},"4 0 752 208",[896,897],"dep-engines-t","dep-engines-d",[66,899,900],{"id":896},"The engine package each Excel format needs in pandas",[70,902,903],{"id":897},"xlsx and xlsm need openpyxl for reading, or xlsxwriter or openpyxl for writing. Legacy xls needs xlrd for reading. xlsb needs pyxlsb or python-calamine. ods needs odfpy. python-calamine reads all of these formats.",[74,905],{"x":76,"y":77,"width":78,"height":906,"fill":80},"208",[74,908],{"x":83,"y":84,"width":909,"height":910,"rx":77,"fill":80,"stroke":89,"style":911},"120.6","40.0","stroke-width:1px",[74,913],{"x":914,"y":84,"width":915,"height":910,"rx":77,"fill":128,"stroke":119,"style":449},"140.6","299.7",[24,917,921],{"x":918,"y":919,"style":920},"290.5","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Read",[74,923],{"x":924,"y":84,"width":915,"height":910,"rx":77,"fill":128,"stroke":119,"style":449},"440.3",[24,926,928],{"x":927,"y":919,"style":920},"590.2","Write",[74,930],{"x":83,"y":931,"width":909,"height":932,"rx":77,"fill":88,"stroke":89,"style":911},"56.0","34.0",[24,934,938],{"x":935,"y":936,"style":937},"32.0","78.0","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start",".xlsx \u002F .xlsm",[74,940],{"x":914,"y":931,"width":915,"height":932,"rx":77,"fill":80,"stroke":89,"style":911},[24,942,944],{"x":918,"y":943,"style":111},"77.0","openpyxl or python-calamine",[74,946],{"x":924,"y":931,"width":915,"height":932,"rx":77,"fill":80,"stroke":89,"style":911},[24,948,949],{"x":927,"y":943,"style":111},"openpyxl or xlsxwriter",[74,951],{"x":83,"y":952,"width":909,"height":932,"rx":77,"fill":88,"stroke":89,"style":911},"90.0",[24,954,956],{"x":935,"y":955,"style":937},"112.0",".xls (97-2003)",[74,958],{"x":914,"y":952,"width":915,"height":932,"rx":77,"fill":80,"stroke":89,"style":911},[24,960,962],{"x":918,"y":961,"style":111},"111.0","xlrd or python-calamine",[74,964],{"x":924,"y":952,"width":915,"height":932,"rx":77,"fill":80,"stroke":89,"style":911},[92,966,968],{"transform":967},"translate(582.2,99.0) scale(0.667)",[96,969],{"d":161,"fill":99,"stroke":155,"style":970},"stroke-width:2.70px;stroke-linecap:round;stroke-linejoin:round",[74,972],{"x":83,"y":973,"width":909,"height":932,"rx":77,"fill":88,"stroke":89,"style":911},"124.0",[24,975,977],{"x":935,"y":976,"style":937},"146.0",".xlsb",[74,979],{"x":914,"y":973,"width":915,"height":932,"rx":77,"fill":80,"stroke":89,"style":911},[24,981,983],{"x":918,"y":982,"style":111},"145.0","pyxlsb or python-calamine",[74,985],{"x":924,"y":973,"width":915,"height":932,"rx":77,"fill":80,"stroke":89,"style":911},[92,987,989],{"transform":988},"translate(582.2,133.0) scale(0.667)",[96,990],{"d":161,"fill":99,"stroke":155,"style":970},[74,992],{"x":83,"y":993,"width":909,"height":932,"rx":77,"fill":88,"stroke":89,"style":911},"158.0",[24,995,997],{"x":935,"y":996,"style":937},"180.0",".ods",[74,999],{"x":914,"y":993,"width":915,"height":932,"rx":77,"fill":80,"stroke":89,"style":911},[24,1001,1003],{"x":918,"y":1002,"style":111},"179.0","odfpy or python-calamine",[74,1005],{"x":924,"y":993,"width":915,"height":932,"rx":77,"fill":80,"stroke":89,"style":911},[24,1007,1008],{"x":927,"y":1002,"style":111},"odfpy",[10,1010,1011,1012,1015,1016,1019,1020,1024,1025,399],{},"A project that reads assorted inputs can install ",[14,1013,1014],{},"python-calamine"," once and pass ",[14,1017,1018],{},"engine=\"calamine\""," to read every format, which also happens to be the fastest option; see ",[49,1021,1023],{"href":1022},"\u002Fadvanced-data-transformation-and-cleaning\u002Freading-excel-with-polars-and-arrow\u002Fspeed-up-pandas-excel-reads-with-the-calamine-engine\u002F","Speed Up pandas Excel Reads with the calamine Engine",". Engine choice in general is covered in ",[49,1026,1028],{"href":1027},"\u002Fgetting-started-with-python-excel-automation\u002Fchoosing-a-python-excel-library\u002Fpick-an-excel-engine-for-xlsx-xlsm-xls-xlsb-and-ods\u002F","Pick an Excel Engine for .xlsx, .xlsm, .xls, .xlsb and .ods",[214,1030,1032],{"id":1031},"step-7-make-it-impossible-for-the-next-person","Step 7 — Make it impossible for the next person",[10,1034,1035],{},"Once fixed on your machine, record the dependency so it cannot go missing again. Declare the engines your code uses next to pandas, and pin versions that you have tested together:",[19,1037,1040],{"className":1038,"code":1039,"language":24,"meta":25},[22],"# requirements.txt\npandas==3.0.6\nopenpyxl==3.1.5\nxlsxwriter==3.2.9\npython-calamine==0.8.2\n",[14,1041,1039],{"__ignoreMap":25},[10,1043,1044,1045,1048,1049,1051,1052,399],{},"A scheduled job, a Docker image or a colleague's checkout then installs everything in one step, and a CI run fails loudly if a dependency is missing instead of the error surfacing at 6 a.m. Checking imports at the start of a job — the loop in Step 5, with ",[14,1046,1047],{},"raise"," instead of ",[14,1050,246],{}," — turns a missing engine into a clear failure before any work is done. Packaging a whole Excel script so it runs elsewhere is covered in ",[49,1053,1055],{"href":1054},"\u002Fautomating-reporting-workflows\u002Ftesting-and-packaging-excel-automation-scripts\u002F","Testing and Packaging Excel Automation Scripts",[214,1057,1059],{"id":1058},"step-8-fail-fast-at-the-start-of-a-job","Step 8 — Fail fast at the start of a job",[10,1061,1062],{},"For a scheduled job, the worst time to discover a missing engine is halfway through, after files have been moved or emails half-sent. Check every engine the job needs before doing anything, and stop with one clear message that names the interpreter:",[19,1064,1066],{"className":223,"code":1065,"language":225,"meta":25,"style":25},"import importlib\nimport sys\n\nREQUIRED = {\"openpyxl\": \"read and write .xlsx\", \"xlsxwriter\": \"formatted output\"}\n\ndef check_engines(required: dict[str, str]) -> None:\n    missing = []\n    for module, purpose in required.items():\n        try:\n            importlib.import_module(module)\n        except ImportError:\n            missing.append(f\"{module} ({purpose})\")\n    if missing:\n        raise SystemExit(\n            f\"Missing packages for {sys.executable}: {', '.join(missing)}. \"\n            f\"Install with: {sys.executable} -m pip install {' '.join(m.split()[0] for m in missing)}\"\n        )\n\ncheck_engines(REQUIRED)\nprint(\"engines OK\")\n",[14,1067,1068,1075,1081,1085,1116,1120,1147,1157,1170,1177,1182,1192,1223,1231,1242,1272,1317,1323,1328,1338],{"__ignoreMap":25},[229,1069,1070,1072],{"class":114,"line":231},[229,1071,235],{"class":234},[229,1073,1074],{"class":238}," importlib\n",[229,1076,1077,1079],{"class":114,"line":242},[229,1078,235],{"class":234},[229,1080,239],{"class":238},[229,1082,1083],{"class":114,"line":252},[229,1084,332],{"emptyLinePlaceholder":331},[229,1086,1087,1090,1093,1096,1098,1101,1104,1106,1108,1110,1113],{"class":114,"line":335},[229,1088,1089],{"class":245},"REQUIRED",[229,1091,1092],{"class":234}," =",[229,1094,1095],{"class":238}," {",[229,1097,702],{"class":319},[229,1099,1100],{"class":238},": ",[229,1102,1103],{"class":319},"\"read and write .xlsx\"",[229,1105,705],{"class":238},[229,1107,713],{"class":319},[229,1109,1100],{"class":238},[229,1111,1112],{"class":319},"\"formatted output\"",[229,1114,1115],{"class":238},"}\n",[229,1117,1118],{"class":114,"line":341},[229,1119,332],{"emptyLinePlaceholder":331},[229,1121,1122,1125,1129,1132,1135,1137,1139,1142,1145],{"class":114,"line":667},[229,1123,1124],{"class":234},"def",[229,1126,1128],{"class":1127},"s_Opv"," check_engines",[229,1130,1131],{"class":238},"(required: dict[",[229,1133,1134],{"class":245},"str",[229,1136,705],{"class":238},[229,1138,1134],{"class":245},[229,1140,1141],{"class":238},"]) -> ",[229,1143,1144],{"class":245},"None",[229,1146,777],{"class":238},[229,1148,1149,1152,1154],{"class":114,"line":687},[229,1150,1151],{"class":238},"    missing ",[229,1153,786],{"class":234},[229,1155,1156],{"class":238}," []\n",[229,1158,1159,1162,1165,1167],{"class":114,"line":723},[229,1160,1161],{"class":234},"    for",[229,1163,1164],{"class":238}," module, purpose ",[229,1166,696],{"class":234},[229,1168,1169],{"class":238}," required.items():\n",[229,1171,1172,1175],{"class":114,"line":747},[229,1173,1174],{"class":234},"        try",[229,1176,777],{"class":238},[229,1178,1179],{"class":114,"line":771},[229,1180,1181],{"class":238},"            importlib.import_module(module)\n",[229,1183,1184,1187,1190],{"class":114,"line":780},[229,1185,1186],{"class":234},"        except",[229,1188,1189],{"class":245}," ImportError",[229,1191,777],{"class":238},[229,1193,1194,1197,1199,1201,1203,1206,1208,1211,1213,1216,1218,1221],{"class":114,"line":792},[229,1195,1196],{"class":238},"            missing.append(",[229,1198,819],{"class":234},[229,1200,822],{"class":319},[229,1202,826],{"class":825},[229,1204,1205],{"class":238},"module",[229,1207,835],{"class":825},[229,1209,1210],{"class":319}," (",[229,1212,826],{"class":825},[229,1214,1215],{"class":238},"purpose",[229,1217,835],{"class":825},[229,1219,1220],{"class":319},")\"",[229,1222,684],{"class":238},[229,1224,1225,1228],{"class":114,"line":801},[229,1226,1227],{"class":234},"    if",[229,1229,1230],{"class":238}," missing:\n",[229,1232,1233,1236,1239],{"class":114,"line":811},[229,1234,1235],{"class":234},"        raise",[229,1237,1238],{"class":245}," SystemExit",[229,1240,1241],{"class":238},"(\n",[229,1243,1245,1248,1251,1253,1255,1257,1259,1261,1264,1267,1269],{"class":114,"line":1244},15,[229,1246,1247],{"class":234},"            f",[229,1249,1250],{"class":319},"\"Missing packages for ",[229,1252,826],{"class":825},[229,1254,573],{"class":238},[229,1256,835],{"class":825},[229,1258,1100],{"class":319},[229,1260,826],{"class":825},[229,1262,1263],{"class":319},"', '",[229,1265,1266],{"class":238},".join(missing)",[229,1268,835],{"class":825},[229,1270,1271],{"class":319},". \"\n",[229,1273,1275,1277,1280,1282,1284,1286,1289,1291,1294,1297,1299,1302,1304,1307,1309,1312,1314],{"class":114,"line":1274},16,[229,1276,1247],{"class":234},[229,1278,1279],{"class":319},"\"Install with: ",[229,1281,826],{"class":825},[229,1283,573],{"class":238},[229,1285,835],{"class":825},[229,1287,1288],{"class":319}," -m pip install ",[229,1290,826],{"class":825},[229,1292,1293],{"class":319},"' '",[229,1295,1296],{"class":238},".join(m.split()[",[229,1298,77],{"class":245},[229,1300,1301],{"class":238},"] ",[229,1303,690],{"class":234},[229,1305,1306],{"class":238}," m ",[229,1308,696],{"class":234},[229,1310,1311],{"class":238}," missing)",[229,1313,835],{"class":825},[229,1315,1316],{"class":319},"\"\n",[229,1318,1320],{"class":114,"line":1319},17,[229,1321,1322],{"class":238},"        )\n",[229,1324,1326],{"class":114,"line":1325},18,[229,1327,332],{"emptyLinePlaceholder":331},[229,1329,1331,1334,1336],{"class":114,"line":1330},19,[229,1332,1333],{"class":238},"check_engines(",[229,1335,1089],{"class":245},[229,1337,684],{"class":238},[229,1339,1341,1343,1345,1348],{"class":114,"line":1340},20,[229,1342,246],{"class":245},[229,1344,672],{"class":238},[229,1346,1347],{"class":319},"\"engines OK\"",[229,1349,684],{"class":238},[10,1351,1352,1353,1356],{},"The message includes the exact command to run, with the exact interpreter path, which turns a confusing traceback in a log into a fix anyone on the team can apply. Call it as the first line of ",[14,1354,1355],{},"main()",", before logging in anywhere or touching any file.",[214,1358,1360],{"id":1359},"common-pitfalls","Common pitfalls",[1362,1363,1364,1377,1383,1397,1407],"ul",{},[1365,1366,1367,1374,1375,399],"li",{},[392,1368,1369,887,1371,1373],{},[14,1370,272],{},[14,1372,225],{}," from different installations."," The most common cause. Always use ",[14,1376,473],{},[1365,1378,1379,1382],{},[392,1380,1381],{},"Not restarting."," A running notebook kernel or interactive session does not see packages installed after it started. Restart it.",[1365,1384,1385,1392,1393,1396],{},[392,1386,1387,1388,1391],{},"Installing ",[14,1389,1390],{},"pandas[excel]"," and assuming everything is covered."," The ",[14,1394,1395],{},"excel"," extra installs the usual engines, but a pinned or older environment may still lack one; check with the listing above.",[1365,1398,1399,1402,1403,1406],{},[392,1400,1401],{},"A broken or partial install."," An interrupted install can leave a package directory without its metadata, and imports then fail in odd ways. ",[14,1404,1405],{},"python -m pip install --force-reinstall openpyxl"," repairs it.",[1365,1408,1409,1415,1416,399],{},[392,1410,1411,1412,399],{},"Naming a file ",[14,1413,1414],{},"openpyxl.py"," A script named after the package shadows it, and imports fail with confusing errors. Rename the file and delete any ",[14,1417,1418],{},"__pycache__",[214,1420,1422],{"id":1421},"conclusion","Conclusion",[10,1424,1425,1426,1428,1429,1431,1432,1434,1435,705,1438,887,1440,1442],{},"\"Missing optional dependency 'openpyxl'\" means the engine pandas needs is not importable from the interpreter running your code. Print ",[14,1427,573],{},", install with that interpreter via ",[14,1430,473],{}," (or ",[14,1433,380],{}," in Jupyter, then restart), point your IDE at the environment you installed into, upgrade when pandas asks for a newer version, and install the right engine for ",[14,1436,1437],{},".xls",[14,1439,977],{},[14,1441,997],{}," files. Record the engines in your requirements so the error does not come back.",[214,1444,1446],{"id":1445},"frequently-asked-questions","Frequently asked questions",[10,1448,1449,1452],{},[392,1450,1451],{},"Why does pandas need openpyxl to read Excel?","\npandas does not parse Excel files itself. It hands .xlsx files to an engine package — openpyxl by default — and treats that package as an optional dependency, so installing pandas alone does not install it.",[10,1454,1455,1458],{},[392,1456,1457],{},"I installed openpyxl but still get the error. Why?","\nIt was installed into a different Python than the one running your code — a different virtual environment, a different Jupyter kernel, or the system Python. Install with the same interpreter using python -m pip, or %pip inside the notebook.",[10,1460,1461,1464],{},[392,1462,1463],{},"What does \"Pandas requires version '3.1.5' or newer of 'openpyxl'\" mean?","\nopenpyxl is installed but older than your pandas version supports. Upgrade it with python -m pip install --upgrade openpyxl.",[10,1466,1467,1470],{},[392,1468,1469],{},"Which package do I need for .xls, .xlsb or .ods files?","\nxlrd for legacy .xls, pyxlsb or python-calamine for .xlsb, and odfpy for .ods. python-calamine reads all of them and .xlsx as well.",[214,1472,1474],{"id":1473},"related","Related",[1362,1476,1477,1483,1490,1497],{},[1365,1478,1479,1480,1482],{},"Up one level: ",[49,1481,52],{"href":51}," — every common error explained.",[1365,1484,1485,1489],{},[49,1486,1488],{"href":1487},"\u002Fgetting-started-with-python-excel-automation\u002Freading-excel-files-with-pandas\u002F","Reading Excel Files with Pandas"," — what comes after the install.",[1365,1491,1492,1496],{},[49,1493,1495],{"href":1494},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-openpyxl-does-not-support-the-old-xls-format\u002F","Fix \"openpyxl does not support the old .xls file format\""," — the right engine for legacy files.",[1365,1498,1499,1503],{},[49,1500,1502],{"href":1501},"\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Frun-a-python-excel-report-in-docker\u002F","Run a Python Excel Report in Docker"," — dependencies baked into an image.",[1505,1506,1507],"style",{},"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 .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-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}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 pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}",{"title":25,"searchDepth":242,"depth":242,"links":1509},[1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521],{"id":216,"depth":242,"text":217},{"id":280,"depth":242,"text":281},{"id":369,"depth":242,"text":370},{"id":562,"depth":242,"text":563},{"id":577,"depth":242,"text":578},{"id":880,"depth":242,"text":881},{"id":1031,"depth":242,"text":1032},{"id":1058,"depth":242,"text":1059},{"id":1359,"depth":242,"text":1360},{"id":1421,"depth":242,"text":1422},{"id":1445,"depth":242,"text":1446},{"id":1473,"depth":242,"text":1474},"2026-09-23","pandas reads and writes Excel through separate engine packages, and the error means the engine is not importable from the Python that runs your code. Find which interpreter is running, install into that one, and handle the version-too-old variant.","md",[1526,1528,1530,1532],{"q":1451,"a":1527},"pandas does not parse Excel files itself. It hands .xlsx files to an engine package — openpyxl by default — and treats that package as an optional dependency, so installing pandas alone does not install it.",{"q":1457,"a":1529},"It was installed into a different Python than the one running your code — a different virtual environment, a different Jupyter kernel, or the system Python. Install with the same interpreter using python -m pip, or %pip inside the notebook.",{"q":1463,"a":1531},"openpyxl is installed but older than your pandas version supports. Upgrade it with python -m pip install --upgrade openpyxl.",{"q":1469,"a":1533},"xlrd for legacy .xls, pyxlsb or python-calamine for .xlsb, and odfpy for .ods. python-calamine reads all of them and .xlsx as well.","fix missing optional dependency 'openpyxl' in pandas",null,{"breadcrumb":1537},[1538,1541,1544],{"name":1539,"item":1540},"Home","\u002F",{"name":1542,"item":1543},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":52,"item":51},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-missing-optional-dependency-openpyxl",{"title":1547,"description":1548},"Fix Missing optional dependency 'openpyxl' (pandas read_excel \u002F to_excel)","Fix pandas ImportError \"Missing optional dependency 'openpyxl'\" and \"`Import openpyxl` failed\" — install the engine into the right interpreter, Jupyter kernels, IDE environments, minimum versions, and the engines for xls, xlsb and ods.","fix-missing-optional-dependency-openpyxl","getting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-missing-optional-dependency-openpyxl\u002Findex",[1552,1553,1554],"troubleshooting","reading-excel","pandas","how-to","pNWdIzlGVi64-foT1Np8HmWUMWfbT6Fyiza7lDAUVwc",[1558,1562],{"title":1559,"path":1560,"stem":1561,"children":-1},"Fix \"MergedCell object attribute value is read-only\" in openpyxl","\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-mergedcell-value-is-read-only-in-openpyxl","getting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-mergedcell-value-is-read-only-in-openpyxl\u002Findex",{"title":1563,"path":1564,"stem":1565,"children":-1},"Fix #NAME? in Formulas Written from Python (XLOOKUP, TEXTJOIN, IFS)","\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-name-error-for-new-excel-functions-written-by-python","getting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-name-error-for-new-excel-functions-written-by-python\u002Findex",[1567,1569],{"path":1568,"title":1542},"\u002Fgetting-started-with-python-excel-automation",{"path":1570,"title":52},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors",[],[1573,1577,1580,1583,1586,1589],{"path":1574,"title":1575,"kind":1576},"\u002Fautomating-reporting-workflows\u002Ferror-handling-and-logging-in-excel-automation\u002Fhandle-permission-denied-when-writing-excel-in-python","Handle Permission Denied When Writing Excel in Python","fix",{"path":1578,"title":1579,"kind":1555},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fwhat-openpyxl-loses-when-saving-an-existing-workbook","What openpyxl Loses When You Save an Existing Workbook",{"path":1581,"title":1582,"kind":1576},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates","Fix Excel Serial Numbers Showing Instead of Dates",{"path":1584,"title":1585,"kind":1555},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fhandle-daylight-saving-time-in-excel-timestamps","Handle Daylight Saving Time in Excel Timestamps",{"path":1587,"title":1588,"kind":1555},"\u002Fautomating-reporting-workflows\u002Fautomating-excel-online-with-microsoft-graph\u002Fhandle-microsoft-graph-throttling-for-excel","Handle Microsoft Graph Throttling in Excel Automation",{"path":1590,"title":1591,"kind":1592},"\u002Fautomating-reporting-workflows\u002Ferror-handling-and-logging-in-excel-automation","Error Handling and Logging in Excel Automation","guide",1790972065975]