[{"data":1,"prerenderedAt":2433},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter":2399,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter":2407,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter":2412,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter":2413},{"id":4,"title":5,"body":6,"dateModified":2365,"datePublished":2365,"description":2366,"extension":2367,"faq":2368,"keyword":2377,"kind":2378,"meta":2379,"navigation":238,"path":2388,"seo":2389,"slug":2392,"stem":2393,"topics":2394,"type":2397,"__hash__":2398},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter\u002Findex.md","Store Formula Results with xlsxwriter So Every Viewer Shows Values",{"type":7,"value":8,"toc":2351},"minimark",[9,19,161,166,198,202,499,506,510,516,749,755,759,762,1114,1122,1285,1289,1292,1438,1445,1449,1459,1689,1699,1812,1816,1823,2220,2226,2230,2233,2237,2270,2274,2286,2290,2296,2302,2308,2314,2318,2347],[10,11,12,13,18],"p",{},"A report written with xlsxwriter looks right in Excel: every total, margin and percentage shows its value. Open the same file with pandas, preview it in a mail client, or convert it with LibreOffice on a server, and the formula columns are all zeros. Nothing is broken — xlsxwriter cannot calculate, so it writes each formula with a cached result of 0 and marks the workbook for recalculation on open. Excel recalculates; almost nothing else does. This guide, part of ",[14,15,17],"a",{"href":16},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002F","Building Excel Reports with xlsxwriter",", stores the real results alongside the formulas so every reader sees the same numbers.",[20,21,29,30,29,34,29,38,29,46,29,54,29,61,29,68,29,71,29,75,29,80,29,86,29,88,29,93,29,95,29,97,29,100,29,104,29,106,29,109,29,111,29,113,29,116,29,120,29,122,29,125,29,127,29,129,29,132,29,136,29,138,29,141,29,143,29,145,29,148,29,152,29,154,29,157,29,159],"svg",{"viewBox":22,"role":23,"ariaLabelledBy":24,"xmlns":27,"style":28},"4 0 752 242","img",[25,26],"fr-readers-t","fr-readers-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  ",[31,32,33],"title",{"id":25},"What each reader shows for an xlsxwriter formula",[35,36,37],"desc",{"id":26},"For the formula A2 times B2 with a true result of 7.5, Excel shows 7.5 because it recalculates on open. pandas read_excel, openpyxl with data_only, file previewers and a headless LibreOffice conversion show the cached value, which is 0 unless the value was stored. With the value stored, all of them show 7.5.",[39,40],"rect",{"x":41,"y":42,"width":43,"height":44,"fill":45},"4","0","752","242","#ffffff",[39,47],{"x":48,"y":49,"width":50,"height":51,"rx":42,"fill":45,"stroke":52,"style":53},"20.0","16.0","168.4","40.0","var(--line,#cdd5e6)","stroke-width:1px",[39,55],{"x":56,"y":49,"width":57,"height":51,"rx":42,"fill":58,"stroke":59,"style":60},"188.4","275.8","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:1.2px",[62,63,67],"text",{"x":64,"y":65,"style":66},"326.3","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","no value stored",[39,69],{"x":70,"y":49,"width":57,"height":51,"rx":42,"fill":58,"stroke":59,"style":60},"464.2",[62,72,74],{"x":73,"y":65,"style":66},"602.1","value stored",[39,76],{"x":48,"y":77,"width":50,"height":78,"rx":42,"fill":79,"stroke":52,"style":53},"56.0","34.0","#e7ebef",[62,81,85],{"x":82,"y":83,"style":84},"32.0","78.0","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start","Excel desktop",[39,87],{"x":56,"y":77,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,89,92],{"x":64,"y":90,"style":91},"77.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","7.5",[39,94],{"x":70,"y":77,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,96,92],{"x":73,"y":90,"style":91},[39,98],{"x":48,"y":99,"width":50,"height":78,"rx":42,"fill":79,"stroke":52,"style":53},"90.0",[62,101,103],{"x":82,"y":102,"style":84},"112.0","pandas read_excel",[39,105],{"x":56,"y":99,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,107,42],{"x":64,"y":108,"style":91},"111.0",[39,110],{"x":70,"y":99,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,112,92],{"x":73,"y":108,"style":91},[39,114],{"x":48,"y":115,"width":50,"height":78,"rx":42,"fill":79,"stroke":52,"style":53},"124.0",[62,117,119],{"x":82,"y":118,"style":84},"146.0","openpyxl data_only",[39,121],{"x":56,"y":115,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,123,42],{"x":64,"y":124,"style":91},"145.0",[39,126],{"x":70,"y":115,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,128,92],{"x":73,"y":124,"style":91},[39,130],{"x":48,"y":131,"width":50,"height":78,"rx":42,"fill":79,"stroke":52,"style":53},"158.0",[62,133,135],{"x":82,"y":134,"style":84},"180.0","headless LibreOffice",[39,137],{"x":56,"y":131,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,139,42],{"x":64,"y":140,"style":91},"179.0",[39,142],{"x":70,"y":131,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,144,92],{"x":73,"y":140,"style":91},[39,146],{"x":48,"y":147,"width":50,"height":78,"rx":42,"fill":79,"stroke":52,"style":53},"192.0",[62,149,151],{"x":82,"y":150,"style":84},"214.0","previews and viewers",[39,153],{"x":56,"y":147,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,155,42],{"x":64,"y":156,"style":91},"213.0",[39,158],{"x":70,"y":147,"width":57,"height":78,"rx":42,"fill":45,"stroke":52,"style":53},[62,160,92],{"x":73,"y":156,"style":91},[162,163,165],"h2",{"id":164},"prerequisites","Prerequisites",[167,168,173],"pre",{"className":169,"code":170,"language":171,"meta":172,"style":172},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install xlsxwriter pandas openpyxl\n","bash","",[174,175,176],"code",{"__ignoreMap":172},[177,178,181,185,189,192,195],"span",{"class":179,"line":180},"line",1,[177,182,184],{"class":183},"sMTad","pip",[177,186,188],{"class":187},"srMev"," install",[177,190,191],{"class":187}," xlsxwriter",[177,193,194],{"class":187}," pandas",[177,196,197],{"class":187}," openpyxl\n",[162,199,201],{"id":200},"step-1-see-the-zeros","Step 1 — See the zeros",[167,203,207],{"className":204,"code":205,"language":206,"meta":172,"style":172},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\nimport xlsxwriter\n\nwb = xlsxwriter.Workbook(\"orders.xlsx\")\nws = wb.add_worksheet(\"Orders\")\nws.write_row(\"A1\", [\"qty\", \"price\", \"total\"])\nfor row, (qty, price) in enumerate([(3, 2.5), (4, 10.0)], start=2):\n    ws.write(f\"A{row}\", qty)\n    ws.write(f\"B{row}\", price)\n    ws.write_formula(f\"C{row}\", f\"=A{row}*B{row}\")\nws.write_formula(\"C4\", \"=SUM(C2:C3)\")\nwb.close()\n\nprint(pd.read_excel(\"orders.xlsx\")[\"total\"].tolist())      # [0, 0, 0]\n","python",[174,208,209,225,233,240,258,274,303,355,383,404,449,465,471,476],{"__ignoreMap":172},[177,210,211,215,219,222],{"class":179,"line":180},[177,212,214],{"class":213},"s-kum","import",[177,216,218],{"class":217},"skGVy"," pandas ",[177,220,221],{"class":213},"as",[177,223,224],{"class":217}," pd\n",[177,226,228,230],{"class":179,"line":227},2,[177,229,214],{"class":213},[177,231,232],{"class":217}," xlsxwriter\n",[177,234,236],{"class":179,"line":235},3,[177,237,239],{"emptyLinePlaceholder":238},true,"\n",[177,241,243,246,249,252,255],{"class":179,"line":242},4,[177,244,245],{"class":217},"wb ",[177,247,248],{"class":213},"=",[177,250,251],{"class":217}," xlsxwriter.Workbook(",[177,253,254],{"class":187},"\"orders.xlsx\"",[177,256,257],{"class":217},")\n",[177,259,261,264,266,269,272],{"class":179,"line":260},5,[177,262,263],{"class":217},"ws ",[177,265,248],{"class":213},[177,267,268],{"class":217}," wb.add_worksheet(",[177,270,271],{"class":187},"\"Orders\"",[177,273,257],{"class":217},[177,275,277,280,283,286,289,292,295,297,300],{"class":179,"line":276},6,[177,278,279],{"class":217},"ws.write_row(",[177,281,282],{"class":187},"\"A1\"",[177,284,285],{"class":217},", [",[177,287,288],{"class":187},"\"qty\"",[177,290,291],{"class":217},", ",[177,293,294],{"class":187},"\"price\"",[177,296,291],{"class":217},[177,298,299],{"class":187},"\"total\"",[177,301,302],{"class":217},"])\n",[177,304,306,309,312,315,319,322,325,327,330,333,335,337,340,343,347,349,352],{"class":179,"line":305},7,[177,307,308],{"class":213},"for",[177,310,311],{"class":217}," row, (qty, price) ",[177,313,314],{"class":213},"in",[177,316,318],{"class":317},"sP0c6"," enumerate",[177,320,321],{"class":217},"([(",[177,323,324],{"class":317},"3",[177,326,291],{"class":217},[177,328,329],{"class":317},"2.5",[177,331,332],{"class":217},"), (",[177,334,41],{"class":317},[177,336,291],{"class":217},[177,338,339],{"class":317},"10.0",[177,341,342],{"class":217},")], ",[177,344,346],{"class":345},"sa561","start",[177,348,248],{"class":213},[177,350,351],{"class":317},"2",[177,353,354],{"class":217},"):\n",[177,356,358,361,364,367,371,374,377,380],{"class":179,"line":357},8,[177,359,360],{"class":217},"    ws.write(",[177,362,363],{"class":213},"f",[177,365,366],{"class":187},"\"A",[177,368,370],{"class":369},"sSjpA","{",[177,372,373],{"class":217},"row",[177,375,376],{"class":369},"}",[177,378,379],{"class":187},"\"",[177,381,382],{"class":217},", qty)\n",[177,384,386,388,390,393,395,397,399,401],{"class":179,"line":385},9,[177,387,360],{"class":217},[177,389,363],{"class":213},[177,391,392],{"class":187},"\"B",[177,394,370],{"class":369},[177,396,373],{"class":217},[177,398,376],{"class":369},[177,400,379],{"class":187},[177,402,403],{"class":217},", price)\n",[177,405,407,410,412,415,417,419,421,423,425,427,430,432,434,436,439,441,443,445,447],{"class":179,"line":406},10,[177,408,409],{"class":217},"    ws.write_formula(",[177,411,363],{"class":213},[177,413,414],{"class":187},"\"C",[177,416,370],{"class":369},[177,418,373],{"class":217},[177,420,376],{"class":369},[177,422,379],{"class":187},[177,424,291],{"class":217},[177,426,363],{"class":213},[177,428,429],{"class":187},"\"=A",[177,431,370],{"class":369},[177,433,373],{"class":217},[177,435,376],{"class":369},[177,437,438],{"class":187},"*B",[177,440,370],{"class":369},[177,442,373],{"class":217},[177,444,376],{"class":369},[177,446,379],{"class":187},[177,448,257],{"class":217},[177,450,452,455,458,460,463],{"class":179,"line":451},11,[177,453,454],{"class":217},"ws.write_formula(",[177,456,457],{"class":187},"\"C4\"",[177,459,291],{"class":217},[177,461,462],{"class":187},"\"=SUM(C2:C3)\"",[177,464,257],{"class":217},[177,466,468],{"class":179,"line":467},12,[177,469,470],{"class":217},"wb.close()\n",[177,472,474],{"class":179,"line":473},13,[177,475,239],{"emptyLinePlaceholder":238},[177,477,479,482,485,487,490,492,495],{"class":179,"line":478},14,[177,480,481],{"class":317},"print",[177,483,484],{"class":217},"(pd.read_excel(",[177,486,254],{"class":187},[177,488,489],{"class":217},")[",[177,491,299],{"class":187},[177,493,494],{"class":217},"].tolist())      ",[177,496,498],{"class":497},"s-wDw","# [0, 0, 0]\n",[10,500,501,502,505],{},"Inside the file, each formula cell holds the formula and a value of 0, and the workbook carries a \"recalculate everything on load\" flag. Excel honours the flag and shows 7.5, 40 and 47.5. pandas reads the stored 0s — and so does ",[174,503,504],{},"openpyxl.load_workbook(..., data_only=True)",". A headless LibreOffice conversion to CSV with default settings also kept the zeros in our test. Any downstream job that reads the report file gets wrong numbers.",[162,507,509],{"id":508},"step-2-pass-the-value-with-the-formula","Step 2 — Pass the value with the formula",[10,511,512,515],{},[174,513,514],{},"write_formula"," takes the result as its fourth argument. Excel still recalculates on open, so the formula stays authoritative, but every other reader now sees the stored number:",[167,517,519],{"className":204,"code":518,"language":206,"meta":172,"style":172},"wb = xlsxwriter.Workbook(\"orders.xlsx\")\nws = wb.add_worksheet(\"Orders\")\nws.write_row(\"A1\", [\"qty\", \"price\", \"total\"])\nrows = [(3, 2.5), (4, 10.0)]\nfor r, (qty, price) in enumerate(rows, start=2):\n    ws.write_row(f\"A{r}\", [qty, price])\n    ws.write_formula(f\"C{r}\", f\"=A{r}*B{r}\", None, qty * price)\nws.write_formula(\"C4\", \"=SUM(C2:C3)\", None, sum(q * p for q, p in rows))\nwb.close()\n\nprint(pd.read_excel(\"orders.xlsx\")[\"total\"].tolist())      # [7.5, 40.0, 47.5]\n",[174,520,521,533,545,565,592,614,635,687,724,728,732],{"__ignoreMap":172},[177,522,523,525,527,529,531],{"class":179,"line":180},[177,524,245],{"class":217},[177,526,248],{"class":213},[177,528,251],{"class":217},[177,530,254],{"class":187},[177,532,257],{"class":217},[177,534,535,537,539,541,543],{"class":179,"line":227},[177,536,263],{"class":217},[177,538,248],{"class":213},[177,540,268],{"class":217},[177,542,271],{"class":187},[177,544,257],{"class":217},[177,546,547,549,551,553,555,557,559,561,563],{"class":179,"line":235},[177,548,279],{"class":217},[177,550,282],{"class":187},[177,552,285],{"class":217},[177,554,288],{"class":187},[177,556,291],{"class":217},[177,558,294],{"class":187},[177,560,291],{"class":217},[177,562,299],{"class":187},[177,564,302],{"class":217},[177,566,567,570,572,575,577,579,581,583,585,587,589],{"class":179,"line":242},[177,568,569],{"class":217},"rows ",[177,571,248],{"class":213},[177,573,574],{"class":217}," [(",[177,576,324],{"class":317},[177,578,291],{"class":217},[177,580,329],{"class":317},[177,582,332],{"class":217},[177,584,41],{"class":317},[177,586,291],{"class":217},[177,588,339],{"class":317},[177,590,591],{"class":217},")]\n",[177,593,594,596,599,601,603,606,608,610,612],{"class":179,"line":260},[177,595,308],{"class":213},[177,597,598],{"class":217}," r, (qty, price) ",[177,600,314],{"class":213},[177,602,318],{"class":317},[177,604,605],{"class":217},"(rows, ",[177,607,346],{"class":345},[177,609,248],{"class":213},[177,611,351],{"class":317},[177,613,354],{"class":217},[177,615,616,619,621,623,625,628,630,632],{"class":179,"line":276},[177,617,618],{"class":217},"    ws.write_row(",[177,620,363],{"class":213},[177,622,366],{"class":187},[177,624,370],{"class":369},[177,626,627],{"class":217},"r",[177,629,376],{"class":369},[177,631,379],{"class":187},[177,633,634],{"class":217},", [qty, price])\n",[177,636,637,639,641,643,645,647,649,651,653,655,657,659,661,663,665,667,669,671,673,675,678,681,684],{"class":179,"line":305},[177,638,409],{"class":217},[177,640,363],{"class":213},[177,642,414],{"class":187},[177,644,370],{"class":369},[177,646,627],{"class":217},[177,648,376],{"class":369},[177,650,379],{"class":187},[177,652,291],{"class":217},[177,654,363],{"class":213},[177,656,429],{"class":187},[177,658,370],{"class":369},[177,660,627],{"class":217},[177,662,376],{"class":369},[177,664,438],{"class":187},[177,666,370],{"class":369},[177,668,627],{"class":217},[177,670,376],{"class":369},[177,672,379],{"class":187},[177,674,291],{"class":217},[177,676,677],{"class":317},"None",[177,679,680],{"class":217},", qty ",[177,682,683],{"class":213},"*",[177,685,686],{"class":217}," price)\n",[177,688,689,691,693,695,697,699,701,703,706,709,711,714,716,719,721],{"class":179,"line":357},[177,690,454],{"class":217},[177,692,457],{"class":187},[177,694,291],{"class":217},[177,696,462],{"class":187},[177,698,291],{"class":217},[177,700,677],{"class":317},[177,702,291],{"class":217},[177,704,705],{"class":317},"sum",[177,707,708],{"class":217},"(q ",[177,710,683],{"class":213},[177,712,713],{"class":217}," p ",[177,715,308],{"class":213},[177,717,718],{"class":217}," q, p ",[177,720,314],{"class":213},[177,722,723],{"class":217}," rows))\n",[177,725,726],{"class":179,"line":385},[177,727,470],{"class":217},[177,729,730],{"class":179,"line":406},[177,731,239],{"emptyLinePlaceholder":238},[177,733,734,736,738,740,742,744,746],{"class":179,"line":451},[177,735,481],{"class":317},[177,737,484],{"class":217},[177,739,254],{"class":187},[177,741,489],{"class":217},[177,743,299],{"class":187},[177,745,494],{"class":217},[177,747,748],{"class":497},"# [7.5, 40.0, 47.5]\n",[10,750,751,752,754],{},"The third argument is the cell format; pass ",[174,753,677],{}," when there is none. The value must be the result Excel would compute — a wrong cached value is worse than 0, because non-recalculating readers show it confidently, and Excel then silently corrects it, so two people looking at the same file see different numbers.",[162,756,758],{"id":757},"step-3-compute-the-results-in-pandas-and-write-both","Step 3 — Compute the results in pandas and write both",[10,760,761],{},"In a real report the data is a DataFrame. Compute each derived column in pandas, then write the formula and its value together, so the file is both live in Excel and correct everywhere else:",[167,763,765],{"className":204,"code":764,"language":206,"meta":172,"style":172},"orders = pd.DataFrame({\"qty\": [3, 4, 2], \"price\": [2.5, 10.0, 7.25]})\norders[\"total\"] = orders[\"qty\"] * orders[\"price\"]\n\nwith pd.ExcelWriter(\"orders_pd.xlsx\", engine=\"xlsxwriter\") as writer:\n    orders[[\"qty\", \"price\"]].to_excel(writer, sheet_name=\"Orders\", index=False)\n    ws = writer.sheets[\"Orders\"]\n    money = writer.book.add_format({\"num_format\": \"#,##0.00\"})\n    ws.write(\"C1\", \"total\")\n    for i, total in enumerate(orders[\"total\"], start=2):\n        ws.write_formula(f\"C{i}\", f\"=A{i}*B{i}\", money, total)\n    last = len(orders) + 1\n    ws.write_formula(f\"C{last + 1}\", f\"=SUM(C2:C{last})\", money, orders[\"total\"].sum())\n\nprint(pd.read_excel(\"orders_pd.xlsx\")[\"total\"].tolist())   # [7.5, 40.0, 14.5, 62.0]\n",[174,766,767,813,841,845,874,907,921,943,956,983,1026,1045,1092,1096],{"__ignoreMap":172},[177,768,769,772,774,777,779,782,784,786,788,790,792,795,797,799,801,803,805,807,810],{"class":179,"line":180},[177,770,771],{"class":217},"orders ",[177,773,248],{"class":213},[177,775,776],{"class":217}," pd.DataFrame({",[177,778,288],{"class":187},[177,780,781],{"class":217},": [",[177,783,324],{"class":317},[177,785,291],{"class":217},[177,787,41],{"class":317},[177,789,291],{"class":217},[177,791,351],{"class":317},[177,793,794],{"class":217},"], ",[177,796,294],{"class":187},[177,798,781],{"class":217},[177,800,329],{"class":317},[177,802,291],{"class":217},[177,804,339],{"class":317},[177,806,291],{"class":217},[177,808,809],{"class":317},"7.25",[177,811,812],{"class":217},"]})\n",[177,814,815,818,820,823,825,828,830,832,834,836,838],{"class":179,"line":227},[177,816,817],{"class":217},"orders[",[177,819,299],{"class":187},[177,821,822],{"class":217},"] ",[177,824,248],{"class":213},[177,826,827],{"class":217}," orders[",[177,829,288],{"class":187},[177,831,822],{"class":217},[177,833,683],{"class":213},[177,835,827],{"class":217},[177,837,294],{"class":187},[177,839,840],{"class":217},"]\n",[177,842,843],{"class":179,"line":235},[177,844,239],{"emptyLinePlaceholder":238},[177,846,847,850,853,856,858,861,863,866,869,871],{"class":179,"line":242},[177,848,849],{"class":213},"with",[177,851,852],{"class":217}," pd.ExcelWriter(",[177,854,855],{"class":187},"\"orders_pd.xlsx\"",[177,857,291],{"class":217},[177,859,860],{"class":345},"engine",[177,862,248],{"class":213},[177,864,865],{"class":187},"\"xlsxwriter\"",[177,867,868],{"class":217},") ",[177,870,221],{"class":213},[177,872,873],{"class":217}," writer:\n",[177,875,876,879,881,883,885,888,891,893,895,897,900,902,905],{"class":179,"line":260},[177,877,878],{"class":217},"    orders[[",[177,880,288],{"class":187},[177,882,291],{"class":217},[177,884,294],{"class":187},[177,886,887],{"class":217},"]].to_excel(writer, ",[177,889,890],{"class":345},"sheet_name",[177,892,248],{"class":213},[177,894,271],{"class":187},[177,896,291],{"class":217},[177,898,899],{"class":345},"index",[177,901,248],{"class":213},[177,903,904],{"class":317},"False",[177,906,257],{"class":217},[177,908,909,912,914,917,919],{"class":179,"line":276},[177,910,911],{"class":217},"    ws ",[177,913,248],{"class":213},[177,915,916],{"class":217}," writer.sheets[",[177,918,271],{"class":187},[177,920,840],{"class":217},[177,922,923,926,928,931,934,937,940],{"class":179,"line":305},[177,924,925],{"class":217},"    money ",[177,927,248],{"class":213},[177,929,930],{"class":217}," writer.book.add_format({",[177,932,933],{"class":187},"\"num_format\"",[177,935,936],{"class":217},": ",[177,938,939],{"class":187},"\"#,##0.00\"",[177,941,942],{"class":217},"})\n",[177,944,945,947,950,952,954],{"class":179,"line":357},[177,946,360],{"class":217},[177,948,949],{"class":187},"\"C1\"",[177,951,291],{"class":217},[177,953,299],{"class":187},[177,955,257],{"class":217},[177,957,958,961,964,966,968,971,973,975,977,979,981],{"class":179,"line":385},[177,959,960],{"class":213},"    for",[177,962,963],{"class":217}," i, total ",[177,965,314],{"class":213},[177,967,318],{"class":317},[177,969,970],{"class":217},"(orders[",[177,972,299],{"class":187},[177,974,794],{"class":217},[177,976,346],{"class":345},[177,978,248],{"class":213},[177,980,351],{"class":317},[177,982,354],{"class":217},[177,984,985,988,990,992,994,997,999,1001,1003,1005,1007,1009,1011,1013,1015,1017,1019,1021,1023],{"class":179,"line":406},[177,986,987],{"class":217},"        ws.write_formula(",[177,989,363],{"class":213},[177,991,414],{"class":187},[177,993,370],{"class":369},[177,995,996],{"class":217},"i",[177,998,376],{"class":369},[177,1000,379],{"class":187},[177,1002,291],{"class":217},[177,1004,363],{"class":213},[177,1006,429],{"class":187},[177,1008,370],{"class":369},[177,1010,996],{"class":217},[177,1012,376],{"class":369},[177,1014,438],{"class":187},[177,1016,370],{"class":369},[177,1018,996],{"class":217},[177,1020,376],{"class":369},[177,1022,379],{"class":187},[177,1024,1025],{"class":217},", money, total)\n",[177,1027,1028,1031,1033,1036,1039,1042],{"class":179,"line":451},[177,1029,1030],{"class":217},"    last ",[177,1032,248],{"class":213},[177,1034,1035],{"class":317}," len",[177,1037,1038],{"class":217},"(orders) ",[177,1040,1041],{"class":213},"+",[177,1043,1044],{"class":317}," 1\n",[177,1046,1047,1049,1051,1053,1055,1058,1060,1063,1065,1067,1069,1071,1074,1076,1079,1081,1084,1087,1089],{"class":179,"line":467},[177,1048,409],{"class":217},[177,1050,363],{"class":213},[177,1052,414],{"class":187},[177,1054,370],{"class":369},[177,1056,1057],{"class":217},"last ",[177,1059,1041],{"class":213},[177,1061,1062],{"class":317}," 1",[177,1064,376],{"class":369},[177,1066,379],{"class":187},[177,1068,291],{"class":217},[177,1070,363],{"class":213},[177,1072,1073],{"class":187},"\"=SUM(C2:C",[177,1075,370],{"class":369},[177,1077,1078],{"class":217},"last",[177,1080,376],{"class":369},[177,1082,1083],{"class":187},")\"",[177,1085,1086],{"class":217},", money, orders[",[177,1088,299],{"class":187},[177,1090,1091],{"class":217},"].sum())\n",[177,1093,1094],{"class":179,"line":473},[177,1095,239],{"emptyLinePlaceholder":238},[177,1097,1098,1100,1102,1104,1106,1108,1111],{"class":179,"line":478},[177,1099,481],{"class":317},[177,1101,484],{"class":217},[177,1103,855],{"class":187},[177,1105,489],{"class":217},[177,1107,299],{"class":187},[177,1109,1110],{"class":217},"].tolist())   ",[177,1112,1113],{"class":497},"# [7.5, 40.0, 14.5, 62.0]\n",[10,1115,1116,1117,1121],{},"The pandas expression and the Excel formula must describe the same calculation. Keep them next to each other in the code, and for anything beyond simple arithmetic add a test that recalculates the file independently and compares — ",[14,1118,1120],{"href":1119},"\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"," shows how.",[20,1123,29,1128,29,1131,29,1134,29,1137,29,1143,29,1154,29,1160,29,1164,29,1168,29,1172,29,1177,29,1182,29,1185,29,1191,29,1195,29,1198,29,1202,29,1205,29,1210,29,1217,29,1222,29,1225,29,1228,29,1231,29,1235,29,1238,29,1241,29,1247,29,1252,29,1256,29,1259,29,1263,29,1266,29,1269,29,1275,29,1279,29,1282],{"viewBox":1124,"role":23,"ariaLabelledBy":1125,"xmlns":27,"style":28},"4 0 752 160",[1126,1127],"fr-flow-t","fr-flow-d",[31,1129,1130],{"id":1126},"Writing formulas that every reader sees correctly",[35,1132,1133],{"id":1127},"Compute the derived values in pandas, write the input columns, then write each formula together with its computed value, write totals the same way, and read the file back with pandas to confirm the cached values match.",[39,1135],{"x":41,"y":42,"width":43,"height":1136,"fill":45},"160",[39,1138],{"x":48,"y":49,"width":1139,"height":1140,"rx":1141,"fill":58,"stroke":59,"style":1142},"115.2","128.0","12","stroke-width:2px",[1144,1145,1147],"g",{"transform":1146},"translate(65.6,29.0) scale(1.000)",[1148,1149],"path",{"d":1150,"fill":1151,"stroke":1152,"style":1153},"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","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[62,1155,1159],{"x":1156,"y":1157,"style":1158},"77.6","75.5","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Compute in",[62,1161,1163],{"x":1156,"y":1162,"style":1158},"93.0","pandas",[62,1165,1167],{"x":1156,"y":1166,"style":91},"112.5","same logic as",[62,1169,1171],{"x":1156,"y":1170,"style":91},"130.0","formula",[179,1173],{"x1":1174,"y1":1175,"x2":1176,"y2":1175,"stroke":59,"style":1142},"140.2","80.0","162.2",[1178,1179],"polygon",{"points":1180,"fill":1181},"166.2,80.0 157.2,85.0 157.2,75.0","#5b5cf0",[39,1183],{"x":1184,"y":49,"width":1139,"height":1140,"rx":1141,"fill":58,"stroke":59,"style":1142},"171.2",[1144,1186,1188],{"transform":1187},"translate(216.8,46.5) scale(1.000)",[1148,1189],{"d":1190,"fill":1151,"stroke":1152,"style":1153},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14",[62,1192,1194],{"x":1193,"y":1162,"style":1158},"228.8","Write inputs",[62,1196,1197],{"x":1193,"y":1166,"style":91},"to_excel",[179,1199],{"x1":1200,"y1":1175,"x2":1201,"y2":1175,"stroke":59,"style":1142},"291.4","313.4",[1178,1203],{"points":1204,"fill":1181},"317.4,80.0 308.4,85.0 308.4,75.0",[39,1206],{"x":1207,"y":49,"width":1139,"height":1140,"rx":1141,"fill":1208,"stroke":1209,"style":1142},"322.4","#d9f4f1","var(--teal,#0f9488)",[1144,1211,1213],{"transform":1212},"translate(368.0,29.0) scale(1.000)",[1148,1214],{"d":1215,"fill":1151,"stroke":1216,"style":1153},"M9 8l-4 4 4 4 M15 8l4 4-4 4","var(--teal-ink,#0b6157)",[62,1218,1221],{"x":1219,"y":1157,"style":1220},"380.0","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Formula +",[62,1223,1224],{"x":1219,"y":1162,"style":1220},"value",[62,1226,1227],{"x":1219,"y":1166,"style":91},"write_formula(…,",[62,1229,1230],{"x":1219,"y":1170,"style":91},"value)",[179,1232],{"x1":1233,"y1":1175,"x2":1234,"y2":1175,"stroke":59,"style":1142},"442.6","464.6",[1178,1236],{"points":1237,"fill":1181},"468.6,80.0 459.6,85.0 459.6,75.0",[39,1239],{"x":1240,"y":49,"width":1139,"height":1140,"rx":1141,"fill":58,"stroke":59,"style":1142},"473.6",[1144,1242,1244],{"transform":1243},"translate(519.2,37.8) scale(1.000)",[1148,1245],{"d":1246,"fill":1151,"stroke":1152,"style":1153},"M5 9h14 M4 15h14 M10 4l-2 16 M16 4l-2 16",[62,1248,1251],{"x":1249,"y":1250,"style":1158},"531.2","84.2","Totals too",[62,1253,1255],{"x":1249,"y":1254,"style":91},"103.8","SUM with its",[62,1257,705],{"x":1249,"y":1258,"style":91},"121.2",[179,1260],{"x1":1261,"y1":1175,"x2":1262,"y2":1175,"stroke":59,"style":1142},"593.8","615.8",[1178,1264],{"points":1265,"fill":1181},"619.8,80.0 610.8,85.0 610.8,75.0",[39,1267],{"x":1268,"y":49,"width":1139,"height":1140,"rx":1141,"fill":58,"stroke":59,"style":1142},"624.8",[1144,1270,1272],{"transform":1271},"translate(670.4,37.8) scale(1.000)",[1148,1273],{"d":1274,"fill":1151,"stroke":1152,"style":1153},"M5 12.5l4.5 4.5L19 7",[62,1276,1278],{"x":1277,"y":1250,"style":1158},"682.4","Read back",[62,1280,1281],{"x":1277,"y":1254,"style":91},"cached =",[62,1283,1284],{"x":1277,"y":1258,"style":91},"computed",[162,1286,1288],{"id":1287},"step-4-text-and-boolean-results","Step 4 — Text and boolean results",[10,1290,1291],{},"The value argument is not only for numbers. Formulas that return text or TRUE\u002FFALSE store those as well, and xlsxwriter writes the right cell type for each:",[167,1293,1295],{"className":204,"code":1294,"language":206,"meta":172,"style":172},"wb = xlsxwriter.Workbook(\"status.xlsx\")\nws = wb.add_worksheet()\nws.write(\"A1\", 3)\nws.write_formula(\"B1\", '=IF(A1>2,\"big\",\"small\")', None, \"big\")\nws.write_formula(\"C1\", \"=A1>2\", None, True)\nwb.close()\n\nfrom openpyxl import load_workbook\nprint([c.value for c in load_workbook(\"status.xlsx\", data_only=True).active[1]])   # [3, 'big', True]\n",[174,1296,1297,1310,1319,1332,1355,1377,1381,1385,1398],{"__ignoreMap":172},[177,1298,1299,1301,1303,1305,1308],{"class":179,"line":180},[177,1300,245],{"class":217},[177,1302,248],{"class":213},[177,1304,251],{"class":217},[177,1306,1307],{"class":187},"\"status.xlsx\"",[177,1309,257],{"class":217},[177,1311,1312,1314,1316],{"class":179,"line":227},[177,1313,263],{"class":217},[177,1315,248],{"class":213},[177,1317,1318],{"class":217}," wb.add_worksheet()\n",[177,1320,1321,1324,1326,1328,1330],{"class":179,"line":235},[177,1322,1323],{"class":217},"ws.write(",[177,1325,282],{"class":187},[177,1327,291],{"class":217},[177,1329,324],{"class":317},[177,1331,257],{"class":217},[177,1333,1334,1336,1339,1341,1344,1346,1348,1350,1353],{"class":179,"line":242},[177,1335,454],{"class":217},[177,1337,1338],{"class":187},"\"B1\"",[177,1340,291],{"class":217},[177,1342,1343],{"class":187},"'=IF(A1>2,\"big\",\"small\")'",[177,1345,291],{"class":217},[177,1347,677],{"class":317},[177,1349,291],{"class":217},[177,1351,1352],{"class":187},"\"big\"",[177,1354,257],{"class":217},[177,1356,1357,1359,1361,1363,1366,1368,1370,1372,1375],{"class":179,"line":260},[177,1358,454],{"class":217},[177,1360,949],{"class":187},[177,1362,291],{"class":217},[177,1364,1365],{"class":187},"\"=A1>2\"",[177,1367,291],{"class":217},[177,1369,677],{"class":317},[177,1371,291],{"class":217},[177,1373,1374],{"class":317},"True",[177,1376,257],{"class":217},[177,1378,1379],{"class":179,"line":276},[177,1380,470],{"class":217},[177,1382,1383],{"class":179,"line":305},[177,1384,239],{"emptyLinePlaceholder":238},[177,1386,1387,1390,1393,1395],{"class":179,"line":357},[177,1388,1389],{"class":213},"from",[177,1391,1392],{"class":217}," openpyxl ",[177,1394,214],{"class":213},[177,1396,1397],{"class":217}," load_workbook\n",[177,1399,1400,1402,1405,1407,1410,1412,1415,1417,1419,1422,1424,1426,1429,1432,1435],{"class":179,"line":385},[177,1401,481],{"class":317},[177,1403,1404],{"class":217},"([c.value ",[177,1406,308],{"class":213},[177,1408,1409],{"class":217}," c ",[177,1411,314],{"class":213},[177,1413,1414],{"class":217}," load_workbook(",[177,1416,1307],{"class":187},[177,1418,291],{"class":217},[177,1420,1421],{"class":345},"data_only",[177,1423,248],{"class":213},[177,1425,1374],{"class":317},[177,1427,1428],{"class":217},").active[",[177,1430,1431],{"class":317},"1",[177,1433,1434],{"class":217},"]])   ",[177,1436,1437],{"class":497},"# [3, 'big', True]\n",[10,1439,1440,1441,1444],{},"Error results can be stored too, as the strings Excel shows — ",[174,1442,1443],{},"\"#DIV\u002F0!\""," for a division by zero — which is better than a misleading 0 when the formula really does fail for some rows.",[162,1446,1448],{"id":1447},"step-5-stop-data-from-turning-into-formulas","Step 5 — Stop data from turning into formulas",[10,1450,1451,1452,1455,1456,1458],{},"xlsxwriter's ",[174,1453,1454],{},"strings_to_formulas"," option is on by default: any string that starts with ",[174,1457,248],{}," is written as a formula. That is convenient for hand-written formulas and dangerous for data. A comment cell reading \"=total\" becomes a formula referring to a name that does not exist:",[167,1460,1462],{"className":204,"code":1461,"language":206,"meta":172,"style":172},"import re\nimport zipfile\n\nnotes = pd.DataFrame({\"note\": [\"=total\", \"plain\"], \"x\": [1, 2]})\nnotes.to_excel(\"notes.xlsx\", index=False, engine=\"xlsxwriter\")\nprint(re.findall(r'\u003Cc r=\"A2\"[^>]*>.*?\u003C\u002Fc>',\n                 zipfile.ZipFile(\"notes.xlsx\").read(\"xl\u002Fworksheets\u002Fsheet1.xml\").decode()))\n# ['\u003Cc r=\"A2\">\u003Cf>total\u003C\u002Ff>\u003Cv>0\u003C\u002Fv>\u003C\u002Fc>']\n\nwith pd.ExcelWriter(\"notes_safe.xlsx\", engine=\"xlsxwriter\",\n                    engine_kwargs={\"options\": {\"strings_to_formulas\": False}}) as writer:\n    notes.to_excel(writer, index=False)\nprint(pd.read_excel(\"notes_safe.xlsx\")[\"note\"].tolist())    # ['=total', 'plain']\n",[174,1463,1464,1471,1478,1482,1519,1545,1585,1601,1606,1610,1629,1658,1671],{"__ignoreMap":172},[177,1465,1466,1468],{"class":179,"line":180},[177,1467,214],{"class":213},[177,1469,1470],{"class":217}," re\n",[177,1472,1473,1475],{"class":179,"line":227},[177,1474,214],{"class":213},[177,1476,1477],{"class":217}," zipfile\n",[177,1479,1480],{"class":179,"line":235},[177,1481,239],{"emptyLinePlaceholder":238},[177,1483,1484,1487,1489,1491,1494,1496,1499,1501,1504,1506,1509,1511,1513,1515,1517],{"class":179,"line":242},[177,1485,1486],{"class":217},"notes ",[177,1488,248],{"class":213},[177,1490,776],{"class":217},[177,1492,1493],{"class":187},"\"note\"",[177,1495,781],{"class":217},[177,1497,1498],{"class":187},"\"=total\"",[177,1500,291],{"class":217},[177,1502,1503],{"class":187},"\"plain\"",[177,1505,794],{"class":217},[177,1507,1508],{"class":187},"\"x\"",[177,1510,781],{"class":217},[177,1512,1431],{"class":317},[177,1514,291],{"class":217},[177,1516,351],{"class":317},[177,1518,812],{"class":217},[177,1520,1521,1524,1527,1529,1531,1533,1535,1537,1539,1541,1543],{"class":179,"line":260},[177,1522,1523],{"class":217},"notes.to_excel(",[177,1525,1526],{"class":187},"\"notes.xlsx\"",[177,1528,291],{"class":217},[177,1530,899],{"class":345},[177,1532,248],{"class":213},[177,1534,904],{"class":317},[177,1536,291],{"class":217},[177,1538,860],{"class":345},[177,1540,248],{"class":213},[177,1542,865],{"class":187},[177,1544,257],{"class":217},[177,1546,1547,1549,1552,1554,1557,1560,1563,1566,1569,1571,1573,1576,1579,1582],{"class":179,"line":276},[177,1548,481],{"class":317},[177,1550,1551],{"class":217},"(re.findall(",[177,1553,627],{"class":213},[177,1555,1556],{"class":187},"'\u003Cc r=\"A2\"",[177,1558,1559],{"class":317},"[",[177,1561,1562],{"class":213},"^",[177,1564,1565],{"class":369},">",[177,1567,1568],{"class":317},"]",[177,1570,683],{"class":213},[177,1572,1565],{"class":187},[177,1574,1575],{"class":317},".",[177,1577,1578],{"class":213},"*?",[177,1580,1581],{"class":187},"\u003C\u002Fc>'",[177,1583,1584],{"class":217},",\n",[177,1586,1587,1590,1592,1595,1598],{"class":179,"line":305},[177,1588,1589],{"class":217},"                 zipfile.ZipFile(",[177,1591,1526],{"class":187},[177,1593,1594],{"class":217},").read(",[177,1596,1597],{"class":187},"\"xl\u002Fworksheets\u002Fsheet1.xml\"",[177,1599,1600],{"class":217},").decode()))\n",[177,1602,1603],{"class":179,"line":357},[177,1604,1605],{"class":497},"# ['\u003Cc r=\"A2\">\u003Cf>total\u003C\u002Ff>\u003Cv>0\u003C\u002Fv>\u003C\u002Fc>']\n",[177,1607,1608],{"class":179,"line":385},[177,1609,239],{"emptyLinePlaceholder":238},[177,1611,1612,1614,1616,1619,1621,1623,1625,1627],{"class":179,"line":406},[177,1613,849],{"class":213},[177,1615,852],{"class":217},[177,1617,1618],{"class":187},"\"notes_safe.xlsx\"",[177,1620,291],{"class":217},[177,1622,860],{"class":345},[177,1624,248],{"class":213},[177,1626,865],{"class":187},[177,1628,1584],{"class":217},[177,1630,1631,1634,1636,1638,1641,1644,1647,1649,1651,1654,1656],{"class":179,"line":451},[177,1632,1633],{"class":345},"                    engine_kwargs",[177,1635,248],{"class":213},[177,1637,370],{"class":217},[177,1639,1640],{"class":187},"\"options\"",[177,1642,1643],{"class":217},": {",[177,1645,1646],{"class":187},"\"strings_to_formulas\"",[177,1648,936],{"class":217},[177,1650,904],{"class":317},[177,1652,1653],{"class":217},"}}) ",[177,1655,221],{"class":213},[177,1657,873],{"class":217},[177,1659,1660,1663,1665,1667,1669],{"class":179,"line":467},[177,1661,1662],{"class":217},"    notes.to_excel(writer, ",[177,1664,899],{"class":345},[177,1666,248],{"class":213},[177,1668,904],{"class":317},[177,1670,257],{"class":217},[177,1672,1673,1675,1677,1679,1681,1683,1686],{"class":179,"line":473},[177,1674,481],{"class":317},[177,1676,484],{"class":217},[177,1678,1618],{"class":187},[177,1680,489],{"class":217},[177,1682,1493],{"class":187},[177,1684,1685],{"class":217},"].tolist())    ",[177,1687,1688],{"class":497},"# ['=total', 'plain']\n",[10,1690,1691,1692,1694,1695,1698],{},"With the option off, strings stay strings and formulas must be written explicitly with ",[174,1693,514],{}," — which is where you want them anyway, since that is where the value goes. Excel shows a ",[174,1696,1697],{},"#NAME?"," error for the accidental formula; other readers see its cached 0, which hides the problem completely.",[20,1700,29,1705,29,1708,29,1711,29,1714,29,1721,29,1729,29,1734,29,1739,29,1744,29,1750,29,1754,29,1761,29,1765,29,1770,29,1773,29,1778,29,1783,29,1787,29,1791,29,1796,29,1799,29,1804,29,1807],{"viewBox":1701,"role":23,"ariaLabelledBy":1702,"xmlns":27,"style":28},"4 0 752 207",[1703,1704],"fr-options-t","fr-options-d",[31,1706,1707],{"id":1703},"Formulas written implicitly versus explicitly",[35,1709,1710],{"id":1704},"With strings_to_formulas on, any text beginning with an equals sign becomes a formula with a cached zero, which suits hand-written templates but corrupts data. With it off, text stays text and every formula is written with write_formula, where its computed value can be stored.",[39,1712],{"x":41,"y":42,"width":43,"height":1713,"fill":45},"207",[39,1715],{"x":48,"y":49,"width":1716,"height":1717,"rx":1718,"fill":1719,"stroke":1720,"style":1142},"351.0","175.0","14","#fdefd8","var(--gold,#b4740a)",[1144,1722,1724],{"transform":1723},"translate(182.5,29.0) scale(1.083)",[1148,1725],{"d":1726,"fill":1151,"stroke":1727,"style":1728},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","var(--gold-ink,#7a4e06)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[62,1730,1733],{"x":1731,"y":83,"style":1732},"195.5","font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","strings_to_formulas on (default)",[179,1735],{"x1":1736,"y1":1737,"x2":1738,"y2":1737,"stroke":1720,"style":53},"36.0","91.0","355.0",[62,1740,1743],{"x":1741,"y":108,"style":1742},"60.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","quick for hand-written sheets",[1144,1745,1747],{"transform":1746},"translate(38.5,99.5) scale(0.625)",[1148,1748],{"d":1274,"fill":1151,"stroke":1209,"style":1749},"stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[62,1751,1753],{"x":1741,"y":1752,"style":1742},"137.0","data starting with = becomes a formula",[1144,1755,1757],{"transform":1756},"translate(38.5,125.5) scale(0.625)",[1148,1758],{"d":1759,"fill":1151,"stroke":1760,"style":1749},"M6 6l12 12 M18 6L6 18","var(--accent,#f43f8f)",[62,1762,1764],{"x":1741,"y":1763,"style":1742},"163.0","cached value is always 0",[1144,1766,1768],{"transform":1767},"translate(38.5,151.5) scale(0.625)",[1148,1769],{"d":1759,"fill":1151,"stroke":1760,"style":1749},[39,1771],{"x":1772,"y":49,"width":1716,"height":1717,"rx":1718,"fill":1208,"stroke":1209,"style":1142},"389.0",[1144,1774,1776],{"transform":1775},"translate(551.5,29.0) scale(1.083)",[1148,1777],{"d":1274,"fill":1151,"stroke":1216,"style":1728},[62,1779,1782],{"x":1780,"y":83,"style":1781},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","off + write_formula",[179,1784],{"x1":1785,"y1":1737,"x2":1786,"y2":1737,"stroke":1209,"style":53},"405.0","724.0",[62,1788,1790],{"x":1789,"y":108,"style":1742},"429.0","text stays text",[1144,1792,1794],{"transform":1793},"translate(407.5,99.5) scale(0.625)",[1148,1795],{"d":1274,"fill":1151,"stroke":1209,"style":1749},[62,1797,1798],{"x":1789,"y":1752,"style":1742},"each formula written deliberately",[1144,1800,1802],{"transform":1801},"translate(407.5,125.5) scale(0.625)",[1148,1803],{"d":1274,"fill":1151,"stroke":1209,"style":1749},[62,1805,1806],{"x":1789,"y":1763,"style":1742},"value stored with the formula",[1144,1808,1810],{"transform":1809},"translate(407.5,151.5) scale(0.625)",[1148,1811],{"d":1274,"fill":1151,"stroke":1209,"style":1749},[162,1813,1815],{"id":1814},"step-6-check-the-stored-values-against-a-recalculation","Step 6 — Check the stored values against a recalculation",[10,1817,1818,1819,1822],{},"A stored value is only useful if it is right. The ",[174,1820,1821],{},"formulas"," package can load the workbook, recalculate every formula in Python and return the results, which you can compare with the cached values openpyxl reads. Here one total has been written wrongly on purpose:",[167,1824,1826],{"className":204,"code":1825,"language":206,"meta":172,"style":172},"import formulas\nfrom openpyxl import load_workbook\n\nwith pd.ExcelWriter(\"check.xlsx\", engine=\"xlsxwriter\") as writer:\n    orders[[\"qty\", \"price\"]].to_excel(writer, sheet_name=\"Orders\", index=False)\n    ws = writer.sheets[\"Orders\"]\n    ws.write(\"C1\", \"total\")\n    for i, total in enumerate(orders[\"total\"], start=2):\n        ws.write_formula(f\"C{i}\", f\"=A{i}*B{i}\", None, total)\n    ws.write_formula(\"C5\", \"=SUM(C2:C4)\", None, orders[\"total\"].sum() + 1)   # a wrong cached value\n\nsolution = formulas.ExcelModel().loads(\"check.xlsx\").finish().calculate()\nrecalculated = {key.split(\"!\")[1]: value.value[0][0] for key, value in solution.items()\n                if \"!\" in key and \":\" not in key}\ncached = load_workbook(\"check.xlsx\", data_only=True)[\"Orders\"]\nbad = [(ref, cached[ref].value, float(recalculated[ref])) for ref in (\"C2\", \"C3\", \"C4\", \"C5\")\n       if abs(cached[ref].value - recalculated[ref]) > 1e-9]\nprint(bad)                                   # [('C5', 63.0, 62.0)]\n",[174,1827,1828,1835,1845,1849,1872,1900,1912,1924,1948,1993,2027,2031,2046,2085,2113,2139,2184,2209],{"__ignoreMap":172},[177,1829,1830,1832],{"class":179,"line":180},[177,1831,214],{"class":213},[177,1833,1834],{"class":217}," formulas\n",[177,1836,1837,1839,1841,1843],{"class":179,"line":227},[177,1838,1389],{"class":213},[177,1840,1392],{"class":217},[177,1842,214],{"class":213},[177,1844,1397],{"class":217},[177,1846,1847],{"class":179,"line":235},[177,1848,239],{"emptyLinePlaceholder":238},[177,1850,1851,1853,1855,1858,1860,1862,1864,1866,1868,1870],{"class":179,"line":242},[177,1852,849],{"class":213},[177,1854,852],{"class":217},[177,1856,1857],{"class":187},"\"check.xlsx\"",[177,1859,291],{"class":217},[177,1861,860],{"class":345},[177,1863,248],{"class":213},[177,1865,865],{"class":187},[177,1867,868],{"class":217},[177,1869,221],{"class":213},[177,1871,873],{"class":217},[177,1873,1874,1876,1878,1880,1882,1884,1886,1888,1890,1892,1894,1896,1898],{"class":179,"line":260},[177,1875,878],{"class":217},[177,1877,288],{"class":187},[177,1879,291],{"class":217},[177,1881,294],{"class":187},[177,1883,887],{"class":217},[177,1885,890],{"class":345},[177,1887,248],{"class":213},[177,1889,271],{"class":187},[177,1891,291],{"class":217},[177,1893,899],{"class":345},[177,1895,248],{"class":213},[177,1897,904],{"class":317},[177,1899,257],{"class":217},[177,1901,1902,1904,1906,1908,1910],{"class":179,"line":276},[177,1903,911],{"class":217},[177,1905,248],{"class":213},[177,1907,916],{"class":217},[177,1909,271],{"class":187},[177,1911,840],{"class":217},[177,1913,1914,1916,1918,1920,1922],{"class":179,"line":305},[177,1915,360],{"class":217},[177,1917,949],{"class":187},[177,1919,291],{"class":217},[177,1921,299],{"class":187},[177,1923,257],{"class":217},[177,1925,1926,1928,1930,1932,1934,1936,1938,1940,1942,1944,1946],{"class":179,"line":357},[177,1927,960],{"class":213},[177,1929,963],{"class":217},[177,1931,314],{"class":213},[177,1933,318],{"class":317},[177,1935,970],{"class":217},[177,1937,299],{"class":187},[177,1939,794],{"class":217},[177,1941,346],{"class":345},[177,1943,248],{"class":213},[177,1945,351],{"class":317},[177,1947,354],{"class":217},[177,1949,1950,1952,1954,1956,1958,1960,1962,1964,1966,1968,1970,1972,1974,1976,1978,1980,1982,1984,1986,1988,1990],{"class":179,"line":385},[177,1951,987],{"class":217},[177,1953,363],{"class":213},[177,1955,414],{"class":187},[177,1957,370],{"class":369},[177,1959,996],{"class":217},[177,1961,376],{"class":369},[177,1963,379],{"class":187},[177,1965,291],{"class":217},[177,1967,363],{"class":213},[177,1969,429],{"class":187},[177,1971,370],{"class":369},[177,1973,996],{"class":217},[177,1975,376],{"class":369},[177,1977,438],{"class":187},[177,1979,370],{"class":369},[177,1981,996],{"class":217},[177,1983,376],{"class":369},[177,1985,379],{"class":187},[177,1987,291],{"class":217},[177,1989,677],{"class":317},[177,1991,1992],{"class":217},", total)\n",[177,1994,1995,1997,2000,2002,2005,2007,2009,2012,2014,2017,2019,2021,2024],{"class":179,"line":406},[177,1996,409],{"class":217},[177,1998,1999],{"class":187},"\"C5\"",[177,2001,291],{"class":217},[177,2003,2004],{"class":187},"\"=SUM(C2:C4)\"",[177,2006,291],{"class":217},[177,2008,677],{"class":317},[177,2010,2011],{"class":217},", orders[",[177,2013,299],{"class":187},[177,2015,2016],{"class":217},"].sum() ",[177,2018,1041],{"class":213},[177,2020,1062],{"class":317},[177,2022,2023],{"class":217},")   ",[177,2025,2026],{"class":497},"# a wrong cached value\n",[177,2028,2029],{"class":179,"line":451},[177,2030,239],{"emptyLinePlaceholder":238},[177,2032,2033,2036,2038,2041,2043],{"class":179,"line":467},[177,2034,2035],{"class":217},"solution ",[177,2037,248],{"class":213},[177,2039,2040],{"class":217}," formulas.ExcelModel().loads(",[177,2042,1857],{"class":187},[177,2044,2045],{"class":217},").finish().calculate()\n",[177,2047,2048,2051,2053,2056,2059,2061,2063,2066,2068,2071,2073,2075,2077,2080,2082],{"class":179,"line":473},[177,2049,2050],{"class":217},"recalculated ",[177,2052,248],{"class":213},[177,2054,2055],{"class":217}," {key.split(",[177,2057,2058],{"class":187},"\"!\"",[177,2060,489],{"class":217},[177,2062,1431],{"class":317},[177,2064,2065],{"class":217},"]: value.value[",[177,2067,42],{"class":317},[177,2069,2070],{"class":217},"][",[177,2072,42],{"class":317},[177,2074,822],{"class":217},[177,2076,308],{"class":213},[177,2078,2079],{"class":217}," key, value ",[177,2081,314],{"class":213},[177,2083,2084],{"class":217}," solution.items()\n",[177,2086,2087,2090,2093,2096,2099,2102,2105,2108,2110],{"class":179,"line":478},[177,2088,2089],{"class":213},"                if",[177,2091,2092],{"class":187}," \"!\"",[177,2094,2095],{"class":213}," in",[177,2097,2098],{"class":217}," key ",[177,2100,2101],{"class":213},"and",[177,2103,2104],{"class":187}," \":\"",[177,2106,2107],{"class":213}," not",[177,2109,2095],{"class":213},[177,2111,2112],{"class":217}," key}\n",[177,2114,2116,2119,2121,2123,2125,2127,2129,2131,2133,2135,2137],{"class":179,"line":2115},15,[177,2117,2118],{"class":217},"cached ",[177,2120,248],{"class":213},[177,2122,1414],{"class":217},[177,2124,1857],{"class":187},[177,2126,291],{"class":217},[177,2128,1421],{"class":345},[177,2130,248],{"class":213},[177,2132,1374],{"class":317},[177,2134,489],{"class":217},[177,2136,271],{"class":187},[177,2138,840],{"class":217},[177,2140,2142,2145,2147,2150,2153,2156,2158,2161,2163,2166,2169,2171,2174,2176,2178,2180,2182],{"class":179,"line":2141},16,[177,2143,2144],{"class":217},"bad ",[177,2146,248],{"class":213},[177,2148,2149],{"class":217}," [(ref, cached[ref].value, ",[177,2151,2152],{"class":317},"float",[177,2154,2155],{"class":217},"(recalculated[ref])) ",[177,2157,308],{"class":213},[177,2159,2160],{"class":217}," ref ",[177,2162,314],{"class":213},[177,2164,2165],{"class":217}," (",[177,2167,2168],{"class":187},"\"C2\"",[177,2170,291],{"class":217},[177,2172,2173],{"class":187},"\"C3\"",[177,2175,291],{"class":217},[177,2177,457],{"class":187},[177,2179,291],{"class":217},[177,2181,1999],{"class":187},[177,2183,257],{"class":217},[177,2185,2187,2190,2193,2196,2199,2202,2204,2207],{"class":179,"line":2186},17,[177,2188,2189],{"class":213},"       if",[177,2191,2192],{"class":317}," abs",[177,2194,2195],{"class":217},"(cached[ref].value ",[177,2197,2198],{"class":213},"-",[177,2200,2201],{"class":217}," recalculated[ref]) ",[177,2203,1565],{"class":213},[177,2205,2206],{"class":317}," 1e-9",[177,2208,840],{"class":217},[177,2210,2212,2214,2217],{"class":179,"line":2211},18,[177,2213,481],{"class":317},[177,2215,2216],{"class":217},"(bad)                                   ",[177,2218,2219],{"class":497},"# [('C5', 63.0, 62.0)]\n",[10,2221,2222,2223,2225],{},"The check finds the one cell whose stored value disagrees with what the formula actually computes. It runs in well under a second for a report of this size, which makes it cheap enough to include in the job's tests. The ",[174,2224,1821],{}," package covers the common worksheet functions but not everything Excel offers; for workbooks that use functions it cannot evaluate, recalculate with LibreOffice in a test environment instead.",[162,2227,2229],{"id":2228},"do-you-need-formulas-at-all","Do you need formulas at all?",[10,2231,2232],{},"Storing values raises an obvious question: if Python already computed every result, why write formulas? Because the reader may change an input. A formula keeps a margin column correct when someone corrects a quantity; a static value does not. The rule of thumb is to write formulas where readers are expected to edit inputs and explore — budgets, planning sheets, calculators — and plain values in reports that are a record of what happened, such as a month-end extract. Mixed reports are common: static data, with formulas only in the summary block that people adjust. Whichever you choose, the file should show the same numbers to everyone who opens it.",[162,2234,2236],{"id":2235},"common-pitfalls","Common pitfalls",[2238,2239,2240,2248,2254,2264],"ul",{},[2241,2242,2243,2247],"li",{},[2244,2245,2246],"strong",{},"Values that drift from the formula."," If the pandas logic and the formula disagree, Excel users and pandas users see different totals. Test one against the other.",[2241,2249,2250,2253],{},[2244,2251,2252],{},"Rounding."," Store the unrounded result; let the number format do the rounding for display, as Excel's own recalculation would.",[2241,2255,2256,2259,2260,2263],{},[2244,2257,2258],{},"Formulas that depend on today."," A cached result of ",[174,2261,2262],{},"=TODAY()-A2"," is correct only on the day the file was written; non-recalculating readers show that day's value forever. Store it, but label such columns with the run date.",[2241,2265,2266,2269],{},[2244,2267,2268],{},"Assuming LibreOffice will fix it."," A server-side conversion is not a recalculation. If you depend on LibreOffice results, store the values or recalculate deliberately.",[162,2271,2273],{"id":2272},"conclusion","Conclusion",[10,2275,2276,2277,2279,2280,2282,2283,2285],{},"xlsxwriter stores a cached 0 for every formula and relies on Excel to recalculate, so pandas, openpyxl, previewers and headless conversions show zeros. Compute each result in Python and pass it as the fourth argument of ",[174,2278,514],{},", for text and boolean results as well as numbers, keep the pandas logic and the formula side by side, and turn off ",[174,2281,1454],{}," when writing data so that text beginning with ",[174,2284,248],{}," stays text.",[162,2287,2289],{"id":2288},"frequently-asked-questions","Frequently asked questions",[10,2291,2292,2295],{},[2244,2293,2294],{},"Why does pandas read 0 for formulas written with xlsxwriter?","\nxlsxwriter cannot calculate formulas, so it stores 0 as each formula's cached result and flags the workbook to recalculate when opened. Excel does that; pandas, openpyxl with data_only=True and many previewers only read the cached value.",[10,2297,2298,2301],{},[2244,2299,2300],{},"How do I store the real result of a formula with xlsxwriter?","\nPass the value as the fourth argument, worksheet.write_formula(\"C2\", \"=A2*B2\", cell_format, 7.5). Excel still recalculates on open, but every other reader sees 7.5 instead of 0.",[10,2303,2304,2307],{},[2244,2305,2306],{},"Does LibreOffice recalculate xlsxwriter files?","\nNot necessarily. In a headless conversion with default settings, LibreOffice kept the cached zeros. Interactive LibreOffice may prompt or recalculate depending on its settings, so do not rely on it for correct values.",[10,2309,2310,2313],{},[2244,2311,2312],{},"Why did a text value starting with \"=\" turn into a formula?","\nxlsxwriter's strings_to_formulas option is on by default, so any string beginning with \"=\" is written as a formula. Turn it off with the workbook option {\"strings_to_formulas\": False} when writing data that may contain such text.",[162,2315,2317],{"id":2316},"related","Related",[2238,2319,2320,2326,2333,2340],{},[2241,2321,2322,2323,2325],{},"Up one level: ",[14,2324,17],{"href":16}," — report writing with XlsxWriter.",[2241,2327,2328,2332],{},[14,2329,2331],{"href":2330},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fread-formula-results-with-openpyxl-data-only\u002F","Read Formula Results with openpyxl data_only"," — the reader that shows the cached values.",[2241,2334,2335,2339],{},[14,2336,2338],{"href":2337},"\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"," — formulas that spill.",[2241,2341,2342,2346],{},[14,2343,2345],{"href":2344},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-a-formatted-excel-report-with-xlsxwriter\u002F","Write a Formatted Excel Report with xlsxwriter"," — formats for the formula columns.",[2348,2349,2350],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}",{"title":172,"searchDepth":227,"depth":227,"links":2352},[2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364],{"id":164,"depth":227,"text":165},{"id":200,"depth":227,"text":201},{"id":508,"depth":227,"text":509},{"id":757,"depth":227,"text":758},{"id":1287,"depth":227,"text":1288},{"id":1447,"depth":227,"text":1448},{"id":1814,"depth":227,"text":1815},{"id":2228,"depth":227,"text":2229},{"id":2235,"depth":227,"text":2236},{"id":2272,"depth":227,"text":2273},{"id":2288,"depth":227,"text":2289},{"id":2316,"depth":227,"text":2317},"2026-09-23","xlsxwriter writes formulas with a cached result of 0, so pandas, openpyxl, previewers and even LibreOffice's command-line conversion show zeros until Excel recalculates. Compute the results in Python and store them with the formula, keep them consistent, and stop text that starts with \"=\" from becoming a formula.","md",[2369,2371,2373,2375],{"q":2294,"a":2370},"xlsxwriter cannot calculate formulas, so it stores 0 as each formula's cached result and flags the workbook to recalculate when opened. Excel does that; pandas, openpyxl with data_only=True and many previewers only read the cached value.",{"q":2300,"a":2372},"Pass the value as the fourth argument, worksheet.write_formula(\"C2\", \"=A2*B2\", cell_format, 7.5). Excel still recalculates on open, but every other reader sees 7.5 instead of 0.",{"q":2306,"a":2374},"Not necessarily. In a headless conversion with default settings, LibreOffice kept the cached zeros. Interactive LibreOffice may prompt or recalculate depending on its settings, so do not rely on it for correct values.",{"q":2312,"a":2376},"xlsxwriter's strings_to_formulas option is on by default, so any string beginning with \"=\" is written as a formula. Turn it off with the workbook option {\"strings_to_formulas\": False} when writing data that may contain such text.","store formula results with xlsxwriter so every viewer shows values",null,{"breadcrumb":2380},[2381,2384,2387],{"name":2382,"item":2383},"Home","\u002F",{"name":2385,"item":2386},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":17,"item":16},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter",{"title":2390,"description":2391},"Store Formula Results with xlsxwriter (cached values, not zeros)","Why xlsxwriter formulas read back as 0 in pandas, openpyxl data_only, previews and headless LibreOffice, how to pass the value argument to write_formula, compute results with pandas, handle text and boolean results and disable strings_to_formulas.","store-formula-results-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter\u002Findex",[2395,2396],"excel-formulas","xlsxwriter","how-to","1e6NeYBO3CZkFigYbKsRdZmAtjZOHSrGW-1b4vtJQAw",[2400,2404],{"title":2401,"path":2402,"stem":2403,"children":-1},"Set Print Options, Headers and Footers with XlsxWriter","\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fset-print-options-headers-and-footers-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fset-print-options-headers-and-footers-with-xlsxwriter\u002Findex",{"title":2345,"path":2405,"stem":2406,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-a-formatted-excel-report-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-a-formatted-excel-report-with-xlsxwriter\u002Findex",[2408,2410],{"path":2409,"title":17},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter",{"path":2411,"title":2385},"\u002Fformatting-and-charting-excel-reports-with-python",[],[2414,2418,2421,2424,2427,2430],{"path":2415,"title":2416,"kind":2417},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python","Working with Excel Formulas in Python","guide",{"path":2419,"title":2420,"kind":2397},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fadd-sum-and-average-formulas-with-python","Add SUM and AVERAGE Formulas with Python",{"path":2422,"title":2423,"kind":2397},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Faudit-every-formula-in-a-workbook-with-python","Audit Every Formula in a Workbook with Python",{"path":2425,"title":2426,"kind":2397},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fconvert-excel-formulas-to-values-with-python","Convert Excel Formulas to Values with Python",{"path":2428,"title":2429,"kind":2397},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fcopy-formula-down-a-column-in-openpyxl","Copy a Formula Down a Column in openpyxl",{"path":2431,"title":2432,"kind":2397},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fcreate-named-range-in-excel-with-openpyxl","Create a Named Range in Excel with openpyxl",1790972108670]