[{"data":1,"prerenderedAt":2103},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter":2095},{"id":4,"title":5,"body":6,"dateModified":2064,"datePublished":2064,"description":2065,"extension":2066,"faq":2067,"meta":2076,"navigation":272,"path":2087,"seo":2088,"slug":2091,"stem":2092,"type":2093,"__hash__":2094},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter\u002Findex.md","Apply Conditional Formatting with xlsxwriter",{"type":7,"value":8,"toc":2050},"minimark",[9,13,22,192,197,226,232,236,758,762,765,1008,1015,1029,1033,1036,1317,1320,1326,1330,1338,1423,1448,1567,1571,1574,1646,1652,1656,1659,1779,1789,1793,1924,1928,1939,1942,1946,1952,1956,1967,1973,1991,1997,2001,2004,2013,2016,2046],[10,11,12],"p",{},"A colour written into a cell is a fact about the moment the file was generated. A conditional format is a rule stored in the workbook, which Excel re-evaluates every time the values change — so a reader who edits a figure, filters the table or pastes in next month's numbers still sees the right cells highlighted.",[10,14,15,16,21],{},"That difference is why conditional formatting is worth reaching for in generated reports rather than computing the colours in pandas. This guide covers xlsxwriter's rule types, the whole-row formula rule that most reports end up wanting, and the reference-anchoring detail that decides whether it works. It is part of ",[17,18,20],"a",{"href":19},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002F","Building Excel Reports with xlsxwriter",".",[23,24,32,33,32,37,32,41,32,48,32,57,32,64,32,72,32,77,32,82,32,87,32,91,32,96,32,101,32,107,32,111,32,114,32,117,32,120,32,123,32,128,32,133,32,141,32,143,32,147,32,151,32,155,32,159,32,165,32,170,32,173,32,177,32,180,32,184,32,188],"svg",{"viewBox":25,"role":26,"ariaLabelledBy":27,"xmlns":30,"style":31},"0 0 740 240","img",[28,29],"xcf-kinds-t","xcf-kinds-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:740px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[34,35,36],"title",{"id":28},"Four rule families and the question each one answers",[38,39,40],"desc",{"id":29},"A cell rule answers a yes-or-no question against a threshold. A colour scale shows where each value sits within the range of the column. A data bar compares magnitudes across rows at a glance. A formula rule tests any expression and can format an entire row from one column's value.",[42,43],"rect",{"x":44,"y":44,"width":45,"height":46,"fill":47},"0","740","240","#ffffff",[42,49],{"x":50,"y":51,"width":52,"height":52,"rx":53,"fill":54,"stroke":55,"style":56},"16","34","170","14","#fce9e9","var(--accent-ink,#be185d)","stroke-width:2px",[58,59,63],"text",{"x":60,"y":61,"style":62},"101","62","font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","cell rule",[42,65],{"x":66,"y":67,"width":68,"height":69,"rx":70,"fill":71},"36","76","130","24","4","#FFC7CE",[58,73,76],{"x":60,"y":74,"style":75},"93","font-size:11px;font-weight:700;fill:#9C0006;text-anchor:middle","-12.5%",[58,78,81],{"x":60,"y":79,"style":80},"126","font-size:11px;fill:var(--text,#172033);text-anchor:middle","\"is this one bad?\"",[58,83,86],{"x":60,"y":84,"style":85},"154","font-size:11px;fill:var(--muted,#5b6780);text-anchor:middle","a threshold everyone",[58,88,90],{"x":60,"y":89,"style":85},"172","already agrees on",[42,92],{"x":93,"y":51,"width":52,"height":52,"rx":53,"fill":94,"stroke":95,"style":56},"198","#fdefd8","var(--gold,#b4740a)",[58,97,100],{"x":98,"y":61,"style":99},"283","font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","colour scale",[42,102],{"x":103,"y":67,"width":104,"height":69,"rx":105,"fill":106},"218","43","3","#C6EFCE",[42,108],{"x":109,"y":67,"width":104,"height":69,"rx":105,"fill":110},"261","#FFEB9C",[42,112],{"x":113,"y":67,"width":104,"height":69,"rx":105,"fill":71},"304",[58,115,116],{"x":98,"y":79,"style":80},"\"where does it sit?\"",[58,118,119],{"x":98,"y":84,"style":85},"a distribution with no",[58,121,122],{"x":98,"y":89,"style":85},"natural cut-off",[42,124],{"x":125,"y":51,"width":52,"height":52,"rx":53,"fill":126,"stroke":127,"style":56},"380","#d9f4f1","var(--teal,#0f9488)",[58,129,132],{"x":130,"y":61,"style":131},"465","font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","data bar",[42,134],{"x":135,"y":136,"width":137,"height":138,"rx":139,"fill":140},"400","74","90","12","2","#0f766e",[42,142],{"x":135,"y":137,"width":68,"height":138,"rx":139,"fill":140},[42,144],{"x":135,"y":145,"width":146,"height":138,"rx":139,"fill":140},"106","52",[58,148,150],{"x":130,"y":149,"style":80},"140","\"which is biggest?\"",[58,152,154],{"x":130,"y":153,"style":85},"164","magnitude, in the cell",[58,156,158],{"x":130,"y":157,"style":85},"182","instead of a chart",[42,160],{"x":161,"y":51,"width":162,"height":52,"rx":53,"fill":163,"stroke":164,"style":56},"562","162","#ebebfd","var(--brand,#5b5cf0)",[58,166,169],{"x":167,"y":61,"style":168},"643","font-size:12px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","formula rule",[42,171],{"x":172,"y":67,"width":79,"height":138,"rx":139,"fill":163,"stroke":164},"580",[42,174],{"x":172,"y":175,"width":79,"height":138,"rx":139,"fill":176},"92","#5b5cf0",[42,178],{"x":172,"y":179,"width":79,"height":138,"rx":139,"fill":163,"stroke":164},"108",[58,181,183],{"x":167,"y":182,"style":80},"142","\"flag the whole row\"",[58,185,187],{"x":167,"y":186,"style":85},"166","one column decides,",[58,189,191],{"x":167,"y":190,"style":85},"184","every column shows it",[193,194,196],"h2",{"id":195},"prerequisites","Prerequisites",[198,199,204],"pre",{"className":200,"code":201,"language":202,"meta":203,"style":203},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install xlsxwriter pandas\n","bash","",[205,206,207],"code",{"__ignoreMap":203},[208,209,212,216,220,223],"span",{"class":210,"line":211},"line",1,[208,213,215],{"class":214},"sMTad","pip",[208,217,219],{"class":218},"srMev"," install",[208,221,222],{"class":218}," xlsxwriter",[208,224,225],{"class":218}," pandas\n",[10,227,228,229,21],{},"The examples build their own workbook, so they run as written. Everything applies equally when xlsxwriter is driven through ",[205,230,231],{},"pd.ExcelWriter(engine=\"xlsxwriter\")",[193,233,235],{"id":234},"step-1-set-up-a-sheet-to-format","Step 1: Set up a sheet to format",[198,237,241],{"className":238,"code":239,"language":240,"meta":203,"style":203},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\nimport xlsxwriter\n\ndf = pd.DataFrame({\n    \"region\":   [\"North\", \"South\", \"East\", \"West\", \"Central\"],\n    \"amount\":   [150.25, 274.75, 75.0, 190.4, 88.1],\n    \"variance\": [0.041, -0.062, -0.128, 0.012, -0.005],\n    \"status\":   [\"ok\", \"watch\", \"breach\", \"ok\", \"ok\"],\n})\n\nwb = xlsxwriter.Workbook(\"flagged.xlsx\")\nws = wb.add_worksheet(\"Regions\")\nheader = wb.add_format({\"bold\": True, \"bg_color\": \"#1F4E78\",\n                        \"font_color\": \"white\", \"border\": 1})\n\nws.write_row(0, 0, [\"Region\", \"Amount\", \"Variance\", \"Status\"], header)\nfor i, row in enumerate(df.itertuples(index=False), start=1):\n    ws.write_string(i, 0, row.region)\n    ws.write_number(i, 1, row.amount)\n    ws.write_number(i, 2, row.variance)\n    ws.write_string(i, 3, row.status)\n\nws.set_column(\"A:A\", 14)\nws.set_column(\"B:B\", 14, wb.add_format({\"num_format\": '#,##0.00'}))\nws.set_column(\"C:C\", 12, wb.add_format({\"num_format\": \"0.0%\"}))\nws.set_column(\"D:D\", 12)\n\nLAST = len(df)                     # last data row, zero-based\n","python",[205,242,243,259,267,274,286,322,356,397,428,434,439,456,472,505,528,533,569,609,620,631,641,651,656,671,697,720,734,739],{"__ignoreMap":203},[208,244,245,249,253,256],{"class":210,"line":211},[208,246,248],{"class":247},"s-kum","import",[208,250,252],{"class":251},"skGVy"," pandas ",[208,254,255],{"class":247},"as",[208,257,258],{"class":251}," pd\n",[208,260,262,264],{"class":210,"line":261},2,[208,263,248],{"class":247},[208,265,266],{"class":251}," xlsxwriter\n",[208,268,270],{"class":210,"line":269},3,[208,271,273],{"emptyLinePlaceholder":272},true,"\n",[208,275,277,280,283],{"class":210,"line":276},4,[208,278,279],{"class":251},"df ",[208,281,282],{"class":247},"=",[208,284,285],{"class":251}," pd.DataFrame({\n",[208,287,289,292,295,298,301,304,306,309,311,314,316,319],{"class":210,"line":288},5,[208,290,291],{"class":218},"    \"region\"",[208,293,294],{"class":251},":   [",[208,296,297],{"class":218},"\"North\"",[208,299,300],{"class":251},", ",[208,302,303],{"class":218},"\"South\"",[208,305,300],{"class":251},[208,307,308],{"class":218},"\"East\"",[208,310,300],{"class":251},[208,312,313],{"class":218},"\"West\"",[208,315,300],{"class":251},[208,317,318],{"class":218},"\"Central\"",[208,320,321],{"class":251},"],\n",[208,323,325,328,330,334,336,339,341,344,346,349,351,354],{"class":210,"line":324},6,[208,326,327],{"class":218},"    \"amount\"",[208,329,294],{"class":251},[208,331,333],{"class":332},"sP0c6","150.25",[208,335,300],{"class":251},[208,337,338],{"class":332},"274.75",[208,340,300],{"class":251},[208,342,343],{"class":332},"75.0",[208,345,300],{"class":251},[208,347,348],{"class":332},"190.4",[208,350,300],{"class":251},[208,352,353],{"class":332},"88.1",[208,355,321],{"class":251},[208,357,359,362,365,368,370,373,376,378,380,383,385,388,390,392,395],{"class":210,"line":358},7,[208,360,361],{"class":218},"    \"variance\"",[208,363,364],{"class":251},": [",[208,366,367],{"class":332},"0.041",[208,369,300],{"class":251},[208,371,372],{"class":247},"-",[208,374,375],{"class":332},"0.062",[208,377,300],{"class":251},[208,379,372],{"class":247},[208,381,382],{"class":332},"0.128",[208,384,300],{"class":251},[208,386,387],{"class":332},"0.012",[208,389,300],{"class":251},[208,391,372],{"class":247},[208,393,394],{"class":332},"0.005",[208,396,321],{"class":251},[208,398,400,403,405,408,410,413,415,418,420,422,424,426],{"class":210,"line":399},8,[208,401,402],{"class":218},"    \"status\"",[208,404,294],{"class":251},[208,406,407],{"class":218},"\"ok\"",[208,409,300],{"class":251},[208,411,412],{"class":218},"\"watch\"",[208,414,300],{"class":251},[208,416,417],{"class":218},"\"breach\"",[208,419,300],{"class":251},[208,421,407],{"class":218},[208,423,300],{"class":251},[208,425,407],{"class":218},[208,427,321],{"class":251},[208,429,431],{"class":210,"line":430},9,[208,432,433],{"class":251},"})\n",[208,435,437],{"class":210,"line":436},10,[208,438,273],{"emptyLinePlaceholder":272},[208,440,442,445,447,450,453],{"class":210,"line":441},11,[208,443,444],{"class":251},"wb ",[208,446,282],{"class":247},[208,448,449],{"class":251}," xlsxwriter.Workbook(",[208,451,452],{"class":218},"\"flagged.xlsx\"",[208,454,455],{"class":251},")\n",[208,457,459,462,464,467,470],{"class":210,"line":458},12,[208,460,461],{"class":251},"ws ",[208,463,282],{"class":247},[208,465,466],{"class":251}," wb.add_worksheet(",[208,468,469],{"class":218},"\"Regions\"",[208,471,455],{"class":251},[208,473,475,478,480,483,486,489,492,494,497,499,502],{"class":210,"line":474},13,[208,476,477],{"class":251},"header ",[208,479,282],{"class":247},[208,481,482],{"class":251}," wb.add_format({",[208,484,485],{"class":218},"\"bold\"",[208,487,488],{"class":251},": ",[208,490,491],{"class":332},"True",[208,493,300],{"class":251},[208,495,496],{"class":218},"\"bg_color\"",[208,498,488],{"class":251},[208,500,501],{"class":218},"\"#1F4E78\"",[208,503,504],{"class":251},",\n",[208,506,508,511,513,516,518,521,523,526],{"class":210,"line":507},14,[208,509,510],{"class":218},"                        \"font_color\"",[208,512,488],{"class":251},[208,514,515],{"class":218},"\"white\"",[208,517,300],{"class":251},[208,519,520],{"class":218},"\"border\"",[208,522,488],{"class":251},[208,524,525],{"class":332},"1",[208,527,433],{"class":251},[208,529,531],{"class":210,"line":530},15,[208,532,273],{"emptyLinePlaceholder":272},[208,534,536,539,541,543,545,548,551,553,556,558,561,563,566],{"class":210,"line":535},16,[208,537,538],{"class":251},"ws.write_row(",[208,540,44],{"class":332},[208,542,300],{"class":251},[208,544,44],{"class":332},[208,546,547],{"class":251},", [",[208,549,550],{"class":218},"\"Region\"",[208,552,300],{"class":251},[208,554,555],{"class":218},"\"Amount\"",[208,557,300],{"class":251},[208,559,560],{"class":218},"\"Variance\"",[208,562,300],{"class":251},[208,564,565],{"class":218},"\"Status\"",[208,567,568],{"class":251},"], header)\n",[208,570,572,575,578,581,584,587,591,593,596,599,602,604,606],{"class":210,"line":571},17,[208,573,574],{"class":247},"for",[208,576,577],{"class":251}," i, row ",[208,579,580],{"class":247},"in",[208,582,583],{"class":332}," enumerate",[208,585,586],{"class":251},"(df.itertuples(",[208,588,590],{"class":589},"sa561","index",[208,592,282],{"class":247},[208,594,595],{"class":332},"False",[208,597,598],{"class":251},"), ",[208,600,601],{"class":589},"start",[208,603,282],{"class":247},[208,605,525],{"class":332},[208,607,608],{"class":251},"):\n",[208,610,612,615,617],{"class":210,"line":611},18,[208,613,614],{"class":251},"    ws.write_string(i, ",[208,616,44],{"class":332},[208,618,619],{"class":251},", row.region)\n",[208,621,623,626,628],{"class":210,"line":622},19,[208,624,625],{"class":251},"    ws.write_number(i, ",[208,627,525],{"class":332},[208,629,630],{"class":251},", row.amount)\n",[208,632,634,636,638],{"class":210,"line":633},20,[208,635,625],{"class":251},[208,637,139],{"class":332},[208,639,640],{"class":251},", row.variance)\n",[208,642,644,646,648],{"class":210,"line":643},21,[208,645,614],{"class":251},[208,647,105],{"class":332},[208,649,650],{"class":251},", row.status)\n",[208,652,654],{"class":210,"line":653},22,[208,655,273],{"emptyLinePlaceholder":272},[208,657,659,662,665,667,669],{"class":210,"line":658},23,[208,660,661],{"class":251},"ws.set_column(",[208,663,664],{"class":218},"\"A:A\"",[208,666,300],{"class":251},[208,668,53],{"class":332},[208,670,455],{"class":251},[208,672,674,676,679,681,683,686,689,691,694],{"class":210,"line":673},24,[208,675,661],{"class":251},[208,677,678],{"class":218},"\"B:B\"",[208,680,300],{"class":251},[208,682,53],{"class":332},[208,684,685],{"class":251},", wb.add_format({",[208,687,688],{"class":218},"\"num_format\"",[208,690,488],{"class":251},[208,692,693],{"class":218},"'#,##0.00'",[208,695,696],{"class":251},"}))\n",[208,698,700,702,705,707,709,711,713,715,718],{"class":210,"line":699},25,[208,701,661],{"class":251},[208,703,704],{"class":218},"\"C:C\"",[208,706,300],{"class":251},[208,708,138],{"class":332},[208,710,685],{"class":251},[208,712,688],{"class":218},[208,714,488],{"class":251},[208,716,717],{"class":218},"\"0.0%\"",[208,719,696],{"class":251},[208,721,723,725,728,730,732],{"class":210,"line":722},26,[208,724,661],{"class":251},[208,726,727],{"class":218},"\"D:D\"",[208,729,300],{"class":251},[208,731,138],{"class":332},[208,733,455],{"class":251},[208,735,737],{"class":210,"line":736},27,[208,738,273],{"emptyLinePlaceholder":272},[208,740,742,745,748,751,754],{"class":210,"line":741},28,[208,743,744],{"class":332},"LAST",[208,746,747],{"class":247}," =",[208,749,750],{"class":332}," len",[208,752,753],{"class":251},"(df)                     ",[208,755,757],{"class":756},"s-wDw","# last data row, zero-based\n",[193,759,761],{"id":760},"step-2-cell-and-text-rules","Step 2: Cell and text rules",[10,763,764],{},"A cell rule compares each cell in the range against a literal:",[198,766,768],{"className":238,"code":767,"language":240,"meta":203,"style":203},"bad = wb.add_format({\"bg_color\": \"#FFC7CE\", \"font_color\": \"#9C0006\"})\ngood = wb.add_format({\"bg_color\": \"#C6EFCE\", \"font_color\": \"#006100\"})\n\nws.conditional_format(1, 2, LAST, 2, {\n    \"type\": \"cell\", \"criteria\": \"\u003C\", \"value\": -0.05, \"format\": bad,\n})\nws.conditional_format(1, 2, LAST, 2, {\n    \"type\": \"cell\", \"criteria\": \">=\", \"value\": 0.0, \"format\": good,\n})\nws.conditional_format(1, 3, LAST, 3, {\n    \"type\": \"text\", \"criteria\": \"containing\", \"value\": \"breach\", \"format\": bad,\n})\n",[205,769,770,798,825,829,851,891,895,915,948,952,972,1004],{"__ignoreMap":203},[208,771,772,775,777,779,781,783,786,788,791,793,796],{"class":210,"line":211},[208,773,774],{"class":251},"bad ",[208,776,282],{"class":247},[208,778,482],{"class":251},[208,780,496],{"class":218},[208,782,488],{"class":251},[208,784,785],{"class":218},"\"#FFC7CE\"",[208,787,300],{"class":251},[208,789,790],{"class":218},"\"font_color\"",[208,792,488],{"class":251},[208,794,795],{"class":218},"\"#9C0006\"",[208,797,433],{"class":251},[208,799,800,803,805,807,809,811,814,816,818,820,823],{"class":210,"line":261},[208,801,802],{"class":251},"good ",[208,804,282],{"class":247},[208,806,482],{"class":251},[208,808,496],{"class":218},[208,810,488],{"class":251},[208,812,813],{"class":218},"\"#C6EFCE\"",[208,815,300],{"class":251},[208,817,790],{"class":218},[208,819,488],{"class":251},[208,821,822],{"class":218},"\"#006100\"",[208,824,433],{"class":251},[208,826,827],{"class":210,"line":269},[208,828,273],{"emptyLinePlaceholder":272},[208,830,831,834,836,838,840,842,844,846,848],{"class":210,"line":276},[208,832,833],{"class":251},"ws.conditional_format(",[208,835,525],{"class":332},[208,837,300],{"class":251},[208,839,139],{"class":332},[208,841,300],{"class":251},[208,843,744],{"class":332},[208,845,300],{"class":251},[208,847,139],{"class":332},[208,849,850],{"class":251},", {\n",[208,852,853,856,858,861,863,866,868,871,873,876,878,880,883,885,888],{"class":210,"line":288},[208,854,855],{"class":218},"    \"type\"",[208,857,488],{"class":251},[208,859,860],{"class":218},"\"cell\"",[208,862,300],{"class":251},[208,864,865],{"class":218},"\"criteria\"",[208,867,488],{"class":251},[208,869,870],{"class":218},"\"\u003C\"",[208,872,300],{"class":251},[208,874,875],{"class":218},"\"value\"",[208,877,488],{"class":251},[208,879,372],{"class":247},[208,881,882],{"class":332},"0.05",[208,884,300],{"class":251},[208,886,887],{"class":218},"\"format\"",[208,889,890],{"class":251},": bad,\n",[208,892,893],{"class":210,"line":324},[208,894,433],{"class":251},[208,896,897,899,901,903,905,907,909,911,913],{"class":210,"line":358},[208,898,833],{"class":251},[208,900,525],{"class":332},[208,902,300],{"class":251},[208,904,139],{"class":332},[208,906,300],{"class":251},[208,908,744],{"class":332},[208,910,300],{"class":251},[208,912,139],{"class":332},[208,914,850],{"class":251},[208,916,917,919,921,923,925,927,929,932,934,936,938,941,943,945],{"class":210,"line":399},[208,918,855],{"class":218},[208,920,488],{"class":251},[208,922,860],{"class":218},[208,924,300],{"class":251},[208,926,865],{"class":218},[208,928,488],{"class":251},[208,930,931],{"class":218},"\">=\"",[208,933,300],{"class":251},[208,935,875],{"class":218},[208,937,488],{"class":251},[208,939,940],{"class":332},"0.0",[208,942,300],{"class":251},[208,944,887],{"class":218},[208,946,947],{"class":251},": good,\n",[208,949,950],{"class":210,"line":430},[208,951,433],{"class":251},[208,953,954,956,958,960,962,964,966,968,970],{"class":210,"line":436},[208,955,833],{"class":251},[208,957,525],{"class":332},[208,959,300],{"class":251},[208,961,105],{"class":332},[208,963,300],{"class":251},[208,965,744],{"class":332},[208,967,300],{"class":251},[208,969,105],{"class":332},[208,971,850],{"class":251},[208,973,974,976,978,981,983,985,987,990,992,994,996,998,1000,1002],{"class":210,"line":441},[208,975,855],{"class":218},[208,977,488],{"class":251},[208,979,980],{"class":218},"\"text\"",[208,982,300],{"class":251},[208,984,865],{"class":218},[208,986,488],{"class":251},[208,988,989],{"class":218},"\"containing\"",[208,991,300],{"class":251},[208,993,875],{"class":218},[208,995,488],{"class":251},[208,997,417],{"class":218},[208,999,300],{"class":251},[208,1001,887],{"class":218},[208,1003,890],{"class":251},[208,1005,1006],{"class":210,"line":458},[208,1007,433],{"class":251},[10,1009,1010,1011,1014],{},"Rules are evaluated in the order they are added, and — unlike some spreadsheet behaviour people expect — several can apply to the same cell, with later rules layering on top for any attribute the earlier ones did not set. Where two rules genuinely conflict, add ",[205,1012,1013],{},"\"stop_if_true\": True"," to the first so the second is skipped.",[10,1016,1017,1018,1021,1022,1025,1026,1028],{},"The row and column form (",[205,1019,1020],{},"conditional_format(first_row, first_col, last_row, last_col, options)",") is worth preferring to the string form (",[205,1023,1024],{},"\"C2:C6\"",") for the same reason chart ranges are: it is computed from ",[205,1027,744],{},", so it stays correct when the data grows.",[193,1030,1032],{"id":1031},"step-3-colour-scales-data-bars-and-icon-sets","Step 3: Colour scales, data bars and icon sets",[10,1034,1035],{},"Where there is no agreed threshold, show the shape of the data instead:",[198,1037,1039],{"className":238,"code":1038,"language":240,"meta":203,"style":203},"ws.conditional_format(1, 1, LAST, 1, {\n    \"type\": \"3_color_scale\",\n    \"min_color\": \"#FFC7CE\", \"mid_color\": \"#FFEB9C\", \"max_color\": \"#C6EFCE\",\n})\n\nws.conditional_format(1, 1, LAST, 1, {\n    \"type\": \"data_bar\",\n    \"bar_color\": \"#5B5CF0\",\n    \"bar_solid\": True,\n    \"bar_only\": False,          # True hides the number and shows only the bar\n    \"data_bar_2010\": True,      # the newer bar style, incl. negative handling\n})\n\nws.conditional_format(1, 2, LAST, 2, {\n    \"type\": \"icon_set\",\n    \"icon_style\": \"3_arrows\",\n    \"icons\": [{\"criteria\": \">=\", \"type\": \"number\", \"value\": 0.02},\n              {\"criteria\": \">=\", \"type\": \"number\", \"value\": -0.02}],\n})\n",[205,1040,1041,1061,1072,1102,1106,1110,1130,1141,1153,1164,1179,1194,1198,1202,1222,1233,1245,1281,1313],{"__ignoreMap":203},[208,1042,1043,1045,1047,1049,1051,1053,1055,1057,1059],{"class":210,"line":211},[208,1044,833],{"class":251},[208,1046,525],{"class":332},[208,1048,300],{"class":251},[208,1050,525],{"class":332},[208,1052,300],{"class":251},[208,1054,744],{"class":332},[208,1056,300],{"class":251},[208,1058,525],{"class":332},[208,1060,850],{"class":251},[208,1062,1063,1065,1067,1070],{"class":210,"line":261},[208,1064,855],{"class":218},[208,1066,488],{"class":251},[208,1068,1069],{"class":218},"\"3_color_scale\"",[208,1071,504],{"class":251},[208,1073,1074,1077,1079,1081,1083,1086,1088,1091,1093,1096,1098,1100],{"class":210,"line":269},[208,1075,1076],{"class":218},"    \"min_color\"",[208,1078,488],{"class":251},[208,1080,785],{"class":218},[208,1082,300],{"class":251},[208,1084,1085],{"class":218},"\"mid_color\"",[208,1087,488],{"class":251},[208,1089,1090],{"class":218},"\"#FFEB9C\"",[208,1092,300],{"class":251},[208,1094,1095],{"class":218},"\"max_color\"",[208,1097,488],{"class":251},[208,1099,813],{"class":218},[208,1101,504],{"class":251},[208,1103,1104],{"class":210,"line":276},[208,1105,433],{"class":251},[208,1107,1108],{"class":210,"line":288},[208,1109,273],{"emptyLinePlaceholder":272},[208,1111,1112,1114,1116,1118,1120,1122,1124,1126,1128],{"class":210,"line":324},[208,1113,833],{"class":251},[208,1115,525],{"class":332},[208,1117,300],{"class":251},[208,1119,525],{"class":332},[208,1121,300],{"class":251},[208,1123,744],{"class":332},[208,1125,300],{"class":251},[208,1127,525],{"class":332},[208,1129,850],{"class":251},[208,1131,1132,1134,1136,1139],{"class":210,"line":358},[208,1133,855],{"class":218},[208,1135,488],{"class":251},[208,1137,1138],{"class":218},"\"data_bar\"",[208,1140,504],{"class":251},[208,1142,1143,1146,1148,1151],{"class":210,"line":399},[208,1144,1145],{"class":218},"    \"bar_color\"",[208,1147,488],{"class":251},[208,1149,1150],{"class":218},"\"#5B5CF0\"",[208,1152,504],{"class":251},[208,1154,1155,1158,1160,1162],{"class":210,"line":430},[208,1156,1157],{"class":218},"    \"bar_solid\"",[208,1159,488],{"class":251},[208,1161,491],{"class":332},[208,1163,504],{"class":251},[208,1165,1166,1169,1171,1173,1176],{"class":210,"line":436},[208,1167,1168],{"class":218},"    \"bar_only\"",[208,1170,488],{"class":251},[208,1172,595],{"class":332},[208,1174,1175],{"class":251},",          ",[208,1177,1178],{"class":756},"# True hides the number and shows only the bar\n",[208,1180,1181,1184,1186,1188,1191],{"class":210,"line":441},[208,1182,1183],{"class":218},"    \"data_bar_2010\"",[208,1185,488],{"class":251},[208,1187,491],{"class":332},[208,1189,1190],{"class":251},",      ",[208,1192,1193],{"class":756},"# the newer bar style, incl. negative handling\n",[208,1195,1196],{"class":210,"line":458},[208,1197,433],{"class":251},[208,1199,1200],{"class":210,"line":474},[208,1201,273],{"emptyLinePlaceholder":272},[208,1203,1204,1206,1208,1210,1212,1214,1216,1218,1220],{"class":210,"line":507},[208,1205,833],{"class":251},[208,1207,525],{"class":332},[208,1209,300],{"class":251},[208,1211,139],{"class":332},[208,1213,300],{"class":251},[208,1215,744],{"class":332},[208,1217,300],{"class":251},[208,1219,139],{"class":332},[208,1221,850],{"class":251},[208,1223,1224,1226,1228,1231],{"class":210,"line":530},[208,1225,855],{"class":218},[208,1227,488],{"class":251},[208,1229,1230],{"class":218},"\"icon_set\"",[208,1232,504],{"class":251},[208,1234,1235,1238,1240,1243],{"class":210,"line":535},[208,1236,1237],{"class":218},"    \"icon_style\"",[208,1239,488],{"class":251},[208,1241,1242],{"class":218},"\"3_arrows\"",[208,1244,504],{"class":251},[208,1246,1247,1250,1253,1255,1257,1259,1261,1264,1266,1269,1271,1273,1275,1278],{"class":210,"line":571},[208,1248,1249],{"class":218},"    \"icons\"",[208,1251,1252],{"class":251},": [{",[208,1254,865],{"class":218},[208,1256,488],{"class":251},[208,1258,931],{"class":218},[208,1260,300],{"class":251},[208,1262,1263],{"class":218},"\"type\"",[208,1265,488],{"class":251},[208,1267,1268],{"class":218},"\"number\"",[208,1270,300],{"class":251},[208,1272,875],{"class":218},[208,1274,488],{"class":251},[208,1276,1277],{"class":332},"0.02",[208,1279,1280],{"class":251},"},\n",[208,1282,1283,1286,1288,1290,1292,1294,1296,1298,1300,1302,1304,1306,1308,1310],{"class":210,"line":611},[208,1284,1285],{"class":251},"              {",[208,1287,865],{"class":218},[208,1289,488],{"class":251},[208,1291,931],{"class":218},[208,1293,300],{"class":251},[208,1295,1263],{"class":218},[208,1297,488],{"class":251},[208,1299,1268],{"class":218},[208,1301,300],{"class":251},[208,1303,875],{"class":218},[208,1305,488],{"class":251},[208,1307,372],{"class":247},[208,1309,1277],{"class":332},[208,1311,1312],{"class":251},"}],\n",[208,1314,1315],{"class":210,"line":622},[208,1316,433],{"class":251},[10,1318,1319],{},"A data bar and a colour scale on the same range is a legitimate combination — the bar shows magnitude, the fill shows position — but it is also the fastest way to make a table look like a toy. Pick one per column.",[10,1321,1322,1325],{},[205,1323,1324],{},"data_bar_2010: True"," opts into the later data-bar specification, which draws negative values from a midpoint rather than from the left edge. Without it, a column containing negatives renders in a way most readers misread.",[193,1327,1329],{"id":1328},"step-4-highlight-an-entire-row-from-one-column","Step 4: Highlight an entire row from one column",[10,1331,1332,1333,1337],{},"This is the rule most reports actually want, and the one that most often comes out wrong. The rule applies to the whole table's range, but its formula must always test the same ",[1334,1335,1336],"em",{},"column"," while moving down the rows:",[198,1339,1341],{"className":238,"code":1340,"language":240,"meta":203,"style":203},"row_flag = wb.add_format({\"bg_color\": \"#FEE8F2\"})\n\nws.conditional_format(1, 0, LAST, 3, {\n    \"type\": \"formula\",\n    \"criteria\": '=$D2=\"breach\"',      # $D anchors the column, 2 is the anchor row\n    \"format\": row_flag,\n})\n",[205,1342,1343,1361,1365,1385,1396,1411,1419],{"__ignoreMap":203},[208,1344,1345,1348,1350,1352,1354,1356,1359],{"class":210,"line":211},[208,1346,1347],{"class":251},"row_flag ",[208,1349,282],{"class":247},[208,1351,482],{"class":251},[208,1353,496],{"class":218},[208,1355,488],{"class":251},[208,1357,1358],{"class":218},"\"#FEE8F2\"",[208,1360,433],{"class":251},[208,1362,1363],{"class":210,"line":261},[208,1364,273],{"emptyLinePlaceholder":272},[208,1366,1367,1369,1371,1373,1375,1377,1379,1381,1383],{"class":210,"line":269},[208,1368,833],{"class":251},[208,1370,525],{"class":332},[208,1372,300],{"class":251},[208,1374,44],{"class":332},[208,1376,300],{"class":251},[208,1378,744],{"class":332},[208,1380,300],{"class":251},[208,1382,105],{"class":332},[208,1384,850],{"class":251},[208,1386,1387,1389,1391,1394],{"class":210,"line":276},[208,1388,855],{"class":218},[208,1390,488],{"class":251},[208,1392,1393],{"class":218},"\"formula\"",[208,1395,504],{"class":251},[208,1397,1398,1401,1403,1406,1408],{"class":210,"line":288},[208,1399,1400],{"class":218},"    \"criteria\"",[208,1402,488],{"class":251},[208,1404,1405],{"class":218},"'=$D2=\"breach\"'",[208,1407,1190],{"class":251},[208,1409,1410],{"class":756},"# $D anchors the column, 2 is the anchor row\n",[208,1412,1413,1416],{"class":210,"line":324},[208,1414,1415],{"class":218},"    \"format\"",[208,1417,1418],{"class":251},": row_flag,\n",[208,1420,1421],{"class":210,"line":358},[208,1422,433],{"class":251},[10,1424,1425,1426,1429,1430,1433,1434,1436,1437,1439,1440,1443,1444,1447],{},"Two things have to line up. The formula is written ",[1334,1427,1428],{},"relative to the top-left cell of the range"," — here ",[205,1431,1432],{},"A2"," — so the row number in the formula is ",[205,1435,139],{},", not ",[205,1438,525],{}," and not ",[205,1441,1442],{},"$2",". And the column must carry a ",[205,1445,1446],{},"$",": without it, the rule tests column A in column A, column B in column B, and so on, which produces a scatter of highlighted cells that looks almost right and is not.",[23,1449,32,1454,32,1457,32,1460,32,1463,32,1468,32,1472,32,1476,32,1478,32,1482,32,1485,32,1489,32,1492,32,1496,32,1500,32,1504,32,1508,32,1513,32,1516,32,1520,32,1523,32,1527,32,1530,32,1534,32,1537,32,1541,32,1544,32,1547,32,1550,32,1557,32,1563],{"viewBox":1450,"role":26,"ariaLabelledBy":1451,"xmlns":30,"style":31},"0 0 740 246",[1452,1453],"xcf-anchor-t","xcf-anchor-d",[34,1455,1456],{"id":1452},"What the dollar sign changes in a whole-row rule",[38,1458,1459],{"id":1453},"Written as D2 without a dollar, Excel shifts the reference sideways for each column, so cell A2 tests D2 but B2 tests E2 and C2 tests F2 — columns that hold something else entirely. Written as $D2, every cell in the row tests column D while the row number still advances down the table.",[42,1461],{"x":44,"y":44,"width":45,"height":1462,"fill":47},"246",[58,1464,1467],{"x":190,"y":1465,"style":1466},"32","font-size:12.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","criteria: =D2=\"breach\"",[42,1469],{"x":69,"y":1470,"width":67,"height":51,"rx":1471,"fill":54,"stroke":55},"50","5",[58,1473,1475],{"x":61,"y":1474,"style":80},"72","A2 → D2",[42,1477],{"x":145,"y":1470,"width":67,"height":51,"rx":1471,"fill":54,"stroke":55},[58,1479,1481],{"x":1480,"y":1474,"style":80},"144","B2 → E2",[42,1483],{"x":1484,"y":1470,"width":67,"height":51,"rx":1471,"fill":54,"stroke":55},"188",[58,1486,1488],{"x":1487,"y":1474,"style":80},"226","C2 → F2",[42,1490],{"x":1491,"y":1470,"width":67,"height":51,"rx":1471,"fill":54,"stroke":55},"270",[58,1493,1495],{"x":1494,"y":1474,"style":80},"308","D2 → G2",[58,1497,1499],{"x":190,"y":179,"style":1498},"font-size:11.5px;fill:var(--text,#172033);text-anchor:middle","each column tests a different cell",[58,1501,1503],{"x":190,"y":1502,"style":85},"132","E2, F2 and G2 are empty or hold other data,",[58,1505,1507],{"x":190,"y":1506,"style":85},"150","so only part of the row lights up",[58,1509,1512],{"x":1510,"y":1465,"style":1511},"556","font-size:12.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","criteria: =$D2=\"breach\"",[42,1514],{"x":1515,"y":1470,"width":67,"height":51,"rx":1471,"fill":126,"stroke":127},"396",[58,1517,1519],{"x":1518,"y":1474,"style":80},"434","A2 → $D2",[42,1521],{"x":1522,"y":1470,"width":67,"height":51,"rx":1471,"fill":126,"stroke":127},"478",[58,1524,1526],{"x":1525,"y":1474,"style":80},"516","B2 → $D2",[42,1528],{"x":1529,"y":1470,"width":67,"height":51,"rx":1471,"fill":126,"stroke":127},"560",[58,1531,1533],{"x":1532,"y":1474,"style":80},"598","C2 → $D2",[42,1535],{"x":1536,"y":1470,"width":67,"height":51,"rx":1471,"fill":126,"stroke":127},"642",[58,1538,1540],{"x":1539,"y":1474,"style":80},"680","D2 → $D2",[58,1542,1543],{"x":1510,"y":179,"style":1498},"every column tests the status column",[58,1545,1546],{"x":1510,"y":1502,"style":85},"and row 3 tests $D3, row 4 tests $D4 —",[58,1548,1549],{"x":1510,"y":1506,"style":85},"the row number is deliberately left relative",[42,1551],{"x":1552,"y":1553,"width":1554,"height":1470,"rx":1555,"fill":1556,"stroke":164},"120","180","500","10","#f0f4ff",[58,1558,1562],{"x":1559,"y":1560,"style":1561},"370","202","font-size:11.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","The formula is always written for the range's top-left cell",[58,1564,1566],{"x":1559,"y":1565,"style":85},"221","start the range at row 2 and the formula says 2 — Excel rewrites the rest",[193,1568,1570],{"id":1569},"step-4b-order-the-rules-deliberately","Step 4b: Order the rules deliberately",[10,1572,1573],{},"Rules are stored in the order they are added, and Excel applies them all — later ones layering over earlier ones for any attribute the earlier ones left unset. That is useful for building up a look from small rules, and it is the reason a \"why is that cell amber when it should be red\" question usually has a boring answer:",[23,1575,32,1580,32,1583,32,1586,32,1589,32,1594,32,1600,32,1605,32,1609,32,1613,32,1616,32,1620,32,1624,32,1626,32,1630,32,1633,32,1637,32,1640,32,1643],{"viewBox":1576,"role":26,"ariaLabelledBy":1577,"xmlns":30,"style":31},"0 0 740 222",[1578,1579],"xcf-order-t","xcf-order-d",[34,1581,1582],{"id":1578},"How two overlapping rules combine, with and without stop_if_true",[38,1584,1585],{"id":1579},"A cell of minus twelve percent matches both the below-zero rule and the below-target rule. Without stop_if_true the second rule's fill layers over the first, so the cell shows the softer amber. With stop_if_true on the first rule, evaluation halts there and the cell keeps the red that the more serious condition assigned.",[42,1587],{"x":44,"y":44,"width":45,"height":1588,"fill":47},"222",[58,1590,1593],{"x":1559,"y":1591,"style":1592},"30","font-size:12.5px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A cell of −12.5% matches both rules",[42,1595],{"x":50,"y":1470,"width":1596,"height":1597,"rx":53,"fill":1598,"stroke":1599,"style":56},"344","152","#f0f2f5","var(--line,#cdd5e6)",[58,1601,1604],{"x":1484,"y":1602,"style":1603},"78","font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","both rules evaluate",[42,1606],{"x":146,"y":175,"width":1607,"height":1608,"rx":70,"fill":54,"stroke":55},"272","26",[58,1610,1612],{"x":1484,"y":1611,"style":80},"110","1. below zero → red",[42,1614],{"x":146,"y":1615,"width":1607,"height":1608,"rx":70,"fill":94,"stroke":95,"style":56},"124",[58,1617,1619],{"x":1484,"y":182,"style":1618},"font-size:11px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","2. below target → amber (wins)",[58,1621,1623],{"x":1484,"y":1622,"style":85},"176","the later rule paints over the earlier one",[42,1625],{"x":125,"y":1470,"width":1596,"height":1597,"rx":53,"fill":126,"stroke":127,"style":56},[58,1627,1629],{"x":1628,"y":1602,"style":131},"552","\"stop_if_true\": True on rule 1",[42,1631],{"x":1632,"y":175,"width":1607,"height":1608,"rx":70,"fill":54,"stroke":55,"style":56},"416",[58,1634,1636],{"x":1628,"y":1611,"style":1635},"font-size:11px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","1. below zero → red (wins)",[42,1638],{"x":1632,"y":1615,"width":1607,"height":1608,"rx":70,"fill":47,"stroke":1599,"style":1639},"stroke-dasharray:4 3",[58,1641,1642],{"x":1628,"y":182,"style":85},"2. never evaluated for this cell",[58,1644,1645],{"x":1628,"y":1622,"style":85},"the more serious condition keeps the cell",[10,1647,1648,1649,1651],{},"The habit that avoids the question entirely is to add rules from most serious to least, with ",[205,1650,1013],{}," on any that should be final. Excel's own dialog exposes the same ordering, so a reader who opens the rules manager sees exactly the sequence your script wrote.",[193,1653,1655],{"id":1654},"step-5-rules-that-reference-other-cells","Step 5: Rules that reference other cells",[10,1657,1658],{},"Because the criteria is an ordinary Excel formula, a threshold can live in a cell rather than in your code — which lets a reader change it without regenerating the file:",[198,1660,1662],{"className":238,"code":1661,"language":240,"meta":203,"style":203},"ws.write(\"F1\", \"Threshold\")\nws.write_number(\"F2\", -0.05, wb.add_format({\"num_format\": \"0.0%\",\n                                            \"bg_color\": \"#FDEFD8\"}))\n\nws.conditional_format(1, 2, LAST, 2, {\n    \"type\": \"formula\",\n    \"criteria\": \"=$C2\u003C$F$2\",         # both anchored: column C by row, F2 absolutely\n    \"format\": bad,\n})\nwb.close()\n",[205,1663,1664,1679,1703,1715,1719,1739,1749,1764,1770,1774],{"__ignoreMap":203},[208,1665,1666,1669,1672,1674,1677],{"class":210,"line":211},[208,1667,1668],{"class":251},"ws.write(",[208,1670,1671],{"class":218},"\"F1\"",[208,1673,300],{"class":251},[208,1675,1676],{"class":218},"\"Threshold\"",[208,1678,455],{"class":251},[208,1680,1681,1684,1687,1689,1691,1693,1695,1697,1699,1701],{"class":210,"line":261},[208,1682,1683],{"class":251},"ws.write_number(",[208,1685,1686],{"class":218},"\"F2\"",[208,1688,300],{"class":251},[208,1690,372],{"class":247},[208,1692,882],{"class":332},[208,1694,685],{"class":251},[208,1696,688],{"class":218},[208,1698,488],{"class":251},[208,1700,717],{"class":218},[208,1702,504],{"class":251},[208,1704,1705,1708,1710,1713],{"class":210,"line":269},[208,1706,1707],{"class":218},"                                            \"bg_color\"",[208,1709,488],{"class":251},[208,1711,1712],{"class":218},"\"#FDEFD8\"",[208,1714,696],{"class":251},[208,1716,1717],{"class":210,"line":276},[208,1718,273],{"emptyLinePlaceholder":272},[208,1720,1721,1723,1725,1727,1729,1731,1733,1735,1737],{"class":210,"line":288},[208,1722,833],{"class":251},[208,1724,525],{"class":332},[208,1726,300],{"class":251},[208,1728,139],{"class":332},[208,1730,300],{"class":251},[208,1732,744],{"class":332},[208,1734,300],{"class":251},[208,1736,139],{"class":332},[208,1738,850],{"class":251},[208,1740,1741,1743,1745,1747],{"class":210,"line":324},[208,1742,855],{"class":218},[208,1744,488],{"class":251},[208,1746,1393],{"class":218},[208,1748,504],{"class":251},[208,1750,1751,1753,1755,1758,1761],{"class":210,"line":358},[208,1752,1400],{"class":218},[208,1754,488],{"class":251},[208,1756,1757],{"class":218},"\"=$C2\u003C$F$2\"",[208,1759,1760],{"class":251},",         ",[208,1762,1763],{"class":756},"# both anchored: column C by row, F2 absolutely\n",[208,1765,1766,1768],{"class":210,"line":399},[208,1767,1415],{"class":218},[208,1769,890],{"class":251},[208,1771,1772],{"class":210,"line":430},[208,1773,433],{"class":251},[208,1775,1776],{"class":210,"line":436},[208,1777,1778],{"class":251},"wb.close()\n",[10,1780,1781,1784,1785,1788],{},[205,1782,1783],{},"$F$2"," is fully absolute so every row compares against the same threshold cell, while ",[205,1786,1787],{},"$C2"," keeps its row relative so it walks down the column. Handing the threshold to the reader like this turns a hard-coded report into one they can explore — and it is the kind of small affordance that stops people exporting your output into their own spreadsheet.",[193,1790,1792],{"id":1791},"common-pitfalls-and-gotchas","Common pitfalls and gotchas",[1794,1795,1796,1812],"table",{},[1797,1798,1799],"thead",{},[1800,1801,1802,1806,1809],"tr",{},[1803,1804,1805],"th",{},"Symptom",[1803,1807,1808],{},"Cause",[1803,1810,1811],{},"Fix",[1813,1814,1815,1833,1846,1860,1874,1887,1898,1909],"tbody",{},[1800,1816,1817,1821,1824],{},[1818,1819,1820],"td",{},"Only part of a row highlights",[1818,1822,1823],{},"Column not anchored in the formula",[1818,1825,1826,1827,1436,1830],{},"Use ",[205,1828,1829],{},"$D2",[205,1831,1832],{},"D2",[1800,1834,1835,1838,1841],{},[1818,1836,1837],{},"Nothing highlights",[1818,1839,1840],{},"Formula row does not match the range's first row",[1818,1842,1843,1844],{},"Range starting at row 2 → formula says ",[205,1845,139],{},[1800,1847,1848,1851,1857],{},[1818,1849,1850],{},"Every row highlights",[1818,1852,1853,1854],{},"Row anchored as well: ",[205,1855,1856],{},"$D$2",[1818,1858,1859],{},"Leave the row relative",[1800,1861,1862,1865,1868],{},[1818,1863,1864],{},"Two rules fight",[1818,1866,1867],{},"Both apply, later one layers on",[1818,1869,1870,1871,1873],{},"Add ",[205,1872,1013],{}," to the first",[1800,1875,1876,1879,1882],{},[1818,1877,1878],{},"Negative data bars look wrong",[1818,1880,1881],{},"Old bar specification",[1818,1883,1884],{},[205,1885,1886],{},"\"data_bar_2010\": True",[1800,1888,1889,1892,1895],{},[1818,1890,1891],{},"Colours ignored in LibreOffice",[1818,1893,1894],{},"Icon set or bar style unsupported there",[1818,1896,1897],{},"Prefer cell rules and colour scales for portability",[1800,1899,1900,1903,1906],{},[1818,1901,1902],{},"The file grows and opens slowly",[1818,1904,1905],{},"One rule written per cell in a loop",[1818,1907,1908],{},"One rule over the whole range",[1800,1910,1911,1914,1921],{},[1818,1912,1913],{},"Rule lost after pandas wrote the sheet",[1818,1915,1916,1917,1920],{},"Applied before ",[205,1918,1919],{},"to_excel"," wrote the cells",[1818,1922,1923],{},"Apply rules after the data is written",[193,1925,1927],{"id":1926},"performance-and-scale-notes","Performance and scale notes",[10,1929,1930,1931,1934,1935,1938],{},"The rule count matters, not the cell count: a single rule over ",[205,1932,1933],{},"A2:D100000"," costs almost nothing, while a hundred thousand single-cell rules bloat the file and make Excel slow to open. If you find yourself in a loop calling ",[205,1936,1937],{},"conditional_format"," per row, the rule you want is a formula rule over the whole range.",[10,1940,1941],{},"Colour scales and data bars over very large ranges are also computed by Excel on every recalculation, so on a sheet with hundreds of thousands of rows they are noticeably heavier than a plain cell rule. On a detail sheet that large, put the visual emphasis on the summary and leave the detail plain — which is usually better reporting anyway.",[193,1943,1945],{"id":1944},"conclusion","Conclusion",[10,1947,1948,1949,1951],{},"Conditional formatting keeps a generated report honest: the highlight belongs to the rule, not to the moment the file was written, so it stays right when a reader edits or filters. Use cell rules where a threshold is agreed, colour scales and data bars where the distribution is the message, and a formula rule with ",[205,1950,1446],{}," on the column when one field should light the whole row. Apply one rule per range rather than per cell, and put the threshold in a cell when it is something readers should be able to change.",[193,1953,1955],{"id":1954},"frequently-asked-questions","Frequently asked questions",[10,1957,1958,1962,1963,1966],{},[1959,1960,1961],"strong",{},"Why does my whole-row rule highlight the wrong rows?","\nThe column reference in the formula is not anchored. Write ",[205,1964,1965],{},"$D5"," — dollar on the column, none on the row — so every column in the row tests the same cell while the row number still moves down.",[10,1968,1969,1972],{},[1959,1970,1971],{},"Which cell does the formula refer to?","\nThe top-left cell of the range you passed. Excel rewrites the reference for every other cell relative to that anchor, which is why the formula and the range must agree.",[10,1974,1975,1978,1979,1982,1983,1986,1987,1990],{},[1959,1976,1977],{},"Can I use a fill colour that is not one of Excel's presets?","\nYes. Pass any hex colour to ",[205,1980,1981],{},"add_format"," with ",[205,1984,1985],{},"bg_color"," and ",[205,1988,1989],{},"font_color",". The classic red-amber-green trio Excel offers is only a convention.",[10,1992,1993,1996],{},[1959,1994,1995],{},"Does conditional formatting slow down a large workbook?","\nOne rule over a large range is cheap. Thousands of separate single-cell rules are not — apply one rule to the whole range instead of looping over cells.",[193,1998,2000],{"id":1999},"related","Related",[10,2002,2003],{},"Up to the parent guide:",[2005,2006,2007],"ul",{},[2008,2009,2010,2012],"li",{},[17,2011,20],{"href":19}," — where these rules fit in the write-once model.",[10,2014,2015],{},"Related guides:",[2005,2017,2018,2025,2032,2039],{},[2008,2019,2020,2024],{},[17,2021,2023],{"href":2022},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002F","Applying Conditional Formatting with openpyxl"," — the same rules on the engine that can edit an existing file.",[2008,2026,2027,2031],{},[17,2028,2030],{"href":2029},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fopenpyxl-apply-conditional-formatting-to-range\u002F","openpyxl: Apply Conditional Formatting to a Range"," — range strings and multi-block ranges.",[2008,2033,2034,2038],{},[17,2035,2037],{"href":2036},"\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"," — the table these rules are applied to.",[2008,2040,2041,2045],{},[17,2042,2044],{"href":2043},"\u002Fadvanced-data-transformation-and-cleaning\u002Fvalidating-excel-data-with-python\u002Fhighlight-invalid-cells-in-excel-with-python\u002F","Highlight Invalid Cells in Excel with Python"," — flagging validation failures rather than thresholds.",[2047,2048,2049],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}",{"title":203,"searchDepth":261,"depth":261,"links":2051},[2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063],{"id":195,"depth":261,"text":196},{"id":234,"depth":261,"text":235},{"id":760,"depth":261,"text":761},{"id":1031,"depth":261,"text":1032},{"id":1328,"depth":261,"text":1329},{"id":1569,"depth":261,"text":1570},{"id":1654,"depth":261,"text":1655},{"id":1791,"depth":261,"text":1792},{"id":1926,"depth":261,"text":1927},{"id":1944,"depth":261,"text":1945},{"id":1954,"depth":261,"text":1955},{"id":1999,"depth":261,"text":2000},"2026-08-10","Write rules Excel re-evaluates: cell and text criteria, colour scales and data bars, a formula rule that highlights whole rows, and the absolute-reference trap that makes a row rule follow the wrong column.","md",[2068,2070,2072,2074],{"q":1961,"a":2069},"The column reference in the formula is not anchored. Write $D5 — dollar on the column, none on the row — so every column in the row tests the same cell while the row number still moves down.",{"q":1971,"a":2071},"The top-left cell of the range you passed. Excel rewrites the reference for every other cell relative to that anchor, which is why the formula and the range must agree.",{"q":1977,"a":2073},"Yes. Pass any hex colour to add_format with bg_color and font_color. The classic red-amber-green trio Excel offers is only a convention.",{"q":1995,"a":2075},"One rule over a large range is cheap. Thousands of separate single-cell rules are not — apply one rule to the whole range instead of looping over cells.",{"breadcrumb":2077},[2078,2081,2084,2085],{"name":2079,"item":2080},"Home","\u002F",{"name":2082,"item":2083},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":20,"item":19},{"name":5,"item":2086},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter\u002F","\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter",{"title":2089,"description":2090},"Conditional Formatting with xlsxwriter in Python","Add conditional formatting to Excel from Python with xlsxwriter — cell rules, colour scales, data bars, icon sets, whole-row formula rules and the $ anchoring that makes them work.","apply-conditional-formatting-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter\u002Findex","how-to","BK1CQtN5LUByzp3QxzenW1iVTQzGGXyo3K26KWwVAhI",[2096,2100],{"title":2097,"path":2098,"stem":2099,"children":-1},"Add a Chart to an Excel File with xlsxwriter","\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter\u002Findex",{"title":2037,"path":2101,"stem":2102,"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",1786800027358]