[{"data":1,"prerenderedAt":766},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fopenpyxl-apply-conditional-formatting-to-range":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fopenpyxl-apply-conditional-formatting-to-range":758},{"id":4,"title":5,"body":6,"description":751,"extension":752,"meta":753,"navigation":106,"path":754,"seo":755,"stem":756,"__hash__":757},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fopenpyxl-apply-conditional-formatting-to-range\u002Findex.md","How to Apply Conditional Formatting to a Range in openpyxl",{"type":7,"value":8,"toc":744},"minimark",[9,13,42,47,393,397,420,439,443,520,524,527,595,608,611,623,713,721,725,740],[10,11,5],"h1",{"id":12},"how-to-apply-conditional-formatting-to-a-range-in-openpyxl",[14,15,16,17,21,22,26,27,30,31,26,34,37,38,41],"p",{},"To ",[18,19,20],"strong",{},"apply conditional formatting to a range"," in openpyxl, instantiate a rule object (",[23,24,25],"code",{},"CellIsRule"," or ",[23,28,29],{},"FormulaRule","), attach a ",[23,32,33],{},"PatternFill",[23,35,36],{},"Font"," style, and register it using ",[23,39,40],{},"ws.conditional_formatting.add()",". openpyxl serializes these rules directly into the worksheet XML, and Excel evaluates the conditions dynamically when the file opens.",[43,44,46],"h2",{"id":45},"working-implementation","Working Implementation",[48,49,54],"pre",{"className":50,"code":51,"language":52,"meta":53,"style":53},"language-python shiki shiki-themes github-light github-dark","from openpyxl import Workbook\nfrom openpyxl.styles import PatternFill, Font\nfrom openpyxl.formatting.rule import CellIsRule\n\nwb = Workbook()\nws = wb.active\n\n# 1. Populate sample data\nfor row in range(1, 11):\n ws.cell(row=row, column=1, value=row * 10)\n\n# 2. Define styling overrides\nwarn_fill = PatternFill(start_color=\"FFC7CE\", end_color=\"FFC7CE\", fill_type=\"solid\")\nbold_red = Font(color=\"9C0006\", bold=True)\n\n# 3. Create & bind the rule\ntarget_range = \"A1:A10\"\nrule = CellIsRule(operator=\"greaterThan\", formula=[\"50\"], fill=warn_fill, font=bold_red)\nws.conditional_formatting.add(target_range, rule)\n\nwb.save(\"conditional_range.xlsx\")\n","python","",[23,55,56,75,88,101,108,120,131,136,143,174,215,220,226,267,298,303,309,320,371,377,382],{"__ignoreMap":53},[57,58,61,65,69,72],"span",{"class":59,"line":60},"line",1,[57,62,64],{"class":63},"szBVR","from",[57,66,68],{"class":67},"sVt8B"," openpyxl ",[57,70,71],{"class":63},"import",[57,73,74],{"class":67}," Workbook\n",[57,76,78,80,83,85],{"class":59,"line":77},2,[57,79,64],{"class":63},[57,81,82],{"class":67}," openpyxl.styles ",[57,84,71],{"class":63},[57,86,87],{"class":67}," PatternFill, Font\n",[57,89,91,93,96,98],{"class":59,"line":90},3,[57,92,64],{"class":63},[57,94,95],{"class":67}," openpyxl.formatting.rule ",[57,97,71],{"class":63},[57,99,100],{"class":67}," CellIsRule\n",[57,102,104],{"class":59,"line":103},4,[57,105,107],{"emptyLinePlaceholder":106},true,"\n",[57,109,111,114,117],{"class":59,"line":110},5,[57,112,113],{"class":67},"wb ",[57,115,116],{"class":63},"=",[57,118,119],{"class":67}," Workbook()\n",[57,121,123,126,128],{"class":59,"line":122},6,[57,124,125],{"class":67},"ws ",[57,127,116],{"class":63},[57,129,130],{"class":67}," wb.active\n",[57,132,134],{"class":59,"line":133},7,[57,135,107],{"emptyLinePlaceholder":106},[57,137,139],{"class":59,"line":138},8,[57,140,142],{"class":141},"sJ8bj","# 1. Populate sample data\n",[57,144,146,149,152,155,159,162,165,168,171],{"class":59,"line":145},9,[57,147,148],{"class":63},"for",[57,150,151],{"class":67}," row ",[57,153,154],{"class":63},"in",[57,156,158],{"class":157},"sj4cs"," range",[57,160,161],{"class":67},"(",[57,163,164],{"class":157},"1",[57,166,167],{"class":67},", ",[57,169,170],{"class":157},"11",[57,172,173],{"class":67},"):\n",[57,175,177,180,184,186,189,192,194,196,198,201,203,206,209,212],{"class":59,"line":176},10,[57,178,179],{"class":67}," ws.cell(",[57,181,183],{"class":182},"s4XuR","row",[57,185,116],{"class":63},[57,187,188],{"class":67},"row, ",[57,190,191],{"class":182},"column",[57,193,116],{"class":63},[57,195,164],{"class":157},[57,197,167],{"class":67},[57,199,200],{"class":182},"value",[57,202,116],{"class":63},[57,204,205],{"class":67},"row ",[57,207,208],{"class":63},"*",[57,210,211],{"class":157}," 10",[57,213,214],{"class":67},")\n",[57,216,218],{"class":59,"line":217},11,[57,219,107],{"emptyLinePlaceholder":106},[57,221,223],{"class":59,"line":222},12,[57,224,225],{"class":141},"# 2. Define styling overrides\n",[57,227,229,232,234,237,240,242,246,248,251,253,255,257,260,262,265],{"class":59,"line":228},13,[57,230,231],{"class":67},"warn_fill ",[57,233,116],{"class":63},[57,235,236],{"class":67}," PatternFill(",[57,238,239],{"class":182},"start_color",[57,241,116],{"class":63},[57,243,245],{"class":244},"sZZnC","\"FFC7CE\"",[57,247,167],{"class":67},[57,249,250],{"class":182},"end_color",[57,252,116],{"class":63},[57,254,245],{"class":244},[57,256,167],{"class":67},[57,258,259],{"class":182},"fill_type",[57,261,116],{"class":63},[57,263,264],{"class":244},"\"solid\"",[57,266,214],{"class":67},[57,268,270,273,275,278,281,283,286,288,291,293,296],{"class":59,"line":269},14,[57,271,272],{"class":67},"bold_red ",[57,274,116],{"class":63},[57,276,277],{"class":67}," Font(",[57,279,280],{"class":182},"color",[57,282,116],{"class":63},[57,284,285],{"class":244},"\"9C0006\"",[57,287,167],{"class":67},[57,289,290],{"class":182},"bold",[57,292,116],{"class":63},[57,294,295],{"class":157},"True",[57,297,214],{"class":67},[57,299,301],{"class":59,"line":300},15,[57,302,107],{"emptyLinePlaceholder":106},[57,304,306],{"class":59,"line":305},16,[57,307,308],{"class":141},"# 3. Create & bind the rule\n",[57,310,312,315,317],{"class":59,"line":311},17,[57,313,314],{"class":67},"target_range ",[57,316,116],{"class":63},[57,318,319],{"class":244}," \"A1:A10\"\n",[57,321,323,326,328,331,334,336,339,341,344,346,349,352,355,358,360,363,366,368],{"class":59,"line":322},18,[57,324,325],{"class":67},"rule ",[57,327,116],{"class":63},[57,329,330],{"class":67}," CellIsRule(",[57,332,333],{"class":182},"operator",[57,335,116],{"class":63},[57,337,338],{"class":244},"\"greaterThan\"",[57,340,167],{"class":67},[57,342,343],{"class":182},"formula",[57,345,116],{"class":63},[57,347,348],{"class":67},"[",[57,350,351],{"class":244},"\"50\"",[57,353,354],{"class":67},"], ",[57,356,357],{"class":182},"fill",[57,359,116],{"class":63},[57,361,362],{"class":67},"warn_fill, ",[57,364,365],{"class":182},"font",[57,367,116],{"class":63},[57,369,370],{"class":67},"bold_red)\n",[57,372,374],{"class":59,"line":373},19,[57,375,376],{"class":67},"ws.conditional_formatting.add(target_range, rule)\n",[57,378,380],{"class":59,"line":379},20,[57,381,107],{"emptyLinePlaceholder":106},[57,383,385,388,391],{"class":59,"line":384},21,[57,386,387],{"class":67},"wb.save(",[57,389,390],{"class":244},"\"conditional_range.xlsx\"",[57,392,214],{"class":67},[43,394,396],{"id":395},"core-mechanics-range-syntax","Core Mechanics & Range Syntax",[14,398,399,400,403,404,407,408,411,412,415,416,419],{},"The ",[23,401,402],{},"add()"," method binds formatting logic to contiguous or non-contiguous ranges. Pass a single Excel-style string (",[23,405,406],{},"\"A1:C10\"",") or a comma-separated list without spaces (",[23,409,410],{},"\"A1:A10,C1:C10\"","). openpyxl does ",[18,413,414],{},"not"," evaluate conditions; it writes the rule into the ",[23,417,418],{},"xl\u002Fworksheets\u002Fsheet1.xml"," conditional formatting block. Excel handles runtime evaluation against each cell in the target range.",[14,421,422,423,425,426,428,429,432,433,438],{},"For dynamic thresholds in automated reporting, swap ",[23,424,25],{}," for ",[23,427,29],{},". This enables relative references (e.g., ",[23,430,431],{},"=B1>0.75",") that scale across the entire range without hardcoding absolute coordinates. When building pipelines within a broader ",[434,435,437],"a",{"href":436},"\u002Fadvanced-data-transformation-and-cleaning\u002F","Advanced Data Transformation and Cleaning"," workflow, generate rule definitions programmatically from your validation thresholds rather than embedding static values.",[43,440,442],{"id":441},"compatibility-rule-priority","Compatibility & Rule Priority",[444,445,446,471,483,493,507],"ul",{},[447,448,449,452,453,456,457,459,460,462,463,466,467,470],"li",{},[18,450,451],{},"openpyxl Version:"," Requires ",[23,454,455],{},">=3.0.0"," for stable ",[23,458,25],{},"\u002F",[23,461,29],{}," serialization. Versions ",[23,464,465],{},"2.6.x"," lack full ",[23,468,469],{},"dxf"," (differential formatting) support.",[447,472,473,476,477,479,480,482],{},[18,474,475],{},"Excel Version:"," Renders correctly in Excel 2013+. Excel 2010 may ignore ",[23,478,33],{}," transparency or misinterpret ",[23,481,36],{}," overrides.",[447,484,485,488,489,492],{},[18,486,487],{},"Rule Priority:"," Rules apply in insertion order. Overlapping ranges default to the last appended rule unless ",[23,490,491],{},"stopIfTrue=True"," is explicitly set.",[447,494,495,498,499,502,503,506],{},[18,496,497],{},"Unsupported Types:"," ",[23,500,501],{},"IconSetRule"," and ",[23,504,505],{},"DataBarRule"," are partially supported. Complex gradients or custom icon sets often require manual XML injection.",[447,508,509,512,513,515,516,519],{},[18,510,511],{},"Range Syntax:"," Named ranges are ",[18,514,414],{}," supported in ",[23,517,518],{},"conditional_formatting.add()",". Use explicit cell references only.",[43,521,523],{"id":522},"troubleshooting-fallbacks","Troubleshooting & Fallbacks",[14,525,526],{},"If styling fails to render, verify these common failure points:",[528,529,530,559,580,589],"ol",{},[447,531,532,535,536,538,539,425,542,544,545,548,549,551,552,554,555,558],{},[18,533,534],{},"Formula Syntax Errors:"," The ",[23,537,343],{}," parameter expects a list of strings. Use ",[23,540,541],{},"[\"50\"]",[23,543,25],{},", not ",[23,546,547],{},"50",". For ",[23,550,29],{},", always include the ",[23,553,116],{}," prefix: ",[23,556,557],{},"[\"=A1>100\"]",".",[447,560,561,498,564,566,567,502,569,571,572,575,576,579],{},[18,562,563],{},"Invisible Fills:",[23,565,33],{}," requires explicit ",[23,568,239],{},[23,570,250],{},". Omitting ",[23,573,574],{},"fill_type=\"solid\""," defaults to ",[23,577,578],{},"None",", rendering invisibly.",[447,581,582,585,586,558],{},[18,583,584],{},"Evaluation Delays:"," Excel's UI cache or calculation state can delay new rules. Reopen the file or trigger ",[23,587,588],{},"Formulas > Calculate Now",[447,590,591,594],{},[18,592,593],{},"Debugging Output:"," Inspect registered rules before saving:",[48,596,598],{"className":50,"code":597,"language":52,"meta":53,"style":53},"print(ws.conditional_formatting.rules)\n",[23,599,600],{"__ignoreMap":53},[57,601,602,605],{"class":59,"line":60},[57,603,604],{"class":157},"print",[57,606,607],{"class":67},"(ws.conditional_formatting.rules)\n",[14,609,610],{},"An empty list or malformed XML indicates the rule was never attached.",[14,612,613,616,617,619,620,622],{},[18,614,615],{},"Fallback Strategy:"," When ",[23,618,25],{}," fails due to operator quirks or complex logic, switch to ",[23,621,29],{}," with a boolean expression. This aligns directly with Excel’s native evaluation engine:",[48,624,626],{"className":50,"code":625,"language":52,"meta":53,"style":53},"from openpyxl.formatting.rule import FormulaRule\n\nfallback_rule = FormulaRule(\n formula=[\"=AND(A1>50, A1\u003C100)\"],\n fill=warn_fill,\n font=bold_red,\n stopIfTrue=True\n)\nws.conditional_formatting.add(\"A1:A10\", fallback_rule)\n",[23,627,628,639,643,653,668,678,688,698,702],{"__ignoreMap":53},[57,629,630,632,634,636],{"class":59,"line":60},[57,631,64],{"class":63},[57,633,95],{"class":67},[57,635,71],{"class":63},[57,637,638],{"class":67}," FormulaRule\n",[57,640,641],{"class":59,"line":77},[57,642,107],{"emptyLinePlaceholder":106},[57,644,645,648,650],{"class":59,"line":90},[57,646,647],{"class":67},"fallback_rule ",[57,649,116],{"class":63},[57,651,652],{"class":67}," FormulaRule(\n",[57,654,655,658,660,662,665],{"class":59,"line":103},[57,656,657],{"class":182}," formula",[57,659,116],{"class":63},[57,661,348],{"class":67},[57,663,664],{"class":244},"\"=AND(A1>50, A1\u003C100)\"",[57,666,667],{"class":67},"],\n",[57,669,670,673,675],{"class":59,"line":110},[57,671,672],{"class":182}," fill",[57,674,116],{"class":63},[57,676,677],{"class":67},"warn_fill,\n",[57,679,680,683,685],{"class":59,"line":122},[57,681,682],{"class":182}," font",[57,684,116],{"class":63},[57,686,687],{"class":67},"bold_red,\n",[57,689,690,693,695],{"class":59,"line":133},[57,691,692],{"class":182}," stopIfTrue",[57,694,116],{"class":63},[57,696,697],{"class":157},"True\n",[57,699,700],{"class":59,"line":138},[57,701,214],{"class":67},[57,703,704,707,710],{"class":59,"line":145},[57,705,706],{"class":67},"ws.conditional_formatting.add(",[57,708,709],{"class":244},"\"A1:A10\"",[57,711,712],{"class":67},", fallback_rule)\n",[14,714,715,716,720],{},"For comprehensive rule configurations, edge-case handling, and multi-sheet iteration patterns, refer to the ",[434,717,719],{"href":718},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002F","Applying Conditional Formatting with openpyxl"," reference.",[43,722,724],{"id":723},"performance-optimization","Performance Optimization",[14,726,727,728,731,732,735,736,739],{},"Applying conditional formatting to ranges exceeding 100,000 cells increases ",[23,729,730],{},".xlsx"," file size and slows Excel's initial load. openpyxl writes each rule as a discrete XML block; overlapping ranges multiply serialization overhead. For large datasets, restrict formatting to summary tables, or use Excel's native ",[23,733,734],{},"Table"," styles via ",[23,737,738],{},"ws.add_table()"," instead of per-cell conditional rules.",[741,742,743],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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);}",{"title":53,"searchDepth":77,"depth":77,"links":745},[746,747,748,749,750],{"id":45,"depth":77,"text":46},{"id":395,"depth":77,"text":396},{"id":441,"depth":77,"text":442},{"id":522,"depth":77,"text":523},{"id":723,"depth":77,"text":724},"To apply conditional formatting to a range in openpyxl, instantiate a rule object (CellIsRule or FormulaRule), attach a PatternFill or Font style, and register it using ws.conditional_formatting.add(). openpyxl serializes these rules directly into the worksheet XML, and Excel evaluates the conditions dynamically when the file opens.","md",{},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fopenpyxl-apply-conditional-formatting-to-range",{"title":5,"description":751},"advanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fopenpyxl-apply-conditional-formatting-to-range\u002Findex","ACwzksgLKFm8vy8EvVMxHptFgYI2CZV3Fio732mV4W4",[759,762],{"title":719,"path":760,"stem":761,"children":-1},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl","advanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Findex",{"title":763,"path":764,"stem":765,"children":-1},"Cleaning Excel Data with Pandas: A Production-Ready Workflow for Automated Reporting","\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas","advanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Findex",1777830515192]