[{"data":1,"prerenderedAt":2412},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-excel-formulas-from-a-pandas-dataframe":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-excel-formulas-from-a-pandas-dataframe":2378,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-excel-formulas-from-a-pandas-dataframe":2387,"children:\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-excel-formulas-from-a-pandas-dataframe":2392,"related:\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-excel-formulas-from-a-pandas-dataframe":2393},{"id":4,"title":5,"body":6,"dateModified":2342,"datePublished":2342,"description":2343,"extension":2344,"faq":2345,"keyword":2354,"kind":2355,"meta":2356,"navigation":103,"path":2366,"seo":2367,"slug":2370,"stem":2371,"topics":2372,"type":2376,"__hash__":2377},"docs\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-excel-formulas-from-a-pandas-dataframe\u002Findex.md","Write Excel Formulas from a pandas DataFrame",{"type":7,"value":8,"toc":2327},"minimark",[9,28,33,64,71,75,322,333,337,347,657,677,896,900,914,1076,1093,1097,1100,1335,1357,1593,1597,1600,1687,1706,1850,1854,1857,2009,2016,2020,2027,2149,2164,2168,2222,2226,2243,2247,2256,2260,2272,2278,2284,2290,2294,2323],[10,11,12,13,17,18,21,22,27],"p",{},"Most reports are computed in pandas and written as values. Sometimes the recipient needs to see — and change — the calculation: a margin column that updates when they adjust a price, a total that follows edits, a commission rate held in one cell. pandas can write those formulas directly: any string that begins with ",[14,15,16],"code",{},"="," is written as a formula by both Excel engines. The work is in producing the right string for each row — the right column letters, the right row numbers once the header, index and ",[14,19,20],{},"startrow"," are taken into account — and in knowing what the file contains until Excel recalculates it. This page belongs to ",[23,24,26],"a",{"href":25},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002F","Writing DataFrames to Excel with pandas",".",[29,30,32],"h2",{"id":31},"prerequisites","Prerequisites",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl xlsxwriter\n","bash","",[14,41,42],{"__ignoreMap":39},[43,44,47,51,55,58,61],"span",{"class":45,"line":46},"line",1,[43,48,50],{"class":49},"sMTad","pip",[43,52,54],{"class":53},"srMev"," install",[43,56,57],{"class":53}," pandas",[43,59,60],{"class":53}," openpyxl",[43,62,63],{"class":53}," xlsxwriter\n",[10,65,66,67,70],{},"LibreOffice (",[14,68,69],{},"soffice",") is used in Step 6 to recalculate the file and check the formulas; it is optional.",[29,72,74],{"id":73},"step-1-a-formula-is-just-a-string-that-starts-with","Step 1 — A formula is just a string that starts with \"=\"",[34,76,80],{"className":77,"code":78,"language":79,"meta":39,"style":39},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\norders = pd.DataFrame({\n    \"Product\": [\"Drill\", \"Saw\", \"Hose\", \"Rake\"],\n    \"Qty\": [3, 5, 12, 4],\n    \"Unit price\": [89.0, 45.5, 14.0, 22.0],\n})\norders[\"Total\"] = [f\"=B{r}*C{r}\" for r in range(2, len(orders) + 2)]\norders.to_excel(\"orders.xlsx\", index=False)\nprint(orders)\n","python",[14,81,82,98,105,116,147,176,204,210,290,313],{"__ignoreMap":39},[43,83,84,88,92,95],{"class":45,"line":46},[43,85,87],{"class":86},"s-kum","import",[43,89,91],{"class":90},"skGVy"," pandas ",[43,93,94],{"class":86},"as",[43,96,97],{"class":90}," pd\n",[43,99,101],{"class":45,"line":100},2,[43,102,104],{"emptyLinePlaceholder":103},true,"\n",[43,106,108,111,113],{"class":45,"line":107},3,[43,109,110],{"class":90},"orders ",[43,112,16],{"class":86},[43,114,115],{"class":90}," pd.DataFrame({\n",[43,117,119,122,125,128,131,134,136,139,141,144],{"class":45,"line":118},4,[43,120,121],{"class":53},"    \"Product\"",[43,123,124],{"class":90},": [",[43,126,127],{"class":53},"\"Drill\"",[43,129,130],{"class":90},", ",[43,132,133],{"class":53},"\"Saw\"",[43,135,130],{"class":90},[43,137,138],{"class":53},"\"Hose\"",[43,140,130],{"class":90},[43,142,143],{"class":53},"\"Rake\"",[43,145,146],{"class":90},"],\n",[43,148,150,153,155,159,161,164,166,169,171,174],{"class":45,"line":149},5,[43,151,152],{"class":53},"    \"Qty\"",[43,154,124],{"class":90},[43,156,158],{"class":157},"sP0c6","3",[43,160,130],{"class":90},[43,162,163],{"class":157},"5",[43,165,130],{"class":90},[43,167,168],{"class":157},"12",[43,170,130],{"class":90},[43,172,173],{"class":157},"4",[43,175,146],{"class":90},[43,177,179,182,184,187,189,192,194,197,199,202],{"class":45,"line":178},6,[43,180,181],{"class":53},"    \"Unit price\"",[43,183,124],{"class":90},[43,185,186],{"class":157},"89.0",[43,188,130],{"class":90},[43,190,191],{"class":157},"45.5",[43,193,130],{"class":90},[43,195,196],{"class":157},"14.0",[43,198,130],{"class":90},[43,200,201],{"class":157},"22.0",[43,203,146],{"class":90},[43,205,207],{"class":45,"line":206},7,[43,208,209],{"class":90},"})\n",[43,211,213,216,219,222,224,227,230,233,237,240,243,246,248,250,252,255,258,261,264,267,270,273,275,278,281,284,287],{"class":45,"line":212},8,[43,214,215],{"class":90},"orders[",[43,217,218],{"class":53},"\"Total\"",[43,220,221],{"class":90},"] ",[43,223,16],{"class":86},[43,225,226],{"class":90}," [",[43,228,229],{"class":86},"f",[43,231,232],{"class":53},"\"=B",[43,234,236],{"class":235},"sSjpA","{",[43,238,239],{"class":90},"r",[43,241,242],{"class":235},"}",[43,244,245],{"class":53},"*C",[43,247,236],{"class":235},[43,249,239],{"class":90},[43,251,242],{"class":235},[43,253,254],{"class":53},"\"",[43,256,257],{"class":86}," for",[43,259,260],{"class":90}," r ",[43,262,263],{"class":86},"in",[43,265,266],{"class":157}," range",[43,268,269],{"class":90},"(",[43,271,272],{"class":157},"2",[43,274,130],{"class":90},[43,276,277],{"class":157},"len",[43,279,280],{"class":90},"(orders) ",[43,282,283],{"class":86},"+",[43,285,286],{"class":157}," 2",[43,288,289],{"class":90},")]\n",[43,291,293,296,299,301,305,307,310],{"class":45,"line":292},9,[43,294,295],{"class":90},"orders.to_excel(",[43,297,298],{"class":53},"\"orders.xlsx\"",[43,300,130],{"class":90},[43,302,304],{"class":303},"sa561","index",[43,306,16],{"class":86},[43,308,309],{"class":157},"False",[43,311,312],{"class":90},")\n",[43,314,316,319],{"class":45,"line":315},10,[43,317,318],{"class":157},"print",[43,320,321],{"class":90},"(orders)\n",[10,323,324,325,328,329,332],{},"Row 1 of the sheet holds the header, so the first data row is row 2 and each formula multiplies the ",[14,326,327],{},"Qty"," and ",[14,330,331],{},"Unit price"," cells of its own row. Open the file in Excel and the Total column shows 267, 227.5, 168 and 88. In pandas the column is just text; the conversion happens in the writer.",[29,334,336],{"id":335},"step-2-look-up-column-letters-by-name","Step 2 — Look up column letters by name",[10,338,339,340,328,343,346],{},"Hard-coding ",[14,341,342],{},"B",[14,344,345],{},"C"," breaks the moment someone adds a column. Derive the letters from the DataFrame's own column positions:",[34,348,350],{"className":77,"code":349,"language":79,"meta":39,"style":39},"from openpyxl.utils import get_column_letter\n\ndef col_letter(df, name, index=False):\n    return get_column_letter(df.columns.get_loc(name) + 1 + (df.index.nlevels if index else 0))\n\ndef per_row(df, template, startrow=0, index=False):\n    first = startrow + 2                       # header row + 1, 1-based\n    letters = {c: col_letter(df, c, index) for c in df.columns}\n    return [template.format(r=r, **{k.replace(\" \", \"_\"): v for k, v in letters.items()})\n            for r in range(first, first + len(df))]\n\norders = orders.drop(columns=\"Total\")\norders.insert(1, \"SKU\", [\"D-01\", \"S-02\", \"H-03\", \"R-04\"])\norders[\"Total\"] = per_row(orders, \"={Qty}{r}*{Unit_price}{r}\")\nprint(orders[\"Total\"].tolist())\n",[14,351,352,365,369,388,422,426,450,468,489,530,552,557,576,614,644],{"__ignoreMap":39},[43,353,354,357,360,362],{"class":45,"line":46},[43,355,356],{"class":86},"from",[43,358,359],{"class":90}," openpyxl.utils ",[43,361,87],{"class":86},[43,363,364],{"class":90}," get_column_letter\n",[43,366,367],{"class":45,"line":100},[43,368,104],{"emptyLinePlaceholder":103},[43,370,371,374,378,381,383,385],{"class":45,"line":107},[43,372,373],{"class":86},"def",[43,375,377],{"class":376},"s_Opv"," col_letter",[43,379,380],{"class":90},"(df, name, index",[43,382,16],{"class":86},[43,384,309],{"class":157},[43,386,387],{"class":90},"):\n",[43,389,390,393,396,398,401,404,407,410,413,416,419],{"class":45,"line":118},[43,391,392],{"class":86},"    return",[43,394,395],{"class":90}," get_column_letter(df.columns.get_loc(name) ",[43,397,283],{"class":86},[43,399,400],{"class":157}," 1",[43,402,403],{"class":86}," +",[43,405,406],{"class":90}," (df.index.nlevels ",[43,408,409],{"class":86},"if",[43,411,412],{"class":90}," index ",[43,414,415],{"class":86},"else",[43,417,418],{"class":157}," 0",[43,420,421],{"class":90},"))\n",[43,423,424],{"class":45,"line":149},[43,425,104],{"emptyLinePlaceholder":103},[43,427,428,430,433,436,438,441,444,446,448],{"class":45,"line":178},[43,429,373],{"class":86},[43,431,432],{"class":376}," per_row",[43,434,435],{"class":90},"(df, template, startrow",[43,437,16],{"class":86},[43,439,440],{"class":157},"0",[43,442,443],{"class":90},", index",[43,445,16],{"class":86},[43,447,309],{"class":157},[43,449,387],{"class":90},[43,451,452,455,457,460,462,464],{"class":45,"line":206},[43,453,454],{"class":90},"    first ",[43,456,16],{"class":86},[43,458,459],{"class":90}," startrow ",[43,461,283],{"class":86},[43,463,286],{"class":157},[43,465,467],{"class":466},"s-wDw","                       # header row + 1, 1-based\n",[43,469,470,473,475,478,481,484,486],{"class":45,"line":212},[43,471,472],{"class":90},"    letters ",[43,474,16],{"class":86},[43,476,477],{"class":90}," {c: col_letter(df, c, index) ",[43,479,480],{"class":86},"for",[43,482,483],{"class":90}," c ",[43,485,263],{"class":86},[43,487,488],{"class":90}," df.columns}\n",[43,490,491,493,496,498,500,503,506,509,512,514,517,520,522,525,527],{"class":45,"line":292},[43,492,392],{"class":86},[43,494,495],{"class":90}," [template.format(",[43,497,239],{"class":303},[43,499,16],{"class":86},[43,501,502],{"class":90},"r, ",[43,504,505],{"class":86},"**",[43,507,508],{"class":90},"{k.replace(",[43,510,511],{"class":53},"\" \"",[43,513,130],{"class":90},[43,515,516],{"class":53},"\"_\"",[43,518,519],{"class":90},"): v ",[43,521,480],{"class":86},[43,523,524],{"class":90}," k, v ",[43,526,263],{"class":86},[43,528,529],{"class":90}," letters.items()})\n",[43,531,532,535,537,539,541,544,546,549],{"class":45,"line":315},[43,533,534],{"class":86},"            for",[43,536,260],{"class":90},[43,538,263],{"class":86},[43,540,266],{"class":157},[43,542,543],{"class":90},"(first, first ",[43,545,283],{"class":86},[43,547,548],{"class":157}," len",[43,550,551],{"class":90},"(df))]\n",[43,553,555],{"class":45,"line":554},11,[43,556,104],{"emptyLinePlaceholder":103},[43,558,560,562,564,567,570,572,574],{"class":45,"line":559},12,[43,561,110],{"class":90},[43,563,16],{"class":86},[43,565,566],{"class":90}," orders.drop(",[43,568,569],{"class":303},"columns",[43,571,16],{"class":86},[43,573,218],{"class":53},[43,575,312],{"class":90},[43,577,579,582,585,587,590,593,596,598,601,603,606,608,611],{"class":45,"line":578},13,[43,580,581],{"class":90},"orders.insert(",[43,583,584],{"class":157},"1",[43,586,130],{"class":90},[43,588,589],{"class":53},"\"SKU\"",[43,591,592],{"class":90},", [",[43,594,595],{"class":53},"\"D-01\"",[43,597,130],{"class":90},[43,599,600],{"class":53},"\"S-02\"",[43,602,130],{"class":90},[43,604,605],{"class":53},"\"H-03\"",[43,607,130],{"class":90},[43,609,610],{"class":53},"\"R-04\"",[43,612,613],{"class":90},"])\n",[43,615,617,619,621,623,625,628,631,634,637,640,642],{"class":45,"line":616},14,[43,618,215],{"class":90},[43,620,218],{"class":53},[43,622,221],{"class":90},[43,624,16],{"class":86},[43,626,627],{"class":90}," per_row(orders, ",[43,629,630],{"class":53},"\"=",[43,632,633],{"class":235},"{Qty}{r}",[43,635,636],{"class":53},"*",[43,638,639],{"class":235},"{Unit_price}{r}",[43,641,254],{"class":53},[43,643,312],{"class":90},[43,645,647,649,652,654],{"class":45,"line":646},15,[43,648,318],{"class":157},[43,650,651],{"class":90},"(orders[",[43,653,218],{"class":53},[43,655,656],{"class":90},"].tolist())\n",[10,658,659,660,663,664,666,667,669,670,130,673,676],{},"After inserting a ",[14,661,662],{},"SKU"," column, ",[14,665,327],{}," moved to C and ",[14,668,331],{}," to D, and the generated formulas follow: ",[14,671,672],{},"=C2*D2",[14,674,675],{},"=C3*D3",", and so on. The template names columns rather than letters (spaces become underscores), so the formula reads like the calculation it performs.",[678,679,687,688,687,692,687,696,687,702,687,710,687,717,687,720,687,725,687,731,687,735,687,741,687,745,687,748,687,752,687,755,687,759,687,763,687,767,687,771,687,774,687,778,687,783,687,787,687,789,687,791,687,793,687,795,687,797,687,799,687,801,687,804,687,807,687,810,687,812,687,815,687,817,687,820,687,822,687,824,687,826,687,829,687,833,687,836,687,839,687,842,687,844,687,847,687,849,687,852,687,854,687,856,687,858,687,860,687,862,687,864,687,869,687,873,687,878,687,883,687,890],"svg",{"viewBox":680,"role":681,"ariaLabelledBy":682,"xmlns":685,"style":686},"4 0 752 164","img",[683,684],"fx-letters-t","fx-letters-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  ",[689,690,691],"title",{"id":683},"Formulas generated from column names follow the layout",[693,694,695],"desc",{"id":684},"The DataFrame has columns Product, SKU, Qty, Unit price and Total. The template \"={Qty}{r}*{Unit_price}{r}\" becomes =C2*D2 on the first data row because Qty sits in column C and Unit price in column D.",[697,698],"rect",{"x":173,"y":440,"width":699,"height":700,"fill":701},"752","164","#ffffff",[697,703],{"x":704,"y":705,"width":706,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},"20.0","40.0","164.0","28.0","var(--line,#cdd5e6)","stroke-width:1px",[711,712,716],"text",{"x":713,"y":714,"style":715},"102.0","59.0","font-size:11px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Total template",[697,718],{"x":704,"y":719,"width":706,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},"68.0",[711,721,724],{"x":713,"y":722,"style":723},"87.0","font-size:11px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","={Qty}{r}*{Unit_price}{r}",[697,726],{"x":727,"y":705,"width":728,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"403.5","32.0","24.0","#e7ebef",[697,732],{"x":733,"y":705,"width":734,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"435.5","66.8",[711,736,740],{"x":737,"y":738,"style":739},"468.9","57.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[697,742],{"x":743,"y":705,"width":744,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"502.3","50.5",[711,746,342],{"x":747,"y":738,"style":739},"527.5",[697,749],{"x":750,"y":705,"width":751,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"552.8","42.9",[711,753,345],{"x":754,"y":738,"style":739},"574.2",[697,756],{"x":757,"y":705,"width":758,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"595.7","76.3",[711,760,762],{"x":761,"y":738,"style":739},"633.8","D",[697,764],{"x":765,"y":705,"width":766,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"671.9","68.1",[711,768,770],{"x":769,"y":738,"style":739},"706.0","E",[697,772],{"x":727,"y":773,"width":728,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},"64.0",[711,775,584],{"x":776,"y":777,"style":739},"419.5","83.0",[697,779],{"x":733,"y":773,"width":734,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},"#f0f4ff","var(--brand,#5b5cf0)","stroke-width:1.5px",[711,784,786],{"x":737,"y":777,"style":785},"font-size:11px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Product",[697,788],{"x":743,"y":773,"width":744,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},[711,790,662],{"x":747,"y":777,"style":785},[697,792],{"x":750,"y":773,"width":751,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},[711,794,327],{"x":754,"y":777,"style":785},[697,796],{"x":757,"y":773,"width":758,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},[711,798,331],{"x":761,"y":777,"style":785},[697,800],{"x":765,"y":773,"width":766,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},[711,802,803],{"x":769,"y":777,"style":785},"Total",[697,805],{"x":727,"y":806,"width":728,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},"92.0",[711,808,272],{"x":776,"y":809,"style":739},"111.0",[697,811],{"x":733,"y":806,"width":734,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,813,814],{"x":737,"y":809,"style":723},"Drill",[697,816],{"x":743,"y":806,"width":744,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,818,819],{"x":747,"y":809,"style":723},"D-01",[697,821],{"x":750,"y":806,"width":751,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,823,158],{"x":754,"y":809,"style":723},[697,825],{"x":757,"y":806,"width":758,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,827,828],{"x":761,"y":809,"style":723},"89",[697,830],{"x":765,"y":806,"width":766,"height":707,"rx":440,"fill":831,"stroke":832,"style":782},"#d9f4f1","var(--teal,#0f9488)",[711,834,672],{"x":769,"y":809,"style":835},"font-size:11px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle",[697,837],{"x":727,"y":838,"width":728,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},"120.0",[711,840,158],{"x":776,"y":841,"style":739},"139.0",[697,843],{"x":733,"y":838,"width":734,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,845,846],{"x":737,"y":841,"style":723},"Saw",[697,848],{"x":743,"y":838,"width":744,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,850,851],{"x":747,"y":841,"style":723},"S-02",[697,853],{"x":750,"y":838,"width":751,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,855,163],{"x":754,"y":841,"style":723},[697,857],{"x":757,"y":838,"width":758,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,859,191],{"x":761,"y":841,"style":723},[697,861],{"x":765,"y":838,"width":766,"height":707,"rx":440,"fill":831,"stroke":832,"style":782},[711,863,675],{"x":769,"y":841,"style":835},[711,865,868],{"x":713,"y":866,"style":867},"29.0","font-size:12.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","template",[711,870,872],{"x":871,"y":866,"style":867},"571.8","written sheet",[45,874],{"x1":875,"y1":719,"x2":876,"y2":719,"stroke":781,"style":877},"194.0","389.5","stroke-width:2px",[879,880],"polygon",{"points":881,"fill":882},"393.5,68.0 384.5,73.0 384.5,63.0","#5b5cf0",[697,884],{"x":885,"y":886,"width":887,"height":201,"rx":888,"fill":701,"stroke":708,"style":889},"222.0","35.0","143.6","11","stroke-width:1.2px",[711,891,895],{"x":892,"y":893,"style":894},"293.8","50.0","font-size:11.5px;font-weight:400;fill:var(--brand-strong,#4338ca);text-anchor:middle;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace","per_row(template)",[29,897,899],{"id":898},"step-3-account-for-the-index-and-startrow","Step 3 — Account for the index and startrow",[10,901,902,903,906,907,909,910,913],{},"Two writer options shift every cell: ",[14,904,905],{},"index=True"," (the default) puts the index in column A, pushing all data one column right, and ",[14,908,20],{}," moves the header down. Formulas generated for one layout are wrong in the other, which is why ",[14,911,912],{},"per_row"," takes both:",[34,915,917],{"className":77,"code":916,"language":79,"meta":39,"style":39},"with pd.ExcelWriter(\"orders_offset.xlsx\", engine=\"openpyxl\") as xw:\n    title_rows = 2\n    df = orders.drop(columns=\"Total\").set_index(\"Product\")\n    df[\"Total\"] = per_row(df, \"={Qty}{r}*{Unit_price}{r}\", startrow=title_rows, index=True)\n    df.to_excel(xw, sheet_name=\"Orders\", startrow=title_rows)\n    xw.sheets[\"Orders\"][\"A1\"] = \"Orders, week 40\"\nprint(df[\"Total\"].tolist())\n",[14,918,919,948,958,981,1023,1045,1065],{"__ignoreMap":39},[43,920,921,924,927,930,932,935,937,940,943,945],{"class":45,"line":46},[43,922,923],{"class":86},"with",[43,925,926],{"class":90}," pd.ExcelWriter(",[43,928,929],{"class":53},"\"orders_offset.xlsx\"",[43,931,130],{"class":90},[43,933,934],{"class":303},"engine",[43,936,16],{"class":86},[43,938,939],{"class":53},"\"openpyxl\"",[43,941,942],{"class":90},") ",[43,944,94],{"class":86},[43,946,947],{"class":90}," xw:\n",[43,949,950,953,955],{"class":45,"line":100},[43,951,952],{"class":90},"    title_rows ",[43,954,16],{"class":86},[43,956,957],{"class":157}," 2\n",[43,959,960,963,965,967,969,971,973,976,979],{"class":45,"line":107},[43,961,962],{"class":90},"    df ",[43,964,16],{"class":86},[43,966,566],{"class":90},[43,968,569],{"class":303},[43,970,16],{"class":86},[43,972,218],{"class":53},[43,974,975],{"class":90},").set_index(",[43,977,978],{"class":53},"\"Product\"",[43,980,312],{"class":90},[43,982,983,986,988,990,992,995,997,999,1001,1003,1005,1007,1009,1011,1014,1016,1018,1021],{"class":45,"line":118},[43,984,985],{"class":90},"    df[",[43,987,218],{"class":53},[43,989,221],{"class":90},[43,991,16],{"class":86},[43,993,994],{"class":90}," per_row(df, ",[43,996,630],{"class":53},[43,998,633],{"class":235},[43,1000,636],{"class":53},[43,1002,639],{"class":235},[43,1004,254],{"class":53},[43,1006,130],{"class":90},[43,1008,20],{"class":303},[43,1010,16],{"class":86},[43,1012,1013],{"class":90},"title_rows, ",[43,1015,304],{"class":303},[43,1017,16],{"class":86},[43,1019,1020],{"class":157},"True",[43,1022,312],{"class":90},[43,1024,1025,1028,1031,1033,1036,1038,1040,1042],{"class":45,"line":149},[43,1026,1027],{"class":90},"    df.to_excel(xw, ",[43,1029,1030],{"class":303},"sheet_name",[43,1032,16],{"class":86},[43,1034,1035],{"class":53},"\"Orders\"",[43,1037,130],{"class":90},[43,1039,20],{"class":303},[43,1041,16],{"class":86},[43,1043,1044],{"class":90},"title_rows)\n",[43,1046,1047,1050,1052,1055,1058,1060,1062],{"class":45,"line":178},[43,1048,1049],{"class":90},"    xw.sheets[",[43,1051,1035],{"class":53},[43,1053,1054],{"class":90},"][",[43,1056,1057],{"class":53},"\"A1\"",[43,1059,221],{"class":90},[43,1061,16],{"class":86},[43,1063,1064],{"class":53}," \"Orders, week 40\"\n",[43,1066,1067,1069,1072,1074],{"class":45,"line":206},[43,1068,318],{"class":157},[43,1070,1071],{"class":90},"(df[",[43,1073,218],{"class":53},[43,1075,656],{"class":90},[10,1077,1078,1079,1082,1083,1085,1086,130,1089,1092],{},"With the index in column A and the header on row 3, the first formula is ",[14,1080,1081],{},"=C4*D4",". Getting the arithmetic in one helper — header row plus ",[14,1084,20],{},", column position plus index levels — means it is right everywhere. When the index is a ",[14,1087,1088],{},"MultiIndex",[14,1090,1091],{},"df.index.nlevels"," columns are inserted, which the helper already allows for.",[29,1094,1096],{"id":1095},"step-4-add-a-totals-row-with-sum","Step 4 — Add a totals row with SUM",[10,1098,1099],{},"A totals row is easiest to write after the data, with the worksheet object the writer exposes, because it does not belong in the DataFrame's columns:",[34,1101,1103],{"className":77,"code":1102,"language":79,"meta":39,"style":39},"orders[\"Total\"] = per_row(orders, \"={Qty}{r}*{Unit_price}{r}\")\nwith pd.ExcelWriter(\"orders_total.xlsx\", engine=\"xlsxwriter\") as xw:\n    orders.to_excel(xw, sheet_name=\"Orders\", index=False)\n    ws, book = xw.sheets[\"Orders\"], xw.book\n    last = len(orders) + 1                    # last data row, 1-based\n    bold = book.add_format({\"bold\": True, \"top\": 1})\n    ws.write(last, 0, \"Total\", bold)          # xlsxwriter rows are 0-based\n    for name in (\"Qty\", \"Total\"):\n        letter = col_letter(orders, name)\n        ws.write_formula(last, orders.columns.get_loc(name), f\"=SUM({letter}2:{letter}{last})\", bold)\nprint(\"SUM range ends at row\", last)\n",[14,1104,1105,1129,1153,1174,1189,1207,1236,1253,1275,1285,1323],{"__ignoreMap":39},[43,1106,1107,1109,1111,1113,1115,1117,1119,1121,1123,1125,1127],{"class":45,"line":46},[43,1108,215],{"class":90},[43,1110,218],{"class":53},[43,1112,221],{"class":90},[43,1114,16],{"class":86},[43,1116,627],{"class":90},[43,1118,630],{"class":53},[43,1120,633],{"class":235},[43,1122,636],{"class":53},[43,1124,639],{"class":235},[43,1126,254],{"class":53},[43,1128,312],{"class":90},[43,1130,1131,1133,1135,1138,1140,1142,1144,1147,1149,1151],{"class":45,"line":100},[43,1132,923],{"class":86},[43,1134,926],{"class":90},[43,1136,1137],{"class":53},"\"orders_total.xlsx\"",[43,1139,130],{"class":90},[43,1141,934],{"class":303},[43,1143,16],{"class":86},[43,1145,1146],{"class":53},"\"xlsxwriter\"",[43,1148,942],{"class":90},[43,1150,94],{"class":86},[43,1152,947],{"class":90},[43,1154,1155,1158,1160,1162,1164,1166,1168,1170,1172],{"class":45,"line":107},[43,1156,1157],{"class":90},"    orders.to_excel(xw, ",[43,1159,1030],{"class":303},[43,1161,16],{"class":86},[43,1163,1035],{"class":53},[43,1165,130],{"class":90},[43,1167,304],{"class":303},[43,1169,16],{"class":86},[43,1171,309],{"class":157},[43,1173,312],{"class":90},[43,1175,1176,1179,1181,1184,1186],{"class":45,"line":118},[43,1177,1178],{"class":90},"    ws, book ",[43,1180,16],{"class":86},[43,1182,1183],{"class":90}," xw.sheets[",[43,1185,1035],{"class":53},[43,1187,1188],{"class":90},"], xw.book\n",[43,1190,1191,1194,1196,1198,1200,1202,1204],{"class":45,"line":149},[43,1192,1193],{"class":90},"    last ",[43,1195,16],{"class":86},[43,1197,548],{"class":157},[43,1199,280],{"class":90},[43,1201,283],{"class":86},[43,1203,400],{"class":157},[43,1205,1206],{"class":466},"                    # last data row, 1-based\n",[43,1208,1209,1212,1214,1217,1220,1223,1225,1227,1230,1232,1234],{"class":45,"line":178},[43,1210,1211],{"class":90},"    bold ",[43,1213,16],{"class":86},[43,1215,1216],{"class":90}," book.add_format({",[43,1218,1219],{"class":53},"\"bold\"",[43,1221,1222],{"class":90},": ",[43,1224,1020],{"class":157},[43,1226,130],{"class":90},[43,1228,1229],{"class":53},"\"top\"",[43,1231,1222],{"class":90},[43,1233,584],{"class":157},[43,1235,209],{"class":90},[43,1237,1238,1241,1243,1245,1247,1250],{"class":45,"line":206},[43,1239,1240],{"class":90},"    ws.write(last, ",[43,1242,440],{"class":157},[43,1244,130],{"class":90},[43,1246,218],{"class":53},[43,1248,1249],{"class":90},", bold)          ",[43,1251,1252],{"class":466},"# xlsxwriter rows are 0-based\n",[43,1254,1255,1258,1261,1263,1266,1269,1271,1273],{"class":45,"line":212},[43,1256,1257],{"class":86},"    for",[43,1259,1260],{"class":90}," name ",[43,1262,263],{"class":86},[43,1264,1265],{"class":90}," (",[43,1267,1268],{"class":53},"\"Qty\"",[43,1270,130],{"class":90},[43,1272,218],{"class":53},[43,1274,387],{"class":90},[43,1276,1277,1280,1282],{"class":45,"line":292},[43,1278,1279],{"class":90},"        letter ",[43,1281,16],{"class":86},[43,1283,1284],{"class":90}," col_letter(orders, name)\n",[43,1286,1287,1290,1292,1295,1297,1300,1302,1305,1307,1309,1312,1315,1317,1320],{"class":45,"line":315},[43,1288,1289],{"class":90},"        ws.write_formula(last, orders.columns.get_loc(name), ",[43,1291,229],{"class":86},[43,1293,1294],{"class":53},"\"=SUM(",[43,1296,236],{"class":235},[43,1298,1299],{"class":90},"letter",[43,1301,242],{"class":235},[43,1303,1304],{"class":53},"2:",[43,1306,236],{"class":235},[43,1308,1299],{"class":90},[43,1310,1311],{"class":235},"}{",[43,1313,1314],{"class":90},"last",[43,1316,242],{"class":235},[43,1318,1319],{"class":53},")\"",[43,1321,1322],{"class":90},", bold)\n",[43,1324,1325,1327,1329,1332],{"class":45,"line":554},[43,1326,318],{"class":157},[43,1328,269],{"class":90},[43,1330,1331],{"class":53},"\"SUM range ends at row\"",[43,1333,1334],{"class":90},", last)\n",[10,1336,1337,1338,1341,1342,1345,1346,1348,1349,1352,1353,27],{},"Mind the two numbering systems: formula text uses Excel's 1-based row numbers (",[14,1339,1340],{},"SUM(C2:C5)","), while xlsxwriter's ",[14,1343,1344],{},"write"," methods use 0-based row and column indexes, so the totals go to index ",[14,1347,1314],{},", which is the sheet's row ",[14,1350,1351],{},"last + 1",". The same totals can be written as a structured table with a total row, as in ",[23,1354,1356],{"href":1355},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fadd-a-total-row-to-an-excel-table\u002F","Add a Total Row to an Excel Table",[678,1358,687,1364,687,1367,687,1370,687,1375,687,1380,687,1382,687,1387,687,1392,687,1395,687,1399,687,1403,687,1407,687,1410,687,1414,687,1417,687,1421,687,1424,687,1428,687,1431,687,1433,687,1436,687,1438,687,1440,687,1442,687,1444,687,1446,687,1448,687,1450,687,1452,687,1454,687,1456,687,1459,687,1462,687,1464,687,1466,687,1468,687,1470,687,1472,687,1474,687,1476,687,1478,687,1480,687,1483,687,1486,687,1489,687,1491,687,1493,687,1495,687,1497,687,1499,687,1501,687,1503,687,1505,687,1507,687,1510,687,1513,687,1516,687,1518,687,1521,687,1523,687,1526,687,1528,687,1530,687,1532,687,1534,687,1536,687,1539,687,1542,687,1545,687,1547,687,1550,687,1552,687,1555,687,1557,687,1559,687,1561,687,1563,687,1565,687,1568,687,1571,687,1575,687,1577,687,1579,687,1581,687,1583,687,1586,687,1588,687,1590],{"viewBox":1359,"role":681,"ariaLabelledBy":1360,"xmlns":685,"style":1363},"197 0 366 252",[1361,1362],"fx-totals-t","fx-totals-d","width:100%;max-width:366px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[689,1365,1366],{"id":1361},"Per-row formulas plus a SUM totals row",[693,1368,1369],{"id":1362},"The finished sheet with Product, SKU, Qty, Unit price and Total columns. Each Total cell multiplies Qty by Unit price on its row, and row 6 holds SUM formulas for Qty and Total.",[697,1371],{"x":1372,"y":440,"width":1373,"height":1374,"fill":701},"197","366","252",[697,1376],{"x":1377,"y":1378,"width":1379,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},"213.1","16.0","333.9",[697,1381],{"x":1377,"y":1378,"width":705,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},[711,1383,1386],{"x":1384,"y":886,"style":1385},"233.1","font-size:12px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","fx",[711,1388,1391],{"x":1389,"y":886,"style":1390},"263.1","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace","=SUM(E2:E5)",[697,1393],{"x":1377,"y":1394,"width":728,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"44.0",[697,1396],{"x":1397,"y":1394,"width":1398,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"245.1","68.8",[711,1400,740],{"x":1401,"y":1402,"style":739},"279.5","61.0",[697,1404],{"x":1405,"y":1394,"width":1406,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"313.8","53.3",[711,1408,342],{"x":1409,"y":1402,"style":739},"340.5",[697,1411],{"x":1412,"y":1394,"width":1413,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"367.1","44.2",[711,1415,345],{"x":1416,"y":1402,"style":739},"389.2",[697,1418],{"x":1419,"y":1394,"width":1420,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"411.3","78.5",[711,1422,762],{"x":1423,"y":1402,"style":739},"450.5",[697,1425],{"x":1426,"y":1394,"width":1427,"height":729,"rx":440,"fill":730,"stroke":708,"style":709},"489.8","57.1",[711,1429,770],{"x":1430,"y":1402,"style":739},"518.4",[697,1432],{"x":1377,"y":719,"width":728,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},[711,1434,584],{"x":1435,"y":722,"style":739},"229.1",[697,1437],{"x":1397,"y":719,"width":1398,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},[711,1439,786],{"x":1401,"y":722,"style":785},[697,1441],{"x":1405,"y":719,"width":1406,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},[711,1443,662],{"x":1409,"y":722,"style":785},[697,1445],{"x":1412,"y":719,"width":1413,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},[711,1447,327],{"x":1416,"y":722,"style":785},[697,1449],{"x":1419,"y":719,"width":1420,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},[711,1451,331],{"x":1423,"y":722,"style":785},[697,1453],{"x":1426,"y":719,"width":1427,"height":707,"rx":440,"fill":780,"stroke":781,"style":782},[711,1455,803],{"x":1430,"y":722,"style":785},[697,1457],{"x":1377,"y":1458,"width":728,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},"96.0",[711,1460,272],{"x":1435,"y":1461,"style":739},"115.0",[697,1463],{"x":1397,"y":1458,"width":1398,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1465,814],{"x":1401,"y":1461,"style":723},[697,1467],{"x":1405,"y":1458,"width":1406,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1469,819],{"x":1409,"y":1461,"style":723},[697,1471],{"x":1412,"y":1458,"width":1413,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1473,158],{"x":1416,"y":1461,"style":723},[697,1475],{"x":1419,"y":1458,"width":1420,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1477,186],{"x":1423,"y":1461,"style":723},[697,1479],{"x":1426,"y":1458,"width":1427,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1481,1482],{"x":1430,"y":1461,"style":723},"267.0",[697,1484],{"x":1377,"y":1485,"width":728,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},"124.0",[711,1487,158],{"x":1435,"y":1488,"style":739},"143.0",[697,1490],{"x":1397,"y":1485,"width":1398,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1492,846],{"x":1401,"y":1488,"style":723},[697,1494],{"x":1405,"y":1485,"width":1406,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1496,851],{"x":1409,"y":1488,"style":723},[697,1498],{"x":1412,"y":1485,"width":1413,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1500,163],{"x":1416,"y":1488,"style":723},[697,1502],{"x":1419,"y":1485,"width":1420,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1504,191],{"x":1423,"y":1488,"style":723},[697,1506],{"x":1426,"y":1485,"width":1427,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1508,1509],{"x":1430,"y":1488,"style":723},"227.5",[697,1511],{"x":1377,"y":1512,"width":728,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},"152.0",[711,1514,173],{"x":1435,"y":1515,"style":739},"171.0",[697,1517],{"x":1397,"y":1512,"width":1398,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1519,1520],{"x":1401,"y":1515,"style":723},"Hose",[697,1522],{"x":1405,"y":1512,"width":1406,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1524,1525],{"x":1409,"y":1515,"style":723},"H-03",[697,1527],{"x":1412,"y":1512,"width":1413,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1529,168],{"x":1416,"y":1515,"style":723},[697,1531],{"x":1419,"y":1512,"width":1420,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1533,196],{"x":1423,"y":1515,"style":723},[697,1535],{"x":1426,"y":1512,"width":1427,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1537,1538],{"x":1430,"y":1515,"style":723},"168.0",[697,1540],{"x":1377,"y":1541,"width":728,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},"180.0",[711,1543,163],{"x":1435,"y":1544,"style":739},"199.0",[697,1546],{"x":1397,"y":1541,"width":1398,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1548,1549],{"x":1401,"y":1544,"style":723},"Rake",[697,1551],{"x":1405,"y":1541,"width":1406,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1553,1554],{"x":1409,"y":1544,"style":723},"R-04",[697,1556],{"x":1412,"y":1541,"width":1413,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1558,173],{"x":1416,"y":1544,"style":723},[697,1560],{"x":1419,"y":1541,"width":1420,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1562,201],{"x":1423,"y":1544,"style":723},[697,1564],{"x":1426,"y":1541,"width":1427,"height":707,"rx":440,"fill":701,"stroke":708,"style":709},[711,1566,1567],{"x":1430,"y":1544,"style":723},"88.0",[697,1569],{"x":1377,"y":1570,"width":728,"height":707,"rx":440,"fill":730,"stroke":708,"style":709},"208.0",[711,1572,1574],{"x":1435,"y":1573,"style":739},"227.0","6",[697,1576],{"x":1397,"y":1570,"width":1398,"height":707,"rx":440,"fill":831,"stroke":832,"style":782},[711,1578,803],{"x":1401,"y":1573,"style":835},[697,1580],{"x":1405,"y":1570,"width":1406,"height":707,"rx":440,"fill":831,"stroke":832,"style":782},[697,1582],{"x":1412,"y":1570,"width":1413,"height":707,"rx":440,"fill":831,"stroke":832,"style":782},[711,1584,1585],{"x":1416,"y":1573,"style":835},"24",[697,1587],{"x":1419,"y":1570,"width":1420,"height":707,"rx":440,"fill":831,"stroke":832,"style":782},[697,1589],{"x":1426,"y":1570,"width":1427,"height":707,"rx":440,"fill":831,"stroke":832,"style":782},[711,1591,1592],{"x":1430,"y":1573,"style":835},"750.5",[29,1594,1596],{"id":1595},"step-5-why-the-results-read-back-as-0-or-nan","Step 5 — Why the results read back as 0 or NaN",[10,1598,1599],{},"A workbook written by Python contains the formulas but no calculated results — nothing has run them yet. Excel calculates on opening, so a person never notices. Another script reading the file does:",[34,1601,1603],{"className":77,"code":1602,"language":79,"meta":39,"style":39},"for engine in (\"xlsxwriter\", \"openpyxl\"):\n    orders.to_excel(f\"check_{engine}.xlsx\", index=False, engine=engine)\n    print(engine, pd.read_excel(f\"check_{engine}.xlsx\")[\"Total\"].tolist())\n",[14,1604,1605,1624,1660],{"__ignoreMap":39},[43,1606,1607,1609,1612,1614,1616,1618,1620,1622],{"class":45,"line":46},[43,1608,480],{"class":86},[43,1610,1611],{"class":90}," engine ",[43,1613,263],{"class":86},[43,1615,1265],{"class":90},[43,1617,1146],{"class":53},[43,1619,130],{"class":90},[43,1621,939],{"class":53},[43,1623,387],{"class":90},[43,1625,1626,1629,1631,1634,1636,1638,1640,1643,1645,1647,1649,1651,1653,1655,1657],{"class":45,"line":100},[43,1627,1628],{"class":90},"    orders.to_excel(",[43,1630,229],{"class":86},[43,1632,1633],{"class":53},"\"check_",[43,1635,236],{"class":235},[43,1637,934],{"class":90},[43,1639,242],{"class":235},[43,1641,1642],{"class":53},".xlsx\"",[43,1644,130],{"class":90},[43,1646,304],{"class":303},[43,1648,16],{"class":86},[43,1650,309],{"class":157},[43,1652,130],{"class":90},[43,1654,934],{"class":303},[43,1656,16],{"class":86},[43,1658,1659],{"class":90},"engine)\n",[43,1661,1662,1665,1668,1670,1672,1674,1676,1678,1680,1683,1685],{"class":45,"line":107},[43,1663,1664],{"class":157},"    print",[43,1666,1667],{"class":90},"(engine, pd.read_excel(",[43,1669,229],{"class":86},[43,1671,1633],{"class":53},[43,1673,236],{"class":235},[43,1675,934],{"class":90},[43,1677,242],{"class":235},[43,1679,1642],{"class":53},[43,1681,1682],{"class":90},")[",[43,1684,218],{"class":53},[43,1686,656],{"class":90},[10,1688,1689,1690,1693,1694,1697,1698,1701,1702,27],{},"The xlsxwriter file reads back as ",[14,1691,1692],{},"[0, 0, 0, 0]",", because xlsxwriter stores a cached result of 0 for every formula; the openpyxl file reads back as ",[14,1695,1696],{},"NaN",", because openpyxl stores no cached result at all. Neither is the real answer. If a downstream step must read numbers, either compute the values in pandas and write those, or cache the result alongside the formula with xlsxwriter's ",[14,1699,1700],{},"write_formula(row, col, formula, fmt, value)"," — see ",[23,1703,1705],{"href":1704},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter\u002F","Store Formula Results with xlsxwriter",[678,1707,687,1712,687,1715,687,1718,687,1721,687,1728,687,1733,687,1737,687,1743,687,1753,687,1757,687,1762,687,1766,687,1771,687,1776,687,1781,687,1785,687,1789,687,1796,687,1799,687,1804,687,1807,687,1812,687,1815,687,1820,687,1824,687,1828,687,1834,687,1837,687,1842,687,1845],{"viewBox":1708,"role":681,"ariaLabelledBy":1709,"xmlns":685,"style":686},"4 0 752 173",[1710,1711],"fx-cache-t","fx-cache-d",[689,1713,1714],{"id":1710},"What a reader sees in a formula cell before Excel opens the file",[693,1716,1717],{"id":1711},"Files written by xlsxwriter contain a cached result of 0 for every formula, so pandas reads 0. Files written by openpyxl contain no cached result, so pandas reads NaN. After recalculation in LibreOffice or Excel the real values appear.",[697,1719],{"x":173,"y":440,"width":699,"height":1720,"fill":701},"173",[697,1722],{"x":704,"y":1378,"width":1723,"height":1724,"rx":1725,"fill":1726,"stroke":1727,"style":877},"228.0","141.0","14","#fdefd8","var(--gold,#b4740a)",[711,1729,1732],{"x":1730,"y":1394,"style":1731},"134.0","font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","xlsxwriter engine",[45,1734],{"x1":1735,"y1":738,"x2":1736,"y2":738,"stroke":1727,"style":709},"36.0","232.0",[711,1738,1742],{"x":1739,"y":1740,"style":1741},"60.0","77.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","cached value 0",[1744,1745,1747],"g",{"transform":1746},"translate(38.5,65.5) scale(0.625)",[1748,1749],"path",{"d":1750,"fill":1751,"stroke":1727,"style":1752},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","none","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[711,1754,1756],{"x":1739,"y":1755,"style":1741},"103.0","read_excel gives 0",[1744,1758,1760],{"transform":1759},"translate(38.5,91.5) scale(0.625)",[1748,1761],{"d":1750,"fill":1751,"stroke":1727,"style":1752},[711,1763,1765],{"x":1739,"y":1764,"style":1741},"129.0","looks like real data",[1744,1767,1769],{"transform":1768},"translate(38.5,117.5) scale(0.625)",[1748,1770],{"d":1750,"fill":1751,"stroke":1727,"style":1752},[697,1772],{"x":1773,"y":1378,"width":1723,"height":1724,"rx":1725,"fill":1774,"stroke":1775,"style":877},"266.0","#fce9e9","var(--danger,#dc2626)",[711,1777,1780],{"x":1778,"y":1394,"style":1779},"380.0","font-size:14px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","openpyxl engine",[45,1782],{"x1":1783,"y1":738,"x2":1784,"y2":738,"stroke":1775,"style":709},"282.0","478.0",[711,1786,1788],{"x":1787,"y":1740,"style":1741},"306.0","no cached value",[1744,1790,1792],{"transform":1791},"translate(284.5,65.5) scale(0.625)",[1748,1793],{"d":1794,"fill":1751,"stroke":1795,"style":1752},"M6 6l12 12 M18 6L6 18","var(--accent,#f43f8f)",[711,1797,1798],{"x":1787,"y":1755,"style":1741},"read_excel gives NaN",[1744,1800,1802],{"transform":1801},"translate(284.5,91.5) scale(0.625)",[1748,1803],{"d":1794,"fill":1751,"stroke":1795,"style":1752},[711,1805,1806],{"x":1787,"y":1764,"style":1741},"obviously missing",[1744,1808,1810],{"transform":1809},"translate(284.5,117.5) scale(0.625)",[1748,1811],{"d":1794,"fill":1751,"stroke":1795,"style":1752},[697,1813],{"x":1814,"y":1378,"width":1723,"height":1724,"rx":1725,"fill":831,"stroke":832,"style":877},"512.0",[711,1816,1819],{"x":1817,"y":1394,"style":1818},"626.0","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","After recalculation",[45,1821],{"x1":1822,"y1":738,"x2":1823,"y2":738,"stroke":832,"style":709},"528.0","724.0",[711,1825,1827],{"x":1826,"y":1740,"style":1741},"552.0","cached values stored",[1744,1829,1831],{"transform":1830},"translate(530.5,65.5) scale(0.625)",[1748,1832],{"d":1833,"fill":1751,"stroke":832,"style":1752},"M5 12.5l4.5 4.5L19 7",[711,1835,1836],{"x":1826,"y":1755,"style":1741},"read_excel gives 267 …",[1744,1838,1840],{"transform":1839},"translate(530.5,91.5) scale(0.625)",[1748,1841],{"d":1833,"fill":1751,"stroke":832,"style":1752},[711,1843,1844],{"x":1826,"y":1764,"style":1741},"safe for other scripts",[1744,1846,1848],{"transform":1847},"translate(530.5,117.5) scale(0.625)",[1748,1849],{"d":1833,"fill":1751,"stroke":832,"style":1752},[29,1851,1853],{"id":1852},"step-6-check-the-formulas-by-recalculating","Step 6 — Check the formulas by recalculating",[10,1855,1856],{},"To test that every generated formula calculates what you expect, let LibreOffice open and resave the file, which stores real cached results, and compare them with the same calculation in pandas:",[34,1858,1860],{"className":77,"code":1859,"language":79,"meta":39,"style":39},"import subprocess\n\nsubprocess.run([\"soffice\", \"--headless\", \"--convert-to\", \"xlsx\", \"--outdir\", \"recalc\",\n                \"check_openpyxl.xlsx\"], check=True, capture_output=True)\nrecalc = pd.read_excel(\"recalc\u002Fcheck_openpyxl.xlsx\")\nexpected = orders[\"Qty\"] * orders[\"Unit price\"]\nprint(recalc[\"Total\"].tolist())\nassert (recalc[\"Total\"] - expected).abs().max() \u003C 1e-9\n",[14,1861,1862,1869,1873,1909,1935,1950,1974,1985],{"__ignoreMap":39},[43,1863,1864,1866],{"class":45,"line":46},[43,1865,87],{"class":86},[43,1867,1868],{"class":90}," subprocess\n",[43,1870,1871],{"class":45,"line":100},[43,1872,104],{"emptyLinePlaceholder":103},[43,1874,1875,1878,1881,1883,1886,1888,1891,1893,1896,1898,1901,1903,1906],{"class":45,"line":107},[43,1876,1877],{"class":90},"subprocess.run([",[43,1879,1880],{"class":53},"\"soffice\"",[43,1882,130],{"class":90},[43,1884,1885],{"class":53},"\"--headless\"",[43,1887,130],{"class":90},[43,1889,1890],{"class":53},"\"--convert-to\"",[43,1892,130],{"class":90},[43,1894,1895],{"class":53},"\"xlsx\"",[43,1897,130],{"class":90},[43,1899,1900],{"class":53},"\"--outdir\"",[43,1902,130],{"class":90},[43,1904,1905],{"class":53},"\"recalc\"",[43,1907,1908],{"class":90},",\n",[43,1910,1911,1914,1917,1920,1922,1924,1926,1929,1931,1933],{"class":45,"line":118},[43,1912,1913],{"class":53},"                \"check_openpyxl.xlsx\"",[43,1915,1916],{"class":90},"], ",[43,1918,1919],{"class":303},"check",[43,1921,16],{"class":86},[43,1923,1020],{"class":157},[43,1925,130],{"class":90},[43,1927,1928],{"class":303},"capture_output",[43,1930,16],{"class":86},[43,1932,1020],{"class":157},[43,1934,312],{"class":90},[43,1936,1937,1940,1942,1945,1948],{"class":45,"line":149},[43,1938,1939],{"class":90},"recalc ",[43,1941,16],{"class":86},[43,1943,1944],{"class":90}," pd.read_excel(",[43,1946,1947],{"class":53},"\"recalc\u002Fcheck_openpyxl.xlsx\"",[43,1949,312],{"class":90},[43,1951,1952,1955,1957,1960,1962,1964,1966,1968,1971],{"class":45,"line":178},[43,1953,1954],{"class":90},"expected ",[43,1956,16],{"class":86},[43,1958,1959],{"class":90}," orders[",[43,1961,1268],{"class":53},[43,1963,221],{"class":90},[43,1965,636],{"class":86},[43,1967,1959],{"class":90},[43,1969,1970],{"class":53},"\"Unit price\"",[43,1972,1973],{"class":90},"]\n",[43,1975,1976,1978,1981,1983],{"class":45,"line":206},[43,1977,318],{"class":157},[43,1979,1980],{"class":90},"(recalc[",[43,1982,218],{"class":53},[43,1984,656],{"class":90},[43,1986,1987,1990,1993,1995,1997,2000,2003,2006],{"class":45,"line":212},[43,1988,1989],{"class":86},"assert",[43,1991,1992],{"class":90}," (recalc[",[43,1994,218],{"class":53},[43,1996,221],{"class":90},[43,1998,1999],{"class":86},"-",[43,2001,2002],{"class":90}," expected).abs().max() ",[43,2004,2005],{"class":86},"\u003C",[43,2007,2008],{"class":157}," 1e-9\n",[10,2010,2011,2012,27],{},"The recalculated totals match the pandas calculation exactly. This check belongs in the test suite of any report that ships formulas; a wrong column letter otherwise surfaces as a plausible-looking but wrong number in someone's inbox. More approaches are in ",[23,2013,2015],{"href":2014},"\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",[29,2017,2019],{"id":2018},"step-7-text-that-starts-with-by-accident","Step 7 — Text that starts with \"=\" by accident",[10,2021,2022,2023,2026],{},"Because the conversion is automatic, a comment like ",[14,2024,2025],{},"\"=== see note ===\""," or a value pasted from another system becomes a broken formula and triggers Excel's repair dialog. With the xlsxwriter engine, switch the conversion off for the whole file and write intended formulas explicitly:",[34,2028,2030],{"className":77,"code":2029,"language":79,"meta":39,"style":39},"notes = pd.DataFrame({\"Note\": [\"=== check stock ===\", \"ok\"]})\nwith pd.ExcelWriter(\"notes.xlsx\", engine=\"xlsxwriter\",\n                    engine_kwargs={\"options\": {\"strings_to_formulas\": False}}) as xw:\n    notes.to_excel(xw, index=False)\nfrom openpyxl import load_workbook\nprint(load_workbook(\"notes.xlsx\").active[\"A2\"].data_type)\n",[14,2031,2032,2058,2077,2106,2119,2131],{"__ignoreMap":39},[43,2033,2034,2037,2039,2042,2045,2047,2050,2052,2055],{"class":45,"line":46},[43,2035,2036],{"class":90},"notes ",[43,2038,16],{"class":86},[43,2040,2041],{"class":90}," pd.DataFrame({",[43,2043,2044],{"class":53},"\"Note\"",[43,2046,124],{"class":90},[43,2048,2049],{"class":53},"\"=== check stock ===\"",[43,2051,130],{"class":90},[43,2053,2054],{"class":53},"\"ok\"",[43,2056,2057],{"class":90},"]})\n",[43,2059,2060,2062,2064,2067,2069,2071,2073,2075],{"class":45,"line":100},[43,2061,923],{"class":86},[43,2063,926],{"class":90},[43,2065,2066],{"class":53},"\"notes.xlsx\"",[43,2068,130],{"class":90},[43,2070,934],{"class":303},[43,2072,16],{"class":86},[43,2074,1146],{"class":53},[43,2076,1908],{"class":90},[43,2078,2079,2082,2084,2086,2089,2092,2095,2097,2099,2102,2104],{"class":45,"line":107},[43,2080,2081],{"class":303},"                    engine_kwargs",[43,2083,16],{"class":86},[43,2085,236],{"class":90},[43,2087,2088],{"class":53},"\"options\"",[43,2090,2091],{"class":90},": {",[43,2093,2094],{"class":53},"\"strings_to_formulas\"",[43,2096,1222],{"class":90},[43,2098,309],{"class":157},[43,2100,2101],{"class":90},"}}) ",[43,2103,94],{"class":86},[43,2105,947],{"class":90},[43,2107,2108,2111,2113,2115,2117],{"class":45,"line":118},[43,2109,2110],{"class":90},"    notes.to_excel(xw, ",[43,2112,304],{"class":303},[43,2114,16],{"class":86},[43,2116,309],{"class":157},[43,2118,312],{"class":90},[43,2120,2121,2123,2126,2128],{"class":45,"line":149},[43,2122,356],{"class":86},[43,2124,2125],{"class":90}," openpyxl ",[43,2127,87],{"class":86},[43,2129,2130],{"class":90}," load_workbook\n",[43,2132,2133,2135,2138,2140,2143,2146],{"class":45,"line":178},[43,2134,318],{"class":157},[43,2136,2137],{"class":90},"(load_workbook(",[43,2139,2066],{"class":53},[43,2141,2142],{"class":90},").active[",[43,2144,2145],{"class":53},"\"A2\"",[43,2147,2148],{"class":90},"].data_type)\n",[10,2150,2151,2152,2155,2156,2159,2160,27],{},"The cell's data type is ",[14,2153,2154],{},"s"," — stored as text. With this option on, add the formulas you do want through ",[14,2157,2158],{},"write_formula",". The openpyxl engine has no such switch, so change accidental values before writing — for example by prefixing them with a space or a quote character — as described in ",[23,2161,2163],{"href":2162},"\u002Fautomating-reporting-workflows\u002Ferror-handling-and-logging-in-excel-automation\u002Fprevent-formula-injection-in-excel-exports\u002F","Prevent Formula Injection in Excel Exports",[29,2165,2167],{"id":2166},"common-pitfalls","Common pitfalls",[2169,2170,2171,2183,2192,2198,2216],"ul",{},[2172,2173,2174,2178,2179,2182],"li",{},[2175,2176,2177],"strong",{},"Off-by-one rows."," The first data row is ",[14,2180,2181],{},"startrow + 2","; forgetting the header row shifts every formula up one.",[2172,2184,2185,2188,2189,2191],{},[2175,2186,2187],{},"Forgetting the index column."," With ",[14,2190,905],{},", every data column moves one letter right.",[2172,2193,2194,2197],{},[2175,2195,2196],{},"Hard-coded letters."," Derive them from column positions so inserted columns do not break the sheet.",[2172,2199,2200,2203,2204,2207,2208,2211,2212,27],{},[2175,2201,2202],{},"Function names."," Write English function names with commas as separators (",[14,2205,2206],{},"=SUMIFS(…)","), whatever the reader's Excel language; newer functions may need the ",[14,2209,2210],{},"_xlfn."," prefix, covered in ",[23,2213,2215],{"href":2214},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-name-error-for-new-excel-functions-written-by-python\u002F","Fix #NAME? Errors for New Excel Functions Written by Python",[2172,2217,2218,2221],{},[2175,2219,2220],{},"Reading your own output."," Formula cells read as 0 or NaN until recalculated.",[29,2223,2225],{"id":2224},"performance-notes","Performance notes",[10,2227,2228,2229,2232,2233,130,2236,130,2239,2242],{},"Formula strings cost the same to write as any other text, so a 100,000-row sheet with a formula column writes about as fast as one with a text column. The cost moves to the reader: Excel recalculates every formula on opening, and a few hundred thousand simple row formulas add a noticeable pause. Whole-column ranges such as ",[14,2230,2231],{},"SUM(E:E)"," are cheap in modern Excel, but volatile functions (",[14,2234,2235],{},"OFFSET",[14,2237,2238],{},"INDIRECT",[14,2240,2241],{},"TODAY",") recalculate on every edit — avoid generating them per row. When nobody will edit the inputs, write values instead and keep formulas for the cells people are meant to change.",[29,2244,2246],{"id":2245},"conclusion","Conclusion",[10,2248,2249,2250,2252,2253,2255],{},"Strings that start with ",[14,2251,16],{}," become formulas when pandas writes them. Generate them per row from column names rather than letters, include the header, ",[14,2254,20],{}," and index offsets in one helper, and write totals with the writer's worksheet object. Remember that the file holds no calculated results until Excel or LibreOffice opens it — cache values or compute them in pandas when other scripts read the output — and recalculate in a test to prove every formula is right.",[29,2257,2259],{"id":2258},"frequently-asked-questions","Frequently asked questions",[10,2261,2262,2265,2266,2268,2269,27],{},[2175,2263,2264],{},"Can pandas write formulas to Excel?","\nYes. Any string value that starts with \"=\" is written as a formula by both the xlsxwriter and openpyxl engines, for example df",[43,2267,218],{}," = ",[43,2270,2271],{},"f\"=B{r}*C{r}\" for r in range(2, len(df) + 2)",[10,2273,2274,2277],{},[2175,2275,2276],{},"Why does pandas read my formula column as 0 or NaN?","\nPython writers do not calculate formulas. xlsxwriter stores a cached result of 0 and openpyxl stores none, so read_excel returns 0 or NaN until the file is opened and saved by Excel or recalculated by LibreOffice.",[10,2279,2280,2283],{},[2175,2281,2282],{},"How do I stop pandas turning text that starts with \"=\" into a formula?","\nWith the xlsxwriter engine, pass engine_kwargs={\"options\": {\"strings_to_formulas\": False}} to ExcelWriter. With openpyxl there is no option, so change the text before writing.",[10,2285,2286,2289],{},[2175,2287,2288],{},"How do I get the right row numbers when using startrow or the index?","\nThe first data row is startrow + 2 in Excel's 1-based numbering, because of the header row. With index=True the data columns shift right by the number of index levels, so add df.index.nlevels to each column position.",[29,2291,2293],{"id":2292},"related","Related",[2169,2295,2296,2302,2309,2316],{},[2172,2297,2298,2299,2301],{},"Up one level: ",[23,2300,26],{"href":25}," — writer options and engines.",[2172,2303,2304,2308],{},[23,2305,2307],{"href":2306},"\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"," — formulas cell by cell.",[2172,2310,2311,2315],{},[23,2312,2314],{"href":2313},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fcopy-formula-down-a-column-in-openpyxl\u002F","Copy a Formula Down a Column in openpyxl"," — translating one formula to many rows.",[2172,2317,2318,2322],{},[23,2319,2321],{"href":2320},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fhow-pandas-data-types-are-written-to-excel-cells\u002F","How pandas Data Types Are Written to Excel Cells"," — what happens to every other kind of value.",[2324,2325,2326],"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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}",{"title":39,"searchDepth":100,"depth":100,"links":2328},[2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341],{"id":31,"depth":100,"text":32},{"id":73,"depth":100,"text":74},{"id":335,"depth":100,"text":336},{"id":898,"depth":100,"text":899},{"id":1095,"depth":100,"text":1096},{"id":1595,"depth":100,"text":1596},{"id":1852,"depth":100,"text":1853},{"id":2018,"depth":100,"text":2019},{"id":2166,"depth":100,"text":2167},{"id":2224,"depth":100,"text":2225},{"id":2245,"depth":100,"text":2246},{"id":2258,"depth":100,"text":2259},{"id":2292,"depth":100,"text":2293},"2026-10-02","Put live formulas into a sheet written with to_excel: build formula strings per row, look up column letters by name so the formulas survive column changes, account for the header, index and startrow offsets, add a totals row, understand why the results read back as 0 or NaN until the file is recalculated, and turn the formula conversion off for text that merely starts with \"=\".","md",[2346,2348,2350,2352],{"q":2264,"a":2347},"Yes. Any string value that starts with \"=\" is written as a formula by both the xlsxwriter and openpyxl engines, for example df[\"Total\"] = [f\"=B{r}*C{r}\" for r in range(2, len(df) + 2)].",{"q":2276,"a":2349},"Python writers do not calculate formulas. xlsxwriter stores a cached result of 0 and openpyxl stores none, so read_excel returns 0 or NaN until the file is opened and saved by Excel or recalculated by LibreOffice.",{"q":2282,"a":2351},"With the xlsxwriter engine, pass engine_kwargs={\"options\": {\"strings_to_formulas\": False}} to ExcelWriter. With openpyxl there is no option, so change the text before writing.",{"q":2288,"a":2353},"The first data row is startrow + 2 in Excel's 1-based numbering, because of the header row. With index=True the data columns shift right by the number of index levels, so add df.index.nlevels to each column position.","write excel formulas from a pandas dataframe",null,{"breadcrumb":2357},[2358,2361,2364],{"name":2359,"item":2360},"Home","\u002F",{"name":2362,"item":2363},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":2365,"item":25},"Writing DataFrames to Excel with Pandas","\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-excel-formulas-from-a-pandas-dataframe",{"title":2368,"description":2369},"Write Excel Formulas from a pandas DataFrame with to_excel","Write working formulas with pandas to_excel: per-row formula strings, column letters from names, header\u002Findex\u002Fstartrow offsets, a SUM totals row, cached 0 vs NaN results, LibreOffice recalculation, and strings_to_formulas=False.","write-excel-formulas-from-a-pandas-dataframe","getting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-excel-formulas-from-a-pandas-dataframe\u002Findex",[2373,2374,2375],"writing-excel","excel-formulas","pandas","how-to","g2T3nu2ZoU_tSMweHTzXS4f9WeUdO5t2XQj-rQ-F8E4",[2379,2383],{"title":2380,"path":2381,"stem":2382,"children":-1},"Write Dates Without the Time Part from pandas to Excel","\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-dates-without-time-from-pandas-to-excel","getting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-dates-without-time-from-pandas-to-excel\u002Findex",{"title":2384,"path":2385,"stem":2386,"children":-1},"Write Grouped Data with Blank Rows Between Groups","\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-grouped-data-with-blank-rows-between-groups","getting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-grouped-data-with-blank-rows-between-groups\u002Findex",[2388,2390],{"path":2389,"title":2362},"\u002Fgetting-started-with-python-excel-automation",{"path":2391,"title":2365},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas",[],[2394,2397,2400,2403,2406,2409],{"path":2395,"title":2396,"kind":2376},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fwrite-multiple-dataframes-to-one-excel-file","Write Multiple DataFrames to One Excel File",{"path":2398,"title":2399,"kind":2376},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-a-formatted-excel-report-with-xlsxwriter","Write a Formatted Excel Report with xlsxwriter",{"path":2401,"title":2402,"kind":2376},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Ffind-and-replace-text-in-excel-with-openpyxl","Find and Replace Text in Excel with openpyxl",{"path":2404,"title":2405,"kind":2376},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Finsert-and-delete-rows-and-columns-with-openpyxl","Insert and Delete Rows and Columns with openpyxl",{"path":2407,"title":2408,"kind":2376},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fopenpyxl-append-data-to-existing-excel-sheet","openpyxl: Append Data to an Existing Excel Sheet",{"path":2410,"title":2411,"kind":2376},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Freorder-columns-to-match-a-template-layout-with-pandas","Reorder Columns to Match a Template Layout with pandas",1790972077894]