[{"data":1,"prerenderedAt":2395},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-legacy-array-formulas-with-openpyxl":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-legacy-array-formulas-with-openpyxl":2360,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-legacy-array-formulas-with-openpyxl":2369,"children:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-legacy-array-formulas-with-openpyxl":2374,"related:\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-legacy-array-formulas-with-openpyxl":2375},{"id":4,"title":5,"body":6,"dateModified":2326,"datePublished":2326,"description":2327,"extension":2328,"faq":2329,"keyword":2338,"kind":2339,"meta":2340,"navigation":114,"path":2349,"seo":2350,"slug":2353,"stem":2354,"topics":2355,"type":2358,"__hash__":2359},"docs\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-legacy-array-formulas-with-openpyxl\u002Findex.md","Write Legacy Array Formulas (Ctrl+Shift+Enter) with openpyxl",{"type":7,"value":8,"toc":2312},"minimark",[9,29,34,62,69,73,354,384,388,544,563,718,722,725,992,1026,1268,1272,1275,1378,1411,1415,1418,1626,1633,1637,1649,1783,1787,1790,2132,2160,2164,2216,2220,2244,2248,2257,2263,2269,2275,2279,2308],[10,11,12,13,17,18,22,23,28],"p",{},"Before Excel 365 introduced dynamic arrays, a formula that worked on whole ranges at once — multiplying two columns and summing the products, or taking the maximum of a column where a condition holds — had to be entered with Ctrl+Shift+Enter. Excel then shows it in braces, ",[14,15,16],"code",{},"{=SUM(A2:A5*B2:B5)}",", and stores it in the file with a flag that says \"evaluate as an array\". Workbooks built for older Excel versions, shared with people who still use them, or following a house style written before 2019 are full of these. Writing one from Python is easy with openpyxl, ",[19,20,21],"em",{},"if"," you know the flag exists: without it the same text is stored as an ordinary formula, and Excel and LibreOffice quietly evaluate only the first row. This page belongs to ",[24,25,27],"a",{"href":26},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002F","Working with Excel Formulas in Python",".",[30,31,33],"h2",{"id":32},"prerequisites","Prerequisites",[35,36,41],"pre",{"className":37,"code":38,"language":39,"meta":40,"style":40},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install openpyxl xlsxwriter\n","bash","",[14,42,43],{"__ignoreMap":40},[44,45,48,52,56,59],"span",{"class":46,"line":47},"line",1,[44,49,51],{"class":50},"sMTad","pip",[44,53,55],{"class":54},"srMev"," install",[44,57,58],{"class":54}," openpyxl",[44,60,61],{"class":54}," xlsxwriter\n",[10,63,64,65,68],{},"LibreOffice (",[14,66,67],{},"soffice",") is used to recalculate the files and check the results; it is optional but strongly recommended, because neither openpyxl nor XlsxWriter calculates formulas.",[30,70,72],{"id":71},"step-1-see-why-the-flag-matters","Step 1 — See why the flag matters",[35,74,78],{"className":75,"code":76,"language":77,"meta":40,"style":40},"language-python shiki shiki-themes github-light github-dark-high-contrast","from openpyxl import Workbook\nfrom openpyxl.worksheet.formula import ArrayFormula\n\ndef order_sheet():\n    wb = Workbook()\n    ws = wb.active\n    ws.title = \"Orders\"\n    ws.append([\"Qty\", \"Price\", \"Line total\"])\n    for row in [(3, 89.0), (5, 45.5), (12, 14.0), (4, 22.0)]:\n        ws.append(row)\n    return wb, ws\n\nwb, ws = order_sheet()\nws[\"E1\"], ws[\"F1\"] = \"Plain formula\", \"Array formula\"\nws[\"E2\"] = \"=SUM(A2:A5*B2:B5)\"\nws[\"F2\"] = ArrayFormula(\"F2\", \"=SUM(A2:A5*B2:B5)\")\nwb.save(\"orders_compare.xlsx\")\n","python",[14,79,80,96,109,116,129,141,152,163,186,244,250,259,264,275,303,318,343],{"__ignoreMap":40},[44,81,82,86,90,93],{"class":46,"line":47},[44,83,85],{"class":84},"s-kum","from",[44,87,89],{"class":88},"skGVy"," openpyxl ",[44,91,92],{"class":84},"import",[44,94,95],{"class":88}," Workbook\n",[44,97,99,101,104,106],{"class":46,"line":98},2,[44,100,85],{"class":84},[44,102,103],{"class":88}," openpyxl.worksheet.formula ",[44,105,92],{"class":84},[44,107,108],{"class":88}," ArrayFormula\n",[44,110,112],{"class":46,"line":111},3,[44,113,115],{"emptyLinePlaceholder":114},true,"\n",[44,117,119,122,126],{"class":46,"line":118},4,[44,120,121],{"class":84},"def",[44,123,125],{"class":124},"s_Opv"," order_sheet",[44,127,128],{"class":88},"():\n",[44,130,132,135,138],{"class":46,"line":131},5,[44,133,134],{"class":88},"    wb ",[44,136,137],{"class":84},"=",[44,139,140],{"class":88}," Workbook()\n",[44,142,144,147,149],{"class":46,"line":143},6,[44,145,146],{"class":88},"    ws ",[44,148,137],{"class":84},[44,150,151],{"class":88}," wb.active\n",[44,153,155,158,160],{"class":46,"line":154},7,[44,156,157],{"class":88},"    ws.title ",[44,159,137],{"class":84},[44,161,162],{"class":54}," \"Orders\"\n",[44,164,166,169,172,175,178,180,183],{"class":46,"line":165},8,[44,167,168],{"class":88},"    ws.append([",[44,170,171],{"class":54},"\"Qty\"",[44,173,174],{"class":88},", ",[44,176,177],{"class":54},"\"Price\"",[44,179,174],{"class":88},[44,181,182],{"class":54},"\"Line total\"",[44,184,185],{"class":88},"])\n",[44,187,189,192,195,198,201,205,207,210,213,216,218,221,223,226,228,231,233,236,238,241],{"class":46,"line":188},9,[44,190,191],{"class":84},"    for",[44,193,194],{"class":88}," row ",[44,196,197],{"class":84},"in",[44,199,200],{"class":88}," [(",[44,202,204],{"class":203},"sP0c6","3",[44,206,174],{"class":88},[44,208,209],{"class":203},"89.0",[44,211,212],{"class":88},"), (",[44,214,215],{"class":203},"5",[44,217,174],{"class":88},[44,219,220],{"class":203},"45.5",[44,222,212],{"class":88},[44,224,225],{"class":203},"12",[44,227,174],{"class":88},[44,229,230],{"class":203},"14.0",[44,232,212],{"class":88},[44,234,235],{"class":203},"4",[44,237,174],{"class":88},[44,239,240],{"class":203},"22.0",[44,242,243],{"class":88},")]:\n",[44,245,247],{"class":46,"line":246},10,[44,248,249],{"class":88},"        ws.append(row)\n",[44,251,253,256],{"class":46,"line":252},11,[44,254,255],{"class":84},"    return",[44,257,258],{"class":88}," wb, ws\n",[44,260,262],{"class":46,"line":261},12,[44,263,115],{"emptyLinePlaceholder":114},[44,265,267,270,272],{"class":46,"line":266},13,[44,268,269],{"class":88},"wb, ws ",[44,271,137],{"class":84},[44,273,274],{"class":88}," order_sheet()\n",[44,276,278,281,284,287,290,293,295,298,300],{"class":46,"line":277},14,[44,279,280],{"class":88},"ws[",[44,282,283],{"class":54},"\"E1\"",[44,285,286],{"class":88},"], ws[",[44,288,289],{"class":54},"\"F1\"",[44,291,292],{"class":88},"] ",[44,294,137],{"class":84},[44,296,297],{"class":54}," \"Plain formula\"",[44,299,174],{"class":88},[44,301,302],{"class":54},"\"Array formula\"\n",[44,304,306,308,311,313,315],{"class":46,"line":305},15,[44,307,280],{"class":88},[44,309,310],{"class":54},"\"E2\"",[44,312,292],{"class":88},[44,314,137],{"class":84},[44,316,317],{"class":54}," \"=SUM(A2:A5*B2:B5)\"\n",[44,319,321,323,326,328,330,333,335,337,340],{"class":46,"line":320},16,[44,322,280],{"class":88},[44,324,325],{"class":54},"\"F2\"",[44,327,292],{"class":88},[44,329,137],{"class":84},[44,331,332],{"class":88}," ArrayFormula(",[44,334,325],{"class":54},[44,336,174],{"class":88},[44,338,339],{"class":54},"\"=SUM(A2:A5*B2:B5)\"",[44,341,342],{"class":88},")\n",[44,344,346,349,352],{"class":46,"line":345},17,[44,347,348],{"class":88},"wb.save(",[44,350,351],{"class":54},"\"orders_compare.xlsx\"",[44,353,342],{"class":88},[10,355,356,359,360,363,364,366,367,370,371,373,374,359,377,379,380,383],{},[14,357,358],{},"E2"," and ",[14,361,362],{},"F2"," contain identical text. The only difference is that ",[14,365,362],{}," is wrapped in ",[14,368,369],{},"ArrayFormula",", whose first argument is the cell or range the array occupies. In the file, ",[14,372,362],{}," is written as ",[14,375,376],{},"\u003Cf t=\"array\" ref=\"F2\">…\u003C\u002Ff>",[14,378,358],{}," as a plain ",[14,381,382],{},"\u003Cf>",". The next step shows what that changes.",[30,385,387],{"id":386},"step-2-recalculate-and-compare","Step 2 — Recalculate and compare",[35,389,391],{"className":75,"code":390,"language":77,"meta":40,"style":40},"import subprocess\nfrom openpyxl import load_workbook\n\nsubprocess.run([\"soffice\", \"--headless\", \"--convert-to\", \"xlsx\", \"--outdir\", \"recalc\",\n                \"orders_compare.xlsx\"], check=True, capture_output=True)\nvalues = load_workbook(\"recalc\u002Forders_compare.xlsx\", data_only=True)[\"Orders\"]\nprint(\"plain formula E2:\", values[\"E2\"].value)\nprint(\"array formula F2:\", values[\"F2\"].value)\n",[14,392,393,400,411,415,451,479,510,529],{"__ignoreMap":40},[44,394,395,397],{"class":46,"line":47},[44,396,92],{"class":84},[44,398,399],{"class":88}," subprocess\n",[44,401,402,404,406,408],{"class":46,"line":98},[44,403,85],{"class":84},[44,405,89],{"class":88},[44,407,92],{"class":84},[44,409,410],{"class":88}," load_workbook\n",[44,412,413],{"class":46,"line":111},[44,414,115],{"emptyLinePlaceholder":114},[44,416,417,420,423,425,428,430,433,435,438,440,443,445,448],{"class":46,"line":118},[44,418,419],{"class":88},"subprocess.run([",[44,421,422],{"class":54},"\"soffice\"",[44,424,174],{"class":88},[44,426,427],{"class":54},"\"--headless\"",[44,429,174],{"class":88},[44,431,432],{"class":54},"\"--convert-to\"",[44,434,174],{"class":88},[44,436,437],{"class":54},"\"xlsx\"",[44,439,174],{"class":88},[44,441,442],{"class":54},"\"--outdir\"",[44,444,174],{"class":88},[44,446,447],{"class":54},"\"recalc\"",[44,449,450],{"class":88},",\n",[44,452,453,456,459,463,465,468,470,473,475,477],{"class":46,"line":131},[44,454,455],{"class":54},"                \"orders_compare.xlsx\"",[44,457,458],{"class":88},"], ",[44,460,462],{"class":461},"sa561","check",[44,464,137],{"class":84},[44,466,467],{"class":203},"True",[44,469,174],{"class":88},[44,471,472],{"class":461},"capture_output",[44,474,137],{"class":84},[44,476,467],{"class":203},[44,478,342],{"class":88},[44,480,481,484,486,489,492,494,497,499,501,504,507],{"class":46,"line":143},[44,482,483],{"class":88},"values ",[44,485,137],{"class":84},[44,487,488],{"class":88}," load_workbook(",[44,490,491],{"class":54},"\"recalc\u002Forders_compare.xlsx\"",[44,493,174],{"class":88},[44,495,496],{"class":461},"data_only",[44,498,137],{"class":84},[44,500,467],{"class":203},[44,502,503],{"class":88},")[",[44,505,506],{"class":54},"\"Orders\"",[44,508,509],{"class":88},"]\n",[44,511,512,515,518,521,524,526],{"class":46,"line":154},[44,513,514],{"class":203},"print",[44,516,517],{"class":88},"(",[44,519,520],{"class":54},"\"plain formula E2:\"",[44,522,523],{"class":88},", values[",[44,525,310],{"class":54},[44,527,528],{"class":88},"].value)\n",[44,530,531,533,535,538,540,542],{"class":46,"line":165},[44,532,514],{"class":203},[44,534,517],{"class":88},[44,536,537],{"class":54},"\"array formula F2:\"",[44,539,523],{"class":88},[44,541,325],{"class":54},[44,543,528],{"class":88},[10,545,546,547,550,551,554,555,558,559,28],{},"The array formula returns 750.5, the sum of all four line totals. The plain formula returns 267 — the first row's product only. Without the array flag, a range inside a scalar formula is reduced to the single cell on the formula's own row (\"implicit intersection\"), so ",[14,548,549],{},"A2:A5*B2:B5"," became ",[14,552,553],{},"A2*B2",". Pre-365 Excel does the same, or shows ",[14,556,557],{},"#VALUE!"," when the formula sits on a row outside the ranges. No error is raised anywhere; the workbook simply reports the wrong total. This is the strongest reason to verify formulas by recalculating, as described in ",[24,560,562],{"href":561},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Frecalculate-excel-formulas-without-excel-in-python\u002F","Recalculate Excel Formulas Without Excel in Python",[564,565,573,574,573,578,573,582,573,589,573,599,573,610,573,617,573,623,573,629,573,637,573,641,573,646,573,650,573,655,573,659,573,664,573,669,573,676,573,681,573,685,573,689,573,694,573,697,573,702,573,705,573,710,573,713],"svg",{"viewBox":566,"role":567,"ariaLabelledBy":568,"xmlns":571,"style":572},"4 0 752 233","img",[569,570],"af-flag-t","af-flag-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  ",[575,576,577],"title",{"id":569},"The same formula text with and without the array flag",[579,580,581],"desc",{"id":570},"Written as a plain formula, =SUM(A2:A5*B2:B5) is evaluated with implicit intersection and returns 267, the first row only. Written as an ArrayFormula it is evaluated over the whole ranges and returns 750.5.",[583,584],"rect",{"x":235,"y":585,"width":586,"height":587,"fill":588},"0","752","233","#ffffff",[583,590],{"x":591,"y":592,"width":593,"height":594,"rx":595,"fill":596,"stroke":597,"style":598},"20.0","16.0","351.0","201.0","14","#fce9e9","var(--danger,#dc2626)","stroke-width:2px",[600,601,603],"g",{"transform":602},"translate(182.5,29.0) scale(1.083)",[604,605],"path",{"d":606,"fill":607,"stroke":608,"style":609},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","none","var(--accent-ink,#be185d)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[611,612,616],"text",{"x":613,"y":614,"style":615},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","ws[\"E2\"] = \"=SUM(…)\"",[46,618],{"x1":619,"y1":620,"x2":621,"y2":620,"stroke":597,"style":622},"36.0","91.0","355.0","stroke-width:1px",[611,624,628],{"x":625,"y":626,"style":627},"60.0","111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","stored as \u003Cf>",[600,630,632],{"transform":631},"translate(38.5,99.5) scale(0.625)",[604,633],{"d":634,"fill":607,"stroke":635,"style":636},"M6 6l12 12 M18 6L6 18","var(--accent,#f43f8f)","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[611,638,640],{"x":625,"y":639,"style":627},"137.0","ranges reduced to one row",[600,642,644],{"transform":643},"translate(38.5,125.5) scale(0.625)",[604,645],{"d":634,"fill":607,"stroke":635,"style":636},[611,647,649],{"x":625,"y":648,"style":627},"163.0","result 267 (first row)",[600,651,653],{"transform":652},"translate(38.5,151.5) scale(0.625)",[604,654],{"d":634,"fill":607,"stroke":635,"style":636},[611,656,658],{"x":625,"y":657,"style":627},"189.0","no error anywhere",[600,660,662],{"transform":661},"translate(38.5,177.5) scale(0.625)",[604,663],{"d":634,"fill":607,"stroke":635,"style":636},[583,665],{"x":666,"y":592,"width":593,"height":594,"rx":595,"fill":667,"stroke":668,"style":598},"389.0","#d9f4f1","var(--teal,#0f9488)",[600,670,672],{"transform":671},"translate(551.5,29.0) scale(1.083)",[604,673],{"d":674,"fill":607,"stroke":675,"style":609},"M5 12.5l4.5 4.5L19 7","var(--teal-ink,#0b6157)",[611,677,680],{"x":678,"y":614,"style":679},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","ArrayFormula(\"F2\", \"=SUM(…)\")",[46,682],{"x1":683,"y1":620,"x2":684,"y2":620,"stroke":668,"style":622},"405.0","724.0",[611,686,688],{"x":687,"y":626,"style":627},"429.0","stored as \u003Cf t=\"array\">",[600,690,692],{"transform":691},"translate(407.5,99.5) scale(0.625)",[604,693],{"d":674,"fill":607,"stroke":668,"style":636},[611,695,696],{"x":687,"y":639,"style":627},"evaluated over all rows",[600,698,700],{"transform":699},"translate(407.5,125.5) scale(0.625)",[604,701],{"d":674,"fill":607,"stroke":668,"style":636},[611,703,704],{"x":687,"y":648,"style":627},"result 750.5",[600,706,708],{"transform":707},"translate(407.5,151.5) scale(0.625)",[604,709],{"d":674,"fill":607,"stroke":668,"style":636},[611,711,712],{"x":687,"y":657,"style":627},"shown in braces in Excel",[600,714,716],{"transform":715},"translate(407.5,177.5) scale(0.625)",[604,717],{"d":674,"fill":607,"stroke":668,"style":636},[30,719,721],{"id":720},"step-3-a-multi-cell-array-formula","Step 3 — A multi-cell array formula",[10,723,724],{},"A legacy array formula can also fill a block of cells with one formula — every cell shows its own element of the result:",[35,726,728],{"className":75,"code":727,"language":77,"meta":40,"style":40},"wb, ws = order_sheet()\nws[\"C2\"] = ArrayFormula(\"C2:C5\", \"=A2:A5*B2:B5\")\nws[\"E1\"], ws[\"E2\"] = \"Highest price for Qty > 4\", ArrayFormula(\"E2\", \"=MAX(IF(A2:A5>4,B2:B5))\")\nws[\"F1\"], ws[\"F2\"] = \"Order total\", ArrayFormula(\"F2\", \"=SUM(C2:C5)\")\nwb.save(\"orders_array.xlsx\")\n\nsubprocess.run([\"soffice\", \"--headless\", \"--convert-to\", \"xlsx\", \"--outdir\", \"recalc\",\n                \"orders_array.xlsx\"], check=True, capture_output=True)\nv = load_workbook(\"recalc\u002Forders_array.xlsx\", data_only=True)[\"Orders\"]\nprint(\"line totals:\", [v[f\"C{r}\"].value for r in range(2, 6)])\nprint(\"max price where qty > 4:\", v[\"E2\"].value, \"| total:\", v[\"F2\"].value)\n",[14,729,730,738,761,790,818,827,831,859,882,908,966],{"__ignoreMap":40},[44,731,732,734,736],{"class":46,"line":47},[44,733,269],{"class":88},[44,735,137],{"class":84},[44,737,274],{"class":88},[44,739,740,742,745,747,749,751,754,756,759],{"class":46,"line":98},[44,741,280],{"class":88},[44,743,744],{"class":54},"\"C2\"",[44,746,292],{"class":88},[44,748,137],{"class":84},[44,750,332],{"class":88},[44,752,753],{"class":54},"\"C2:C5\"",[44,755,174],{"class":88},[44,757,758],{"class":54},"\"=A2:A5*B2:B5\"",[44,760,342],{"class":88},[44,762,763,765,767,769,771,773,775,778,781,783,785,788],{"class":46,"line":111},[44,764,280],{"class":88},[44,766,283],{"class":54},[44,768,286],{"class":88},[44,770,310],{"class":54},[44,772,292],{"class":88},[44,774,137],{"class":84},[44,776,777],{"class":54}," \"Highest price for Qty > 4\"",[44,779,780],{"class":88},", ArrayFormula(",[44,782,310],{"class":54},[44,784,174],{"class":88},[44,786,787],{"class":54},"\"=MAX(IF(A2:A5>4,B2:B5))\"",[44,789,342],{"class":88},[44,791,792,794,796,798,800,802,804,807,809,811,813,816],{"class":46,"line":118},[44,793,280],{"class":88},[44,795,289],{"class":54},[44,797,286],{"class":88},[44,799,325],{"class":54},[44,801,292],{"class":88},[44,803,137],{"class":84},[44,805,806],{"class":54}," \"Order total\"",[44,808,780],{"class":88},[44,810,325],{"class":54},[44,812,174],{"class":88},[44,814,815],{"class":54},"\"=SUM(C2:C5)\"",[44,817,342],{"class":88},[44,819,820,822,825],{"class":46,"line":131},[44,821,348],{"class":88},[44,823,824],{"class":54},"\"orders_array.xlsx\"",[44,826,342],{"class":88},[44,828,829],{"class":46,"line":143},[44,830,115],{"emptyLinePlaceholder":114},[44,832,833,835,837,839,841,843,845,847,849,851,853,855,857],{"class":46,"line":154},[44,834,419],{"class":88},[44,836,422],{"class":54},[44,838,174],{"class":88},[44,840,427],{"class":54},[44,842,174],{"class":88},[44,844,432],{"class":54},[44,846,174],{"class":88},[44,848,437],{"class":54},[44,850,174],{"class":88},[44,852,442],{"class":54},[44,854,174],{"class":88},[44,856,447],{"class":54},[44,858,450],{"class":88},[44,860,861,864,866,868,870,872,874,876,878,880],{"class":46,"line":165},[44,862,863],{"class":54},"                \"orders_array.xlsx\"",[44,865,458],{"class":88},[44,867,462],{"class":461},[44,869,137],{"class":84},[44,871,467],{"class":203},[44,873,174],{"class":88},[44,875,472],{"class":461},[44,877,137],{"class":84},[44,879,467],{"class":203},[44,881,342],{"class":88},[44,883,884,887,889,891,894,896,898,900,902,904,906],{"class":46,"line":188},[44,885,886],{"class":88},"v ",[44,888,137],{"class":84},[44,890,488],{"class":88},[44,892,893],{"class":54},"\"recalc\u002Forders_array.xlsx\"",[44,895,174],{"class":88},[44,897,496],{"class":461},[44,899,137],{"class":84},[44,901,467],{"class":203},[44,903,503],{"class":88},[44,905,506],{"class":54},[44,907,509],{"class":88},[44,909,910,912,914,917,920,923,926,930,933,936,939,942,945,948,950,953,955,958,960,963],{"class":46,"line":246},[44,911,514],{"class":203},[44,913,517],{"class":88},[44,915,916],{"class":54},"\"line totals:\"",[44,918,919],{"class":88},", [v[",[44,921,922],{"class":84},"f",[44,924,925],{"class":54},"\"C",[44,927,929],{"class":928},"sSjpA","{",[44,931,932],{"class":88},"r",[44,934,935],{"class":928},"}",[44,937,938],{"class":54},"\"",[44,940,941],{"class":88},"].value ",[44,943,944],{"class":84},"for",[44,946,947],{"class":88}," r ",[44,949,197],{"class":84},[44,951,952],{"class":203}," range",[44,954,517],{"class":88},[44,956,957],{"class":203},"2",[44,959,174],{"class":88},[44,961,962],{"class":203},"6",[44,964,965],{"class":88},")])\n",[44,967,968,970,972,975,978,980,983,986,988,990],{"class":46,"line":252},[44,969,514],{"class":203},[44,971,517],{"class":88},[44,973,974],{"class":54},"\"max price where qty > 4:\"",[44,976,977],{"class":88},", v[",[44,979,310],{"class":54},[44,981,982],{"class":88},"].value, ",[44,984,985],{"class":54},"\"| total:\"",[44,987,977],{"class":88},[44,989,325],{"class":54},[44,991,528],{"class":88},[10,993,994,995,998,999,1002,1003,1006,1007,1010,1011,1014,1015,1018,1019,1022,1023,1025],{},"The formula is assigned to the top-left cell, ",[14,996,997],{},"C2",", and its ",[14,1000,1001],{},"ref"," names the whole block, ",[14,1004,1005],{},"C2:C5",". After recalculation the four cells hold 267, 227.5, 168 and 88. ",[14,1008,1009],{},"MAX(IF(A2:A5>4, B2:B5))"," is the classic conditional maximum that needs array evaluation: the ",[14,1012,1013],{},"IF"," builds an array of prices where the quantity exceeds 4 and ",[14,1016,1017],{},"FALSE"," elsewhere, and ",[14,1020,1021],{},"MAX"," ignores the ",[14,1024,1017],{}," values, giving 45.5. In Excel the block behaves as a unit: users cannot edit or delete one cell of it, only the whole range.",[564,1027,573,1033,573,1036,573,1039,573,1044,573,1050,573,1054,573,1060,573,1065,573,1070,573,1074,573,1080,573,1084,573,1088,573,1092,573,1096,573,1099,573,1103,573,1107,573,1111,573,1115,573,1119,573,1122,573,1127,573,1132,573,1136,573,1138,573,1141,573,1143,573,1146,573,1148,573,1150,573,1153,573,1155,573,1158,573,1161,573,1164,573,1166,573,1169,573,1171,573,1173,573,1175,573,1179,573,1181,573,1185,573,1188,573,1190,573,1193,573,1196,573,1199,573,1201,573,1203,573,1205,573,1207,573,1209,573,1212,573,1214,573,1216,573,1218,573,1221,573,1224,573,1226,573,1228,573,1230,573,1232,573,1234,573,1237,573,1239,573,1241,573,1243,573,1246,573,1249,573,1251,573,1253,573,1255,573,1257,573,1259,573,1262,573,1264,573,1266],{"viewBox":1028,"role":567,"ariaLabelledBy":1029,"xmlns":571,"style":1032},"137 0 486 224",[1030,1031],"af-block-t","af-block-d","width:100%;max-width:486px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[575,1034,1035],{"id":1030},"One array formula filling C2:C5",[579,1037,1038],{"id":1031},"The order sheet after recalculation. A single array formula stored in C2 with ref C2:C5 fills the line totals 267, 227.5, 168 and 88. E2 holds the conditional maximum 45.5 and F2 the total 750.5.",[583,1040],{"x":1041,"y":585,"width":1042,"height":1043,"fill":588},"137","486","224",[583,1045],{"x":1046,"y":592,"width":1047,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},"153.0","454.0","28.0","var(--line,#cdd5e6)",[583,1051],{"x":1046,"y":592,"width":1052,"height":1048,"rx":585,"fill":1053,"stroke":1049,"style":622},"40.0","#e7ebef",[611,1055,1059],{"x":1056,"y":1057,"style":1058},"173.0","35.0","font-size:12px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","fx",[611,1061,1064],{"x":1062,"y":1057,"style":1063},"203.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace","{=A2:A5*B2:B5}",[583,1066],{"x":1046,"y":1067,"width":1068,"height":1069,"rx":585,"fill":1053,"stroke":1049,"style":622},"44.0","32.0","24.0",[583,1071],{"x":1072,"y":1067,"width":1073,"height":1069,"rx":585,"fill":1053,"stroke":1049,"style":622},"185.0","44.2",[611,1075,1079],{"x":1076,"y":1077,"style":1078},"207.1","61.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[583,1081],{"x":1082,"y":1067,"width":1083,"height":1069,"rx":585,"fill":1053,"stroke":1049,"style":622},"229.2","53.0",[611,1085,1087],{"x":1086,"y":1077,"style":1078},"255.7","B",[583,1089],{"x":1090,"y":1067,"width":1091,"height":1069,"rx":585,"fill":1053,"stroke":1049,"style":622},"282.2","75.8",[611,1093,1095],{"x":1094,"y":1077,"style":1078},"320.1","C",[583,1097],{"x":1098,"y":1067,"width":1067,"height":1069,"rx":585,"fill":1053,"stroke":1049,"style":622},"358.0",[611,1100,1102],{"x":1101,"y":1077,"style":1078},"380.0","D",[583,1104],{"x":1105,"y":1067,"width":1106,"height":1069,"rx":585,"fill":1053,"stroke":1049,"style":622},"402.0","120.4",[611,1108,1110],{"x":1109,"y":1077,"style":1078},"462.2","E",[583,1112],{"x":1113,"y":1067,"width":1114,"height":1069,"rx":585,"fill":1053,"stroke":1049,"style":622},"522.4","84.6",[611,1116,1118],{"x":1117,"y":1077,"style":1078},"564.7","F",[583,1120],{"x":1046,"y":1121,"width":1068,"height":1048,"rx":585,"fill":1053,"stroke":1049,"style":622},"68.0",[611,1123,1126],{"x":1124,"y":1125,"style":1078},"169.0","87.0","1",[583,1128],{"x":1072,"y":1121,"width":1073,"height":1048,"rx":585,"fill":1129,"stroke":1130,"style":1131},"#f0f4ff","var(--brand,#5b5cf0)","stroke-width:1.5px",[611,1133,1135],{"x":1076,"y":1125,"style":1134},"font-size:11px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Qty",[583,1137],{"x":1082,"y":1121,"width":1083,"height":1048,"rx":585,"fill":1129,"stroke":1130,"style":1131},[611,1139,1140],{"x":1086,"y":1125,"style":1134},"Price",[583,1142],{"x":1090,"y":1121,"width":1091,"height":1048,"rx":585,"fill":1129,"stroke":1130,"style":1131},[611,1144,1145],{"x":1094,"y":1125,"style":1134},"Line total",[583,1147],{"x":1098,"y":1121,"width":1067,"height":1048,"rx":585,"fill":1129,"stroke":1130,"style":1131},[583,1149],{"x":1105,"y":1121,"width":1106,"height":1048,"rx":585,"fill":1129,"stroke":1130,"style":1131},[611,1151,1152],{"x":1109,"y":1125,"style":1134},"Max price, qty>4",[583,1154],{"x":1113,"y":1121,"width":1114,"height":1048,"rx":585,"fill":1129,"stroke":1130,"style":1131},[611,1156,1157],{"x":1117,"y":1125,"style":1134},"Order total",[583,1159],{"x":1046,"y":1160,"width":1068,"height":1048,"rx":585,"fill":1053,"stroke":1049,"style":622},"96.0",[611,1162,957],{"x":1124,"y":1163,"style":1078},"115.0",[583,1165],{"x":1072,"y":1160,"width":1073,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[611,1167,204],{"x":1076,"y":1163,"style":1168},"font-size:11px;font-weight:400;fill:var(--text,#172033);text-anchor:middle",[583,1170],{"x":1082,"y":1160,"width":1083,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[611,1172,209],{"x":1086,"y":1163,"style":1168},[583,1174],{"x":1090,"y":1160,"width":1091,"height":1048,"rx":585,"fill":667,"stroke":668,"style":1131},[611,1176,1178],{"x":1094,"y":1163,"style":1177},"font-size:11px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","267.0",[583,1180],{"x":1098,"y":1160,"width":1067,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[583,1182],{"x":1105,"y":1160,"width":1106,"height":1048,"rx":585,"fill":1183,"stroke":1184,"style":1131},"#fdefd8","var(--gold,#b4740a)",[611,1186,220],{"x":1109,"y":1163,"style":1187},"font-size:11px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle",[583,1189],{"x":1113,"y":1160,"width":1114,"height":1048,"rx":585,"fill":1183,"stroke":1184,"style":1131},[611,1191,1192],{"x":1117,"y":1163,"style":1187},"750.5",[583,1194],{"x":1046,"y":1195,"width":1068,"height":1048,"rx":585,"fill":1053,"stroke":1049,"style":622},"124.0",[611,1197,204],{"x":1124,"y":1198,"style":1078},"143.0",[583,1200],{"x":1072,"y":1195,"width":1073,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[611,1202,215],{"x":1076,"y":1198,"style":1168},[583,1204],{"x":1082,"y":1195,"width":1083,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[611,1206,220],{"x":1086,"y":1198,"style":1168},[583,1208],{"x":1090,"y":1195,"width":1091,"height":1048,"rx":585,"fill":667,"stroke":668,"style":1131},[611,1210,1211],{"x":1094,"y":1198,"style":1177},"227.5",[583,1213],{"x":1098,"y":1195,"width":1067,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[583,1215],{"x":1105,"y":1195,"width":1106,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[583,1217],{"x":1113,"y":1195,"width":1114,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[583,1219],{"x":1046,"y":1220,"width":1068,"height":1048,"rx":585,"fill":1053,"stroke":1049,"style":622},"152.0",[611,1222,235],{"x":1124,"y":1223,"style":1078},"171.0",[583,1225],{"x":1072,"y":1220,"width":1073,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[611,1227,225],{"x":1076,"y":1223,"style":1168},[583,1229],{"x":1082,"y":1220,"width":1083,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[611,1231,230],{"x":1086,"y":1223,"style":1168},[583,1233],{"x":1090,"y":1220,"width":1091,"height":1048,"rx":585,"fill":667,"stroke":668,"style":1131},[611,1235,1236],{"x":1094,"y":1223,"style":1177},"168.0",[583,1238],{"x":1098,"y":1220,"width":1067,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[583,1240],{"x":1105,"y":1220,"width":1106,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[583,1242],{"x":1113,"y":1220,"width":1114,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[583,1244],{"x":1046,"y":1245,"width":1068,"height":1048,"rx":585,"fill":1053,"stroke":1049,"style":622},"180.0",[611,1247,215],{"x":1124,"y":1248,"style":1078},"199.0",[583,1250],{"x":1072,"y":1245,"width":1073,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[611,1252,235],{"x":1076,"y":1248,"style":1168},[583,1254],{"x":1082,"y":1245,"width":1083,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[611,1256,240],{"x":1086,"y":1248,"style":1168},[583,1258],{"x":1090,"y":1245,"width":1091,"height":1048,"rx":585,"fill":667,"stroke":668,"style":1131},[611,1260,1261],{"x":1094,"y":1248,"style":1177},"88.0",[583,1263],{"x":1098,"y":1245,"width":1067,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[583,1265],{"x":1105,"y":1245,"width":1106,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[583,1267],{"x":1113,"y":1245,"width":1114,"height":1048,"rx":585,"fill":588,"stroke":1049,"style":622},[30,1269,1271],{"id":1270},"step-4-read-array-formulas-back","Step 4 — Read array formulas back",[10,1273,1274],{},"When you load a workbook that contains array formulas, openpyxl gives you the same object back:",[35,1276,1278],{"className":75,"code":1277,"language":77,"meta":40,"style":40},"ws = load_workbook(\"orders_array.xlsx\")[\"Orders\"]\nfor coord in (\"C2\", \"C3\", \"E2\"):\n    value = ws[coord].value\n    if isinstance(value, ArrayFormula):\n        print(coord, \"ArrayFormula\", value.ref, value.text)\n    else:\n        print(coord, repr(value))\n",[14,1279,1280,1297,1323,1333,1344,1358,1366],{"__ignoreMap":40},[44,1281,1282,1285,1287,1289,1291,1293,1295],{"class":46,"line":47},[44,1283,1284],{"class":88},"ws ",[44,1286,137],{"class":84},[44,1288,488],{"class":88},[44,1290,824],{"class":54},[44,1292,503],{"class":88},[44,1294,506],{"class":54},[44,1296,509],{"class":88},[44,1298,1299,1301,1304,1306,1309,1311,1313,1316,1318,1320],{"class":46,"line":98},[44,1300,944],{"class":84},[44,1302,1303],{"class":88}," coord ",[44,1305,197],{"class":84},[44,1307,1308],{"class":88}," (",[44,1310,744],{"class":54},[44,1312,174],{"class":88},[44,1314,1315],{"class":54},"\"C3\"",[44,1317,174],{"class":88},[44,1319,310],{"class":54},[44,1321,1322],{"class":88},"):\n",[44,1324,1325,1328,1330],{"class":46,"line":111},[44,1326,1327],{"class":88},"    value ",[44,1329,137],{"class":84},[44,1331,1332],{"class":88}," ws[coord].value\n",[44,1334,1335,1338,1341],{"class":46,"line":118},[44,1336,1337],{"class":84},"    if",[44,1339,1340],{"class":203}," isinstance",[44,1342,1343],{"class":88},"(value, ArrayFormula):\n",[44,1345,1346,1349,1352,1355],{"class":46,"line":131},[44,1347,1348],{"class":203},"        print",[44,1350,1351],{"class":88},"(coord, ",[44,1353,1354],{"class":54},"\"ArrayFormula\"",[44,1356,1357],{"class":88},", value.ref, value.text)\n",[44,1359,1360,1363],{"class":46,"line":143},[44,1361,1362],{"class":84},"    else",[44,1364,1365],{"class":88},":\n",[44,1367,1368,1370,1372,1375],{"class":46,"line":154},[44,1369,1348],{"class":203},[44,1371,1351],{"class":88},[44,1373,1374],{"class":203},"repr",[44,1376,1377],{"class":88},"(value))\n",[10,1379,1380,1382,1383,1385,1386,1388,1389,1391,1392,1395,1396,1399,1400,1402,1403,1405,1406,1410],{},[14,1381,997],{}," holds an ",[14,1384,369],{}," with ",[14,1387,1001],{}," ",[14,1390,1005],{}," and its text; ",[14,1393,1394],{},"C3",", which is covered by the array, reads as ",[14,1397,1398],{},"None"," — the formula lives only in the top-left cell. Code that audits formulas must therefore check for ",[14,1401,369],{}," objects as well as strings starting with ",[14,1404,137],{},"; a scan that only looks for strings misses every array formula. The audit approach in ",[24,1407,1409],{"href":1408},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Faudit-every-formula-in-a-workbook-with-python\u002F","Audit Every Formula in a Workbook with Python"," can be extended the same way.",[30,1412,1414],{"id":1413},"step-5-the-same-with-xlsxwriter","Step 5 — The same with XlsxWriter",[10,1416,1417],{},"XlsxWriter has a dedicated method. Its arguments are the range, the formula and an optional format and cached value:",[35,1419,1421],{"className":75,"code":1420,"language":77,"meta":40,"style":40},"import xlsxwriter\n\nbook = xlsxwriter.Workbook(\"orders_xw.xlsx\")\nsheet = book.add_worksheet(\"Orders\")\nsheet.write_row(0, 0, [\"Qty\", \"Price\", \"Line total\"])\nfor i, row in enumerate([(3, 89.0), (5, 45.5), (12, 14.0), (4, 22.0)], start=1):\n    sheet.write_row(i, 0, row)\nsheet.write_array_formula(\"C2:C5\", \"{=A2:A5*B2:B5}\")\nsheet.write_array_formula(\"F2\", \"{=SUM(A2:A5*B2:B5)}\", None, 750.5)\nbook.close()\nprint(type(load_workbook(\"orders_xw.xlsx\")[\"Orders\"][\"F2\"].value).__name__)\n",[14,1422,1423,1429,1433,1448,1462,1488,1545,1555,1569,1590,1595],{"__ignoreMap":40},[44,1424,1425,1427],{"class":46,"line":47},[44,1426,92],{"class":84},[44,1428,61],{"class":88},[44,1430,1431],{"class":46,"line":98},[44,1432,115],{"emptyLinePlaceholder":114},[44,1434,1435,1438,1440,1443,1446],{"class":46,"line":111},[44,1436,1437],{"class":88},"book ",[44,1439,137],{"class":84},[44,1441,1442],{"class":88}," xlsxwriter.Workbook(",[44,1444,1445],{"class":54},"\"orders_xw.xlsx\"",[44,1447,342],{"class":88},[44,1449,1450,1453,1455,1458,1460],{"class":46,"line":118},[44,1451,1452],{"class":88},"sheet ",[44,1454,137],{"class":84},[44,1456,1457],{"class":88}," book.add_worksheet(",[44,1459,506],{"class":54},[44,1461,342],{"class":88},[44,1463,1464,1467,1469,1471,1473,1476,1478,1480,1482,1484,1486],{"class":46,"line":131},[44,1465,1466],{"class":88},"sheet.write_row(",[44,1468,585],{"class":203},[44,1470,174],{"class":88},[44,1472,585],{"class":203},[44,1474,1475],{"class":88},", [",[44,1477,171],{"class":54},[44,1479,174],{"class":88},[44,1481,177],{"class":54},[44,1483,174],{"class":88},[44,1485,182],{"class":54},[44,1487,185],{"class":88},[44,1489,1490,1492,1495,1497,1500,1503,1505,1507,1509,1511,1513,1515,1517,1519,1521,1523,1525,1527,1529,1531,1533,1536,1539,1541,1543],{"class":46,"line":143},[44,1491,944],{"class":84},[44,1493,1494],{"class":88}," i, row ",[44,1496,197],{"class":84},[44,1498,1499],{"class":203}," enumerate",[44,1501,1502],{"class":88},"([(",[44,1504,204],{"class":203},[44,1506,174],{"class":88},[44,1508,209],{"class":203},[44,1510,212],{"class":88},[44,1512,215],{"class":203},[44,1514,174],{"class":88},[44,1516,220],{"class":203},[44,1518,212],{"class":88},[44,1520,225],{"class":203},[44,1522,174],{"class":88},[44,1524,230],{"class":203},[44,1526,212],{"class":88},[44,1528,235],{"class":203},[44,1530,174],{"class":88},[44,1532,240],{"class":203},[44,1534,1535],{"class":88},")], ",[44,1537,1538],{"class":461},"start",[44,1540,137],{"class":84},[44,1542,1126],{"class":203},[44,1544,1322],{"class":88},[44,1546,1547,1550,1552],{"class":46,"line":154},[44,1548,1549],{"class":88},"    sheet.write_row(i, ",[44,1551,585],{"class":203},[44,1553,1554],{"class":88},", row)\n",[44,1556,1557,1560,1562,1564,1567],{"class":46,"line":165},[44,1558,1559],{"class":88},"sheet.write_array_formula(",[44,1561,753],{"class":54},[44,1563,174],{"class":88},[44,1565,1566],{"class":54},"\"{=A2:A5*B2:B5}\"",[44,1568,342],{"class":88},[44,1570,1571,1573,1575,1577,1580,1582,1584,1586,1588],{"class":46,"line":188},[44,1572,1559],{"class":88},[44,1574,325],{"class":54},[44,1576,174],{"class":88},[44,1578,1579],{"class":54},"\"{=SUM(A2:A5*B2:B5)}\"",[44,1581,174],{"class":88},[44,1583,1398],{"class":203},[44,1585,174],{"class":88},[44,1587,1192],{"class":203},[44,1589,342],{"class":88},[44,1591,1592],{"class":46,"line":246},[44,1593,1594],{"class":88},"book.close()\n",[44,1596,1597,1599,1601,1604,1607,1609,1611,1613,1616,1618,1621,1624],{"class":46,"line":252},[44,1598,514],{"class":203},[44,1600,517],{"class":88},[44,1602,1603],{"class":203},"type",[44,1605,1606],{"class":88},"(load_workbook(",[44,1608,1445],{"class":54},[44,1610,503],{"class":88},[44,1612,506],{"class":54},[44,1614,1615],{"class":88},"][",[44,1617,325],{"class":54},[44,1619,1620],{"class":88},"].value).",[44,1622,1623],{"class":203},"__name__",[44,1625,342],{"class":88},[10,1627,1628,1629,28],{},"The braces in the formula string are optional; XlsxWriter strips them. Passing the result as the last argument caches it, so programs that read the file without recalculating see 750.5 instead of 0 — the problem described in ",[24,1630,1632],{"href":1631},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-formula-cells-reading-as-nan-in-pandas\u002F","Fix Formula Cells Reading as NaN (or 0) in pandas",[30,1634,1636],{"id":1635},"step-6-legacy-arrays-or-dynamic-arrays","Step 6 — Legacy arrays or dynamic arrays?",[10,1638,1639,1640,1643,1644,1648],{},"Excel 365 evaluates every formula as an array formula and spills multi-cell results automatically, so ",[14,1641,1642],{},"=A2:A5*B2:B5"," typed into one cell fills four. Files written for 365 can use those dynamic array formulas instead, covered in ",[24,1645,1647],{"href":1646},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-dynamic-array-formulas-with-python\u002F","Write Dynamic Array Formulas with Python",". Legacy array formulas are still the right choice when the workbook must work in Excel 2016 or 2019, in LibreOffice versions without spilling, or in a house style that expects fixed blocks — and they work in Excel 365 too, which opens them unchanged with their braces.",[564,1650,573,1655,573,1658,573,1661,573,1664,573,1669,573,1677,573,1681,573,1685,573,1689,573,1692,573,1697,573,1705,573,1710,573,1715,573,1720,573,1725,573,1730,573,1732,573,1735,573,1739,573,1742,573,1745,573,1751,573,1753,573,1756,573,1758,573,1761,573,1765,573,1768,573,1771,573,1777,573,1780],{"viewBox":1651,"role":567,"ariaLabelledBy":1652,"xmlns":571,"style":572},"4 0 752 272",[1653,1654],"af-choose-t","af-choose-d",[575,1656,1657],{"id":1653},"Legacy array formula or dynamic array?",[579,1659,1660],{"id":1654},"If recipients may use Excel 2019 or older, or the block size must be fixed, use a legacy ArrayFormula. If everyone uses Excel 365 and the result size can vary, write a dynamic array formula that spills.",[583,1662],{"x":235,"y":585,"width":586,"height":1663,"fill":588},"272",[583,1665],{"x":1666,"y":592,"width":1667,"height":1668,"rx":225,"fill":1129,"stroke":1130,"style":598},"240.0","280.0","75.5",[600,1670,1672],{"transform":1671},"translate(368.0,29.0) scale(1.000)",[604,1673],{"d":1674,"fill":607,"stroke":1675,"style":1676},"M9 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z M2.5 20c0-3.6 2.9-6 6.5-6s6.5 2.4 6.5 6 M16 4.5a3.3 3.3 0 0 1 0 6.3 M18 14.3c2.2.7 3.5 2.8 3.5 5.7","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[611,1678,1680],{"x":1101,"y":1668,"style":1679},"font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Who opens the workbook?",[46,1682],{"x1":1101,"y1":1683,"x2":1101,"y2":1684,"stroke":1130,"style":598},"91.5","111.5",[46,1686],{"x1":1687,"y1":1684,"x2":1688,"y2":1684,"stroke":1130,"style":598},"134.7","625.3",[46,1690],{"x1":1687,"y1":1684,"x2":1687,"y2":1691,"stroke":1130,"style":598},"157.5",[1693,1694],"polygon",{"points":1695,"fill":1696},"134.7,161.5 129.7,152.5 139.7,152.5","#5b5cf0",[583,1698],{"x":1699,"y":1700,"width":1701,"height":1702,"rx":1703,"fill":588,"stroke":1049,"style":1704},"69.7","121.5","130.0","21.0","10","stroke-width:1.2px",[611,1706,1709],{"x":1687,"y":1707,"style":1708},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","Excel 2019 or older",[583,1711],{"x":591,"y":1712,"width":1713,"height":1714,"rx":225,"fill":667,"stroke":668,"style":598},"163.5","229.3","93.0",[600,1716,1718],{"transform":1717},"translate(122.7,176.5) scale(1.000)",[604,1719],{"d":674,"fill":607,"stroke":675,"style":1676},[611,1721,1724],{"x":1687,"y":1722,"style":1723},"223.0","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Legacy ArrayFormula",[611,1726,1729],{"x":1687,"y":1727,"style":1728},"242.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","works everywhere",[46,1731],{"x1":1101,"y1":1684,"x2":1101,"y2":1691,"stroke":1130,"style":598},[1693,1733],{"points":1734,"fill":1696},"380.0,161.5 375.0,152.5 385.0,152.5",[583,1736],{"x":1737,"y":1700,"width":1738,"height":1702,"rx":1703,"fill":588,"stroke":1049,"style":1704},"300.1","159.8",[611,1740,1741],{"x":1101,"y":1707,"style":1708},"fixed-size block wanted",[583,1743],{"x":1744,"y":1712,"width":1713,"height":1714,"rx":225,"fill":667,"stroke":668,"style":598},"265.3",[600,1746,1748],{"transform":1747},"translate(368.0,176.5) scale(1.000)",[604,1749],{"d":1750,"fill":607,"stroke":675,"style":1676},"M4 4h16v16H4z M4 9h16 M4 14h16 M10 4v16",[611,1752,1724],{"x":1101,"y":1722,"style":1723},[611,1754,1755],{"x":1101,"y":1727,"style":1728},"ref fixes the range",[46,1757],{"x1":1688,"y1":1684,"x2":1688,"y2":1691,"stroke":1130,"style":598},[1693,1759],{"points":1760,"fill":1696},"625.3,161.5 620.3,152.5 630.3,152.5",[583,1762],{"x":1763,"y":1700,"width":1764,"height":1702,"rx":1703,"fill":588,"stroke":1049,"style":1704},"573.2","104.2",[611,1766,1767],{"x":1688,"y":1707,"style":1708},"Excel 365 only",[583,1769],{"x":1770,"y":1712,"width":1713,"height":1714,"rx":225,"fill":1129,"stroke":1130,"style":598},"510.7",[600,1772,1774],{"transform":1773},"translate(613.3,176.5) scale(1.000)",[604,1775],{"d":1776,"fill":607,"stroke":1675,"style":1676},"M13 2L4 14h7l-1 8 9-12h-7z",[611,1778,1779],{"x":1688,"y":1722,"style":1679},"Dynamic array",[611,1781,1782],{"x":1688,"y":1727,"style":1728},"spills to fit the result",[30,1784,1786],{"id":1785},"step-7-find-plain-formulas-that-should-be-arrays","Step 7 — Find plain formulas that should be arrays",[10,1788,1789],{},"Workbooks generated by older scripts may already contain the bug from Step 1. A rough scan finds candidates: ordinary formulas in which a range takes part in arithmetic or a comparison — the pattern that only makes sense under array evaluation:",[35,1791,1793],{"className":75,"code":1792,"language":77,"meta":40,"style":40},"import re\n\nRANGE_OP = re.compile(r\"[A-Z]+\\d+:[A-Z]+\\d+\\s*[*\u002F+\\-\u003C>=]|[*\u002F+\\-\u003C>=]\\s*[A-Z]+\\d+:[A-Z]+\\d+\")\n\ndef suspicious_formulas(ws):\n    hits = []\n    for row in ws.iter_rows():\n        for cell in row:\n            v = cell.value\n            if isinstance(v, str) and v.startswith(\"=\") and RANGE_OP.search(v) and \"SUMPRODUCT\" not in v.upper():\n                hits.append((cell.coordinate, v))\n    return hits\n\nlegacy = load_workbook(\"orders_compare.xlsx\")[\"Orders\"]\nfor coord, text in suspicious_formulas(legacy):\n    print(\"candidate:\", coord, text)\n    legacy[coord] = ArrayFormula(coord, text)\nlegacy.parent.save(\"orders_fixed.xlsx\")\nprint(type(load_workbook(\"orders_fixed.xlsx\")[\"Orders\"][\"E2\"].value).__name__)\n",[14,1794,1795,1802,1806,1919,1923,1933,1943,1954,1967,1977,2026,2031,2038,2042,2059,2071,2084,2094,2105],{"__ignoreMap":40},[44,1796,1797,1799],{"class":46,"line":47},[44,1798,92],{"class":84},[44,1800,1801],{"class":88}," re\n",[44,1803,1804],{"class":46,"line":98},[44,1805,115],{"emptyLinePlaceholder":114},[44,1807,1808,1811,1814,1817,1819,1821,1824,1827,1830,1833,1836,1838,1841,1843,1845,1847,1849,1851,1853,1856,1859,1861,1864,1868,1871,1873,1876,1878,1880,1882,1884,1887,1889,1891,1893,1895,1897,1899,1901,1903,1905,1907,1909,1911,1913,1915,1917],{"class":46,"line":111},[44,1809,1810],{"class":203},"RANGE_OP",[44,1812,1813],{"class":84}," =",[44,1815,1816],{"class":88}," re.compile(",[44,1818,932],{"class":84},[44,1820,938],{"class":54},[44,1822,1823],{"class":203},"[",[44,1825,1826],{"class":928},"A-Z",[44,1828,1829],{"class":203},"]",[44,1831,1832],{"class":84},"+",[44,1834,1835],{"class":203},"\\d",[44,1837,1832],{"class":84},[44,1839,1840],{"class":54},":",[44,1842,1823],{"class":203},[44,1844,1826],{"class":928},[44,1846,1829],{"class":203},[44,1848,1832],{"class":84},[44,1850,1835],{"class":203},[44,1852,1832],{"class":84},[44,1854,1855],{"class":203},"\\s",[44,1857,1858],{"class":84},"*",[44,1860,1823],{"class":203},[44,1862,1863],{"class":928},"*\u002F+",[44,1865,1867],{"class":1866},"s_b0D","\\-",[44,1869,1870],{"class":928},"\u003C>=",[44,1872,1829],{"class":203},[44,1874,1875],{"class":84},"|",[44,1877,1823],{"class":203},[44,1879,1863],{"class":928},[44,1881,1867],{"class":1866},[44,1883,1870],{"class":928},[44,1885,1886],{"class":203},"]\\s",[44,1888,1858],{"class":84},[44,1890,1823],{"class":203},[44,1892,1826],{"class":928},[44,1894,1829],{"class":203},[44,1896,1832],{"class":84},[44,1898,1835],{"class":203},[44,1900,1832],{"class":84},[44,1902,1840],{"class":54},[44,1904,1823],{"class":203},[44,1906,1826],{"class":928},[44,1908,1829],{"class":203},[44,1910,1832],{"class":84},[44,1912,1835],{"class":203},[44,1914,1832],{"class":84},[44,1916,938],{"class":54},[44,1918,342],{"class":88},[44,1920,1921],{"class":46,"line":118},[44,1922,115],{"emptyLinePlaceholder":114},[44,1924,1925,1927,1930],{"class":46,"line":131},[44,1926,121],{"class":84},[44,1928,1929],{"class":124}," suspicious_formulas",[44,1931,1932],{"class":88},"(ws):\n",[44,1934,1935,1938,1940],{"class":46,"line":143},[44,1936,1937],{"class":88},"    hits ",[44,1939,137],{"class":84},[44,1941,1942],{"class":88}," []\n",[44,1944,1945,1947,1949,1951],{"class":46,"line":154},[44,1946,191],{"class":84},[44,1948,194],{"class":88},[44,1950,197],{"class":84},[44,1952,1953],{"class":88}," ws.iter_rows():\n",[44,1955,1956,1959,1962,1964],{"class":46,"line":165},[44,1957,1958],{"class":84},"        for",[44,1960,1961],{"class":88}," cell ",[44,1963,197],{"class":84},[44,1965,1966],{"class":88}," row:\n",[44,1968,1969,1972,1974],{"class":46,"line":188},[44,1970,1971],{"class":88},"            v ",[44,1973,137],{"class":84},[44,1975,1976],{"class":88}," cell.value\n",[44,1978,1979,1982,1984,1987,1990,1993,1996,1999,2002,2004,2006,2009,2012,2014,2017,2020,2023],{"class":46,"line":246},[44,1980,1981],{"class":84},"            if",[44,1983,1340],{"class":203},[44,1985,1986],{"class":88},"(v, ",[44,1988,1989],{"class":203},"str",[44,1991,1992],{"class":88},") ",[44,1994,1995],{"class":84},"and",[44,1997,1998],{"class":88}," v.startswith(",[44,2000,2001],{"class":54},"\"=\"",[44,2003,1992],{"class":88},[44,2005,1995],{"class":84},[44,2007,2008],{"class":203}," RANGE_OP",[44,2010,2011],{"class":88},".search(v) ",[44,2013,1995],{"class":84},[44,2015,2016],{"class":54}," \"SUMPRODUCT\"",[44,2018,2019],{"class":84}," not",[44,2021,2022],{"class":84}," in",[44,2024,2025],{"class":88}," v.upper():\n",[44,2027,2028],{"class":46,"line":252},[44,2029,2030],{"class":88},"                hits.append((cell.coordinate, v))\n",[44,2032,2033,2035],{"class":46,"line":261},[44,2034,255],{"class":84},[44,2036,2037],{"class":88}," hits\n",[44,2039,2040],{"class":46,"line":266},[44,2041,115],{"emptyLinePlaceholder":114},[44,2043,2044,2047,2049,2051,2053,2055,2057],{"class":46,"line":277},[44,2045,2046],{"class":88},"legacy ",[44,2048,137],{"class":84},[44,2050,488],{"class":88},[44,2052,351],{"class":54},[44,2054,503],{"class":88},[44,2056,506],{"class":54},[44,2058,509],{"class":88},[44,2060,2061,2063,2066,2068],{"class":46,"line":305},[44,2062,944],{"class":84},[44,2064,2065],{"class":88}," coord, text ",[44,2067,197],{"class":84},[44,2069,2070],{"class":88}," suspicious_formulas(legacy):\n",[44,2072,2073,2076,2078,2081],{"class":46,"line":320},[44,2074,2075],{"class":203},"    print",[44,2077,517],{"class":88},[44,2079,2080],{"class":54},"\"candidate:\"",[44,2082,2083],{"class":88},", coord, text)\n",[44,2085,2086,2089,2091],{"class":46,"line":345},[44,2087,2088],{"class":88},"    legacy[coord] ",[44,2090,137],{"class":84},[44,2092,2093],{"class":88}," ArrayFormula(coord, text)\n",[44,2095,2097,2100,2103],{"class":46,"line":2096},18,[44,2098,2099],{"class":88},"legacy.parent.save(",[44,2101,2102],{"class":54},"\"orders_fixed.xlsx\"",[44,2104,342],{"class":88},[44,2106,2108,2110,2112,2114,2116,2118,2120,2122,2124,2126,2128,2130],{"class":46,"line":2107},19,[44,2109,514],{"class":203},[44,2111,517],{"class":88},[44,2113,1603],{"class":203},[44,2115,1606],{"class":88},[44,2117,2102],{"class":54},[44,2119,503],{"class":88},[44,2121,506],{"class":54},[44,2123,1615],{"class":88},[44,2125,310],{"class":54},[44,2127,1620],{"class":88},[44,2129,1623],{"class":203},[44,2131,342],{"class":88},[10,2133,2134,2135,2138,2139,2141,2142,2144,2145,2147,2148,2151,2152,2155,2156,2159],{},"The pattern flags ",[14,2136,2137],{},"=SUM(A2:A5*B2:B5)"," in ",[14,2140,358],{}," and leaves ",[14,2143,362],{}," alone, because it is already an ",[14,2146,369],{}," object rather than a string. ",[14,2149,2150],{},"SUMPRODUCT"," is excluded because it evaluates its arguments as arrays by itself — which also makes it the usual way to avoid array formulas altogether: ",[14,2153,2154],{},"=SUMPRODUCT(A2:A5, B2:B5)"," returns 750.5 as an ordinary formula. Treat the scan as a list of suspects to check, not an automatic fix: a formula such as ",[14,2157,2158],{},"=A2:A5=B2"," might be deliberate, and a recalculation before and after the change shows whether the numbers moved.",[30,2161,2163],{"id":2162},"common-pitfalls","Common pitfalls",[2165,2166,2167,2177,2190,2202,2210],"ul",{},[2168,2169,2170,2176],"li",{},[2171,2172,2173,2174,28],"strong",{},"Plain text instead of ",[14,2175,369],{}," The formula silently evaluates one row; always wrap range-wise formulas.",[2168,2178,2179,2185,2186,2189],{},[2171,2180,2181,2182,2184],{},"A ",[14,2183,1001],{}," that does not match the result."," In a LibreOffice recalculation, a block smaller than the result showed only the first values, and a larger one filled the extra cells with ",[14,2187,2188],{},"#N\u002FA","; size the block to the result.",[2168,2191,2192,2195,2196,2198,2199,2201],{},[2171,2193,2194],{},"Writing into a covered cell."," openpyxl lets you assign a value to ",[14,2197,1394],{}," inside the ",[14,2200,1005],{}," array, producing a file Excel complains about; leave covered cells alone.",[2168,2203,2204,1388,2207,2209],{},[2171,2205,2206],{},"Scanning formulas as strings only.",[14,2208,369],{}," objects are not strings; check for them explicitly.",[2168,2211,2212,2215],{},[2171,2213,2214],{},"Expecting cached results."," openpyxl stores none; recalculate or use XlsxWriter's value argument.",[30,2217,2219],{"id":2218},"conclusion","Conclusion",[10,2221,2222,2223,174,2226,2229,2230,2233,2234,2237,2238,2240,2241,2243],{},"Formulas that operate on whole ranges — ",[14,2224,2225],{},"SUM(A2:A5*B2:B5)",[14,2227,2228],{},"MAX(IF(...))"," — must be stored with the array flag, or they quietly evaluate a single row. Write them with ",[14,2231,2232],{},"ArrayFormula(ref, text)"," in openpyxl or ",[14,2235,2236],{},"write_array_formula"," in XlsxWriter, put multi-cell arrays in the top-left cell with a ",[14,2239,1001],{}," covering the block, read them back as ",[14,2242,369],{}," objects, and verify the results by recalculating in LibreOffice. Use dynamic arrays when every reader has Excel 365.",[30,2245,2247],{"id":2246},"frequently-asked-questions","Frequently asked questions",[10,2249,2250,2253,2254,2256],{},[2171,2251,2252],{},"How do I write a Ctrl+Shift+Enter array formula with openpyxl?","\nAssign an ArrayFormula object to the top-left cell: ws",[44,2255,325],{}," = ArrayFormula(\"F2\", \"=SUM(A2:A5*B2:B5)\"). The first argument is the cell or range the array occupies.",[10,2258,2259,2262],{},[2171,2260,2261],{},"Why does my SUM of two multiplied ranges return only the first row?","\nIt was written as an ordinary formula, so Excel and LibreOffice reduce each range to the cell on the formula's row. Write it as an ArrayFormula so it is evaluated over the whole ranges.",[10,2264,2265,2268],{},[2171,2266,2267],{},"How do I write an array formula that fills several cells?","\nUse ArrayFormula(\"C2:C5\", \"=A2:A5*B2:B5\") on cell C2. The ref covers the whole block, and the other cells in the block stay empty in openpyxl.",[10,2270,2271,2274],{},[2171,2272,2273],{},"How do I detect array formulas when reading a workbook?","\nLoad it without data_only and check isinstance(cell.value, ArrayFormula); the object has ref and text attributes. Covered cells in a multi-cell array read as None.",[30,2276,2278],{"id":2277},"related","Related",[2165,2280,2281,2287,2294,2301],{},[2168,2282,2283,2284,2286],{},"Up one level: ",[24,2285,27],{"href":26}," — writing, reading and checking formulas.",[2168,2288,2289,2293],{},[24,2290,2292],{"href":2291},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-formula-to-excel-cell-with-openpyxl\u002F","Write a Formula to an Excel Cell with openpyxl"," — ordinary formulas.",[2168,2295,2296,2300],{},[24,2297,2299],{"href":2298},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fuse-structured-table-references-in-formulas-from-python\u002F","Use Structured Table References in Formulas from Python"," — formulas that name table columns.",[2168,2302,2303,2307],{},[24,2304,2306],{"href":2305},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsumproduct-and-weighted-average-in-pandas\u002F","SUMPRODUCT and Weighted Average in pandas"," — the same calculation in pandas.",[2309,2310,2311],"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 .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s_b0D, html code.shiki .s_b0D{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold}",{"title":40,"searchDepth":98,"depth":98,"links":2313},[2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325],{"id":32,"depth":98,"text":33},{"id":71,"depth":98,"text":72},{"id":386,"depth":98,"text":387},{"id":720,"depth":98,"text":721},{"id":1270,"depth":98,"text":1271},{"id":1413,"depth":98,"text":1414},{"id":1635,"depth":98,"text":1636},{"id":1785,"depth":98,"text":1786},{"id":2162,"depth":98,"text":2163},{"id":2218,"depth":98,"text":2219},{"id":2246,"depth":98,"text":2247},{"id":2277,"depth":98,"text":2278},"2026-10-02","Some formulas only work as array formulas — SUM over a product of two ranges, MAX(IF(...)) with a condition — and written as ordinary formulas they silently return the first row's answer. Write them with openpyxl's ArrayFormula for one cell or a block, read them back, write them with XlsxWriter, verify the results with LibreOffice, and know when a dynamic array formula is the better choice.","md",[2330,2332,2334,2336],{"q":2252,"a":2331},"Assign an ArrayFormula object to the top-left cell: ws[\"F2\"] = ArrayFormula(\"F2\", \"=SUM(A2:A5*B2:B5)\"). The first argument is the cell or range the array occupies.",{"q":2261,"a":2333},"It was written as an ordinary formula, so Excel and LibreOffice reduce each range to the cell on the formula's row. Write it as an ArrayFormula so it is evaluated over the whole ranges.",{"q":2267,"a":2335},"Use ArrayFormula(\"C2:C5\", \"=A2:A5*B2:B5\") on cell C2. The ref covers the whole block, and the other cells in the block stay empty in openpyxl.",{"q":2273,"a":2337},"Load it without data_only and check isinstance(cell.value, ArrayFormula); the object has ref and text attributes. Covered cells in a multi-cell array read as None.","write legacy array formulas with openpyxl",null,{"breadcrumb":2341},[2342,2345,2348],{"name":2343,"item":2344},"Home","\u002F",{"name":2346,"item":2347},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":27,"item":26},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-legacy-array-formulas-with-openpyxl",{"title":2351,"description":2352},"Write Array Formulas (CSE) with openpyxl ArrayFormula","Write Ctrl+Shift+Enter array formulas from Python: openpyxl ArrayFormula for single cells and multi-cell ranges, why a plain =SUM(A2:A5*B2:B5) returns only the first row, reading ArrayFormula back, XlsxWriter write_array_formula, and checking with LibreOffice.","write-legacy-array-formulas-with-openpyxl","getting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-legacy-array-formulas-with-openpyxl\u002Findex",[2356,2357],"excel-formulas","openpyxl","how-to","sV54bj1-QVAR_UF3k-ch_n2MIJOLFqDm4e8AzkNUJTM",[2361,2365],{"title":2362,"path":2363,"stem":2364,"children":-1},"Write Formulas That Reference Other Sheets with openpyxl","\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-formulas-that-reference-other-sheets-with-openpyxl","getting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-formulas-that-reference-other-sheets-with-openpyxl\u002Findex",{"title":2366,"path":2367,"stem":2368,"children":-1},"Write LET and LAMBDA Formulas from Python","\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-let-and-lambda-formulas-from-python","getting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-let-and-lambda-formulas-from-python\u002Findex",[2370,2372],{"path":2371,"title":2346},"\u002Fgetting-started-with-python-excel-automation",{"path":2373,"title":27},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python",[],[2376,2379,2383,2386,2389,2392],{"path":2377,"title":2378,"kind":2358},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter","Store Formula Results with xlsxwriter So Every Viewer Shows Values",{"path":2380,"title":2381,"kind":2382},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-cells-with-formula-errors-using-conditional-formatting","Highlight Cells with Formula Errors Using Conditional Formatting","fix",{"path":2384,"title":2385,"kind":2358},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fgoal-seek-in-python-instead-of-excel","Goal Seek in Python Instead of Excel",{"path":2387,"title":2388,"kind":2358},"\u002Fadvanced-data-transformation-and-cleaning\u002Fvalidating-excel-data-with-python\u002Fcheck-that-totals-in-a-report-add-up","Check That Totals in a Report Add Up",{"path":2390,"title":2391,"kind":2358},"\u002Fautomating-reporting-workflows\u002Fautomating-excel-online-with-microsoft-graph\u002Fcall-excel-worksheet-functions-through-microsoft-graph","Call Excel Worksheet Functions Through Microsoft Graph",{"path":2393,"title":2394,"kind":2358},"\u002Fautomating-reporting-workflows\u002Fautomating-excel-online-with-microsoft-graph\u002Frecalculate-excel-online-workbooks-with-graph-sessions","Recalculate Excel Online Workbooks with Graph Sessions",1790972075955]