[{"data":1,"prerenderedAt":2558},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fapply-autofilter-criteria-and-hide-rows":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fapply-autofilter-criteria-and-hide-rows":2526,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fapply-autofilter-criteria-and-hide-rows":2535,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fapply-autofilter-criteria-and-hide-rows":2540,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fapply-autofilter-criteria-and-hide-rows":2541},{"id":4,"title":5,"body":6,"dateModified":2492,"datePublished":2492,"description":2493,"extension":2494,"faq":2495,"keyword":2504,"kind":2505,"meta":2506,"navigation":445,"path":2515,"seo":2516,"slug":2519,"stem":2520,"topics":2521,"type":2524,"__hash__":2525},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fapply-autofilter-criteria-and-hide-rows\u002Findex.md","Apply Autofilter Criteria and Hide the Filtered Rows with openpyxl",{"type":7,"value":8,"toc":2480},"minimark",[9,24,368,373,401,404,694,701,705,724,842,876,880,887,1292,1295,1456,1460,1463,1791,1806,1810,1813,1940,1947,2056,2060,2071,2304,2329,2333,2380,2384,2407,2411,2421,2431,2437,2443,2447,2476],[10,11,12,13,18,19,23],"p",{},"Filtering a report before sending it — only open orders, only this region, only amounts over a threshold — saves every reader the same clicks. openpyxl has the pieces to write filter criteria into an autofilter, and many people stop there. Then the file opens with the filter dropdowns showing a filter icon, but every row still visible: openpyxl records criteria, while hiding rows is something Excel does only when a user applies a filter. This guide, part of ",[14,15,17],"a",{"href":16},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002F","Creating Excel Tables and Autofilters with Python",", writes the criteria and hides the matching rows so the workbook opens exactly as a filtered sheet would. Setting up the autofilter range is covered in ",[14,20,22],{"href":21},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fadd-an-autofilter-to-an-excel-sheet-with-openpyxl\u002F","Add an Autofilter to an Excel Sheet with openpyxl",".",[25,26,34,35,34,39,34,43,34,51,34,60,34,64,34,71,34,75,34,79,34,83,34,87,34,91,34,96,34,98,34,102,34,104,34,107,34,109,34,112,34,115,34,119,34,121,34,125,34,127,34,130,34,132,34,135,34,138,34,142,34,144,34,147,34,149,34,152,34,154,34,157,34,160,34,163,34,165,34,168,34,170,34,173,34,175,34,178,34,181,34,185,34,187,34,190,34,192,34,194,34,196,34,199,34,202,34,206,34,208,34,211,34,213,34,216,34,218,34,221,34,224,34,228,34,230,34,233,34,235,34,237,34,239,34,242,34,245,34,249,34,252,34,256,34,259,34,263,34,266,34,268,34,271,34,273,34,275,34,277,34,279,34,281,34,283,34,285,34,287,34,289,34,291,34,293,34,295,34,297,34,299,34,301,34,303,34,305,34,307,34,309,34,311,34,313,34,315,34,317,34,319,34,321,34,324,34,326,34,328,34,331,34,337,34,341,34,349,34,354,34,362],"svg",{"viewBox":27,"role":28,"ariaLabelledBy":29,"xmlns":32,"style":33},"4 0 752 276","img",[30,31],"af-before-after-t","af-before-after-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[36,37,38],"title",{"id":30},"Criteria alone versus criteria plus hidden rows",[40,41,42],"desc",{"id":31},"With criteria only, the sheet opens showing all six orders under a filter that claims to show North and South orders of at least 100. With the non-matching rows also hidden, only orders 101 and 106 are visible and the SUBTOTAL total reads 2,020.",[44,45],"rect",{"x":46,"y":47,"width":48,"height":49,"fill":50},"4","0","752","276","#ffffff",[44,52],{"x":53,"y":54,"width":55,"height":56,"rx":47,"fill":57,"stroke":58,"style":59},"20.0","40.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)","stroke-width:1px",[44,61],{"x":62,"y":54,"width":63,"height":56,"rx":47,"fill":57,"stroke":58,"style":59},"52.0","53.3",[65,66,70],"text",{"x":67,"y":68,"style":69},"78.6","57.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[44,72],{"x":73,"y":54,"width":74,"height":56,"rx":47,"fill":57,"stroke":58,"style":59},"105.3","59.8",[65,76,78],{"x":77,"y":68,"style":69},"135.2","B",[44,80],{"x":81,"y":54,"width":82,"height":56,"rx":47,"fill":57,"stroke":58,"style":59},"165.1","65.4",[65,84,86],{"x":85,"y":68,"style":69},"197.8","C",[44,88],{"x":53,"y":89,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},"64.0","28.0",[65,92,95],{"x":93,"y":94,"style":69},"36.0","83.0","1",[44,97],{"x":62,"y":89,"width":63,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,99,101],{"x":67,"y":94,"style":100},"font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Order",[44,103],{"x":73,"y":89,"width":74,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,105,106],{"x":77,"y":94,"style":100},"Region",[44,108],{"x":81,"y":89,"width":82,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,110,111],{"x":85,"y":94,"style":100},"Amount",[44,113],{"x":53,"y":114,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},"92.0",[65,116,118],{"x":93,"y":117,"style":69},"111.0","2",[44,120],{"x":62,"y":114,"width":63,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,122,124],{"x":67,"y":117,"style":123},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","101",[44,126],{"x":73,"y":114,"width":74,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,128,129],{"x":77,"y":117,"style":123},"North",[44,131],{"x":81,"y":114,"width":82,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,133,134],{"x":85,"y":117,"style":123},"1,200",[44,136],{"x":53,"y":137,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},"120.0",[65,139,141],{"x":93,"y":140,"style":69},"139.0","3",[44,143],{"x":62,"y":137,"width":63,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,145,146],{"x":67,"y":140,"style":123},"102",[44,148],{"x":73,"y":137,"width":74,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,150,151],{"x":77,"y":140,"style":123},"South",[44,153],{"x":81,"y":137,"width":82,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,155,156],{"x":85,"y":140,"style":123},"90",[44,158],{"x":53,"y":159,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},"148.0",[65,161,46],{"x":93,"y":162,"style":69},"167.0",[44,164],{"x":62,"y":159,"width":63,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,166,167],{"x":67,"y":162,"style":123},"103",[44,169],{"x":73,"y":159,"width":74,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,171,172],{"x":77,"y":162,"style":123},"East",[44,174],{"x":81,"y":159,"width":82,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,176,177],{"x":85,"y":162,"style":123},"640",[44,179],{"x":53,"y":180,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},"176.0",[65,182,184],{"x":93,"y":183,"style":69},"195.0","5",[44,186],{"x":62,"y":180,"width":63,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,188,189],{"x":67,"y":183,"style":123},"104",[44,191],{"x":73,"y":180,"width":74,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,193,129],{"x":77,"y":183,"style":123},[44,195],{"x":81,"y":180,"width":82,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,197,198],{"x":85,"y":183,"style":123},"75",[44,200],{"x":53,"y":201,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},"204.0",[65,203,205],{"x":93,"y":204,"style":69},"223.0","6",[44,207],{"x":62,"y":201,"width":63,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,209,210],{"x":67,"y":204,"style":123},"105",[44,212],{"x":73,"y":201,"width":74,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,214,215],{"x":77,"y":204,"style":123},"West",[44,217],{"x":81,"y":201,"width":82,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,219,220],{"x":85,"y":204,"style":123},"1,500",[44,222],{"x":53,"y":223,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},"232.0",[65,225,227],{"x":93,"y":226,"style":69},"251.0","7",[44,229],{"x":62,"y":223,"width":63,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,231,232],{"x":67,"y":226,"style":123},"106",[44,234],{"x":73,"y":223,"width":74,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,236,151],{"x":77,"y":226,"style":123},[44,238],{"x":81,"y":223,"width":82,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,240,241],{"x":85,"y":226,"style":123},"820",[44,243],{"x":244,"y":54,"width":55,"height":56,"rx":47,"fill":57,"stroke":58,"style":59},"495.4",[44,246],{"x":247,"y":54,"width":248,"height":56,"rx":47,"fill":57,"stroke":58,"style":59},"527.4","87.0",[65,250,70],{"x":251,"y":68,"style":69},"570.9",[44,253],{"x":254,"y":54,"width":255,"height":56,"rx":47,"fill":57,"stroke":58,"style":59},"614.4","60.0",[65,257,78],{"x":258,"y":68,"style":69},"644.4",[44,260],{"x":261,"y":54,"width":262,"height":56,"rx":47,"fill":57,"stroke":58,"style":59},"674.4","65.6",[65,264,86],{"x":265,"y":68,"style":69},"707.2",[44,267],{"x":244,"y":89,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},[65,269,95],{"x":270,"y":94,"style":69},"511.4",[44,272],{"x":247,"y":89,"width":248,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,274,101],{"x":251,"y":94,"style":100},[44,276],{"x":254,"y":89,"width":255,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,278,106],{"x":258,"y":94,"style":100},[44,280],{"x":261,"y":89,"width":262,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,282,111],{"x":265,"y":94,"style":100},[44,284],{"x":244,"y":114,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},[65,286,118],{"x":270,"y":117,"style":69},[44,288],{"x":247,"y":114,"width":248,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,290,124],{"x":251,"y":117,"style":123},[44,292],{"x":254,"y":114,"width":255,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,294,129],{"x":258,"y":117,"style":123},[44,296],{"x":261,"y":114,"width":262,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,298,134],{"x":265,"y":117,"style":123},[44,300],{"x":244,"y":137,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},[65,302,141],{"x":270,"y":140,"style":69},[44,304],{"x":247,"y":137,"width":248,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,306,232],{"x":251,"y":140,"style":123},[44,308],{"x":254,"y":137,"width":255,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,310,151],{"x":258,"y":140,"style":123},[44,312],{"x":261,"y":137,"width":262,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,314,241],{"x":265,"y":140,"style":123},[44,316],{"x":244,"y":159,"width":55,"height":90,"rx":47,"fill":57,"stroke":58,"style":59},[65,318,46],{"x":270,"y":162,"style":69},[44,320],{"x":247,"y":159,"width":248,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,322,323],{"x":251,"y":162,"style":123},"Visible total",[44,325],{"x":254,"y":159,"width":255,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[44,327],{"x":261,"y":159,"width":262,"height":90,"rx":47,"fill":50,"stroke":58,"style":59},[65,329,330],{"x":265,"y":162,"style":123},"2,020",[65,332,336],{"x":333,"y":334,"style":335},"125.3","29.0","font-size:12.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","before",[65,338,340],{"x":339,"y":334,"style":335},"617.7","after",[342,343],"line",{"x1":344,"y1":345,"x2":346,"y2":345,"stroke":347,"style":348},"240.5","108.0","481.4","var(--brand,#5b5cf0)","stroke-width:2px",[350,351],"polygon",{"points":352,"fill":353},"485.4,108.0 476.4,113.0 476.4,103.0","#5b5cf0",[44,355],{"x":356,"y":357,"width":358,"height":359,"rx":360,"fill":50,"stroke":58,"style":361},"273.0","75.0","179.9","22.0","11","stroke-width:1.2px",[65,363,367],{"x":364,"y":365,"style":366},"363.0","90.0","font-size:11.5px;font-weight:400;fill:var(--brand-strong,#4338ca);text-anchor:middle;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace","hide non-matching rows",[369,370,372],"h2",{"id":371},"prerequisites","Prerequisites",[374,375,380],"pre",{"className":376,"code":377,"language":378,"meta":379,"style":379},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install openpyxl pandas\n","bash","",[381,382,383],"code",{"__ignoreMap":379},[384,385,387,391,395,398],"span",{"class":342,"line":386},1,[384,388,390],{"class":389},"sMTad","pip",[384,392,394],{"class":393},"srMev"," install",[384,396,397],{"class":393}," openpyxl",[384,399,400],{"class":393}," pandas\n",[10,402,403],{},"An order list with a visible-total row below the data:",[374,405,409],{"className":406,"code":407,"language":408,"meta":379,"style":379},"language-python shiki shiki-themes github-light github-dark-high-contrast","from openpyxl import Workbook, load_workbook\nfrom openpyxl.worksheet.filters import CustomFilter, CustomFilters, FilterColumn, Filters\n\nrows = [(101, \"North\", 1200), (102, \"South\", 90), (103, \"East\", 640),\n        (104, \"North\", 75), (105, \"West\", 1500), (106, \"South\", 820)]\nwb = Workbook()\nws = wb.active\nws.title = \"Orders\"\nws.append([\"Order\", \"Region\", \"Amount\"])\nfor row in rows:\n    ws.append(row)\nlast = ws.max_row\nws.append([\"Visible total\", None, f\"=SUBTOTAL(109,C2:C{last})\"])\nws.auto_filter.ref = f\"A1:C{last}\"\n","python",[381,410,411,427,440,447,503,548,559,570,581,603,618,624,635,671],{"__ignoreMap":379},[384,412,413,417,421,424],{"class":342,"line":386},[384,414,416],{"class":415},"s-kum","from",[384,418,420],{"class":419},"skGVy"," openpyxl ",[384,422,423],{"class":415},"import",[384,425,426],{"class":419}," Workbook, load_workbook\n",[384,428,430,432,435,437],{"class":342,"line":429},2,[384,431,416],{"class":415},[384,433,434],{"class":419}," openpyxl.worksheet.filters ",[384,436,423],{"class":415},[384,438,439],{"class":419}," CustomFilter, CustomFilters, FilterColumn, Filters\n",[384,441,443],{"class":342,"line":442},3,[384,444,446],{"emptyLinePlaceholder":445},true,"\n",[384,448,450,453,456,459,462,465,468,470,473,476,478,480,483,485,487,489,491,493,496,498,500],{"class":342,"line":449},4,[384,451,452],{"class":419},"rows ",[384,454,455],{"class":415},"=",[384,457,458],{"class":419}," [(",[384,460,124],{"class":461},"sP0c6",[384,463,464],{"class":419},", ",[384,466,467],{"class":393},"\"North\"",[384,469,464],{"class":419},[384,471,472],{"class":461},"1200",[384,474,475],{"class":419},"), (",[384,477,146],{"class":461},[384,479,464],{"class":419},[384,481,482],{"class":393},"\"South\"",[384,484,464],{"class":419},[384,486,156],{"class":461},[384,488,475],{"class":419},[384,490,167],{"class":461},[384,492,464],{"class":419},[384,494,495],{"class":393},"\"East\"",[384,497,464],{"class":419},[384,499,177],{"class":461},[384,501,502],{"class":419},"),\n",[384,504,506,509,511,513,515,517,519,521,523,525,528,530,533,535,537,539,541,543,545],{"class":342,"line":505},5,[384,507,508],{"class":419},"        (",[384,510,189],{"class":461},[384,512,464],{"class":419},[384,514,467],{"class":393},[384,516,464],{"class":419},[384,518,198],{"class":461},[384,520,475],{"class":419},[384,522,210],{"class":461},[384,524,464],{"class":419},[384,526,527],{"class":393},"\"West\"",[384,529,464],{"class":419},[384,531,532],{"class":461},"1500",[384,534,475],{"class":419},[384,536,232],{"class":461},[384,538,464],{"class":419},[384,540,482],{"class":393},[384,542,464],{"class":419},[384,544,241],{"class":461},[384,546,547],{"class":419},")]\n",[384,549,551,554,556],{"class":342,"line":550},6,[384,552,553],{"class":419},"wb ",[384,555,455],{"class":415},[384,557,558],{"class":419}," Workbook()\n",[384,560,562,565,567],{"class":342,"line":561},7,[384,563,564],{"class":419},"ws ",[384,566,455],{"class":415},[384,568,569],{"class":419}," wb.active\n",[384,571,573,576,578],{"class":342,"line":572},8,[384,574,575],{"class":419},"ws.title ",[384,577,455],{"class":415},[384,579,580],{"class":393}," \"Orders\"\n",[384,582,584,587,590,592,595,597,600],{"class":342,"line":583},9,[384,585,586],{"class":419},"ws.append([",[384,588,589],{"class":393},"\"Order\"",[384,591,464],{"class":419},[384,593,594],{"class":393},"\"Region\"",[384,596,464],{"class":419},[384,598,599],{"class":393},"\"Amount\"",[384,601,602],{"class":419},"])\n",[384,604,606,609,612,615],{"class":342,"line":605},10,[384,607,608],{"class":415},"for",[384,610,611],{"class":419}," row ",[384,613,614],{"class":415},"in",[384,616,617],{"class":419}," rows:\n",[384,619,621],{"class":342,"line":620},11,[384,622,623],{"class":419},"    ws.append(row)\n",[384,625,627,630,632],{"class":342,"line":626},12,[384,628,629],{"class":419},"last ",[384,631,455],{"class":415},[384,633,634],{"class":419}," ws.max_row\n",[384,636,638,640,643,645,648,650,653,656,660,663,666,669],{"class":342,"line":637},13,[384,639,586],{"class":419},[384,641,642],{"class":393},"\"Visible total\"",[384,644,464],{"class":419},[384,646,647],{"class":461},"None",[384,649,464],{"class":419},[384,651,652],{"class":415},"f",[384,654,655],{"class":393},"\"=SUBTOTAL(109,C2:C",[384,657,659],{"class":658},"sSjpA","{",[384,661,662],{"class":419},"last",[384,664,665],{"class":658},"}",[384,667,668],{"class":393},")\"",[384,670,602],{"class":419},[384,672,674,677,679,682,685,687,689,691],{"class":342,"line":673},14,[384,675,676],{"class":419},"ws.auto_filter.ref ",[384,678,455],{"class":415},[384,680,681],{"class":415}," f",[384,683,684],{"class":393},"\"A1:C",[384,686,659],{"class":658},[384,688,662],{"class":419},[384,690,665],{"class":658},[384,692,693],{"class":393},"\"\n",[10,695,696,697,700],{},"The total sits outside the filter range on purpose, so it is never hidden itself. ",[381,698,699],{},"SUBTOTAL"," with function 109 sums only visible rows, so it follows the filter.",[369,702,704],{"id":703},"step-1-write-the-criteria","Step 1 — Write the criteria",[10,706,707,708,711,712,715,716,719,720,723],{},"Each filtered column is a ",[381,709,710],{},"FilterColumn"," whose ",[381,713,714],{},"colId"," is the column's zero-based position within the autofilter range — here Region is 1 and Amount is 2. A list of values to show goes in ",[381,717,718],{},"Filters","; comparisons go in ",[381,721,722],{},"CustomFilters",":",[374,725,727],{"className":406,"code":726,"language":408,"meta":379,"style":379},"region_filter = FilterColumn(colId=1, filters=Filters(filter=[\"North\", \"South\"]))\namount_filter = FilterColumn(colId=2, customFilters=CustomFilters(customFilter=[\n    CustomFilter(operator=\"greaterThanOrEqual\", val=\"100\")]))\nws.auto_filter.filterColumn.append(region_filter)\nws.auto_filter.filterColumn.append(amount_filter)\n",[381,728,729,773,806,832,837],{"__ignoreMap":379},[384,730,731,734,736,739,742,744,746,748,751,753,756,759,761,764,766,768,770],{"class":342,"line":386},[384,732,733],{"class":419},"region_filter ",[384,735,455],{"class":415},[384,737,738],{"class":419}," FilterColumn(",[384,740,714],{"class":741},"sa561",[384,743,455],{"class":415},[384,745,95],{"class":461},[384,747,464],{"class":419},[384,749,750],{"class":741},"filters",[384,752,455],{"class":415},[384,754,755],{"class":419},"Filters(",[384,757,758],{"class":741},"filter",[384,760,455],{"class":415},[384,762,763],{"class":419},"[",[384,765,467],{"class":393},[384,767,464],{"class":419},[384,769,482],{"class":393},[384,771,772],{"class":419},"]))\n",[384,774,775,778,780,782,784,786,788,790,793,795,798,801,803],{"class":342,"line":429},[384,776,777],{"class":419},"amount_filter ",[384,779,455],{"class":415},[384,781,738],{"class":419},[384,783,714],{"class":741},[384,785,455],{"class":415},[384,787,118],{"class":461},[384,789,464],{"class":419},[384,791,792],{"class":741},"customFilters",[384,794,455],{"class":415},[384,796,797],{"class":419},"CustomFilters(",[384,799,800],{"class":741},"customFilter",[384,802,455],{"class":415},[384,804,805],{"class":419},"[\n",[384,807,808,811,814,816,819,821,824,826,829],{"class":342,"line":442},[384,809,810],{"class":419},"    CustomFilter(",[384,812,813],{"class":741},"operator",[384,815,455],{"class":415},[384,817,818],{"class":393},"\"greaterThanOrEqual\"",[384,820,464],{"class":419},[384,822,823],{"class":741},"val",[384,825,455],{"class":415},[384,827,828],{"class":393},"\"100\"",[384,830,831],{"class":419},")]))\n",[384,833,834],{"class":342,"line":449},[384,835,836],{"class":419},"ws.auto_filter.filterColumn.append(region_filter)\n",[384,838,839],{"class":342,"line":505},[384,840,841],{"class":419},"ws.auto_filter.filterColumn.append(amount_filter)\n",[10,843,844,845,464,848,464,851,464,854,464,857,860,861,864,865,867,868,871,872,875],{},"Custom filter operators are ",[381,846,847],{},"equal",[381,849,850],{},"notEqual",[381,852,853],{},"greaterThan",[381,855,856],{},"greaterThanOrEqual",[381,858,859],{},"lessThan"," and ",[381,862,863],{},"lessThanOrEqual",", and ",[381,866,823],{}," is always a string in the file, even for numbers. Up to two custom filters can share a column, combined with ",[381,869,870],{},"CustomFilters(_and=True, customFilter=[...])"," for a range such as 100 to 1,000; without ",[381,873,874],{},"_and",", either condition is enough. At this point the file would open with both filter buttons showing as active — and all six orders visible.",[369,877,879],{"id":878},"step-2-evaluate-the-same-criteria-and-hide-rows","Step 2 — Evaluate the same criteria and hide rows",[10,881,882,883,886],{},"Hiding is a row property: ",[381,884,885],{},"row_dimensions[row].hidden = True",". Evaluate the criteria in Python against each data row and hide the ones that fail. Keep the criteria in one structure so the written filter and the hidden rows cannot drift apart:",[374,888,890],{"className":406,"code":889,"language":408,"meta":379,"style":379},"import operator\n\nOPS = {\"equal\": operator.eq, \"notEqual\": operator.ne, \"greaterThan\": operator.gt,\n       \"greaterThanOrEqual\": operator.ge, \"lessThan\": operator.lt, \"lessThanOrEqual\": operator.le}\n\ndef row_matches(values, filter_columns):\n    for fc in filter_columns:\n        value = values[fc.colId]\n        if fc.filters is not None and str(value) not in fc.filters.filter:\n            return False\n        if fc.customFilters is not None:\n            tests = [OPS[cf.operator](value, float(cf.val)) for cf in fc.customFilters.customFilter]\n            combined = all(tests) if fc.customFilters._and else any(tests)\n            if not combined:\n                return False\n    return True\n\nfor r in range(2, last + 1):\n    values = [ws.cell(r, c).value for c in range(1, 4)]\n    ws.row_dimensions[r].hidden = not row_matches(values, ws.auto_filter.filterColumn)\nwb.save(\"orders_filtered.xlsx\")\n\ncheck = load_workbook(\"orders_filtered.xlsx\")[\"Orders\"]\nprint([r for r in range(2, last + 1) if check.row_dimensions[r].hidden])     # [3, 4, 5, 6]\n",[381,891,892,899,903,932,952,956,968,981,991,1026,1034,1050,1081,1109,1119,1127,1136,1141,1171,1201,1214,1226,1231,1253],{"__ignoreMap":379},[384,893,894,896],{"class":342,"line":386},[384,895,423],{"class":415},[384,897,898],{"class":419}," operator\n",[384,900,901],{"class":342,"line":429},[384,902,446],{"emptyLinePlaceholder":445},[384,904,905,908,911,914,917,920,923,926,929],{"class":342,"line":442},[384,906,907],{"class":461},"OPS",[384,909,910],{"class":415}," =",[384,912,913],{"class":419}," {",[384,915,916],{"class":393},"\"equal\"",[384,918,919],{"class":419},": operator.eq, ",[384,921,922],{"class":393},"\"notEqual\"",[384,924,925],{"class":419},": operator.ne, ",[384,927,928],{"class":393},"\"greaterThan\"",[384,930,931],{"class":419},": operator.gt,\n",[384,933,934,937,940,943,946,949],{"class":342,"line":449},[384,935,936],{"class":393},"       \"greaterThanOrEqual\"",[384,938,939],{"class":419},": operator.ge, ",[384,941,942],{"class":393},"\"lessThan\"",[384,944,945],{"class":419},": operator.lt, ",[384,947,948],{"class":393},"\"lessThanOrEqual\"",[384,950,951],{"class":419},": operator.le}\n",[384,953,954],{"class":342,"line":505},[384,955,446],{"emptyLinePlaceholder":445},[384,957,958,961,965],{"class":342,"line":550},[384,959,960],{"class":415},"def",[384,962,964],{"class":963},"s_Opv"," row_matches",[384,966,967],{"class":419},"(values, filter_columns):\n",[384,969,970,973,976,978],{"class":342,"line":561},[384,971,972],{"class":415},"    for",[384,974,975],{"class":419}," fc ",[384,977,614],{"class":415},[384,979,980],{"class":419}," filter_columns:\n",[384,982,983,986,988],{"class":342,"line":572},[384,984,985],{"class":419},"        value ",[384,987,455],{"class":415},[384,989,990],{"class":419}," values[fc.colId]\n",[384,992,993,996,999,1002,1005,1008,1011,1014,1017,1020,1023],{"class":342,"line":583},[384,994,995],{"class":415},"        if",[384,997,998],{"class":419}," fc.filters ",[384,1000,1001],{"class":415},"is",[384,1003,1004],{"class":415}," not",[384,1006,1007],{"class":461}," None",[384,1009,1010],{"class":415}," and",[384,1012,1013],{"class":461}," str",[384,1015,1016],{"class":419},"(value) ",[384,1018,1019],{"class":415},"not",[384,1021,1022],{"class":415}," in",[384,1024,1025],{"class":419}," fc.filters.filter:\n",[384,1027,1028,1031],{"class":342,"line":605},[384,1029,1030],{"class":415},"            return",[384,1032,1033],{"class":461}," False\n",[384,1035,1036,1038,1041,1043,1045,1047],{"class":342,"line":620},[384,1037,995],{"class":415},[384,1039,1040],{"class":419}," fc.customFilters ",[384,1042,1001],{"class":415},[384,1044,1004],{"class":415},[384,1046,1007],{"class":461},[384,1048,1049],{"class":419},":\n",[384,1051,1052,1055,1057,1060,1062,1065,1068,1071,1073,1076,1078],{"class":342,"line":626},[384,1053,1054],{"class":419},"            tests ",[384,1056,455],{"class":415},[384,1058,1059],{"class":419}," [",[384,1061,907],{"class":461},[384,1063,1064],{"class":419},"[cf.operator](value, ",[384,1066,1067],{"class":461},"float",[384,1069,1070],{"class":419},"(cf.val)) ",[384,1072,608],{"class":415},[384,1074,1075],{"class":419}," cf ",[384,1077,614],{"class":415},[384,1079,1080],{"class":419}," fc.customFilters.customFilter]\n",[384,1082,1083,1086,1088,1091,1094,1097,1100,1103,1106],{"class":342,"line":637},[384,1084,1085],{"class":419},"            combined ",[384,1087,455],{"class":415},[384,1089,1090],{"class":461}," all",[384,1092,1093],{"class":419},"(tests) ",[384,1095,1096],{"class":415},"if",[384,1098,1099],{"class":419}," fc.customFilters._and ",[384,1101,1102],{"class":415},"else",[384,1104,1105],{"class":461}," any",[384,1107,1108],{"class":419},"(tests)\n",[384,1110,1111,1114,1116],{"class":342,"line":673},[384,1112,1113],{"class":415},"            if",[384,1115,1004],{"class":415},[384,1117,1118],{"class":419}," combined:\n",[384,1120,1122,1125],{"class":342,"line":1121},15,[384,1123,1124],{"class":415},"                return",[384,1126,1033],{"class":461},[384,1128,1130,1133],{"class":342,"line":1129},16,[384,1131,1132],{"class":415},"    return",[384,1134,1135],{"class":461}," True\n",[384,1137,1139],{"class":342,"line":1138},17,[384,1140,446],{"emptyLinePlaceholder":445},[384,1142,1144,1146,1149,1151,1154,1157,1159,1162,1165,1168],{"class":342,"line":1143},18,[384,1145,608],{"class":415},[384,1147,1148],{"class":419}," r ",[384,1150,614],{"class":415},[384,1152,1153],{"class":461}," range",[384,1155,1156],{"class":419},"(",[384,1158,118],{"class":461},[384,1160,1161],{"class":419},", last ",[384,1163,1164],{"class":415},"+",[384,1166,1167],{"class":461}," 1",[384,1169,1170],{"class":419},"):\n",[384,1172,1174,1177,1179,1182,1184,1187,1189,1191,1193,1195,1197,1199],{"class":342,"line":1173},19,[384,1175,1176],{"class":419},"    values ",[384,1178,455],{"class":415},[384,1180,1181],{"class":419}," [ws.cell(r, c).value ",[384,1183,608],{"class":415},[384,1185,1186],{"class":419}," c ",[384,1188,614],{"class":415},[384,1190,1153],{"class":461},[384,1192,1156],{"class":419},[384,1194,95],{"class":461},[384,1196,464],{"class":419},[384,1198,46],{"class":461},[384,1200,547],{"class":419},[384,1202,1204,1207,1209,1211],{"class":342,"line":1203},20,[384,1205,1206],{"class":419},"    ws.row_dimensions[r].hidden ",[384,1208,455],{"class":415},[384,1210,1004],{"class":415},[384,1212,1213],{"class":419}," row_matches(values, ws.auto_filter.filterColumn)\n",[384,1215,1217,1220,1223],{"class":342,"line":1216},21,[384,1218,1219],{"class":419},"wb.save(",[384,1221,1222],{"class":393},"\"orders_filtered.xlsx\"",[384,1224,1225],{"class":419},")\n",[384,1227,1229],{"class":342,"line":1228},22,[384,1230,446],{"emptyLinePlaceholder":445},[384,1232,1234,1237,1239,1242,1244,1247,1250],{"class":342,"line":1233},23,[384,1235,1236],{"class":419},"check ",[384,1238,455],{"class":415},[384,1240,1241],{"class":419}," load_workbook(",[384,1243,1222],{"class":393},[384,1245,1246],{"class":419},")[",[384,1248,1249],{"class":393},"\"Orders\"",[384,1251,1252],{"class":419},"]\n",[384,1254,1256,1259,1262,1264,1266,1268,1270,1272,1274,1276,1278,1280,1283,1285,1288],{"class":342,"line":1255},24,[384,1257,1258],{"class":461},"print",[384,1260,1261],{"class":419},"([r ",[384,1263,608],{"class":415},[384,1265,1148],{"class":419},[384,1267,614],{"class":415},[384,1269,1153],{"class":461},[384,1271,1156],{"class":419},[384,1273,118],{"class":461},[384,1275,1161],{"class":419},[384,1277,1164],{"class":415},[384,1279,1167],{"class":461},[384,1281,1282],{"class":419},") ",[384,1284,1096],{"class":415},[384,1286,1287],{"class":419}," check.row_dimensions[r].hidden])     ",[384,1289,1291],{"class":1290},"s-wDw","# [3, 4, 5, 6]\n",[10,1293,1294],{},"Rows 3 to 6 — South at 90, East, North at 75 and West — are hidden, and orders 101 and 106 remain. Rendering the file in LibreOffice shows exactly those two rows with a visible total of 2,020; the other four are still in the file, just hidden, and Excel will show them again when the reader clears the filter.",[25,1296,34,1301,34,1304,34,1307,34,1310,34,1317,34,1328,34,1334,34,1339,34,1344,34,1347,34,1350,34,1356,34,1361,34,1365,34,1368,34,1372,34,1375,34,1380,34,1387,34,1392,34,1396,34,1399,34,1403,34,1406,34,1409,34,1415,34,1419,34,1422,34,1426,34,1429,34,1434,34,1441,34,1446,34,1449,34,1452],{"viewBox":1297,"role":28,"ariaLabelledBy":1298,"xmlns":32,"style":33},"4 0 752 160",[1299,1300],"af-flow-t","af-flow-d",[36,1302,1303],{"id":1299},"Opening a workbook already filtered",[40,1305,1306],{"id":1300},"Set the autofilter range, describe the criteria once as FilterColumn objects, write them to the autofilter, evaluate the same criteria against every data row in Python, hide the rows that fail, and keep SUBTOTAL totals outside the range so they sum only visible rows.",[44,1308],{"x":46,"y":47,"width":48,"height":1309,"fill":50},"160",[44,1311],{"x":53,"y":1312,"width":1313,"height":1314,"rx":1315,"fill":1316,"stroke":347,"style":348},"16.0","115.2","128.0","12","#f0f4ff",[1318,1319,1321],"g",{"transform":1320},"translate(65.6,46.5) scale(1.000)",[1322,1323],"path",{"d":1324,"fill":1325,"stroke":1326,"style":1327},"M3 5h18l-7 8v6l-4 2v-8z","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[65,1329,1333],{"x":1330,"y":1331,"style":1332},"77.6","93.0","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Filter range",[65,1335,1338],{"x":1330,"y":1336,"style":1337},"112.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","header + data",[342,1340],{"x1":1341,"y1":1342,"x2":1343,"y2":1342,"stroke":347,"style":348},"140.2","80.0","162.2",[350,1345],{"points":1346,"fill":353},"166.2,80.0 157.2,85.0 157.2,75.0",[44,1348],{"x":1349,"y":1312,"width":1313,"height":1314,"rx":1315,"fill":1316,"stroke":347,"style":348},"171.2",[1318,1351,1353],{"transform":1352},"translate(216.8,37.8) scale(1.000)",[1322,1354],{"d":1355,"fill":1325,"stroke":1326,"style":1327},"M11 4a7 7 0 1 0 .01 0z M16 16l5 5",[65,1357,1360],{"x":1358,"y":1359,"style":1332},"228.8","84.2","Criteria",[65,1362,1364],{"x":1358,"y":1363,"style":1337},"103.8","Filters,",[65,1366,722],{"x":1358,"y":1367,"style":1337},"121.2",[342,1369],{"x1":1370,"y1":1342,"x2":1371,"y2":1342,"stroke":347,"style":348},"291.4","313.4",[350,1373],{"points":1374,"fill":353},"317.4,80.0 308.4,85.0 308.4,75.0",[44,1376],{"x":1377,"y":1312,"width":1313,"height":1314,"rx":1315,"fill":1378,"stroke":1379,"style":348},"322.4","#d9f4f1","var(--teal,#0f9488)",[1318,1381,1383],{"transform":1382},"translate(368.0,37.8) scale(1.000)",[1322,1384],{"d":1385,"fill":1325,"stroke":1386,"style":1327},"M12 3c-4 0-4 1.6-4 3v2h4.2v1H6c-2 0-3 1.4-3 4s1 4 3 4h2v-2.6c0-1.6 1.3-2.9 2.9-2.9h4.2c1.3 0 2.4-1.1 2.4-2.4V6c0-1.6-1.8-3-5.5-3z M10 5.5h.01 M12 21c4 0 4-1.6 4-3v-2h-4.2v-1H18c2 0 3-1.4 3-4s-1-4-3-4h-2v2.6c0 1.6-1.3 2.9-2.9 2.9H8.9c-1.3 0-2.4 1.1-2.4 2.4V18c0 1.6 1.8 3 5.5 3z M14 18.5h.01","var(--teal-ink,#0b6157)",[65,1388,1391],{"x":1389,"y":1359,"style":1390},"380.0","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Evaluate in",[65,1393,1395],{"x":1389,"y":1394,"style":1390},"101.8","Python",[65,1397,1398],{"x":1389,"y":1367,"style":1337},"same criteria",[342,1400],{"x1":1401,"y1":1342,"x2":1402,"y2":1342,"stroke":347,"style":348},"442.6","464.6",[350,1404],{"points":1405,"fill":353},"468.6,80.0 459.6,85.0 459.6,75.0",[44,1407],{"x":1408,"y":1312,"width":1313,"height":1314,"rx":1315,"fill":1316,"stroke":347,"style":348},"473.6",[1318,1410,1412],{"transform":1411},"translate(519.2,46.5) scale(1.000)",[1322,1413],{"d":1414,"fill":1325,"stroke":1326,"style":1327},"M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z M12 9a3 3 0 1 0 .01 0z",[65,1416,1418],{"x":1417,"y":1331,"style":1332},"531.2","Hide rows",[65,1420,1421],{"x":1417,"y":1336,"style":1337},"row_dimensions",[342,1423],{"x1":1424,"y1":1342,"x2":1425,"y2":1342,"stroke":347,"style":348},"593.8","615.8",[350,1427],{"points":1428,"fill":353},"619.8,80.0 610.8,85.0 610.8,75.0",[44,1430],{"x":1431,"y":1312,"width":1313,"height":1314,"rx":1315,"fill":1432,"stroke":1433,"style":348},"624.8","#fdefd8","var(--gold,#b4740a)",[1318,1435,1437],{"transform":1436},"translate(670.4,29.0) scale(1.000)",[1322,1438],{"d":1439,"fill":1325,"stroke":1440,"style":1327},"M5 9h14 M4 15h14 M10 4l-2 16 M16 4l-2 16","var(--gold-ink,#7a4e06)",[65,1442,699],{"x":1443,"y":1444,"style":1445},"682.4","75.5","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle",[65,1447,1448],{"x":1443,"y":1331,"style":1445},"totals",[65,1450,1451],{"x":1443,"y":1336,"style":1337},"visible rows",[65,1453,1455],{"x":1443,"y":1454,"style":1337},"130.0","only",[369,1457,1459],{"id":1458},"step-3-drive-the-filter-from-pandas","Step 3 — Drive the filter from pandas",[10,1461,1462],{},"When the report is built from a DataFrame, compute the mask with pandas — where the logic is easiest to test — and use it for the hidden rows, writing matching criteria for the dropdowns:",[374,1464,1466],{"className":406,"code":1465,"language":408,"meta":379,"style":379},"import pandas as pd\n\ndf = pd.DataFrame(rows, columns=[\"Order\", \"Region\", \"Amount\"])\nmask = df[\"Region\"].isin([\"North\", \"South\"]) & (df[\"Amount\"] >= 100)\n\nwith pd.ExcelWriter(\"orders_pd.xlsx\", engine=\"openpyxl\") as writer:\n    df.to_excel(writer, sheet_name=\"Orders\", index=False)\n    sheet = writer.sheets[\"Orders\"]\n    sheet.auto_filter.ref = f\"A1:C{len(df) + 1}\"\n    sheet.auto_filter.filterColumn.append(FilterColumn(colId=1, filters=Filters(filter=[\"North\", \"South\"])))\n    sheet.auto_filter.filterColumn.append(FilterColumn(colId=2, customFilters=CustomFilters(\n        customFilter=[CustomFilter(operator=\"greaterThanOrEqual\", val=\"100\")])))\n    for i, keep in enumerate(mask, start=2):\n        sheet.row_dimensions[i].hidden = not keep\nprint(int(mask.sum()), \"rows visible\")          # 2 rows visible\n",[381,1467,1468,1481,1485,1514,1557,1561,1589,1613,1627,1654,1688,1707,1734,1758,1770],{"__ignoreMap":379},[384,1469,1470,1472,1475,1478],{"class":342,"line":386},[384,1471,423],{"class":415},[384,1473,1474],{"class":419}," pandas ",[384,1476,1477],{"class":415},"as",[384,1479,1480],{"class":419}," pd\n",[384,1482,1483],{"class":342,"line":429},[384,1484,446],{"emptyLinePlaceholder":445},[384,1486,1487,1490,1492,1495,1498,1500,1502,1504,1506,1508,1510,1512],{"class":342,"line":442},[384,1488,1489],{"class":419},"df ",[384,1491,455],{"class":415},[384,1493,1494],{"class":419}," pd.DataFrame(rows, ",[384,1496,1497],{"class":741},"columns",[384,1499,455],{"class":415},[384,1501,763],{"class":419},[384,1503,589],{"class":393},[384,1505,464],{"class":419},[384,1507,594],{"class":393},[384,1509,464],{"class":419},[384,1511,599],{"class":393},[384,1513,602],{"class":419},[384,1515,1516,1519,1521,1524,1526,1529,1531,1533,1535,1538,1541,1544,1546,1549,1552,1555],{"class":342,"line":449},[384,1517,1518],{"class":419},"mask ",[384,1520,455],{"class":415},[384,1522,1523],{"class":419}," df[",[384,1525,594],{"class":393},[384,1527,1528],{"class":419},"].isin([",[384,1530,467],{"class":393},[384,1532,464],{"class":419},[384,1534,482],{"class":393},[384,1536,1537],{"class":419},"]) ",[384,1539,1540],{"class":415},"&",[384,1542,1543],{"class":419}," (df[",[384,1545,599],{"class":393},[384,1547,1548],{"class":419},"] ",[384,1550,1551],{"class":415},">=",[384,1553,1554],{"class":461}," 100",[384,1556,1225],{"class":419},[384,1558,1559],{"class":342,"line":505},[384,1560,446],{"emptyLinePlaceholder":445},[384,1562,1563,1566,1569,1572,1574,1577,1579,1582,1584,1586],{"class":342,"line":550},[384,1564,1565],{"class":415},"with",[384,1567,1568],{"class":419}," pd.ExcelWriter(",[384,1570,1571],{"class":393},"\"orders_pd.xlsx\"",[384,1573,464],{"class":419},[384,1575,1576],{"class":741},"engine",[384,1578,455],{"class":415},[384,1580,1581],{"class":393},"\"openpyxl\"",[384,1583,1282],{"class":419},[384,1585,1477],{"class":415},[384,1587,1588],{"class":419}," writer:\n",[384,1590,1591,1594,1597,1599,1601,1603,1606,1608,1611],{"class":342,"line":561},[384,1592,1593],{"class":419},"    df.to_excel(writer, ",[384,1595,1596],{"class":741},"sheet_name",[384,1598,455],{"class":415},[384,1600,1249],{"class":393},[384,1602,464],{"class":419},[384,1604,1605],{"class":741},"index",[384,1607,455],{"class":415},[384,1609,1610],{"class":461},"False",[384,1612,1225],{"class":419},[384,1614,1615,1618,1620,1623,1625],{"class":342,"line":572},[384,1616,1617],{"class":419},"    sheet ",[384,1619,455],{"class":415},[384,1621,1622],{"class":419}," writer.sheets[",[384,1624,1249],{"class":393},[384,1626,1252],{"class":419},[384,1628,1629,1632,1634,1636,1638,1640,1643,1646,1648,1650,1652],{"class":342,"line":583},[384,1630,1631],{"class":419},"    sheet.auto_filter.ref ",[384,1633,455],{"class":415},[384,1635,681],{"class":415},[384,1637,684],{"class":393},[384,1639,659],{"class":658},[384,1641,1642],{"class":461},"len",[384,1644,1645],{"class":419},"(df) ",[384,1647,1164],{"class":415},[384,1649,1167],{"class":461},[384,1651,665],{"class":658},[384,1653,693],{"class":393},[384,1655,1656,1659,1661,1663,1665,1667,1669,1671,1673,1675,1677,1679,1681,1683,1685],{"class":342,"line":605},[384,1657,1658],{"class":419},"    sheet.auto_filter.filterColumn.append(FilterColumn(",[384,1660,714],{"class":741},[384,1662,455],{"class":415},[384,1664,95],{"class":461},[384,1666,464],{"class":419},[384,1668,750],{"class":741},[384,1670,455],{"class":415},[384,1672,755],{"class":419},[384,1674,758],{"class":741},[384,1676,455],{"class":415},[384,1678,763],{"class":419},[384,1680,467],{"class":393},[384,1682,464],{"class":419},[384,1684,482],{"class":393},[384,1686,1687],{"class":419},"])))\n",[384,1689,1690,1692,1694,1696,1698,1700,1702,1704],{"class":342,"line":620},[384,1691,1658],{"class":419},[384,1693,714],{"class":741},[384,1695,455],{"class":415},[384,1697,118],{"class":461},[384,1699,464],{"class":419},[384,1701,792],{"class":741},[384,1703,455],{"class":415},[384,1705,1706],{"class":419},"CustomFilters(\n",[384,1708,1709,1712,1714,1717,1719,1721,1723,1725,1727,1729,1731],{"class":342,"line":626},[384,1710,1711],{"class":741},"        customFilter",[384,1713,455],{"class":415},[384,1715,1716],{"class":419},"[CustomFilter(",[384,1718,813],{"class":741},[384,1720,455],{"class":415},[384,1722,818],{"class":393},[384,1724,464],{"class":419},[384,1726,823],{"class":741},[384,1728,455],{"class":415},[384,1730,828],{"class":393},[384,1732,1733],{"class":419},")])))\n",[384,1735,1736,1738,1741,1743,1746,1749,1752,1754,1756],{"class":342,"line":637},[384,1737,972],{"class":415},[384,1739,1740],{"class":419}," i, keep ",[384,1742,614],{"class":415},[384,1744,1745],{"class":461}," enumerate",[384,1747,1748],{"class":419},"(mask, ",[384,1750,1751],{"class":741},"start",[384,1753,455],{"class":415},[384,1755,118],{"class":461},[384,1757,1170],{"class":419},[384,1759,1760,1763,1765,1767],{"class":342,"line":673},[384,1761,1762],{"class":419},"        sheet.row_dimensions[i].hidden ",[384,1764,455],{"class":415},[384,1766,1004],{"class":415},[384,1768,1769],{"class":419}," keep\n",[384,1771,1772,1774,1776,1779,1782,1785,1788],{"class":342,"line":1121},[384,1773,1258],{"class":461},[384,1775,1156],{"class":419},[384,1777,1778],{"class":461},"int",[384,1780,1781],{"class":419},"(mask.sum()), ",[384,1783,1784],{"class":393},"\"rows visible\"",[384,1786,1787],{"class":419},")          ",[384,1789,1790],{"class":1290},"# 2 rows visible\n",[10,1792,1793,1794,1797,1798,1801,1802,23],{},"Row ",[381,1795,1796],{},"i + 2"," of the sheet is DataFrame row ",[381,1799,1800],{},"i"," because of the header — keep that offset in one place. If the pandas mask and the written criteria ever disagree, Excel will show one thing until the reader touches the filter and another after, so a test that compares them is worth the few lines. Reading such a sheet back while respecting the hidden rows is covered in ",[14,1803,1805],{"href":1804},"\u002Fadvanced-data-transformation-and-cleaning\u002Fextracting-data-from-messy-excel-sheets\u002Fskip-hidden-and-filtered-rows-when-reading-excel\u002F","Skip Hidden and Filtered Rows When Reading Excel",[369,1807,1809],{"id":1808},"step-4-clear-a-filter","Step 4 — Clear a filter",[10,1811,1812],{},"Removing a filter means undoing both halves: drop the criteria and unhide the rows. Leaving rows hidden under a filter with no criteria produces a sheet where rows are missing for no visible reason:",[374,1814,1816],{"className":406,"code":1815,"language":408,"meta":379,"style":379},"wb = load_workbook(\"orders_filtered.xlsx\")\nws = wb[\"Orders\"]\nws.auto_filter.filterColumn = []\nfor r in range(2, ws.max_row + 1):\n    ws.row_dimensions[r].hidden = False\nwb.save(\"orders_unfiltered.xlsx\")\nprint(sum(load_workbook(\"orders_unfiltered.xlsx\")[\"Orders\"].row_dimensions[r].hidden\n          for r in range(2, 8)))                  # 0\n",[381,1817,1818,1830,1843,1853,1876,1884,1893,1914],{"__ignoreMap":379},[384,1819,1820,1822,1824,1826,1828],{"class":342,"line":386},[384,1821,553],{"class":419},[384,1823,455],{"class":415},[384,1825,1241],{"class":419},[384,1827,1222],{"class":393},[384,1829,1225],{"class":419},[384,1831,1832,1834,1836,1839,1841],{"class":342,"line":429},[384,1833,564],{"class":419},[384,1835,455],{"class":415},[384,1837,1838],{"class":419}," wb[",[384,1840,1249],{"class":393},[384,1842,1252],{"class":419},[384,1844,1845,1848,1850],{"class":342,"line":442},[384,1846,1847],{"class":419},"ws.auto_filter.filterColumn ",[384,1849,455],{"class":415},[384,1851,1852],{"class":419}," []\n",[384,1854,1855,1857,1859,1861,1863,1865,1867,1870,1872,1874],{"class":342,"line":449},[384,1856,608],{"class":415},[384,1858,1148],{"class":419},[384,1860,614],{"class":415},[384,1862,1153],{"class":461},[384,1864,1156],{"class":419},[384,1866,118],{"class":461},[384,1868,1869],{"class":419},", ws.max_row ",[384,1871,1164],{"class":415},[384,1873,1167],{"class":461},[384,1875,1170],{"class":419},[384,1877,1878,1880,1882],{"class":342,"line":505},[384,1879,1206],{"class":419},[384,1881,455],{"class":415},[384,1883,1033],{"class":461},[384,1885,1886,1888,1891],{"class":342,"line":550},[384,1887,1219],{"class":419},[384,1889,1890],{"class":393},"\"orders_unfiltered.xlsx\"",[384,1892,1225],{"class":419},[384,1894,1895,1897,1899,1902,1905,1907,1909,1911],{"class":342,"line":561},[384,1896,1258],{"class":461},[384,1898,1156],{"class":419},[384,1900,1901],{"class":461},"sum",[384,1903,1904],{"class":419},"(load_workbook(",[384,1906,1890],{"class":393},[384,1908,1246],{"class":419},[384,1910,1249],{"class":393},[384,1912,1913],{"class":419},"].row_dimensions[r].hidden\n",[384,1915,1916,1919,1921,1923,1925,1927,1929,1931,1934,1937],{"class":342,"line":572},[384,1917,1918],{"class":415},"          for",[384,1920,1148],{"class":419},[384,1922,614],{"class":415},[384,1924,1153],{"class":461},[384,1926,1156],{"class":419},[384,1928,118],{"class":461},[384,1930,464],{"class":419},[384,1932,1933],{"class":461},"8",[384,1935,1936],{"class":419},")))                  ",[384,1938,1939],{"class":1290},"# 0\n",[10,1941,1942,1943,1946],{},"The autofilter range stays, so readers still get the dropdowns. To remove the dropdowns too, set ",[381,1944,1945],{},"ws.auto_filter.ref = None",". Clearing is also the right first step when re-filtering an existing workbook: start from all rows visible, then apply the new criteria, so no row stays hidden by an old rule.",[25,1948,34,1953,34,1956,34,1959,34,1962,34,1967,34,1973,34,1979,34,1983,34,1987,34,1994,34,1998,34,2003,34,2007,34,2014,34,2017,34,2022,34,2027,34,2031,34,2035,34,2040,34,2043,34,2048,34,2051],{"viewBox":1949,"role":28,"ariaLabelledBy":1950,"xmlns":32,"style":33},"4 0 752 207",[1951,1952],"af-halves-t","af-halves-d",[36,1954,1955],{"id":1951},"The two halves of an applied filter",[40,1957,1958],{"id":1952},"The filter criteria are what Excel's dropdowns show and what Excel uses when the reader changes the filter. The hidden rows are what the reader sees on opening. openpyxl writes the criteria when asked but never hides rows, so both halves must be written together and cleared together.",[44,1960],{"x":46,"y":47,"width":48,"height":1961,"fill":50},"207",[44,1963],{"x":53,"y":1312,"width":1964,"height":1965,"rx":1966,"fill":1316,"stroke":347,"style":348},"351.0","175.0","14",[1318,1968,1970],{"transform":1969},"translate(182.5,29.0) scale(1.083)",[1322,1971],{"d":1324,"fill":1325,"stroke":1326,"style":1972},"stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[65,1974,1978],{"x":1975,"y":1976,"style":1977},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Criteria (auto_filter.filterColumn)",[342,1980],{"x1":93,"y1":1981,"x2":1982,"y2":1981,"stroke":347,"style":59},"91.0","355.0",[65,1984,1986],{"x":255,"y":117,"style":1985},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","dropdowns show the filter",[1318,1988,1990],{"transform":1989},"translate(38.5,99.5) scale(0.625)",[1322,1991],{"d":1992,"fill":1325,"stroke":1379,"style":1993},"M5 12.5l4.5 4.5L19 7","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[65,1995,1997],{"x":255,"y":1996,"style":1985},"137.0","Excel reapplies on change",[1318,1999,2001],{"transform":2000},"translate(38.5,125.5) scale(0.625)",[1322,2002],{"d":1992,"fill":1325,"stroke":1379,"style":1993},[65,2004,2006],{"x":255,"y":2005,"style":1985},"163.0","hides nothing by itself",[1318,2008,2010],{"transform":2009},"translate(38.5,151.5) scale(0.625)",[1322,2011],{"d":2012,"fill":1325,"stroke":2013,"style":1993},"M6 6l12 12 M18 6L6 18","var(--accent,#f43f8f)",[44,2015],{"x":2016,"y":1312,"width":1964,"height":1965,"rx":1966,"fill":1378,"stroke":1379,"style":348},"389.0",[1318,2018,2020],{"transform":2019},"translate(551.5,29.0) scale(1.083)",[1322,2021],{"d":1414,"fill":1325,"stroke":1386,"style":1972},[65,2023,2026],{"x":2024,"y":1976,"style":2025},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Hidden rows (row_dimensions)",[342,2028],{"x1":2029,"y1":1981,"x2":2030,"y2":1981,"stroke":1379,"style":59},"405.0","724.0",[65,2032,2034],{"x":2033,"y":117,"style":1985},"429.0","what readers see on opening",[1318,2036,2038],{"transform":2037},"translate(407.5,99.5) scale(0.625)",[1322,2039],{"d":1992,"fill":1325,"stroke":1379,"style":1993},[65,2041,2042],{"x":2033,"y":1996,"style":1985},"SUBTOTAL respects them",[1318,2044,2046],{"transform":2045},"translate(407.5,125.5) scale(0.625)",[1322,2047],{"d":1992,"fill":1325,"stroke":1379,"style":1993},[65,2049,2050],{"x":2033,"y":2005,"style":1985},"invisible without criteria",[1318,2052,2054],{"transform":2053},"translate(407.5,151.5) scale(0.625)",[1322,2055],{"d":2012,"fill":1325,"stroke":2013,"style":1993},[369,2057,2059],{"id":2058},"step-5-top-n-filters","Step 5 — Top-N filters",[10,2061,2062,2063,2066,2067,2070],{},"Excel's \"Top 10\" filter shows the largest (or smallest) N values or N percent. openpyxl writes it with ",[381,2064,2065],{},"Top10","; as before, the hiding is up to you, and pandas' ",[381,2068,2069],{},"nlargest"," gives the rows to keep:",[374,2072,2074],{"className":406,"code":2073,"language":408,"meta":379,"style":379},"from openpyxl.worksheet.filters import Top10\n\nwb = Workbook()\nws = wb.active\nws.append([\"Order\", \"Region\", \"Amount\"])\nfor row in rows:\n    ws.append(row)\nws.auto_filter.ref = f\"A1:C{len(rows) + 1}\"\nws.auto_filter.filterColumn.append(FilterColumn(colId=2, top10=Top10(top=True, val=3)))\n\nkeep = set(df.nlargest(3, \"Amount\").index)\nfor i in range(len(df)):\n    ws.row_dimensions[i + 2].hidden = i not in keep\nwb.save(\"orders_top3.xlsx\")\nprint(sorted(df.loc[list(keep), \"Order\"]))       # [101, 105, 106]\n",[381,2075,2076,2087,2091,2099,2107,2123,2133,2137,2162,2202,2206,2228,2246,2269,2278],{"__ignoreMap":379},[384,2077,2078,2080,2082,2084],{"class":342,"line":386},[384,2079,416],{"class":415},[384,2081,434],{"class":419},[384,2083,423],{"class":415},[384,2085,2086],{"class":419}," Top10\n",[384,2088,2089],{"class":342,"line":429},[384,2090,446],{"emptyLinePlaceholder":445},[384,2092,2093,2095,2097],{"class":342,"line":442},[384,2094,553],{"class":419},[384,2096,455],{"class":415},[384,2098,558],{"class":419},[384,2100,2101,2103,2105],{"class":342,"line":449},[384,2102,564],{"class":419},[384,2104,455],{"class":415},[384,2106,569],{"class":419},[384,2108,2109,2111,2113,2115,2117,2119,2121],{"class":342,"line":505},[384,2110,586],{"class":419},[384,2112,589],{"class":393},[384,2114,464],{"class":419},[384,2116,594],{"class":393},[384,2118,464],{"class":419},[384,2120,599],{"class":393},[384,2122,602],{"class":419},[384,2124,2125,2127,2129,2131],{"class":342,"line":550},[384,2126,608],{"class":415},[384,2128,611],{"class":419},[384,2130,614],{"class":415},[384,2132,617],{"class":419},[384,2134,2135],{"class":342,"line":561},[384,2136,623],{"class":419},[384,2138,2139,2141,2143,2145,2147,2149,2151,2154,2156,2158,2160],{"class":342,"line":572},[384,2140,676],{"class":419},[384,2142,455],{"class":415},[384,2144,681],{"class":415},[384,2146,684],{"class":393},[384,2148,659],{"class":658},[384,2150,1642],{"class":461},[384,2152,2153],{"class":419},"(rows) ",[384,2155,1164],{"class":415},[384,2157,1167],{"class":461},[384,2159,665],{"class":658},[384,2161,693],{"class":393},[384,2163,2164,2167,2169,2171,2173,2175,2178,2180,2183,2186,2188,2191,2193,2195,2197,2199],{"class":342,"line":583},[384,2165,2166],{"class":419},"ws.auto_filter.filterColumn.append(FilterColumn(",[384,2168,714],{"class":741},[384,2170,455],{"class":415},[384,2172,118],{"class":461},[384,2174,464],{"class":419},[384,2176,2177],{"class":741},"top10",[384,2179,455],{"class":415},[384,2181,2182],{"class":419},"Top10(",[384,2184,2185],{"class":741},"top",[384,2187,455],{"class":415},[384,2189,2190],{"class":461},"True",[384,2192,464],{"class":419},[384,2194,823],{"class":741},[384,2196,455],{"class":415},[384,2198,141],{"class":461},[384,2200,2201],{"class":419},")))\n",[384,2203,2204],{"class":342,"line":605},[384,2205,446],{"emptyLinePlaceholder":445},[384,2207,2208,2211,2213,2216,2219,2221,2223,2225],{"class":342,"line":620},[384,2209,2210],{"class":419},"keep ",[384,2212,455],{"class":415},[384,2214,2215],{"class":461}," set",[384,2217,2218],{"class":419},"(df.nlargest(",[384,2220,141],{"class":461},[384,2222,464],{"class":419},[384,2224,599],{"class":393},[384,2226,2227],{"class":419},").index)\n",[384,2229,2230,2232,2235,2237,2239,2241,2243],{"class":342,"line":626},[384,2231,608],{"class":415},[384,2233,2234],{"class":419}," i ",[384,2236,614],{"class":415},[384,2238,1153],{"class":461},[384,2240,1156],{"class":419},[384,2242,1642],{"class":461},[384,2244,2245],{"class":419},"(df)):\n",[384,2247,2248,2251,2253,2256,2259,2261,2263,2265,2267],{"class":342,"line":637},[384,2249,2250],{"class":419},"    ws.row_dimensions[i ",[384,2252,1164],{"class":415},[384,2254,2255],{"class":461}," 2",[384,2257,2258],{"class":419},"].hidden ",[384,2260,455],{"class":415},[384,2262,2234],{"class":419},[384,2264,1019],{"class":415},[384,2266,1022],{"class":415},[384,2268,1769],{"class":419},[384,2270,2271,2273,2276],{"class":342,"line":673},[384,2272,1219],{"class":419},[384,2274,2275],{"class":393},"\"orders_top3.xlsx\"",[384,2277,1225],{"class":419},[384,2279,2280,2282,2284,2287,2290,2293,2296,2298,2301],{"class":342,"line":1121},[384,2281,1258],{"class":461},[384,2283,1156],{"class":419},[384,2285,2286],{"class":461},"sorted",[384,2288,2289],{"class":419},"(df.loc[",[384,2291,2292],{"class":461},"list",[384,2294,2295],{"class":419},"(keep), ",[384,2297,589],{"class":393},[384,2299,2300],{"class":419},"]))       ",[384,2302,2303],{"class":1290},"# [101, 105, 106]\n",[10,2305,2306,2307,2310,2311,2314,2315,2317,2318,2320,2321,2324,2325,2328],{},"The three largest orders — 1,500, 1,200 and 820 — stay visible. ",[381,2308,2309],{},"top=False"," gives the bottom N, and ",[381,2312,2313],{},"percent=True"," makes ",[381,2316,823],{}," a percentage of the rows. Ties need a decision: Excel shows every row tied with the Nth value, while ",[381,2319,2069],{}," keeps exactly N unless you pass ",[381,2322,2323],{},"keep=\"all\"",", which matches Excel's behaviour. Date filters such as \"this month\" (",[381,2326,2327],{},"DynamicFilter",") follow the same pattern — write the dynamic filter, compute the date range in Python, hide the rest — but remember that a dynamic filter is re-evaluated against the date when the reader reapplies it, while your hidden rows reflect the day the file was written.",[369,2330,2332],{"id":2331},"common-pitfalls","Common pitfalls",[2334,2335,2336,2348,2354,2370],"ul",{},[2337,2338,2339,2343,2344,2347],"li",{},[2340,2341,2342],"strong",{},"colId as a sheet column."," For a filter range starting in column C, the first column is ",[381,2345,2346],{},"colId=0",", not 2.",[2337,2349,2350,2353],{},[2340,2351,2352],{},"Filters on a sheet that pandas rewrites."," Writing the DataFrame again after setting the filter replaces the sheet and loses both the criteria and the hidden rows. Apply filters last.",[2337,2355,2356,2359,2360,2363,2364,2366,2367,2369],{},[2340,2357,2358],{},"Numbers as values in Filters."," ",[381,2361,2362],{},"Filters(filter=[...])"," matches displayed text; for numeric conditions use ",[381,2365,722],{},", whose ",[381,2368,823],{}," is compared numerically.",[2337,2371,2372,2375,2376,23],{},[2340,2373,2374],{},"Totals inside the filter range."," A total row inside the range can itself be hidden by the filter. Keep it below the range or in a table's totals row, as in ",[14,2377,2379],{"href":2378},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fadd-a-total-row-to-an-excel-table\u002F","Add a Total Row to an Excel Table with Python",[369,2381,2383],{"id":2382},"conclusion","Conclusion",[10,2385,2386,2387,2389,2390,2392,2393,2395,2396,2399,2400,2403,2404,2406],{},"openpyxl's autofilter records criteria but never hides rows. Describe the criteria once as ",[381,2388,710],{}," objects with ",[381,2391,718],{}," for value lists and ",[381,2394,722],{}," for comparisons, write them to ",[381,2397,2398],{},"ws.auto_filter",", evaluate the same criteria in Python — or with a pandas mask — and hide the rows that fail with ",[381,2401,2402],{},"row_dimensions[row].hidden",". Keep ",[381,2405,699],{}," totals outside the range so they sum what readers see, and clear both halves together when removing a filter.",[369,2408,2410],{"id":2409},"frequently-asked-questions","Frequently asked questions",[10,2412,2413,2416,2417,2420],{},[2340,2414,2415],{},"Why does my openpyxl autofilter not hide any rows?","\nopenpyxl only writes the filter settings into the file. Hiding rows is something Excel does when a user applies a filter; the saved file stores hidden rows separately, as row properties. Set row_dimensions",[384,2418,2419],{},"row",".hidden for the rows that do not match.",[10,2422,2423,2426,2427,2430],{},[2340,2424,2425],{},"How do I filter for several values in one column?","\nAdd a FilterColumn with Filters(filter=",[384,2428,2429],{},"...",") listing the values to show. Its colId is the zero-based position of the column within the autofilter range, not the sheet column letter.",[10,2432,2433,2436],{},[2340,2434,2435],{},"How do I filter numbers greater than a value?","\nUse CustomFilters with a CustomFilter such as operator=\"greaterThanOrEqual\" and val=\"100\". Two custom filters in one column can be combined with _and=True so both must hold.",[10,2438,2439,2442],{},[2340,2440,2441],{},"Will the filter still work in Excel after I hide rows myself?","\nYes. Excel sees an active filter with its criteria and rows already hidden to match. When the reader clears or changes the filter, Excel recalculates which rows to show from the data.",[369,2444,2446],{"id":2445},"related","Related",[2334,2448,2449,2455,2462,2469],{},[2337,2450,2451,2452,2454],{},"Up one level: ",[14,2453,17],{"href":16}," — tables, filters and grouping.",[2337,2456,2457,2461],{},[14,2458,2460],{"href":2459},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fgroup-and-outline-rows-in-excel-with-openpyxl\u002F","Group and Outline Rows in Excel with openpyxl"," — another way to hide and show rows.",[2337,2463,2464,2468],{},[14,2465,2467],{"href":2466},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fsort-excel-rows-with-python-before-writing\u002F","Sort Excel Rows with Python Before Writing"," — ordering what the filter shows.",[2337,2470,2471,2475],{},[14,2472,2474],{"href":2473},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-an-entire-row-based-on-a-cell-value-with-openpyxl\u002F","Highlight an Entire Row Based on a Cell Value with openpyxl"," — marking rows instead of hiding them.",[2477,2478,2479],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}",{"title":379,"searchDepth":429,"depth":429,"links":2481},[2482,2483,2484,2485,2486,2487,2488,2489,2490,2491],{"id":371,"depth":429,"text":372},{"id":703,"depth":429,"text":704},{"id":878,"depth":429,"text":879},{"id":1458,"depth":429,"text":1459},{"id":1808,"depth":429,"text":1809},{"id":2058,"depth":429,"text":2059},{"id":2331,"depth":429,"text":2332},{"id":2382,"depth":429,"text":2383},{"id":2409,"depth":429,"text":2410},{"id":2445,"depth":429,"text":2446},"2026-09-23","openpyxl can record autofilter criteria, but it never hides a row — the file opens showing everything under a filter that claims otherwise. Write the criteria and hide the non-matching rows yourself so the workbook opens already filtered, with SUBTOTAL totals that match what readers see.","md",[2496,2498,2500,2502],{"q":2415,"a":2497},"openpyxl only writes the filter settings into the file. Hiding rows is something Excel does when a user applies a filter; the saved file stores hidden rows separately, as row properties. Set row_dimensions[row].hidden for the rows that do not match.",{"q":2425,"a":2499},"Add a FilterColumn with Filters(filter=[...]) listing the values to show. Its colId is the zero-based position of the column within the autofilter range, not the sheet column letter.",{"q":2435,"a":2501},"Use CustomFilters with a CustomFilter such as operator=\"greaterThanOrEqual\" and val=\"100\". Two custom filters in one column can be combined with _and=True so both must hold.",{"q":2441,"a":2503},"Yes. Excel sees an active filter with its criteria and rows already hidden to match. When the reader clears or changes the filter, Excel recalculates which rows to show from the data.","apply autofilter criteria and hide the filtered rows with openpyxl",null,{"breadcrumb":2507},[2508,2511,2514],{"name":2509,"item":2510},"Home","\u002F",{"name":2512,"item":2513},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":17,"item":16},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fapply-autofilter-criteria-and-hide-rows",{"title":2517,"description":2518},"Apply Autofilter Criteria and Hide Rows with openpyxl","Make an openpyxl autofilter actually filter — FilterColumn with Filters and CustomFilters, evaluating the same criteria in Python, row_dimensions hidden, SUBTOTAL totals for visible rows, clearing a filter, and a pandas-driven version.","apply-autofilter-criteria-and-hide-rows","formatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fapply-autofilter-criteria-and-hide-rows\u002Findex",[2522,2523],"tables-and-filters","openpyxl","how-to","OtBxg4ZI7HqKQ0nIh1wUdQSb4iPWInDpmz6vCJsqz9U",[2527,2531],{"title":2528,"path":2529,"stem":2530,"children":-1},"Append Rows to an Excel Table and Resize It with openpyxl","\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fappend-rows-to-an-excel-table-and-resize-it","formatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fappend-rows-to-an-excel-table-and-resize-it\u002Findex",{"title":2532,"path":2533,"stem":2534,"children":-1},"Choose and Customise Excel Table Styles with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fchoose-and-customise-excel-table-styles-with-python","formatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fchoose-and-customise-excel-table-styles-with-python\u002Findex",[2536,2538],{"path":2537,"title":17},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python",{"path":2539,"title":2512},"\u002Fformatting-and-charting-excel-reports-with-python",[],[2542,2545,2548,2551,2554,2556],{"path":2543,"title":2544,"kind":2524},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fapply-conditional-formatting-to-an-excel-table-that-grows","Apply Conditional Formatting to an Excel Table That Grows",{"path":2546,"title":2547,"kind":2524},"\u002Fautomating-reporting-workflows\u002Fautomating-excel-online-with-microsoft-graph\u002Fsort-and-filter-an-excel-online-table-with-microsoft-graph","Sort and Filter an Excel Online Table with Microsoft Graph",{"path":2549,"title":2550,"kind":2524},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-an-excel-table-with-formula-columns-using-xlsxwriter","Write an Excel Table with Formula Columns Using XlsxWriter",{"path":2552,"title":2553,"kind":2524},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002Fmake-an-excel-chart-grow-with-its-data","Make an Excel Chart Grow with Its Data",{"path":2555,"title":2379,"kind":2524},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fadd-a-total-row-to-an-excel-table",{"path":2557,"title":22,"kind":2524},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fadd-an-autofilter-to-an-excel-sheet-with-openpyxl",1790972116364]