[{"data":1,"prerenderedAt":2782},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-cells-above-a-threshold-with-openpyxl":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-cells-above-a-threshold-with-openpyxl":2774},{"id":4,"title":5,"body":6,"dateModified":2751,"datePublished":2751,"description":2752,"extension":2753,"faq":2754,"meta":2765,"navigation":216,"path":2766,"seo":2767,"slug":2770,"stem":2771,"type":2772,"__hash__":2773},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-cells-above-a-threshold-with-openpyxl\u002Findex.md","Highlight Cells Above a Threshold with openpyxl",{"type":7,"value":8,"toc":2738},"minimark",[9,19,151,156,185,188,360,367,371,377,611,637,640,722,803,807,817,1069,1087,1094,1098,1106,1203,1373,1378,1385,1457,1461,1464,1749,1760,1764,1868,1874,2249,2256,2260,2385,2389,2392,2395,2587,2611,2619,2623,2641,2645,2651,2663,2672,2684,2693,2697,2734],[10,11,12,13,18],"p",{},"A report with four hundred rows and one number that needs attention is a report nobody reads carefully. Conditional formatting solves that by making the exceptions visible without changing any values — and unlike a static fill, the rule stays live, so a cell that later falls below the threshold loses its highlight automatically. This guide covers fixed thresholds, thresholds that live in a cell so readers can change them, whole-row highlighting, and what happens when rules overlap. It extends ",[14,15,17],"a",{"href":16},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002F","Applying Conditional Formatting with openpyxl",".",[20,21,30,31,30,35,30,39,30,46,30,54,30,61,30,65,30,69,30,74,30,80,30,85,30,88,30,92,30,97,30,102,30,106,30,110,30,115,30,118,30,122,30,124,30,127,30,129,30,132,30,136,30,138,30,141,30,145],"svg",{"viewBox":22,"role":23,"ariaLabel":24,"ariaLabelledBy":25,"xmlns":28,"style":29},"14 14 604 232","img","A sheet where revenue cells above a threshold are tinted and the rest are plain, with the threshold itself stored in an editable cell above the table.",[26,27],"thr-t","thr-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:604px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[32,33,34],"title",{"id":26},"A live threshold rule reading from an editable cell",[36,37,38],"desc",{"id":27},"A small report with a threshold cell holding four thousand at the top. Rows whose revenue exceeds that threshold are tinted teal; rows below it stay plain. Because the rule references the threshold cell rather than a hard-coded number, a reader who types a different threshold sees the highlighting update immediately without the report being regenerated.",[40,41],"rect",{"x":42,"y":42,"width":43,"height":44,"fill":45},"14","604","232","#ffffff",[40,47],{"x":48,"y":48,"width":49,"height":48,"rx":50,"fill":51,"stroke":52,"style":53},"30","200","5","#fdefd8","var(--gold,#b4740a)","stroke-width:2px",[55,56,60],"text",{"x":57,"y":58,"style":59},"130","50","font-size:11px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","threshold",[40,62],{"x":63,"y":48,"width":64,"height":48,"rx":50,"fill":45,"stroke":52,"style":53},"234","120",[55,66,68],{"x":67,"y":58,"style":59},"294","4,000",[55,70,73],{"x":71,"y":58,"style":72},"386","font-size:10.5px;fill:var(--muted,#5b6780)","B1 — readers can change this",[40,75],{"x":48,"y":76,"width":49,"height":77,"rx":50,"fill":78,"stroke":79,"style":53},"76","28","#ebebfd","var(--brand,#5b5cf0)",[55,81,84],{"x":57,"y":82,"style":83},"95","font-size:10.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","region",[40,86],{"x":63,"y":76,"width":87,"height":77,"rx":50,"fill":78,"stroke":79,"style":53},"160",[55,89,91],{"x":90,"y":82,"style":83},"314","revenue",[40,93],{"x":48,"y":94,"width":49,"height":95,"rx":50,"fill":45,"stroke":96},"108","26","var(--line,#cdd5e6)",[55,98,101],{"x":57,"y":99,"style":100},"126","font-size:10.5px;fill:var(--text,#172033);text-anchor:middle","North",[40,103],{"x":63,"y":94,"width":87,"height":95,"rx":50,"fill":104,"stroke":105,"style":53},"#d9f4f1","var(--teal,#0f9488)",[55,107,109],{"x":90,"y":99,"style":108},"font-size:10.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","5,150.00",[55,111,114],{"x":112,"y":99,"style":113},"410","font-size:10px;fill:var(--teal-ink,#0b6157)","above → tinted",[40,116],{"x":48,"y":117,"width":49,"height":95,"rx":50,"fill":45,"stroke":96},"138",[55,119,121],{"x":57,"y":120,"style":100},"156","South",[40,123],{"x":63,"y":117,"width":87,"height":95,"rx":50,"fill":104,"stroke":105,"style":53},[55,125,126],{"x":90,"y":120,"style":108},"4,268.50",[55,128,114],{"x":112,"y":120,"style":113},[40,130],{"x":48,"y":131,"width":49,"height":95,"rx":50,"fill":45,"stroke":96},"168",[55,133,135],{"x":57,"y":134,"style":100},"186","West",[40,137],{"x":63,"y":131,"width":87,"height":95,"rx":50,"fill":45,"stroke":96},[55,139,140],{"x":90,"y":134,"style":100},"3,511.25",[55,142,144],{"x":112,"y":134,"style":143},"font-size:10px;fill:var(--muted,#5b6780)","below → plain",[55,146,150],{"x":147,"y":148,"style":149},"400","228","font-size:11px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","the rule is live: change B1 and the highlighting follows, with no regeneration",[152,153,155],"h2",{"id":154},"prerequisites","Prerequisites",[157,158,163],"pre",{"className":159,"code":160,"language":161,"meta":162,"style":162},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install openpyxl pandas\n","bash","",[164,165,166],"code",{"__ignoreMap":162},[167,168,171,175,179,182],"span",{"class":169,"line":170},"line",1,[167,172,174],{"class":173},"sMTad","pip",[167,176,178],{"class":177},"srMev"," install",[167,180,181],{"class":177}," openpyxl",[167,183,184],{"class":177}," pandas\n",[10,186,187],{},"A sheet to format:",[157,189,193],{"className":190,"code":191,"language":192,"meta":162,"style":162},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\npd.DataFrame({\n    \"region\": [\"North\", \"South\", \"West\", \"East\", \"Central\"],\n    \"revenue\": [5150.00, 4268.50, 3511.25, 2980.10, 6402.75],\n    \"target\": [4500.00, 4500.00, 3000.00, 3500.00, 5000.00],\n}).to_excel(\"report.xlsx\", index=False, startrow=1)\n","python",[164,194,195,211,218,224,260,294,326],{"__ignoreMap":162},[167,196,197,201,205,208],{"class":169,"line":170},[167,198,200],{"class":199},"s-kum","import",[167,202,204],{"class":203},"skGVy"," pandas ",[167,206,207],{"class":199},"as",[167,209,210],{"class":203}," pd\n",[167,212,214],{"class":169,"line":213},2,[167,215,217],{"emptyLinePlaceholder":216},true,"\n",[167,219,221],{"class":169,"line":220},3,[167,222,223],{"class":203},"pd.DataFrame({\n",[167,225,227,230,233,236,239,242,244,247,249,252,254,257],{"class":169,"line":226},4,[167,228,229],{"class":177},"    \"region\"",[167,231,232],{"class":203},": [",[167,234,235],{"class":177},"\"North\"",[167,237,238],{"class":203},", ",[167,240,241],{"class":177},"\"South\"",[167,243,238],{"class":203},[167,245,246],{"class":177},"\"West\"",[167,248,238],{"class":203},[167,250,251],{"class":177},"\"East\"",[167,253,238],{"class":203},[167,255,256],{"class":177},"\"Central\"",[167,258,259],{"class":203},"],\n",[167,261,263,266,268,272,274,277,279,282,284,287,289,292],{"class":169,"line":262},5,[167,264,265],{"class":177},"    \"revenue\"",[167,267,232],{"class":203},[167,269,271],{"class":270},"sP0c6","5150.00",[167,273,238],{"class":203},[167,275,276],{"class":270},"4268.50",[167,278,238],{"class":203},[167,280,281],{"class":270},"3511.25",[167,283,238],{"class":203},[167,285,286],{"class":270},"2980.10",[167,288,238],{"class":203},[167,290,291],{"class":270},"6402.75",[167,293,259],{"class":203},[167,295,297,300,302,305,307,309,311,314,316,319,321,324],{"class":169,"line":296},6,[167,298,299],{"class":177},"    \"target\"",[167,301,232],{"class":203},[167,303,304],{"class":270},"4500.00",[167,306,238],{"class":203},[167,308,304],{"class":270},[167,310,238],{"class":203},[167,312,313],{"class":270},"3000.00",[167,315,238],{"class":203},[167,317,318],{"class":270},"3500.00",[167,320,238],{"class":203},[167,322,323],{"class":270},"5000.00",[167,325,259],{"class":203},[167,327,329,332,335,337,341,344,347,349,352,354,357],{"class":169,"line":328},7,[167,330,331],{"class":203},"}).to_excel(",[167,333,334],{"class":177},"\"report.xlsx\"",[167,336,238],{"class":203},[167,338,340],{"class":339},"sa561","index",[167,342,343],{"class":199},"=",[167,345,346],{"class":270},"False",[167,348,238],{"class":203},[167,350,351],{"class":339},"startrow",[167,353,343],{"class":199},[167,355,356],{"class":270},"1",[167,358,359],{"class":203},")\n",[10,361,362,363,366],{},"Note ",[164,364,365],{},"startrow=1",", leaving row 1 free for the threshold cell.",[152,368,370],{"id":369},"step-1-a-fixed-threshold-with-cellisrule","Step 1 — A fixed threshold with CellIsRule",[10,372,373,376],{},[164,374,375],{},"CellIsRule"," covers the common comparisons against a constant:",[157,378,380],{"className":190,"code":379,"language":192,"meta":162,"style":162},"from openpyxl import load_workbook\nfrom openpyxl.formatting.rule import CellIsRule\nfrom openpyxl.styles import PatternFill, Font\n\nwb = load_workbook(\"report.xlsx\")\nws = wb.active\n\nabove = PatternFill(start_color=\"D9F4F1\", end_color=\"D9F4F1\", fill_type=\"solid\")\nabove_font = Font(color=\"0B6157\", bold=True)\n\nws.conditional_formatting.add(\n    \"B3:B7\",\n    CellIsRule(operator=\"greaterThan\", formula=[\"4000\"],\n               fill=above, font=above_font),\n)\n\nwb.save(\"report_formatted.xlsx\")\n",[164,381,382,395,407,419,423,437,447,451,491,522,527,533,542,571,590,595,600],{"__ignoreMap":162},[167,383,384,387,390,392],{"class":169,"line":170},[167,385,386],{"class":199},"from",[167,388,389],{"class":203}," openpyxl ",[167,391,200],{"class":199},[167,393,394],{"class":203}," load_workbook\n",[167,396,397,399,402,404],{"class":169,"line":213},[167,398,386],{"class":199},[167,400,401],{"class":203}," openpyxl.formatting.rule ",[167,403,200],{"class":199},[167,405,406],{"class":203}," CellIsRule\n",[167,408,409,411,414,416],{"class":169,"line":220},[167,410,386],{"class":199},[167,412,413],{"class":203}," openpyxl.styles ",[167,415,200],{"class":199},[167,417,418],{"class":203}," PatternFill, Font\n",[167,420,421],{"class":169,"line":226},[167,422,217],{"emptyLinePlaceholder":216},[167,424,425,428,430,433,435],{"class":169,"line":262},[167,426,427],{"class":203},"wb ",[167,429,343],{"class":199},[167,431,432],{"class":203}," load_workbook(",[167,434,334],{"class":177},[167,436,359],{"class":203},[167,438,439,442,444],{"class":169,"line":296},[167,440,441],{"class":203},"ws ",[167,443,343],{"class":199},[167,445,446],{"class":203}," wb.active\n",[167,448,449],{"class":169,"line":328},[167,450,217],{"emptyLinePlaceholder":216},[167,452,454,457,459,462,465,467,470,472,475,477,479,481,484,486,489],{"class":169,"line":453},8,[167,455,456],{"class":203},"above ",[167,458,343],{"class":199},[167,460,461],{"class":203}," PatternFill(",[167,463,464],{"class":339},"start_color",[167,466,343],{"class":199},[167,468,469],{"class":177},"\"D9F4F1\"",[167,471,238],{"class":203},[167,473,474],{"class":339},"end_color",[167,476,343],{"class":199},[167,478,469],{"class":177},[167,480,238],{"class":203},[167,482,483],{"class":339},"fill_type",[167,485,343],{"class":199},[167,487,488],{"class":177},"\"solid\"",[167,490,359],{"class":203},[167,492,494,497,499,502,505,507,510,512,515,517,520],{"class":169,"line":493},9,[167,495,496],{"class":203},"above_font ",[167,498,343],{"class":199},[167,500,501],{"class":203}," Font(",[167,503,504],{"class":339},"color",[167,506,343],{"class":199},[167,508,509],{"class":177},"\"0B6157\"",[167,511,238],{"class":203},[167,513,514],{"class":339},"bold",[167,516,343],{"class":199},[167,518,519],{"class":270},"True",[167,521,359],{"class":203},[167,523,525],{"class":169,"line":524},10,[167,526,217],{"emptyLinePlaceholder":216},[167,528,530],{"class":169,"line":529},11,[167,531,532],{"class":203},"ws.conditional_formatting.add(\n",[167,534,536,539],{"class":169,"line":535},12,[167,537,538],{"class":177},"    \"B3:B7\"",[167,540,541],{"class":203},",\n",[167,543,545,548,551,553,556,558,561,563,566,569],{"class":169,"line":544},13,[167,546,547],{"class":203},"    CellIsRule(",[167,549,550],{"class":339},"operator",[167,552,343],{"class":199},[167,554,555],{"class":177},"\"greaterThan\"",[167,557,238],{"class":203},[167,559,560],{"class":339},"formula",[167,562,343],{"class":199},[167,564,565],{"class":203},"[",[167,567,568],{"class":177},"\"4000\"",[167,570,259],{"class":203},[167,572,574,577,579,582,585,587],{"class":169,"line":573},14,[167,575,576],{"class":339},"               fill",[167,578,343],{"class":199},[167,580,581],{"class":203},"above, ",[167,583,584],{"class":339},"font",[167,586,343],{"class":199},[167,588,589],{"class":203},"above_font),\n",[167,591,593],{"class":169,"line":592},15,[167,594,359],{"class":203},[167,596,598],{"class":169,"line":597},16,[167,599,217],{"emptyLinePlaceholder":216},[167,601,603,606,609],{"class":169,"line":602},17,[167,604,605],{"class":203},"wb.save(",[167,607,608],{"class":177},"\"report_formatted.xlsx\"",[167,610,359],{"class":203},[10,612,613,614,616,617,621,622,625,626,629,630,633,634,636],{},"Two details trip people up. The ",[164,615,560],{}," argument is a ",[618,619,620],"strong",{},"list of strings",", even for a single number — ",[164,623,624],{},"[\"4000\"]",", not ",[164,627,628],{},"4000",". And the fill must be a solid ",[164,631,632],{},"PatternFill"," with both colours set; a fill with only ",[164,635,464],{}," renders as nothing in some Excel versions.",[10,638,639],{},"The operators available:",[641,642,643,656],"table",{},[644,645,646],"thead",{},[647,648,649,653],"tr",{},[650,651,652],"th",{},"Operator",[650,654,655],{},"Meaning",[657,658,659,670,680,694,709],"tbody",{},[647,660,661,667],{},[662,663,664],"td",{},[164,665,666],{},"greaterThan",[662,668,669],{},"strictly above",[647,671,672,677],{},[662,673,674],{},[164,675,676],{},"greaterThanOrEqual",[662,678,679],{},"at or above",[647,681,682,691],{},[662,683,684,687,688],{},[164,685,686],{},"lessThan"," \u002F ",[164,689,690],{},"lessThanOrEqual",[662,692,693],{},"below \u002F at or below",[647,695,696,704],{},[662,697,698,687,701],{},[164,699,700],{},"between",[164,702,703],{},"notBetween",[662,705,706,707],{},"two values in ",[164,708,560],{},[647,710,711,719],{},[662,712,713,687,716],{},[164,714,715],{},"equal",[164,717,718],{},"notEqual",[662,720,721],{},"exact match",[157,723,725],{"className":190,"code":724,"language":192,"meta":162,"style":162},"ws.conditional_formatting.add(\n    \"B3:B7\",\n    CellIsRule(operator=\"between\", formula=[\"3000\", \"4000\"],\n               fill=PatternFill(\"solid\", start_color=\"FDEFD8\",\n                                end_color=\"FDEFD8\")),\n)\n",[164,726,727,731,737,765,787,799],{"__ignoreMap":162},[167,728,729],{"class":169,"line":170},[167,730,532],{"class":203},[167,732,733,735],{"class":169,"line":213},[167,734,538],{"class":177},[167,736,541],{"class":203},[167,738,739,741,743,745,748,750,752,754,756,759,761,763],{"class":169,"line":220},[167,740,547],{"class":203},[167,742,550],{"class":339},[167,744,343],{"class":199},[167,746,747],{"class":177},"\"between\"",[167,749,238],{"class":203},[167,751,560],{"class":339},[167,753,343],{"class":199},[167,755,565],{"class":203},[167,757,758],{"class":177},"\"3000\"",[167,760,238],{"class":203},[167,762,568],{"class":177},[167,764,259],{"class":203},[167,766,767,769,771,774,776,778,780,782,785],{"class":169,"line":226},[167,768,576],{"class":339},[167,770,343],{"class":199},[167,772,773],{"class":203},"PatternFill(",[167,775,488],{"class":177},[167,777,238],{"class":203},[167,779,464],{"class":339},[167,781,343],{"class":199},[167,783,784],{"class":177},"\"FDEFD8\"",[167,786,541],{"class":203},[167,788,789,792,794,796],{"class":169,"line":262},[167,790,791],{"class":339},"                                end_color",[167,793,343],{"class":199},[167,795,784],{"class":177},[167,797,798],{"class":203},")),\n",[167,800,801],{"class":169,"line":296},[167,802,359],{"class":203},[152,804,806],{"id":805},"step-2-a-threshold-readers-can-change","Step 2 — A threshold readers can change",[10,808,809,810,812,813,816],{},"Hard-coding ",[164,811,628],{}," means regenerating the report whenever somebody wants a different cut-off. ",[164,814,815],{},"FormulaRule"," with an absolute reference lets the threshold live in a cell:",[157,818,820],{"className":190,"code":819,"language":192,"meta":162,"style":162},"from openpyxl import load_workbook\nfrom openpyxl.formatting.rule import FormulaRule\nfrom openpyxl.styles import PatternFill, Font\n\nwb = load_workbook(\"report.xlsx\")\nws = wb.active\n\nws[\"A1\"] = \"Threshold\"\nws[\"B1\"] = 4000\nws[\"B1\"].number_format = \"#,##0.00\"\nws[\"A1\"].font = Font(bold=True)\n\nws.conditional_formatting.add(\n    \"B3:B7\",\n    FormulaRule(\n        formula=[\"AND(B3\u003C>\\\"\\\", B3>$B$1)\"],\n        fill=PatternFill(\"solid\", start_color=\"D9F4F1\", end_color=\"D9F4F1\"),\n        font=Font(color=\"0B6157\", bold=True),\n    ),\n)\n\nwb.save(\"report_dynamic.xlsx\")\n",[164,821,822,832,843,853,857,869,877,881,897,911,925,946,950,954,960,965,986,1016,1043,1049,1054,1059],{"__ignoreMap":162},[167,823,824,826,828,830],{"class":169,"line":170},[167,825,386],{"class":199},[167,827,389],{"class":203},[167,829,200],{"class":199},[167,831,394],{"class":203},[167,833,834,836,838,840],{"class":169,"line":213},[167,835,386],{"class":199},[167,837,401],{"class":203},[167,839,200],{"class":199},[167,841,842],{"class":203}," FormulaRule\n",[167,844,845,847,849,851],{"class":169,"line":220},[167,846,386],{"class":199},[167,848,413],{"class":203},[167,850,200],{"class":199},[167,852,418],{"class":203},[167,854,855],{"class":169,"line":226},[167,856,217],{"emptyLinePlaceholder":216},[167,858,859,861,863,865,867],{"class":169,"line":262},[167,860,427],{"class":203},[167,862,343],{"class":199},[167,864,432],{"class":203},[167,866,334],{"class":177},[167,868,359],{"class":203},[167,870,871,873,875],{"class":169,"line":296},[167,872,441],{"class":203},[167,874,343],{"class":199},[167,876,446],{"class":203},[167,878,879],{"class":169,"line":328},[167,880,217],{"emptyLinePlaceholder":216},[167,882,883,886,889,892,894],{"class":169,"line":453},[167,884,885],{"class":203},"ws[",[167,887,888],{"class":177},"\"A1\"",[167,890,891],{"class":203},"] ",[167,893,343],{"class":199},[167,895,896],{"class":177}," \"Threshold\"\n",[167,898,899,901,904,906,908],{"class":169,"line":493},[167,900,885],{"class":203},[167,902,903],{"class":177},"\"B1\"",[167,905,891],{"class":203},[167,907,343],{"class":199},[167,909,910],{"class":270}," 4000\n",[167,912,913,915,917,920,922],{"class":169,"line":524},[167,914,885],{"class":203},[167,916,903],{"class":177},[167,918,919],{"class":203},"].number_format ",[167,921,343],{"class":199},[167,923,924],{"class":177}," \"#,##0.00\"\n",[167,926,927,929,931,934,936,938,940,942,944],{"class":169,"line":529},[167,928,885],{"class":203},[167,930,888],{"class":177},[167,932,933],{"class":203},"].font ",[167,935,343],{"class":199},[167,937,501],{"class":203},[167,939,514],{"class":339},[167,941,343],{"class":199},[167,943,519],{"class":270},[167,945,359],{"class":203},[167,947,948],{"class":169,"line":535},[167,949,217],{"emptyLinePlaceholder":216},[167,951,952],{"class":169,"line":544},[167,953,532],{"class":203},[167,955,956,958],{"class":169,"line":573},[167,957,538],{"class":177},[167,959,541],{"class":203},[167,961,962],{"class":169,"line":592},[167,963,964],{"class":203},"    FormulaRule(\n",[167,966,967,970,972,974,977,981,984],{"class":169,"line":597},[167,968,969],{"class":339},"        formula",[167,971,343],{"class":199},[167,973,565],{"class":203},[167,975,976],{"class":177},"\"AND(B3\u003C>",[167,978,980],{"class":979},"sSjpA","\\\"\\\"",[167,982,983],{"class":177},", B3>$B$1)\"",[167,985,259],{"class":203},[167,987,988,991,993,995,997,999,1001,1003,1005,1007,1009,1011,1013],{"class":169,"line":602},[167,989,990],{"class":339},"        fill",[167,992,343],{"class":199},[167,994,773],{"class":203},[167,996,488],{"class":177},[167,998,238],{"class":203},[167,1000,464],{"class":339},[167,1002,343],{"class":199},[167,1004,469],{"class":177},[167,1006,238],{"class":203},[167,1008,474],{"class":339},[167,1010,343],{"class":199},[167,1012,469],{"class":177},[167,1014,1015],{"class":203},"),\n",[167,1017,1019,1022,1024,1027,1029,1031,1033,1035,1037,1039,1041],{"class":169,"line":1018},18,[167,1020,1021],{"class":339},"        font",[167,1023,343],{"class":199},[167,1025,1026],{"class":203},"Font(",[167,1028,504],{"class":339},[167,1030,343],{"class":199},[167,1032,509],{"class":177},[167,1034,238],{"class":203},[167,1036,514],{"class":339},[167,1038,343],{"class":199},[167,1040,519],{"class":270},[167,1042,1015],{"class":203},[167,1044,1046],{"class":169,"line":1045},19,[167,1047,1048],{"class":203},"    ),\n",[167,1050,1052],{"class":169,"line":1051},20,[167,1053,359],{"class":203},[167,1055,1057],{"class":169,"line":1056},21,[167,1058,217],{"emptyLinePlaceholder":216},[167,1060,1062,1064,1067],{"class":169,"line":1061},22,[167,1063,605],{"class":203},[167,1065,1066],{"class":177},"\"report_dynamic.xlsx\"",[167,1068,359],{"class":203},[10,1070,1071,1072,1075,1076,1079,1080,1083,1084,1086],{},"The reference style is the whole trick. ",[164,1073,1074],{},"$B$1"," is absolute, so every cell in the range compares against that one threshold cell. ",[164,1077,1078],{},"B3"," is relative and refers to the ",[618,1081,1082],{},"top-left cell of the range"," — Excel slides it down as it evaluates each row, so writing ",[164,1085,1078],{}," gives you \"this row's revenue\".",[10,1088,1089,1090,1093],{},"The ",[164,1091,1092],{},"AND(B3\u003C>\"\", ...)"," guard matters: without it, blank cells compare as zero and the rule fires or does not fire on cells that hold nothing, which looks like a bug to a reader.",[152,1095,1097],{"id":1096},"step-3-highlight-the-whole-row","Step 3 — Highlight the whole row",[10,1099,1100,1101,1105],{},"Tinting one cell tells the reader which value is high; tinting the row tells them which ",[1102,1103,1104],"em",{},"record"," is. The difference is one anchor.",[20,1107,30,1114,30,1117,30,1120,30,1125,30,1131,30,1135,30,1140,30,1145,30,1150,30,1153,30,1157,30,1160,30,1164,30,1167,30,1170,30,1173,30,1176,30,1179,30,1182,30,1187,30,1191,30,1194,30,1197,30,1200],{"viewBox":1108,"role":23,"ariaLabel":1109,"ariaLabelledBy":1110,"xmlns":28,"style":1113},"0 0 800 244","Reference anchoring in a conditional formatting formula: fully relative slides in both directions, fully absolute never moves, and column-anchored slides down rows while always testing one column.",[1111,1112],"anch-t","anch-d","width:100%;max-width:800px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[32,1115,1116],{"id":1111},"Three anchorings, three very different rules",[36,1118,1119],{"id":1112},"Three formula references compared. A fully relative reference such as B3 slides both down and across, so applied to a whole-row range each column tests its own value — rarely what is wanted. A fully absolute reference such as dollar B dollar 3 never moves, so every cell in every row tests the same single cell. A column-anchored reference such as dollar B3 keeps the column fixed while the row slides, which is exactly the behaviour a whole-row highlight needs.",[40,1121],{"x":1122,"y":1122,"width":1123,"height":1124,"fill":45},"0","800","244",[40,1126],{"x":42,"y":77,"width":1127,"height":1128,"rx":42,"fill":1129,"stroke":1130,"style":53},"248","192","#fee8f2","var(--accent,#f43f8f)",[55,1132,1078],{"x":117,"y":1133,"style":1134},"58","font-size:14px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle",[55,1136,1139],{"x":117,"y":1137,"style":1138},"82","font-size:11px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","fully relative",[55,1141,1144],{"x":117,"y":1142,"style":1143},"114","font-size:11px;fill:var(--text,#172033);text-anchor:middle","slides down AND across",[55,1146,1149],{"x":117,"y":1147,"style":1148},"140","font-size:11px;fill:var(--muted,#5b6780);text-anchor:middle","column A tests A3,",[55,1151,1152],{"x":117,"y":87,"style":1148},"column C tests C3",[55,1154,1156],{"x":117,"y":1155,"style":1138},"196","rarely what you want",[40,1158],{"x":1159,"y":77,"width":1127,"height":1128,"rx":42,"fill":51,"stroke":52,"style":53},"276",[55,1161,1163],{"x":147,"y":1133,"style":1162},"font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","$B$3",[55,1165,1166],{"x":147,"y":1137,"style":59},"fully absolute",[55,1168,1169],{"x":147,"y":1142,"style":1143},"never moves at all",[55,1171,1172],{"x":147,"y":1147,"style":1148},"every row tests the",[55,1174,1175],{"x":147,"y":87,"style":1148},"same single cell",[55,1177,1178],{"x":147,"y":1155,"style":59},"right for the threshold cell",[40,1180],{"x":1181,"y":77,"width":1127,"height":1128,"rx":42,"fill":104,"stroke":105,"style":53},"538",[55,1183,1186],{"x":1184,"y":1133,"style":1185},"662","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","$B3",[55,1188,1190],{"x":1184,"y":1137,"style":1189},"font-size:11px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","column anchored",[55,1192,1193],{"x":1184,"y":1142,"style":1143},"slides down, not across",[55,1195,1196],{"x":1184,"y":1147,"style":1148},"every column in a row",[55,1198,1199],{"x":1184,"y":87,"style":1148},"tests that row's B",[55,1201,1202],{"x":1184,"y":1155,"style":1189},"right for whole-row highlighting",[157,1204,1206],{"className":190,"code":1205,"language":192,"meta":162,"style":162},"from openpyxl import load_workbook\nfrom openpyxl.formatting.rule import FormulaRule\nfrom openpyxl.styles import PatternFill\n\nwb = load_workbook(\"report.xlsx\")\nws = wb.active\nws[\"A1\"], ws[\"B1\"] = \"Threshold\", 4000\n\n# Apply across every column of the data, testing column B in each row.\nws.conditional_formatting.add(\n    \"A3:C7\",\n    FormulaRule(\n        formula=['AND($B3\u003C>\"\", $B3>$B$1)'],\n        fill=PatternFill(\"solid\", start_color=\"D9F4F1\", end_color=\"D9F4F1\"),\n    ),\n)\n\nwb.save(\"report_rows.xlsx\")\n",[164,1207,1208,1218,1228,1239,1243,1255,1263,1286,1290,1296,1300,1307,1311,1324,1352,1356,1360,1364],{"__ignoreMap":162},[167,1209,1210,1212,1214,1216],{"class":169,"line":170},[167,1211,386],{"class":199},[167,1213,389],{"class":203},[167,1215,200],{"class":199},[167,1217,394],{"class":203},[167,1219,1220,1222,1224,1226],{"class":169,"line":213},[167,1221,386],{"class":199},[167,1223,401],{"class":203},[167,1225,200],{"class":199},[167,1227,842],{"class":203},[167,1229,1230,1232,1234,1236],{"class":169,"line":220},[167,1231,386],{"class":199},[167,1233,413],{"class":203},[167,1235,200],{"class":199},[167,1237,1238],{"class":203}," PatternFill\n",[167,1240,1241],{"class":169,"line":226},[167,1242,217],{"emptyLinePlaceholder":216},[167,1244,1245,1247,1249,1251,1253],{"class":169,"line":262},[167,1246,427],{"class":203},[167,1248,343],{"class":199},[167,1250,432],{"class":203},[167,1252,334],{"class":177},[167,1254,359],{"class":203},[167,1256,1257,1259,1261],{"class":169,"line":296},[167,1258,441],{"class":203},[167,1260,343],{"class":199},[167,1262,446],{"class":203},[167,1264,1265,1267,1269,1272,1274,1276,1278,1281,1283],{"class":169,"line":328},[167,1266,885],{"class":203},[167,1268,888],{"class":177},[167,1270,1271],{"class":203},"], ws[",[167,1273,903],{"class":177},[167,1275,891],{"class":203},[167,1277,343],{"class":199},[167,1279,1280],{"class":177}," \"Threshold\"",[167,1282,238],{"class":203},[167,1284,1285],{"class":270},"4000\n",[167,1287,1288],{"class":169,"line":453},[167,1289,217],{"emptyLinePlaceholder":216},[167,1291,1292],{"class":169,"line":493},[167,1293,1295],{"class":1294},"s-wDw","# Apply across every column of the data, testing column B in each row.\n",[167,1297,1298],{"class":169,"line":524},[167,1299,532],{"class":203},[167,1301,1302,1305],{"class":169,"line":529},[167,1303,1304],{"class":177},"    \"A3:C7\"",[167,1306,541],{"class":203},[167,1308,1309],{"class":169,"line":535},[167,1310,964],{"class":203},[167,1312,1313,1315,1317,1319,1322],{"class":169,"line":544},[167,1314,969],{"class":339},[167,1316,343],{"class":199},[167,1318,565],{"class":203},[167,1320,1321],{"class":177},"'AND($B3\u003C>\"\", $B3>$B$1)'",[167,1323,259],{"class":203},[167,1325,1326,1328,1330,1332,1334,1336,1338,1340,1342,1344,1346,1348,1350],{"class":169,"line":573},[167,1327,990],{"class":339},[167,1329,343],{"class":199},[167,1331,773],{"class":203},[167,1333,488],{"class":177},[167,1335,238],{"class":203},[167,1337,464],{"class":339},[167,1339,343],{"class":199},[167,1341,469],{"class":177},[167,1343,238],{"class":203},[167,1345,474],{"class":339},[167,1347,343],{"class":199},[167,1349,469],{"class":177},[167,1351,1015],{"class":203},[167,1353,1354],{"class":169,"line":592},[167,1355,1048],{"class":203},[167,1357,1358],{"class":169,"line":597},[167,1359,359],{"class":203},[167,1361,1362],{"class":169,"line":602},[167,1363,217],{"emptyLinePlaceholder":216},[167,1365,1366,1368,1371],{"class":169,"line":1018},[167,1367,605],{"class":203},[167,1369,1370],{"class":177},"\"report_rows.xlsx\"",[167,1372,359],{"class":203},[10,1374,1375,1377],{},[164,1376,1186],{}," — column anchored, row relative — is the pattern to remember. It is the single most useful reference form in conditional formatting, and getting it wrong is why a whole-row rule so often highlights a diagonal.",[10,1379,1380,1381,1384],{},"Comparing against another ",[1102,1382,1383],{},"column"," rather than a fixed cell is the same shape, and is often more useful than an absolute threshold:",[157,1386,1388],{"className":190,"code":1387,"language":192,"meta":162,"style":162},"# Highlight rows where revenue beat the row's own target.\nws.conditional_formatting.add(\n    \"A3:C7\",\n    FormulaRule(formula=[\"$B3>$C3\"],\n                fill=PatternFill(\"solid\", start_color=\"D9F4F1\",\n                                 end_color=\"D9F4F1\")),\n)\n",[164,1389,1390,1395,1399,1405,1421,1442,1453],{"__ignoreMap":162},[167,1391,1392],{"class":169,"line":170},[167,1393,1394],{"class":1294},"# Highlight rows where revenue beat the row's own target.\n",[167,1396,1397],{"class":169,"line":213},[167,1398,532],{"class":203},[167,1400,1401,1403],{"class":169,"line":220},[167,1402,1304],{"class":177},[167,1404,541],{"class":203},[167,1406,1407,1410,1412,1414,1416,1419],{"class":169,"line":226},[167,1408,1409],{"class":203},"    FormulaRule(",[167,1411,560],{"class":339},[167,1413,343],{"class":199},[167,1415,565],{"class":203},[167,1417,1418],{"class":177},"\"$B3>$C3\"",[167,1420,259],{"class":203},[167,1422,1423,1426,1428,1430,1432,1434,1436,1438,1440],{"class":169,"line":262},[167,1424,1425],{"class":339},"                fill",[167,1427,343],{"class":199},[167,1429,773],{"class":203},[167,1431,488],{"class":177},[167,1433,238],{"class":203},[167,1435,464],{"class":339},[167,1437,343],{"class":199},[167,1439,469],{"class":177},[167,1441,541],{"class":203},[167,1443,1444,1447,1449,1451],{"class":169,"line":296},[167,1445,1446],{"class":339},"                                 end_color",[167,1448,343],{"class":199},[167,1450,469],{"class":177},[167,1452,798],{"class":203},[167,1454,1455],{"class":169,"line":328},[167,1456,359],{"class":203},[152,1458,1460],{"id":1459},"step-4-order-overlapping-rules","Step 4 — Order overlapping rules",[10,1462,1463],{},"Rules are evaluated in the order they were added, and several can apply to one cell — their formats merge, which produces muddled results when they conflict. Add the most specific first and stop evaluation:",[157,1465,1467],{"className":190,"code":1466,"language":192,"meta":162,"style":162},"from openpyxl.formatting.rule import CellIsRule\nfrom openpyxl.styles import PatternFill\n\nRED = PatternFill(\"solid\", start_color=\"FEE8F2\", end_color=\"FEE8F2\")\nAMBER = PatternFill(\"solid\", start_color=\"FDEFD8\", end_color=\"FDEFD8\")\nGREEN = PatternFill(\"solid\", start_color=\"D9F4F1\", end_color=\"D9F4F1\")\n\ncritical = CellIsRule(operator=\"greaterThan\", formula=[\"6000\"], fill=RED)\ncritical.stopIfTrue = True\nws.conditional_formatting.add(\"B3:B7\", critical)\n\nwarn = CellIsRule(operator=\"greaterThan\", formula=[\"4000\"], fill=AMBER)\nwarn.stopIfTrue = True\nws.conditional_formatting.add(\"B3:B7\", warn)\n\nws.conditional_formatting.add(\n    \"B3:B7\", CellIsRule(operator=\"lessThanOrEqual\", formula=[\"4000\"], fill=GREEN)\n)\n",[164,1468,1469,1479,1489,1493,1524,1553,1582,1586,1625,1635,1646,1650,1685,1694,1703,1707,1711,1745],{"__ignoreMap":162},[167,1470,1471,1473,1475,1477],{"class":169,"line":170},[167,1472,386],{"class":199},[167,1474,401],{"class":203},[167,1476,200],{"class":199},[167,1478,406],{"class":203},[167,1480,1481,1483,1485,1487],{"class":169,"line":213},[167,1482,386],{"class":199},[167,1484,413],{"class":203},[167,1486,200],{"class":199},[167,1488,1238],{"class":203},[167,1490,1491],{"class":169,"line":220},[167,1492,217],{"emptyLinePlaceholder":216},[167,1494,1495,1498,1501,1503,1505,1507,1509,1511,1514,1516,1518,1520,1522],{"class":169,"line":226},[167,1496,1497],{"class":270},"RED",[167,1499,1500],{"class":199}," =",[167,1502,461],{"class":203},[167,1504,488],{"class":177},[167,1506,238],{"class":203},[167,1508,464],{"class":339},[167,1510,343],{"class":199},[167,1512,1513],{"class":177},"\"FEE8F2\"",[167,1515,238],{"class":203},[167,1517,474],{"class":339},[167,1519,343],{"class":199},[167,1521,1513],{"class":177},[167,1523,359],{"class":203},[167,1525,1526,1529,1531,1533,1535,1537,1539,1541,1543,1545,1547,1549,1551],{"class":169,"line":262},[167,1527,1528],{"class":270},"AMBER",[167,1530,1500],{"class":199},[167,1532,461],{"class":203},[167,1534,488],{"class":177},[167,1536,238],{"class":203},[167,1538,464],{"class":339},[167,1540,343],{"class":199},[167,1542,784],{"class":177},[167,1544,238],{"class":203},[167,1546,474],{"class":339},[167,1548,343],{"class":199},[167,1550,784],{"class":177},[167,1552,359],{"class":203},[167,1554,1555,1558,1560,1562,1564,1566,1568,1570,1572,1574,1576,1578,1580],{"class":169,"line":296},[167,1556,1557],{"class":270},"GREEN",[167,1559,1500],{"class":199},[167,1561,461],{"class":203},[167,1563,488],{"class":177},[167,1565,238],{"class":203},[167,1567,464],{"class":339},[167,1569,343],{"class":199},[167,1571,469],{"class":177},[167,1573,238],{"class":203},[167,1575,474],{"class":339},[167,1577,343],{"class":199},[167,1579,469],{"class":177},[167,1581,359],{"class":203},[167,1583,1584],{"class":169,"line":328},[167,1585,217],{"emptyLinePlaceholder":216},[167,1587,1588,1591,1593,1596,1598,1600,1602,1604,1606,1608,1610,1613,1616,1619,1621,1623],{"class":169,"line":453},[167,1589,1590],{"class":203},"critical ",[167,1592,343],{"class":199},[167,1594,1595],{"class":203}," CellIsRule(",[167,1597,550],{"class":339},[167,1599,343],{"class":199},[167,1601,555],{"class":177},[167,1603,238],{"class":203},[167,1605,560],{"class":339},[167,1607,343],{"class":199},[167,1609,565],{"class":203},[167,1611,1612],{"class":177},"\"6000\"",[167,1614,1615],{"class":203},"], ",[167,1617,1618],{"class":339},"fill",[167,1620,343],{"class":199},[167,1622,1497],{"class":270},[167,1624,359],{"class":203},[167,1626,1627,1630,1632],{"class":169,"line":493},[167,1628,1629],{"class":203},"critical.stopIfTrue ",[167,1631,343],{"class":199},[167,1633,1634],{"class":270}," True\n",[167,1636,1637,1640,1643],{"class":169,"line":524},[167,1638,1639],{"class":203},"ws.conditional_formatting.add(",[167,1641,1642],{"class":177},"\"B3:B7\"",[167,1644,1645],{"class":203},", critical)\n",[167,1647,1648],{"class":169,"line":529},[167,1649,217],{"emptyLinePlaceholder":216},[167,1651,1652,1655,1657,1659,1661,1663,1665,1667,1669,1671,1673,1675,1677,1679,1681,1683],{"class":169,"line":535},[167,1653,1654],{"class":203},"warn ",[167,1656,343],{"class":199},[167,1658,1595],{"class":203},[167,1660,550],{"class":339},[167,1662,343],{"class":199},[167,1664,555],{"class":177},[167,1666,238],{"class":203},[167,1668,560],{"class":339},[167,1670,343],{"class":199},[167,1672,565],{"class":203},[167,1674,568],{"class":177},[167,1676,1615],{"class":203},[167,1678,1618],{"class":339},[167,1680,343],{"class":199},[167,1682,1528],{"class":270},[167,1684,359],{"class":203},[167,1686,1687,1690,1692],{"class":169,"line":544},[167,1688,1689],{"class":203},"warn.stopIfTrue ",[167,1691,343],{"class":199},[167,1693,1634],{"class":270},[167,1695,1696,1698,1700],{"class":169,"line":573},[167,1697,1639],{"class":203},[167,1699,1642],{"class":177},[167,1701,1702],{"class":203},", warn)\n",[167,1704,1705],{"class":169,"line":592},[167,1706,217],{"emptyLinePlaceholder":216},[167,1708,1709],{"class":169,"line":597},[167,1710,532],{"class":203},[167,1712,1713,1715,1718,1720,1722,1725,1727,1729,1731,1733,1735,1737,1739,1741,1743],{"class":169,"line":602},[167,1714,538],{"class":177},[167,1716,1717],{"class":203},", CellIsRule(",[167,1719,550],{"class":339},[167,1721,343],{"class":199},[167,1723,1724],{"class":177},"\"lessThanOrEqual\"",[167,1726,238],{"class":203},[167,1728,560],{"class":339},[167,1730,343],{"class":199},[167,1732,565],{"class":203},[167,1734,568],{"class":177},[167,1736,1615],{"class":203},[167,1738,1618],{"class":339},[167,1740,343],{"class":199},[167,1742,1557],{"class":270},[167,1744,359],{"class":203},[167,1746,1747],{"class":169,"line":1018},[167,1748,359],{"class":203},[10,1750,1751,1752,1755,1756,18],{},"Without ",[164,1753,1754],{},"stopIfTrue",", a value of 6,500 matches both the critical and the warning rule, and Excel merges the two formats — usually giving you the first rule's fill with the second's font, which is neither. The banding is covered further in ",[14,1757,1759],{"href":1758},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fadd-data-bars-and-colour-scales-with-openpyxl\u002F","adding data bars and colour scales with openpyxl",[152,1761,1763],{"id":1762},"step-5-apply-it-after-a-pandas-write","Step 5 — Apply it after a pandas write",[20,1765,30,1771,30,1774,30,1777,30,1780,30,1786,30,1791,30,1796,30,1800,30,1805,30,1812,30,1818,30,1822,30,1826,30,1830,30,1833,30,1837,30,1841,30,1845,30,1849,30,1853,30,1856,30,1860,30,1864],{"viewBox":1766,"role":23,"ariaLabel":1767,"ariaLabelledBy":1768,"xmlns":28,"style":1113},"0 0 800 226","Rule evaluation order: the most specific rule is added first and stops evaluation, so a value matching two rules gets one clean format rather than a merge of both.",[1769,1770],"prio-t","prio-d",[32,1772,1773],{"id":1769},"Why the most specific rule must be added first",[36,1775,1776],{"id":1770},"A value of six thousand five hundred is tested against three rules in the order they were added. The critical rule, above six thousand, matches first and because stopIfTrue is set no further rules are evaluated, so the cell gets the red format alone. Without stopIfTrue the warning rule would also match and Excel would merge the two formats, typically taking the fill from one and the font from the other.",[40,1778],{"x":1122,"y":1122,"width":1123,"height":1779,"fill":45},"226",[40,1781],{"x":42,"y":1782,"width":1147,"height":1783,"rx":1784,"fill":1785,"stroke":96,"style":53},"88","60","12","#f0f2f5",[55,1787,1790],{"x":1788,"y":1142,"style":1789},"84","font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","value 6,500",[55,1792,1795],{"x":1788,"y":1793,"style":1794},"134","font-size:10px;fill:var(--muted,#5b6780);text-anchor:middle","matches two rules",[169,1797],{"x1":1798,"y1":1799,"x2":134,"y2":1799,"stroke":79,"style":53},"154","118",[1801,1802],"polygon",{"points":1803,"fill":1804},"194,118 182,112 182,124","#5b5cf0",[40,1806],{"x":1807,"y":1808,"width":1809,"height":1810,"rx":1811,"fill":1129,"stroke":1130,"style":53},"202","34","252","52","11",[55,1813,1817],{"x":1814,"y":1815,"style":1816},"328","56","font-size:11.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","1 · above 6,000 · stopIfTrue",[55,1819,1821],{"x":1814,"y":1820,"style":1794},"75","matches — evaluation ends here",[40,1823],{"x":1807,"y":1824,"width":1809,"height":1825,"rx":1811,"fill":1785,"stroke":96},"96","44",[55,1827,1829],{"x":1814,"y":1828,"style":1148},"123","2 · above 4,000 — never reached",[40,1831],{"x":1807,"y":1832,"width":1809,"height":1825,"rx":1811,"fill":1785,"stroke":96},"150",[55,1834,1836],{"x":1814,"y":1835,"style":1148},"177","3 · 4,000 or below — never reached",[169,1838],{"x1":1839,"y1":1783,"x2":1840,"y2":1783,"stroke":1130,"style":53},"454","490",[1801,1842],{"points":1843,"fill":1844},"498,60 486,54 486,66","#f43f8f",[40,1846],{"x":1847,"y":1808,"width":1848,"height":1810,"rx":1811,"fill":1129,"stroke":1130,"style":53},"506","278",[55,1850,1852],{"x":1851,"y":1815,"style":1816},"645","one clean format",[55,1854,1855],{"x":1851,"y":1820,"style":1794},"red fill, red bold font",[40,1857],{"x":1847,"y":1858,"width":1848,"height":1859,"rx":1811,"fill":51,"stroke":52,"style":53},"132","62",[55,1861,1863],{"x":1851,"y":120,"style":1862},"font-size:11.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","without stopIfTrue",[55,1865,1867],{"x":1851,"y":1866,"style":1794},"176","rules 1 and 2 both match and merge",[10,1869,1870,1873],{},[164,1871,1872],{},"to_excel"," replaces the sheet, so conditional formatting applied first is discarded. Either format after writing with openpyxl, or add the rule through the xlsxwriter engine while the writer is open:",[157,1875,1877],{"className":190,"code":1876,"language":192,"meta":162,"style":162},"import pandas as pd\n\ndf = pd.DataFrame({\n    \"region\": [\"North\", \"South\", \"West\", \"East\", \"Central\"],\n    \"revenue\": [5150.00, 4268.50, 3511.25, 2980.10, 6402.75],\n})\n\nwith pd.ExcelWriter(\"report.xlsx\", engine=\"xlsxwriter\") as writer:\n    df.to_excel(writer, sheet_name=\"Report\", index=False, startrow=1)\n    book, sheet = writer.book, writer.sheets[\"Report\"]\n\n    sheet.write(0, 0, \"Threshold\")\n    sheet.write_number(0, 1, 4000, book.add_format({\"num_format\": \"#,##0.00\"}))\n\n    high = book.add_format({\"bg_color\": \"#D9F4F1\", \"font_color\": \"#0B6157\",\n                            \"bold\": True})\n    sheet.conditional_format(\n        2, 1, len(df) + 1, 1,\n        {\"type\": \"formula\", \"criteria\": '=AND($B3\u003C>\"\", $B3>$B$1)',\n         \"format\": high},\n    )\n    sheet.set_column(\"A:A\", 14)\n    sheet.set_column(\"B:B\", 14,\n                     book.add_format({\"num_format\": \"#,##0.00\"}))\n",[164,1878,1879,1889,1893,1903,1929,1955,1960,1964,1992,2023,2038,2042,2060,2090,2094,2124,2135,2140,2169,2194,2202,2207,2221,2235],{"__ignoreMap":162},[167,1880,1881,1883,1885,1887],{"class":169,"line":170},[167,1882,200],{"class":199},[167,1884,204],{"class":203},[167,1886,207],{"class":199},[167,1888,210],{"class":203},[167,1890,1891],{"class":169,"line":213},[167,1892,217],{"emptyLinePlaceholder":216},[167,1894,1895,1898,1900],{"class":169,"line":220},[167,1896,1897],{"class":203},"df ",[167,1899,343],{"class":199},[167,1901,1902],{"class":203}," pd.DataFrame({\n",[167,1904,1905,1907,1909,1911,1913,1915,1917,1919,1921,1923,1925,1927],{"class":169,"line":226},[167,1906,229],{"class":177},[167,1908,232],{"class":203},[167,1910,235],{"class":177},[167,1912,238],{"class":203},[167,1914,241],{"class":177},[167,1916,238],{"class":203},[167,1918,246],{"class":177},[167,1920,238],{"class":203},[167,1922,251],{"class":177},[167,1924,238],{"class":203},[167,1926,256],{"class":177},[167,1928,259],{"class":203},[167,1930,1931,1933,1935,1937,1939,1941,1943,1945,1947,1949,1951,1953],{"class":169,"line":262},[167,1932,265],{"class":177},[167,1934,232],{"class":203},[167,1936,271],{"class":270},[167,1938,238],{"class":203},[167,1940,276],{"class":270},[167,1942,238],{"class":203},[167,1944,281],{"class":270},[167,1946,238],{"class":203},[167,1948,286],{"class":270},[167,1950,238],{"class":203},[167,1952,291],{"class":270},[167,1954,259],{"class":203},[167,1956,1957],{"class":169,"line":296},[167,1958,1959],{"class":203},"})\n",[167,1961,1962],{"class":169,"line":328},[167,1963,217],{"emptyLinePlaceholder":216},[167,1965,1966,1969,1972,1974,1976,1979,1981,1984,1987,1989],{"class":169,"line":453},[167,1967,1968],{"class":199},"with",[167,1970,1971],{"class":203}," pd.ExcelWriter(",[167,1973,334],{"class":177},[167,1975,238],{"class":203},[167,1977,1978],{"class":339},"engine",[167,1980,343],{"class":199},[167,1982,1983],{"class":177},"\"xlsxwriter\"",[167,1985,1986],{"class":203},") ",[167,1988,207],{"class":199},[167,1990,1991],{"class":203}," writer:\n",[167,1993,1994,1997,2000,2002,2005,2007,2009,2011,2013,2015,2017,2019,2021],{"class":169,"line":493},[167,1995,1996],{"class":203},"    df.to_excel(writer, ",[167,1998,1999],{"class":339},"sheet_name",[167,2001,343],{"class":199},[167,2003,2004],{"class":177},"\"Report\"",[167,2006,238],{"class":203},[167,2008,340],{"class":339},[167,2010,343],{"class":199},[167,2012,346],{"class":270},[167,2014,238],{"class":203},[167,2016,351],{"class":339},[167,2018,343],{"class":199},[167,2020,356],{"class":270},[167,2022,359],{"class":203},[167,2024,2025,2028,2030,2033,2035],{"class":169,"line":524},[167,2026,2027],{"class":203},"    book, sheet ",[167,2029,343],{"class":199},[167,2031,2032],{"class":203}," writer.book, writer.sheets[",[167,2034,2004],{"class":177},[167,2036,2037],{"class":203},"]\n",[167,2039,2040],{"class":169,"line":529},[167,2041,217],{"emptyLinePlaceholder":216},[167,2043,2044,2047,2049,2051,2053,2055,2058],{"class":169,"line":535},[167,2045,2046],{"class":203},"    sheet.write(",[167,2048,1122],{"class":270},[167,2050,238],{"class":203},[167,2052,1122],{"class":270},[167,2054,238],{"class":203},[167,2056,2057],{"class":177},"\"Threshold\"",[167,2059,359],{"class":203},[167,2061,2062,2065,2067,2069,2071,2073,2075,2078,2081,2084,2087],{"class":169,"line":544},[167,2063,2064],{"class":203},"    sheet.write_number(",[167,2066,1122],{"class":270},[167,2068,238],{"class":203},[167,2070,356],{"class":270},[167,2072,238],{"class":203},[167,2074,628],{"class":270},[167,2076,2077],{"class":203},", book.add_format({",[167,2079,2080],{"class":177},"\"num_format\"",[167,2082,2083],{"class":203},": ",[167,2085,2086],{"class":177},"\"#,##0.00\"",[167,2088,2089],{"class":203},"}))\n",[167,2091,2092],{"class":169,"line":573},[167,2093,217],{"emptyLinePlaceholder":216},[167,2095,2096,2099,2101,2104,2107,2109,2112,2114,2117,2119,2122],{"class":169,"line":592},[167,2097,2098],{"class":203},"    high ",[167,2100,343],{"class":199},[167,2102,2103],{"class":203}," book.add_format({",[167,2105,2106],{"class":177},"\"bg_color\"",[167,2108,2083],{"class":203},[167,2110,2111],{"class":177},"\"#D9F4F1\"",[167,2113,238],{"class":203},[167,2115,2116],{"class":177},"\"font_color\"",[167,2118,2083],{"class":203},[167,2120,2121],{"class":177},"\"#0B6157\"",[167,2123,541],{"class":203},[167,2125,2126,2129,2131,2133],{"class":169,"line":597},[167,2127,2128],{"class":177},"                            \"bold\"",[167,2130,2083],{"class":203},[167,2132,519],{"class":270},[167,2134,1959],{"class":203},[167,2136,2137],{"class":169,"line":602},[167,2138,2139],{"class":203},"    sheet.conditional_format(\n",[167,2141,2142,2145,2147,2149,2151,2154,2157,2160,2163,2165,2167],{"class":169,"line":1018},[167,2143,2144],{"class":270},"        2",[167,2146,238],{"class":203},[167,2148,356],{"class":270},[167,2150,238],{"class":203},[167,2152,2153],{"class":270},"len",[167,2155,2156],{"class":203},"(df) ",[167,2158,2159],{"class":199},"+",[167,2161,2162],{"class":270}," 1",[167,2164,238],{"class":203},[167,2166,356],{"class":270},[167,2168,541],{"class":203},[167,2170,2171,2174,2177,2179,2182,2184,2187,2189,2192],{"class":169,"line":1045},[167,2172,2173],{"class":203},"        {",[167,2175,2176],{"class":177},"\"type\"",[167,2178,2083],{"class":203},[167,2180,2181],{"class":177},"\"formula\"",[167,2183,238],{"class":203},[167,2185,2186],{"class":177},"\"criteria\"",[167,2188,2083],{"class":203},[167,2190,2191],{"class":177},"'=AND($B3\u003C>\"\", $B3>$B$1)'",[167,2193,541],{"class":203},[167,2195,2196,2199],{"class":169,"line":1051},[167,2197,2198],{"class":177},"         \"format\"",[167,2200,2201],{"class":203},": high},\n",[167,2203,2204],{"class":169,"line":1056},[167,2205,2206],{"class":203},"    )\n",[167,2208,2209,2212,2215,2217,2219],{"class":169,"line":1061},[167,2210,2211],{"class":203},"    sheet.set_column(",[167,2213,2214],{"class":177},"\"A:A\"",[167,2216,238],{"class":203},[167,2218,42],{"class":270},[167,2220,359],{"class":203},[167,2222,2224,2226,2229,2231,2233],{"class":169,"line":2223},23,[167,2225,2211],{"class":203},[167,2227,2228],{"class":177},"\"B:B\"",[167,2230,238],{"class":203},[167,2232,42],{"class":270},[167,2234,541],{"class":203},[167,2236,2238,2241,2243,2245,2247],{"class":169,"line":2237},24,[167,2239,2240],{"class":203},"                     book.add_format({",[167,2242,2080],{"class":177},[167,2244,2083],{"class":203},[167,2246,2086],{"class":177},[167,2248,2089],{"class":203},[10,2250,2251,2252,2255],{},"xlsxwriter's ",[164,2253,2254],{},"conditional_format"," takes zero-based row and column bounds, where openpyxl takes an A1 range string — an easy source of off-by-one errors when porting between the two.",[152,2257,2259],{"id":2258},"common-pitfalls-and-fixes","Common pitfalls and fixes",[641,2261,2262,2275],{},[644,2263,2264],{},[647,2265,2266,2269,2272],{},[650,2267,2268],{},"Symptom",[650,2270,2271],{},"Cause",[650,2273,2274],{},"Fix",[657,2276,2277,2295,2308,2321,2332,2347,2361,2374],{},[647,2278,2279,2285,2290],{},[662,2280,2281,2284],{},[164,2282,2283],{},"TypeError"," on the rule",[662,2286,2287,2289],{},[164,2288,560],{}," given as a number",[662,2291,2292,2293,18],{},"Pass a list of strings: ",[164,2294,624],{},[647,2296,2297,2300,2305],{},[662,2298,2299],{},"Rule added but nothing highlights",[662,2301,2302,2303],{},"Fill missing ",[164,2304,474],{},[662,2306,2307],{},"Use a solid fill with both colours set.",[647,2309,2310,2313,2316],{},[662,2311,2312],{},"Whole-row rule highlights a diagonal",[662,2314,2315],{},"Fully relative reference",[662,2317,2318,2319,18],{},"Anchor the column: ",[164,2320,1186],{},[647,2322,2323,2326,2329],{},[662,2324,2325],{},"Every row highlights identically",[662,2327,2328],{},"Fully absolute reference",[662,2330,2331],{},"Leave the row relative.",[647,2333,2334,2337,2340],{},[662,2335,2336],{},"Blank cells highlighted",[662,2338,2339],{},"Blanks compare as zero",[662,2341,2342,2343,2346],{},"Add an ",[164,2344,2345],{},"AND(cell\u003C>\"\", ...)"," guard.",[647,2348,2349,2352,2355],{},[662,2350,2351],{},"Two rules produce a muddled format",[662,2353,2354],{},"Both matched and merged",[662,2356,2357,2358,2360],{},"Set ",[164,2359,1754],{}," on the more specific rule.",[647,2362,2363,2366,2371],{},[662,2364,2365],{},"Formatting gone after the job runs",[662,2367,2368,2370],{},[164,2369,1872],{}," replaced the sheet",[662,2372,2373],{},"Apply the rules after writing.",[647,2375,2376,2379,2382],{},[662,2377,2378],{},"Off-by-one in the range",[662,2380,2381],{},"xlsxwriter is zero-based, openpyxl is A1",[662,2383,2384],{},"Check which API you are using.",[152,2386,2388],{"id":2387},"performance-and-scale-notes","Performance and scale notes",[10,2390,2391],{},"A conditional format is a single rule object covering a range, so it costs the same whether the range is ten rows or a hundred thousand — unlike per-cell fills, which create a style entry each and can approach Excel's ceiling of roughly 64,000 distinct formats.",[10,2393,2394],{},"That makes the comparison stark:",[157,2396,2398],{"className":190,"code":2397,"language":192,"meta":162,"style":162},"from openpyxl.styles import PatternFill\n\n# Expensive: one style per cell, and it goes stale on the first edit.\ntint = PatternFill(\"solid\", start_color=\"D9F4F1\", end_color=\"D9F4F1\")\nfor (cell,) in ws.iter_rows(min_row=3, max_row=100_003, min_col=2, max_col=2):\n    if cell.value and cell.value > 4000:\n        cell.fill = tint\n\n# Cheap: one rule object, and it stays live.\nws.conditional_formatting.add(\n    \"B3:B100003\",\n    CellIsRule(operator=\"greaterThan\", formula=[\"4000\"], fill=tint),\n)\n",[164,2399,2400,2410,2414,2419,2448,2502,2524,2534,2538,2543,2547,2554,2583],{"__ignoreMap":162},[167,2401,2402,2404,2406,2408],{"class":169,"line":170},[167,2403,386],{"class":199},[167,2405,413],{"class":203},[167,2407,200],{"class":199},[167,2409,1238],{"class":203},[167,2411,2412],{"class":169,"line":213},[167,2413,217],{"emptyLinePlaceholder":216},[167,2415,2416],{"class":169,"line":220},[167,2417,2418],{"class":1294},"# Expensive: one style per cell, and it goes stale on the first edit.\n",[167,2420,2421,2424,2426,2428,2430,2432,2434,2436,2438,2440,2442,2444,2446],{"class":169,"line":226},[167,2422,2423],{"class":203},"tint ",[167,2425,343],{"class":199},[167,2427,461],{"class":203},[167,2429,488],{"class":177},[167,2431,238],{"class":203},[167,2433,464],{"class":339},[167,2435,343],{"class":199},[167,2437,469],{"class":177},[167,2439,238],{"class":203},[167,2441,474],{"class":339},[167,2443,343],{"class":199},[167,2445,469],{"class":177},[167,2447,359],{"class":203},[167,2449,2450,2453,2456,2459,2462,2465,2467,2470,2472,2475,2477,2480,2482,2485,2487,2490,2492,2495,2497,2499],{"class":169,"line":262},[167,2451,2452],{"class":199},"for",[167,2454,2455],{"class":203}," (cell,) ",[167,2457,2458],{"class":199},"in",[167,2460,2461],{"class":203}," ws.iter_rows(",[167,2463,2464],{"class":339},"min_row",[167,2466,343],{"class":199},[167,2468,2469],{"class":270},"3",[167,2471,238],{"class":203},[167,2473,2474],{"class":339},"max_row",[167,2476,343],{"class":199},[167,2478,2479],{"class":270},"100_003",[167,2481,238],{"class":203},[167,2483,2484],{"class":339},"min_col",[167,2486,343],{"class":199},[167,2488,2489],{"class":270},"2",[167,2491,238],{"class":203},[167,2493,2494],{"class":339},"max_col",[167,2496,343],{"class":199},[167,2498,2489],{"class":270},[167,2500,2501],{"class":203},"):\n",[167,2503,2504,2507,2510,2513,2515,2518,2521],{"class":169,"line":296},[167,2505,2506],{"class":199},"    if",[167,2508,2509],{"class":203}," cell.value ",[167,2511,2512],{"class":199},"and",[167,2514,2509],{"class":203},[167,2516,2517],{"class":199},">",[167,2519,2520],{"class":270}," 4000",[167,2522,2523],{"class":203},":\n",[167,2525,2526,2529,2531],{"class":169,"line":328},[167,2527,2528],{"class":203},"        cell.fill ",[167,2530,343],{"class":199},[167,2532,2533],{"class":203}," tint\n",[167,2535,2536],{"class":169,"line":453},[167,2537,217],{"emptyLinePlaceholder":216},[167,2539,2540],{"class":169,"line":493},[167,2541,2542],{"class":1294},"# Cheap: one rule object, and it stays live.\n",[167,2544,2545],{"class":169,"line":524},[167,2546,532],{"class":203},[167,2548,2549,2552],{"class":169,"line":529},[167,2550,2551],{"class":177},"    \"B3:B100003\"",[167,2553,541],{"class":203},[167,2555,2556,2558,2560,2562,2564,2566,2568,2570,2572,2574,2576,2578,2580],{"class":169,"line":535},[167,2557,547],{"class":203},[167,2559,550],{"class":339},[167,2561,343],{"class":199},[167,2563,555],{"class":177},[167,2565,238],{"class":203},[167,2567,560],{"class":339},[167,2569,343],{"class":199},[167,2571,565],{"class":203},[167,2573,568],{"class":177},[167,2575,1615],{"class":203},[167,2577,1618],{"class":339},[167,2579,343],{"class":199},[167,2581,2582],{"class":203},"tint),\n",[167,2584,2585],{"class":169,"line":544},[167,2586,359],{"class":203},[10,2588,2589,2590,2593,2594,2083,2597,238,2600,238,2603,2606,2607,2610],{},"Two further habits. ",[618,2591,2592],{},"Use one rule over one range rather than many small ranges"," — Excel evaluates each rule over each of its ranges, and a hundred single-row rules is a hundred times the work of one covering all hundred rows. And ",[618,2595,2596],{},"avoid volatile functions in the formula",[164,2598,2599],{},"INDIRECT",[164,2601,2602],{},"OFFSET",[164,2604,2605],{},"TODAY"," and ",[164,2608,2609],{},"NOW"," force re-evaluation on every recalculation, which makes a large sheet sluggish. Compute the value in Python and write it to a cell the rule references instead.",[10,2612,2613,2614,2618],{},"The static-fill approach retains one advantage worth noting: it survives a conversion to PDF or CSV, where conditional formatting does not always render. For a report destined for ",[14,2615,2617],{"href":2616},"\u002Fautomating-reporting-workflows\u002Fexporting-excel-reports-to-pdf\u002F","PDF export",", verify the highlighting appears in the output, and fall back to static fills for that specific artefact while keeping live rules in the workbook readers open.",[152,2620,2622],{"id":2621},"conclusion","Conclusion",[10,2624,2625,2626,2628,2629,2631,2632,2634,2635,2637,2638,2640],{},"Conditional formatting makes exceptions visible without touching the data, and it stays correct when the data changes — which a static fill does not. Use ",[164,2627,375],{}," for a fixed comparison, ",[164,2630,815],{}," with an absolute ",[164,2633,1074],{}," reference when the threshold should live in a cell readers can edit, and ",[164,2636,1186],{}," — column anchored, row relative — when the whole row should highlight. Order overlapping rules from most to least specific and set ",[164,2639,1754],{},", guard against blank cells comparing as zero, and always apply the rules after the data has been written.",[152,2642,2644],{"id":2643},"frequently-asked-questions","Frequently asked questions",[10,2646,2647,2650],{},[618,2648,2649],{},"What is the difference between a conditional format and just setting a fill?","\nA conditional format is a live rule Excel re-evaluates whenever the data changes, so a cell that later drops below the threshold loses its highlight. A static fill is baked in and stays wrong the moment somebody edits a value.",[10,2652,2653,2656,2657,2659,2660,2662],{},[618,2654,2655],{},"How do I reference a threshold stored in a cell?","\nUse ",[164,2658,815],{}," with an absolute reference such as ",[164,2661,1074],{},". Keep the row and column anchored so every cell in the range compares against the same threshold cell rather than a shifting one.",[10,2664,2665,2668,2669,2671],{},[618,2666,2667],{},"Why does my whole-row rule highlight only one column?","\nThe formula uses a fully relative or fully absolute reference. Anchor the column and leave the row relative — ",[164,2670,1186],{}," — so the rule slides down the rows while always testing column B.",[10,2673,2674,2677,2678,2680,2681,2683],{},[618,2675,2676],{},"Which rule wins when two overlap?","\nThe one added first, unless a rule sets ",[164,2679,1754],{},". Order your rules from most specific to least specific and set ",[164,2682,1754],{}," on the ones that should end evaluation.",[10,2685,2686,2689,2690,2692],{},[618,2687,2688],{},"Do conditional formats survive a pandas write?","\nNo. ",[164,2691,1872],{}," replaces the sheet, so apply conditional formatting after all data has been written, or add it through the xlsxwriter engine while the writer is open.",[152,2694,2696],{"id":2695},"related","Related",[2698,2699,2700,2707,2714,2720,2727],"ul",{},[2701,2702,2703,2704,2706],"li",{},"Up to the parent: ",[14,2705,17],{"href":16}," — the wider rule vocabulary.",[2701,2708,2709,2713],{},[14,2710,2712],{"href":2711},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fopenpyxl-apply-conditional-formatting-to-range\u002F","openpyxl: Apply Conditional Formatting to a Range"," — the range mechanics in depth.",[2701,2715,2716,2719],{},[14,2717,2718],{"href":1758},"Add Data Bars and Colour Scales with openpyxl"," — graduated alternatives to a hard threshold.",[2701,2721,2722,2726],{},[14,2723,2725],{"href":2724},"\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"," — the same technique aimed at data quality.",[2701,2728,2729,2733],{},[14,2730,2732],{"href":2731},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter\u002F","Apply Conditional Formatting with xlsxwriter"," — the other engine's API.",[2735,2736,2737],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}",{"title":162,"searchDepth":213,"depth":213,"links":2739},[2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750],{"id":154,"depth":213,"text":155},{"id":369,"depth":213,"text":370},{"id":805,"depth":213,"text":806},{"id":1096,"depth":213,"text":1097},{"id":1459,"depth":213,"text":1460},{"id":1762,"depth":213,"text":1763},{"id":2258,"depth":213,"text":2259},{"id":2387,"depth":213,"text":2388},{"id":2621,"depth":213,"text":2622},{"id":2643,"depth":213,"text":2644},{"id":2695,"depth":213,"text":2696},"2026-08-15","Draw the eye to the numbers that matter — CellIsRule for fixed thresholds, FormulaRule for a threshold that lives in a cell, whole-row highlighting, and rule priority.","md",[2755,2757,2759,2761,2763],{"q":2649,"a":2756},"A conditional format is a live rule Excel re-evaluates whenever the data changes, so a cell that later drops below the threshold loses its highlight. A static fill is baked in and stays wrong the moment somebody edits a value.",{"q":2655,"a":2758},"Use FormulaRule with an absolute reference such as dollar B dollar 1. Keep the row and column anchored so every cell in the range compares against the same threshold cell rather than a shifting one.",{"q":2667,"a":2760},"The formula uses a fully relative or fully absolute reference. Anchor the column and leave the row relative — dollar D2 — so the rule slides down the rows while always testing column D.",{"q":2676,"a":2762},"The one added first, unless a rule sets stopIfTrue. Order your rules from most specific to least specific and set stopIfTrue on the ones that should end evaluation.",{"q":2688,"a":2764},"No. to_excel replaces the sheet, so apply conditional formatting after all data has been written, or add it through the xlsxwriter engine while the writer is open.",{},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-cells-above-a-threshold-with-openpyxl",{"title":2768,"description":2769},"Highlight Cells Above a Threshold in openpyxl","Conditional formatting in Python: CellIsRule for greaterThan, FormulaRule with mixed references for whole-row highlighting, stopIfTrue priority, and dynamic thresholds.","highlight-cells-above-a-threshold-with-openpyxl","advanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-cells-above-a-threshold-with-openpyxl\u002Findex","how-to","q48kf5s_m4OYXe3kOQZJ8eYYLAEJh9qLldHoff9UVms",[2775,2778],{"title":2718,"path":2776,"stem":2777,"children":-1},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fadd-data-bars-and-colour-scales-with-openpyxl","advanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fadd-data-bars-and-colour-scales-with-openpyxl\u002Findex",{"title":2779,"path":2780,"stem":2781,"children":-1},"Apply Conditional Formatting to a Range in openpyxl","\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fopenpyxl-apply-conditional-formatting-to-range","advanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fopenpyxl-apply-conditional-formatting-to-range\u002Findex",1786800028613]