[{"data":1,"prerenderedAt":2398},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fstyle-whole-columns-and-rows-efficiently-with-openpyxl":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fstyle-whole-columns-and-rows-efficiently-with-openpyxl":2364,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fstyle-whole-columns-and-rows-efficiently-with-openpyxl":2373,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fstyle-whole-columns-and-rows-efficiently-with-openpyxl":2378,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fstyle-whole-columns-and-rows-efficiently-with-openpyxl":2379},{"id":4,"title":5,"body":6,"dateModified":2332,"datePublished":2332,"description":2333,"extension":2334,"faq":2335,"keyword":2344,"kind":2345,"meta":2346,"navigation":152,"path":2354,"seo":2355,"slug":2357,"stem":2358,"topics":2359,"type":2362,"__hash__":2363},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fstyle-whole-columns-and-rows-efficiently-with-openpyxl\u002Findex.md","Style Whole Columns and Rows Efficiently with openpyxl",{"type":7,"value":8,"toc":2322},"minimark",[9,37,42,70,81,85,88,795,806,817,927,931,934,1536,1546,1618,1622,1625,2066,2088,2201,2205,2243,2247,2257,2261,2267,2273,2279,2285,2289,2318],[10,11,12,13,17,18,22,23,26,27,30,31,36],"p",{},"Formatting a report column — bold amounts, a currency format, a fill on the header row — is easy in openpyxl for a few hundred cells and noticeably slow for a few hundred thousand. Two tempting shortcuts cause trouble. The first is styling the ",[14,15,16],"em",{},"column"," itself through ",[19,20,21],"code",{},"ws.column_dimensions",", which looks like Excel's \"select column, click Bold\" but does not do what that does: cells that already hold data keep their own formatting. The second is creating a fresh ",[19,24,25],{},"Font"," or ",[19,28,29],{},"PatternFill"," object for every cell inside the loop, which works but wastes most of the run time. This page shows what column and row styles really change, measures the cost of the common ways of styling many cells, and settles on an approach that is both correct and fast: style the cells in the used range, with shared style objects or a named style, and use column and row styles only for the cells people will add later. It belongs to ",[32,33,35],"a",{"href":34},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002F","Styling Excel Cells with openpyxl",".",[38,39,41],"h2",{"id":40},"prerequisites","Prerequisites",[43,44,49],"pre",{"className":45,"code":46,"language":47,"meta":48,"style":48},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install openpyxl pillow\n","bash","",[19,50,51],{"__ignoreMap":48},[52,53,56,60,64,67],"span",{"class":54,"line":55},"line",1,[52,57,59],{"class":58},"sMTad","pip",[52,61,63],{"class":62},"srMev"," install",[52,65,66],{"class":62}," openpyxl",[52,68,69],{"class":62}," pillow\n",[10,71,72,73,76,77,80],{},"LibreOffice (",[19,74,75],{},"soffice",") and ",[19,78,79],{},"pdftoppm"," render workbooks in Step 1 to show what a column style does to existing cells. Timings in Step 2 come from the machine that built this page; the ratios between methods matter more than the absolute numbers.",[38,82,84],{"id":83},"step-1-what-a-column-style-does-and-does-not-do","Step 1 — What a column style does, and does not, do",[10,86,87],{},"Write a small sheet, give column B a bold dark-blue font through its column dimension, and give column C the same font cell by cell; then render it:",[43,89,93],{"className":90,"code":91,"language":92,"meta":48,"style":48},"language-python shiki shiki-themes github-light github-dark-high-contrast","import subprocess\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\nfrom PIL import Image\n\nBLUE = \"1F3864\"\nwb = Workbook()\nws = wb.active\nws.append([\"Item\", \"Via column style\", \"Via cell style\"])\nfor i in range(1, 21):\n    ws.append([f\"Item {i}\", i * 1000.5, i * 1000.5])\nws.column_dimensions[\"B\"].font = Font(name=\"Calibri\", bold=True, color=BLUE, size=14)\nfor (cell,) in ws.iter_rows(min_row=2, min_col=3, max_col=3):\n    cell.font = Font(name=\"Calibri\", bold=True, color=BLUE, size=14)\nfor col in \"BC\":\n    ws.column_dimensions[col].width = 18\nwb.save(\"column_style.xlsx\")\n\nsubprocess.run([\"soffice\", \"--headless\", \"--convert-to\", \"pdf\", \"column_style.xlsx\"], check=True, capture_output=True)\nsubprocess.run([\"pdftoppm\", \"-png\", \"-r\", \"100\", \"-f\", \"1\", \"-l\", \"1\", \"column_style.pdf\", \"colstyle\"], check=True)\nimg = Image.open(\"colstyle-1.png\").convert(\"RGB\")\nw = img.width\ndef blue_pixels(x0, x1):\n    return sum(1 for x in range(int(x0), int(x1)) for y in range(img.height) if img.getpixel((x, y)) == (0x1F, 0x38, 0x64))\nprint(\"rendered blue px — column B:\", blue_pixels(w * 0.15, w * 0.34), \"| column C:\", blue_pixels(w * 0.34, w * 0.5))\nprint(\"cell fonts as stored — B2:\", ws[\"B2\"].font.b, ws[\"B2\"].font.sz, \"| C2:\", ws[\"C2\"].font.b, ws[\"C2\"].font.sz)\n","python",[19,94,95,105,119,132,147,154,166,178,189,212,241,283,341,383,425,441,452,463,468,517,579,601,612,625,708,756],{"__ignoreMap":48},[52,96,97,101],{"class":54,"line":55},[52,98,100],{"class":99},"s-kum","import",[52,102,104],{"class":103},"skGVy"," subprocess\n",[52,106,108,111,114,116],{"class":54,"line":107},2,[52,109,110],{"class":99},"from",[52,112,113],{"class":103}," openpyxl ",[52,115,100],{"class":99},[52,117,118],{"class":103}," Workbook\n",[52,120,122,124,127,129],{"class":54,"line":121},3,[52,123,110],{"class":99},[52,125,126],{"class":103}," openpyxl.styles ",[52,128,100],{"class":99},[52,130,131],{"class":103}," Font\n",[52,133,135,137,141,144],{"class":54,"line":134},4,[52,136,110],{"class":99},[52,138,140],{"class":139},"sP0c6"," PIL",[52,142,143],{"class":99}," import",[52,145,146],{"class":103}," Image\n",[52,148,150],{"class":54,"line":149},5,[52,151,153],{"emptyLinePlaceholder":152},true,"\n",[52,155,157,160,163],{"class":54,"line":156},6,[52,158,159],{"class":139},"BLUE",[52,161,162],{"class":99}," =",[52,164,165],{"class":62}," \"1F3864\"\n",[52,167,169,172,175],{"class":54,"line":168},7,[52,170,171],{"class":103},"wb ",[52,173,174],{"class":99},"=",[52,176,177],{"class":103}," Workbook()\n",[52,179,181,184,186],{"class":54,"line":180},8,[52,182,183],{"class":103},"ws ",[52,185,174],{"class":99},[52,187,188],{"class":103}," wb.active\n",[52,190,192,195,198,201,204,206,209],{"class":54,"line":191},9,[52,193,194],{"class":103},"ws.append([",[52,196,197],{"class":62},"\"Item\"",[52,199,200],{"class":103},", ",[52,202,203],{"class":62},"\"Via column style\"",[52,205,200],{"class":103},[52,207,208],{"class":62},"\"Via cell style\"",[52,210,211],{"class":103},"])\n",[52,213,215,218,221,224,227,230,233,235,238],{"class":54,"line":214},10,[52,216,217],{"class":99},"for",[52,219,220],{"class":103}," i ",[52,222,223],{"class":99},"in",[52,225,226],{"class":139}," range",[52,228,229],{"class":103},"(",[52,231,232],{"class":139},"1",[52,234,200],{"class":103},[52,236,237],{"class":139},"21",[52,239,240],{"class":103},"):\n",[52,242,244,247,250,253,257,260,263,266,269,272,275,277,279,281],{"class":54,"line":243},11,[52,245,246],{"class":103},"    ws.append([",[52,248,249],{"class":99},"f",[52,251,252],{"class":62},"\"Item ",[52,254,256],{"class":255},"sSjpA","{",[52,258,259],{"class":103},"i",[52,261,262],{"class":255},"}",[52,264,265],{"class":62},"\"",[52,267,268],{"class":103},", i ",[52,270,271],{"class":99},"*",[52,273,274],{"class":139}," 1000.5",[52,276,268],{"class":103},[52,278,271],{"class":99},[52,280,274],{"class":139},[52,282,211],{"class":103},[52,284,286,289,292,295,297,300,304,306,309,311,314,316,319,321,324,326,328,330,333,335,338],{"class":54,"line":285},12,[52,287,288],{"class":103},"ws.column_dimensions[",[52,290,291],{"class":62},"\"B\"",[52,293,294],{"class":103},"].font ",[52,296,174],{"class":99},[52,298,299],{"class":103}," Font(",[52,301,303],{"class":302},"sa561","name",[52,305,174],{"class":99},[52,307,308],{"class":62},"\"Calibri\"",[52,310,200],{"class":103},[52,312,313],{"class":302},"bold",[52,315,174],{"class":99},[52,317,318],{"class":139},"True",[52,320,200],{"class":103},[52,322,323],{"class":302},"color",[52,325,174],{"class":99},[52,327,159],{"class":139},[52,329,200],{"class":103},[52,331,332],{"class":302},"size",[52,334,174],{"class":99},[52,336,337],{"class":139},"14",[52,339,340],{"class":103},")\n",[52,342,344,346,349,351,354,357,359,362,364,367,369,372,374,377,379,381],{"class":54,"line":343},13,[52,345,217],{"class":99},[52,347,348],{"class":103}," (cell,) ",[52,350,223],{"class":99},[52,352,353],{"class":103}," ws.iter_rows(",[52,355,356],{"class":302},"min_row",[52,358,174],{"class":99},[52,360,361],{"class":139},"2",[52,363,200],{"class":103},[52,365,366],{"class":302},"min_col",[52,368,174],{"class":99},[52,370,371],{"class":139},"3",[52,373,200],{"class":103},[52,375,376],{"class":302},"max_col",[52,378,174],{"class":99},[52,380,371],{"class":139},[52,382,240],{"class":103},[52,384,386,389,391,393,395,397,399,401,403,405,407,409,411,413,415,417,419,421,423],{"class":54,"line":385},14,[52,387,388],{"class":103},"    cell.font ",[52,390,174],{"class":99},[52,392,299],{"class":103},[52,394,303],{"class":302},[52,396,174],{"class":99},[52,398,308],{"class":62},[52,400,200],{"class":103},[52,402,313],{"class":302},[52,404,174],{"class":99},[52,406,318],{"class":139},[52,408,200],{"class":103},[52,410,323],{"class":302},[52,412,174],{"class":99},[52,414,159],{"class":139},[52,416,200],{"class":103},[52,418,332],{"class":302},[52,420,174],{"class":99},[52,422,337],{"class":139},[52,424,340],{"class":103},[52,426,428,430,433,435,438],{"class":54,"line":427},15,[52,429,217],{"class":99},[52,431,432],{"class":103}," col ",[52,434,223],{"class":99},[52,436,437],{"class":62}," \"BC\"",[52,439,440],{"class":103},":\n",[52,442,444,447,449],{"class":54,"line":443},16,[52,445,446],{"class":103},"    ws.column_dimensions[col].width ",[52,448,174],{"class":99},[52,450,451],{"class":139}," 18\n",[52,453,455,458,461],{"class":54,"line":454},17,[52,456,457],{"class":103},"wb.save(",[52,459,460],{"class":62},"\"column_style.xlsx\"",[52,462,340],{"class":103},[52,464,466],{"class":54,"line":465},18,[52,467,153],{"emptyLinePlaceholder":152},[52,469,471,474,477,479,482,484,487,489,492,494,496,499,502,504,506,508,511,513,515],{"class":54,"line":470},19,[52,472,473],{"class":103},"subprocess.run([",[52,475,476],{"class":62},"\"soffice\"",[52,478,200],{"class":103},[52,480,481],{"class":62},"\"--headless\"",[52,483,200],{"class":103},[52,485,486],{"class":62},"\"--convert-to\"",[52,488,200],{"class":103},[52,490,491],{"class":62},"\"pdf\"",[52,493,200],{"class":103},[52,495,460],{"class":62},[52,497,498],{"class":103},"], ",[52,500,501],{"class":302},"check",[52,503,174],{"class":99},[52,505,318],{"class":139},[52,507,200],{"class":103},[52,509,510],{"class":302},"capture_output",[52,512,174],{"class":99},[52,514,318],{"class":139},[52,516,340],{"class":103},[52,518,520,522,525,527,530,532,535,537,540,542,545,547,550,552,555,557,559,561,564,566,569,571,573,575,577],{"class":54,"line":519},20,[52,521,473],{"class":103},[52,523,524],{"class":62},"\"pdftoppm\"",[52,526,200],{"class":103},[52,528,529],{"class":62},"\"-png\"",[52,531,200],{"class":103},[52,533,534],{"class":62},"\"-r\"",[52,536,200],{"class":103},[52,538,539],{"class":62},"\"100\"",[52,541,200],{"class":103},[52,543,544],{"class":62},"\"-f\"",[52,546,200],{"class":103},[52,548,549],{"class":62},"\"1\"",[52,551,200],{"class":103},[52,553,554],{"class":62},"\"-l\"",[52,556,200],{"class":103},[52,558,549],{"class":62},[52,560,200],{"class":103},[52,562,563],{"class":62},"\"column_style.pdf\"",[52,565,200],{"class":103},[52,567,568],{"class":62},"\"colstyle\"",[52,570,498],{"class":103},[52,572,501],{"class":302},[52,574,174],{"class":99},[52,576,318],{"class":139},[52,578,340],{"class":103},[52,580,582,585,587,590,593,596,599],{"class":54,"line":581},21,[52,583,584],{"class":103},"img ",[52,586,174],{"class":99},[52,588,589],{"class":103}," Image.open(",[52,591,592],{"class":62},"\"colstyle-1.png\"",[52,594,595],{"class":103},").convert(",[52,597,598],{"class":62},"\"RGB\"",[52,600,340],{"class":103},[52,602,604,607,609],{"class":54,"line":603},22,[52,605,606],{"class":103},"w ",[52,608,174],{"class":99},[52,610,611],{"class":103}," img.width\n",[52,613,615,618,622],{"class":54,"line":614},23,[52,616,617],{"class":99},"def",[52,619,621],{"class":620},"s_Opv"," blue_pixels",[52,623,624],{"class":103},"(x0, x1):\n",[52,626,628,631,634,636,638,641,644,646,648,650,653,656,658,661,663,666,668,670,673,676,679,682,685,688,691,693,695,698,700,702,705],{"class":54,"line":627},24,[52,629,630],{"class":99},"    return",[52,632,633],{"class":139}," sum",[52,635,229],{"class":103},[52,637,232],{"class":139},[52,639,640],{"class":99}," for",[52,642,643],{"class":103}," x ",[52,645,223],{"class":99},[52,647,226],{"class":139},[52,649,229],{"class":103},[52,651,652],{"class":139},"int",[52,654,655],{"class":103},"(x0), ",[52,657,652],{"class":139},[52,659,660],{"class":103},"(x1)) ",[52,662,217],{"class":99},[52,664,665],{"class":103}," y ",[52,667,223],{"class":99},[52,669,226],{"class":139},[52,671,672],{"class":103},"(img.height) ",[52,674,675],{"class":99},"if",[52,677,678],{"class":103}," img.getpixel((x, y)) ",[52,680,681],{"class":99},"==",[52,683,684],{"class":103}," (",[52,686,687],{"class":99},"0x",[52,689,690],{"class":139},"1F",[52,692,200],{"class":103},[52,694,687],{"class":99},[52,696,697],{"class":139},"38",[52,699,200],{"class":103},[52,701,687],{"class":99},[52,703,704],{"class":139},"64",[52,706,707],{"class":103},"))\n",[52,709,711,714,716,719,722,724,727,730,732,735,738,741,743,745,747,749,751,754],{"class":54,"line":710},25,[52,712,713],{"class":139},"print",[52,715,229],{"class":103},[52,717,718],{"class":62},"\"rendered blue px — column B:\"",[52,720,721],{"class":103},", blue_pixels(w ",[52,723,271],{"class":99},[52,725,726],{"class":139}," 0.15",[52,728,729],{"class":103},", w ",[52,731,271],{"class":99},[52,733,734],{"class":139}," 0.34",[52,736,737],{"class":103},"), ",[52,739,740],{"class":62},"\"| column C:\"",[52,742,721],{"class":103},[52,744,271],{"class":99},[52,746,734],{"class":139},[52,748,729],{"class":103},[52,750,271],{"class":99},[52,752,753],{"class":139}," 0.5",[52,755,707],{"class":103},[52,757,759,761,763,766,769,772,775,777,780,783,785,788,790,792],{"class":54,"line":758},26,[52,760,713],{"class":139},[52,762,229],{"class":103},[52,764,765],{"class":62},"\"cell fonts as stored — B2:\"",[52,767,768],{"class":103},", ws[",[52,770,771],{"class":62},"\"B2\"",[52,773,774],{"class":103},"].font.b, ws[",[52,776,771],{"class":62},[52,778,779],{"class":103},"].font.sz, ",[52,781,782],{"class":62},"\"| C2:\"",[52,784,768],{"class":103},[52,786,787],{"class":62},"\"C2\"",[52,789,774],{"class":103},[52,791,787],{"class":62},[52,793,794],{"class":103},"].font.sz)\n",[10,796,797,798,801,802,805],{},"Both columns print in bold dark blue in LibreOffice — yet the cells themselves tell a different story: B2 still has the default 11-point, non-bold font, while C2 has the font that was set on it. A column style is stored once, on the ",[19,799,800],{},"\u003Ccol>"," element of the sheet, and the cells in column B were written without a style of their own. LibreOffice fills that gap with the column's style. Excel's behaviour is the one openpyxl's own documentation describes: column and row styles apply to cells ",[14,803,804],{},"created afterwards"," — when someone types into an empty cell of column B, the value appears bold and blue — while cells already in the file keep their own formatting. The same report can therefore look different depending on the application that opens it, and code that reads cell fonts back sees neither version.",[10,807,808,809,812,813,816],{},"The safe rule follows from that: use ",[19,810,811],{},"column_dimensions[...]"," and ",[19,814,815],{},"row_dimensions[...]"," styles for cells people will add later, such as an input column below the data, and style the data you write on the cells themselves. Row dimensions behave the same way as columns.",[818,819,827,828,827,832,827,836,827,844,827,853,827,864,827,871,827,877,827,882,827,886,827,890,827,894,827,899,827,906,827,911,827,915,827,918,827,921,827,924],"svg",{"viewBox":820,"role":821,"ariaLabelledBy":822,"xmlns":825,"style":826},"4 0 752 233","img",[823,824],"sc-colstyle-t","sc-colstyle-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  ",[829,830,831],"title",{"id":823},"Column style or cell style",[833,834,835],"desc",{"id":824},"A style set on a column dimension is stored once on the column. Excel applies it to cells created later, such as values typed in, while LibreOffice also applies it to written cells that have no style of their own. A style set on each cell changes the cells that hold data in every application.",[837,838],"rect",{"x":839,"y":840,"width":841,"height":842,"fill":843},"4","0","752","233","#ffffff",[837,845],{"x":846,"y":847,"width":848,"height":849,"rx":337,"fill":850,"stroke":851,"style":852},"20.0","16.0","351.0","201.0","#fdefd8","var(--gold,#b4740a)","stroke-width:2px",[854,855,857],"g",{"transform":856},"translate(182.5,29.0) scale(1.083)",[858,859],"path",{"d":860,"fill":861,"stroke":862,"style":863},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14","none","var(--gold-ink,#7a4e06)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[865,866,870],"text",{"x":867,"y":868,"style":869},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","column_dimensions['B'].font",[54,872],{"x1":873,"y1":874,"x2":875,"y2":874,"stroke":851,"style":876},"36.0","91.0","355.0","stroke-width:1px",[865,878,881],{"x":867,"y":879,"style":880},"111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","stored once on the column",[865,883,885],{"x":867,"y":884,"style":880},"137.0","Excel: new cells only",[865,887,889],{"x":867,"y":888,"style":880},"163.0","LibreOffice: unstyled cells too",[865,891,893],{"x":867,"y":892,"style":880},"189.0","good for input columns",[837,895],{"x":896,"y":847,"width":848,"height":849,"rx":337,"fill":897,"stroke":898,"style":852},"389.0","#d9f4f1","var(--teal,#0f9488)",[854,900,902],{"transform":901},"translate(551.5,29.0) scale(1.083)",[858,903],{"d":904,"fill":861,"stroke":905,"style":863},"M5 12.5l4.5 4.5L19 7","var(--teal-ink,#0b6157)",[865,907,910],{"x":908,"y":868,"style":909},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","cell.font for each cell",[54,912],{"x1":913,"y1":874,"x2":914,"y2":874,"stroke":898,"style":876},"405.0","724.0",[865,916,917],{"x":908,"y":879,"style":880},"stored per cell",[865,919,920],{"x":908,"y":884,"style":880},"same result everywhere",[865,922,923],{"x":908,"y":888,"style":880},"needed for report output",[865,925,926],{"x":908,"y":892,"style":880},"cost grows with cell count",[38,928,930],{"id":929},"step-2-measure-the-ways-of-styling-many-cells","Step 2 — Measure the ways of styling many cells",[10,932,933],{},"Style the amounts in a 20,000-row sheet four ways and time each:",[43,935,937],{"className":90,"code":936,"language":92,"meta":48,"style":48},"import os, time\nfrom openpyxl.styles import NamedStyle\n\ndef sheet():\n    wb = Workbook()\n    ws = wb.active\n    for r in range(20_000):\n        ws.append([f\"SO-{r:05d}\", r * 1.5, r % 7, r * 2.25])\n    return wb, ws\n\ndef amounts(ws):\n    for (b, c, d) in ws.iter_rows(min_col=2, max_col=4):\n        yield b\n        yield d\n\nresults = {}\nfor method in [\"new objects per cell\", \"shared objects\", \"named style\"]:\n    wb, ws = sheet()\n    start = time.perf_counter()\n    if method == \"new objects per cell\":\n        for cell in amounts(ws):\n            cell.font = Font(color=BLUE)\n            cell.number_format = \"#,##0.00\"\n    elif method == \"shared objects\":\n        font = Font(color=BLUE)\n        for cell in amounts(ws):\n            cell.font = font\n            cell.number_format = \"#,##0.00\"\n    else:\n        wb.add_named_style(NamedStyle(name=\"amount\", font=Font(color=BLUE), number_format=\"#,##0.00\"))\n        for cell in amounts(ws):\n            cell.style = \"amount\"\n    results[method] = time.perf_counter() - start\n    wb.save(\"timing.xlsx\")\n    print(f\"{method:\u003C22} {results[method]:.3f}s  file {os.path.getsize('timing.xlsx') \u002F 1024:.0f} KB  cell formats {len(wb._cell_styles)}\")\nbase = results[\"new objects per cell\"]\nprint({m: f\"{base \u002F t:.1f}x faster\" for m, t in results.items() if m != \"new objects per cell\"})\n",[19,938,939,946,957,961,971,980,989,1008,1055,1062,1066,1076,1103,1111,1118,1122,1132,1160,1170,1180,1194,1207,1224,1234,1248,1265,1275,1285,1294,1302,1343,1354,1365,1382,1393,1468,1484],{"__ignoreMap":48},[52,940,941,943],{"class":54,"line":55},[52,942,100],{"class":99},[52,944,945],{"class":103}," os, time\n",[52,947,948,950,952,954],{"class":54,"line":107},[52,949,110],{"class":99},[52,951,126],{"class":103},[52,953,100],{"class":99},[52,955,956],{"class":103}," NamedStyle\n",[52,958,959],{"class":54,"line":121},[52,960,153],{"emptyLinePlaceholder":152},[52,962,963,965,968],{"class":54,"line":134},[52,964,617],{"class":99},[52,966,967],{"class":620}," sheet",[52,969,970],{"class":103},"():\n",[52,972,973,976,978],{"class":54,"line":149},[52,974,975],{"class":103},"    wb ",[52,977,174],{"class":99},[52,979,177],{"class":103},[52,981,982,985,987],{"class":54,"line":156},[52,983,984],{"class":103},"    ws ",[52,986,174],{"class":99},[52,988,188],{"class":103},[52,990,991,994,997,999,1001,1003,1006],{"class":54,"line":168},[52,992,993],{"class":99},"    for",[52,995,996],{"class":103}," r ",[52,998,223],{"class":99},[52,1000,226],{"class":139},[52,1002,229],{"class":103},[52,1004,1005],{"class":139},"20_000",[52,1007,240],{"class":103},[52,1009,1010,1013,1015,1018,1020,1023,1026,1028,1030,1033,1035,1038,1040,1043,1046,1048,1050,1053],{"class":54,"line":180},[52,1011,1012],{"class":103},"        ws.append([",[52,1014,249],{"class":99},[52,1016,1017],{"class":62},"\"SO-",[52,1019,256],{"class":255},[52,1021,1022],{"class":103},"r",[52,1024,1025],{"class":99},":05d",[52,1027,262],{"class":255},[52,1029,265],{"class":62},[52,1031,1032],{"class":103},", r ",[52,1034,271],{"class":99},[52,1036,1037],{"class":139}," 1.5",[52,1039,1032],{"class":103},[52,1041,1042],{"class":99},"%",[52,1044,1045],{"class":139}," 7",[52,1047,1032],{"class":103},[52,1049,271],{"class":99},[52,1051,1052],{"class":139}," 2.25",[52,1054,211],{"class":103},[52,1056,1057,1059],{"class":54,"line":191},[52,1058,630],{"class":99},[52,1060,1061],{"class":103}," wb, ws\n",[52,1063,1064],{"class":54,"line":214},[52,1065,153],{"emptyLinePlaceholder":152},[52,1067,1068,1070,1073],{"class":54,"line":243},[52,1069,617],{"class":99},[52,1071,1072],{"class":620}," amounts",[52,1074,1075],{"class":103},"(ws):\n",[52,1077,1078,1080,1083,1085,1087,1089,1091,1093,1095,1097,1099,1101],{"class":54,"line":285},[52,1079,993],{"class":99},[52,1081,1082],{"class":103}," (b, c, d) ",[52,1084,223],{"class":99},[52,1086,353],{"class":103},[52,1088,366],{"class":302},[52,1090,174],{"class":99},[52,1092,361],{"class":139},[52,1094,200],{"class":103},[52,1096,376],{"class":302},[52,1098,174],{"class":99},[52,1100,839],{"class":139},[52,1102,240],{"class":103},[52,1104,1105,1108],{"class":54,"line":343},[52,1106,1107],{"class":99},"        yield",[52,1109,1110],{"class":103}," b\n",[52,1112,1113,1115],{"class":54,"line":385},[52,1114,1107],{"class":99},[52,1116,1117],{"class":103}," d\n",[52,1119,1120],{"class":54,"line":427},[52,1121,153],{"emptyLinePlaceholder":152},[52,1123,1124,1127,1129],{"class":54,"line":443},[52,1125,1126],{"class":103},"results ",[52,1128,174],{"class":99},[52,1130,1131],{"class":103}," {}\n",[52,1133,1134,1136,1139,1141,1144,1147,1149,1152,1154,1157],{"class":54,"line":454},[52,1135,217],{"class":99},[52,1137,1138],{"class":103}," method ",[52,1140,223],{"class":99},[52,1142,1143],{"class":103}," [",[52,1145,1146],{"class":62},"\"new objects per cell\"",[52,1148,200],{"class":103},[52,1150,1151],{"class":62},"\"shared objects\"",[52,1153,200],{"class":103},[52,1155,1156],{"class":62},"\"named style\"",[52,1158,1159],{"class":103},"]:\n",[52,1161,1162,1165,1167],{"class":54,"line":465},[52,1163,1164],{"class":103},"    wb, ws ",[52,1166,174],{"class":99},[52,1168,1169],{"class":103}," sheet()\n",[52,1171,1172,1175,1177],{"class":54,"line":470},[52,1173,1174],{"class":103},"    start ",[52,1176,174],{"class":99},[52,1178,1179],{"class":103}," time.perf_counter()\n",[52,1181,1182,1185,1187,1189,1192],{"class":54,"line":519},[52,1183,1184],{"class":99},"    if",[52,1186,1138],{"class":103},[52,1188,681],{"class":99},[52,1190,1191],{"class":62}," \"new objects per cell\"",[52,1193,440],{"class":103},[52,1195,1196,1199,1202,1204],{"class":54,"line":581},[52,1197,1198],{"class":99},"        for",[52,1200,1201],{"class":103}," cell ",[52,1203,223],{"class":99},[52,1205,1206],{"class":103}," amounts(ws):\n",[52,1208,1209,1212,1214,1216,1218,1220,1222],{"class":54,"line":603},[52,1210,1211],{"class":103},"            cell.font ",[52,1213,174],{"class":99},[52,1215,299],{"class":103},[52,1217,323],{"class":302},[52,1219,174],{"class":99},[52,1221,159],{"class":139},[52,1223,340],{"class":103},[52,1225,1226,1229,1231],{"class":54,"line":614},[52,1227,1228],{"class":103},"            cell.number_format ",[52,1230,174],{"class":99},[52,1232,1233],{"class":62}," \"#,##0.00\"\n",[52,1235,1236,1239,1241,1243,1246],{"class":54,"line":627},[52,1237,1238],{"class":99},"    elif",[52,1240,1138],{"class":103},[52,1242,681],{"class":99},[52,1244,1245],{"class":62}," \"shared objects\"",[52,1247,440],{"class":103},[52,1249,1250,1253,1255,1257,1259,1261,1263],{"class":54,"line":710},[52,1251,1252],{"class":103},"        font ",[52,1254,174],{"class":99},[52,1256,299],{"class":103},[52,1258,323],{"class":302},[52,1260,174],{"class":99},[52,1262,159],{"class":139},[52,1264,340],{"class":103},[52,1266,1267,1269,1271,1273],{"class":54,"line":758},[52,1268,1198],{"class":99},[52,1270,1201],{"class":103},[52,1272,223],{"class":99},[52,1274,1206],{"class":103},[52,1276,1278,1280,1282],{"class":54,"line":1277},27,[52,1279,1211],{"class":103},[52,1281,174],{"class":99},[52,1283,1284],{"class":103}," font\n",[52,1286,1288,1290,1292],{"class":54,"line":1287},28,[52,1289,1228],{"class":103},[52,1291,174],{"class":99},[52,1293,1233],{"class":62},[52,1295,1297,1300],{"class":54,"line":1296},29,[52,1298,1299],{"class":99},"    else",[52,1301,440],{"class":103},[52,1303,1305,1308,1310,1312,1315,1317,1320,1322,1325,1327,1329,1331,1333,1336,1338,1341],{"class":54,"line":1304},30,[52,1306,1307],{"class":103},"        wb.add_named_style(NamedStyle(",[52,1309,303],{"class":302},[52,1311,174],{"class":99},[52,1313,1314],{"class":62},"\"amount\"",[52,1316,200],{"class":103},[52,1318,1319],{"class":302},"font",[52,1321,174],{"class":99},[52,1323,1324],{"class":103},"Font(",[52,1326,323],{"class":302},[52,1328,174],{"class":99},[52,1330,159],{"class":139},[52,1332,737],{"class":103},[52,1334,1335],{"class":302},"number_format",[52,1337,174],{"class":99},[52,1339,1340],{"class":62},"\"#,##0.00\"",[52,1342,707],{"class":103},[52,1344,1346,1348,1350,1352],{"class":54,"line":1345},31,[52,1347,1198],{"class":99},[52,1349,1201],{"class":103},[52,1351,223],{"class":99},[52,1353,1206],{"class":103},[52,1355,1357,1360,1362],{"class":54,"line":1356},32,[52,1358,1359],{"class":103},"            cell.style ",[52,1361,174],{"class":99},[52,1363,1364],{"class":62}," \"amount\"\n",[52,1366,1368,1371,1373,1376,1379],{"class":54,"line":1367},33,[52,1369,1370],{"class":103},"    results[method] ",[52,1372,174],{"class":99},[52,1374,1375],{"class":103}," time.perf_counter() ",[52,1377,1378],{"class":99},"-",[52,1380,1381],{"class":103}," start\n",[52,1383,1385,1388,1391],{"class":54,"line":1384},34,[52,1386,1387],{"class":103},"    wb.save(",[52,1389,1390],{"class":62},"\"timing.xlsx\"",[52,1392,340],{"class":103},[52,1394,1396,1399,1401,1403,1405,1407,1410,1413,1415,1418,1421,1424,1426,1429,1431,1434,1437,1440,1443,1446,1449,1451,1454,1456,1459,1462,1464,1466],{"class":54,"line":1395},35,[52,1397,1398],{"class":139},"    print",[52,1400,229],{"class":103},[52,1402,249],{"class":99},[52,1404,265],{"class":62},[52,1406,256],{"class":255},[52,1408,1409],{"class":103},"method",[52,1411,1412],{"class":99},":\u003C22",[52,1414,262],{"class":255},[52,1416,1417],{"class":255}," {",[52,1419,1420],{"class":103},"results[method]",[52,1422,1423],{"class":99},":.3f",[52,1425,262],{"class":255},[52,1427,1428],{"class":62},"s  file ",[52,1430,256],{"class":255},[52,1432,1433],{"class":103},"os.path.getsize(",[52,1435,1436],{"class":62},"'timing.xlsx'",[52,1438,1439],{"class":103},") ",[52,1441,1442],{"class":99},"\u002F",[52,1444,1445],{"class":139}," 1024",[52,1447,1448],{"class":99},":.0f",[52,1450,262],{"class":255},[52,1452,1453],{"class":62}," KB  cell formats ",[52,1455,256],{"class":255},[52,1457,1458],{"class":139},"len",[52,1460,1461],{"class":103},"(wb._cell_styles)",[52,1463,262],{"class":255},[52,1465,265],{"class":62},[52,1467,340],{"class":103},[52,1469,1471,1474,1476,1479,1481],{"class":54,"line":1470},36,[52,1472,1473],{"class":103},"base ",[52,1475,174],{"class":99},[52,1477,1478],{"class":103}," results[",[52,1480,1146],{"class":62},[52,1482,1483],{"class":103},"]\n",[52,1485,1487,1489,1492,1494,1496,1498,1500,1502,1505,1508,1510,1513,1515,1518,1520,1523,1525,1528,1531,1533],{"class":54,"line":1486},37,[52,1488,713],{"class":139},[52,1490,1491],{"class":103},"({m: ",[52,1493,249],{"class":99},[52,1495,265],{"class":62},[52,1497,256],{"class":255},[52,1499,1473],{"class":103},[52,1501,1442],{"class":99},[52,1503,1504],{"class":103}," t",[52,1506,1507],{"class":99},":.1f",[52,1509,262],{"class":255},[52,1511,1512],{"class":62},"x faster\"",[52,1514,640],{"class":99},[52,1516,1517],{"class":103}," m, t ",[52,1519,223],{"class":99},[52,1521,1522],{"class":103}," results.items() ",[52,1524,675],{"class":99},[52,1526,1527],{"class":103}," m ",[52,1529,1530],{"class":99},"!=",[52,1532,1191],{"class":62},[52,1534,1535],{"class":103},"})\n",[10,1537,1538,1539,1542,1543,1545],{},"All three produce the same file — the same size and the same small number of cell formats — because openpyxl de-duplicates identical styles when it saves: forty thousand ",[19,1540,1541],{},"Font(color=BLUE)"," objects still become one font entry. The difference is time. Creating a new ",[19,1544,25],{}," object for every cell was nearly four times slower here than creating one and assigning it repeatedly, and a named style, which sets font and number format in a single assignment, was about eight times faster than the baseline. On a report with a dozen styled columns and hundreds of thousands of rows that is the difference between seconds and minutes. The exact ratios vary from machine to machine and run to run, so treat them as an order of magnitude; the ranking does not change.",[818,1547,827,1553,827,1556,827,1559,827,1563,827,1570,827,1576,827,1581,827,1586,827,1589,827,1593,827,1598,827,1603,827,1606,827,1610,827,1613],{"viewBox":1548,"role":821,"ariaLabelledBy":1549,"xmlns":825,"style":1552},"4 0 732 140",[1550,1551],"sc-timing-t","sc-timing-d","width:100%;max-width:732px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[829,1554,1555],{"id":1550},"Relative time to style 40,000 cells",[833,1557,1558],{"id":1551},"Creating a new Font object for each cell is the slowest. Reusing one shared Font object is several times faster, and assigning a named style that carries both font and number format is fastest. All three produce the same file.",[837,1560],{"x":839,"y":840,"width":1561,"height":1562,"fill":843},"732","140",[837,1564],{"x":846,"y":847,"width":1565,"height":1566,"rx":1567,"fill":1568,"stroke":1569,"style":876},"158.0","28.0","7","#e7ebef","var(--line,#cdd5e6)",[865,1571,1575],{"x":1572,"y":1573,"style":1574},"99.0","34.5","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","New objects per cell",[837,1577],{"x":1578,"y":847,"width":1579,"height":1566,"rx":1567,"fill":850,"stroke":851,"style":1580},"188.0","471.8","stroke-width:1.5px",[865,1582,1585],{"x":1583,"y":1573,"style":1584},"667.7","font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:start","baseline",[837,1587],{"x":846,"y":1588,"width":1565,"height":1566,"rx":1567,"fill":1568,"stroke":1569,"style":876},"56.0",[865,1590,1592],{"x":1572,"y":1591,"style":1574},"74.5","Shared objects",[837,1594],{"x":1578,"y":1588,"width":1595,"height":1566,"rx":1567,"fill":1596,"stroke":1597,"style":1580},"127.4","#f0f4ff","var(--brand,#5b5cf0)",[865,1599,1602],{"x":1600,"y":1591,"style":1601},"323.3","font-size:12px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:start","≈4× faster",[837,1604],{"x":846,"y":1605,"width":1565,"height":1566,"rx":1567,"fill":1568,"stroke":1569,"style":876},"96.0",[865,1607,1609],{"x":1572,"y":1608,"style":1574},"114.5","Named style",[837,1611],{"x":1578,"y":1605,"width":1612,"height":1566,"rx":1567,"fill":897,"stroke":898,"style":1580},"56.6",[865,1614,1617],{"x":1615,"y":1608,"style":1616},"252.6","font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:start","≈8× faster",[38,1619,1621],{"id":1620},"step-3-the-pattern-for-a-real-report","Step 3 — The pattern for a real report",[10,1623,1624],{},"Combine both tools: style the written data cell by cell with shared objects or a named style, limited to the used range, and set column and row styles for the cells people will add:",[43,1626,1628],{"className":90,"code":1627,"language":92,"meta":48,"style":48},"from openpyxl.styles import PatternFill, Alignment\n\nwb, ws = sheet()\nws.insert_rows(1)\nfor col, name in enumerate([\"Order\", \"Amount\", \"Weekday\", \"Total\"], start=1):\n    ws.cell(1, col, name)\n\nheader = NamedStyle(name=\"header\", font=Font(bold=True, color=\"FFFFFF\"), fill=PatternFill(\"solid\", fgColor=BLUE),\n                    alignment=Alignment(horizontal=\"center\"))\namount = NamedStyle(name=\"amount\", font=Font(color=BLUE), number_format=\"#,##0.00\")\nwb.add_named_style(header)\nwb.add_named_style(amount)\nstart = time.perf_counter()\nfor cell in ws[1]:\n    cell.style = \"header\"\nfor col in (\"B\", \"D\"):\n    for (cell,) in ws.iter_rows(min_row=2, max_row=ws.max_row, min_col=ord(col) - 64, max_col=ord(col) - 64):\n        cell.style = \"amount\"\n    ws.column_dimensions[col].number_format = \"#,##0.00\"      # for rows added later in Excel\nws.freeze_panes = \"A2\"\nwb.save(\"report.xlsx\")\nprint(f\"styled {ws.max_row - 1:,} rows in {time.perf_counter() - start:.2f}s | cell formats: {len(wb._cell_styles)}\")\n",[19,1629,1630,1641,1645,1654,1663,1707,1717,1721,1786,1806,1845,1850,1855,1864,1879,1889,1908,1965,1974,1988,1998,2007],{"__ignoreMap":48},[52,1631,1632,1634,1636,1638],{"class":54,"line":55},[52,1633,110],{"class":99},[52,1635,126],{"class":103},[52,1637,100],{"class":99},[52,1639,1640],{"class":103}," PatternFill, Alignment\n",[52,1642,1643],{"class":54,"line":107},[52,1644,153],{"emptyLinePlaceholder":152},[52,1646,1647,1650,1652],{"class":54,"line":121},[52,1648,1649],{"class":103},"wb, ws ",[52,1651,174],{"class":99},[52,1653,1169],{"class":103},[52,1655,1656,1659,1661],{"class":54,"line":134},[52,1657,1658],{"class":103},"ws.insert_rows(",[52,1660,232],{"class":139},[52,1662,340],{"class":103},[52,1664,1665,1667,1670,1672,1675,1678,1681,1683,1686,1688,1691,1693,1696,1698,1701,1703,1705],{"class":54,"line":149},[52,1666,217],{"class":99},[52,1668,1669],{"class":103}," col, name ",[52,1671,223],{"class":99},[52,1673,1674],{"class":139}," enumerate",[52,1676,1677],{"class":103},"([",[52,1679,1680],{"class":62},"\"Order\"",[52,1682,200],{"class":103},[52,1684,1685],{"class":62},"\"Amount\"",[52,1687,200],{"class":103},[52,1689,1690],{"class":62},"\"Weekday\"",[52,1692,200],{"class":103},[52,1694,1695],{"class":62},"\"Total\"",[52,1697,498],{"class":103},[52,1699,1700],{"class":302},"start",[52,1702,174],{"class":99},[52,1704,232],{"class":139},[52,1706,240],{"class":103},[52,1708,1709,1712,1714],{"class":54,"line":156},[52,1710,1711],{"class":103},"    ws.cell(",[52,1713,232],{"class":139},[52,1715,1716],{"class":103},", col, name)\n",[52,1718,1719],{"class":54,"line":168},[52,1720,153],{"emptyLinePlaceholder":152},[52,1722,1723,1726,1728,1731,1733,1735,1738,1740,1742,1744,1746,1748,1750,1752,1754,1756,1758,1761,1763,1766,1768,1771,1774,1776,1779,1781,1783],{"class":54,"line":180},[52,1724,1725],{"class":103},"header ",[52,1727,174],{"class":99},[52,1729,1730],{"class":103}," NamedStyle(",[52,1732,303],{"class":302},[52,1734,174],{"class":99},[52,1736,1737],{"class":62},"\"header\"",[52,1739,200],{"class":103},[52,1741,1319],{"class":302},[52,1743,174],{"class":99},[52,1745,1324],{"class":103},[52,1747,313],{"class":302},[52,1749,174],{"class":99},[52,1751,318],{"class":139},[52,1753,200],{"class":103},[52,1755,323],{"class":302},[52,1757,174],{"class":99},[52,1759,1760],{"class":62},"\"FFFFFF\"",[52,1762,737],{"class":103},[52,1764,1765],{"class":302},"fill",[52,1767,174],{"class":99},[52,1769,1770],{"class":103},"PatternFill(",[52,1772,1773],{"class":62},"\"solid\"",[52,1775,200],{"class":103},[52,1777,1778],{"class":302},"fgColor",[52,1780,174],{"class":99},[52,1782,159],{"class":139},[52,1784,1785],{"class":103},"),\n",[52,1787,1788,1791,1793,1796,1799,1801,1804],{"class":54,"line":191},[52,1789,1790],{"class":302},"                    alignment",[52,1792,174],{"class":99},[52,1794,1795],{"class":103},"Alignment(",[52,1797,1798],{"class":302},"horizontal",[52,1800,174],{"class":99},[52,1802,1803],{"class":62},"\"center\"",[52,1805,707],{"class":103},[52,1807,1808,1811,1813,1815,1817,1819,1821,1823,1825,1827,1829,1831,1833,1835,1837,1839,1841,1843],{"class":54,"line":214},[52,1809,1810],{"class":103},"amount ",[52,1812,174],{"class":99},[52,1814,1730],{"class":103},[52,1816,303],{"class":302},[52,1818,174],{"class":99},[52,1820,1314],{"class":62},[52,1822,200],{"class":103},[52,1824,1319],{"class":302},[52,1826,174],{"class":99},[52,1828,1324],{"class":103},[52,1830,323],{"class":302},[52,1832,174],{"class":99},[52,1834,159],{"class":139},[52,1836,737],{"class":103},[52,1838,1335],{"class":302},[52,1840,174],{"class":99},[52,1842,1340],{"class":62},[52,1844,340],{"class":103},[52,1846,1847],{"class":54,"line":243},[52,1848,1849],{"class":103},"wb.add_named_style(header)\n",[52,1851,1852],{"class":54,"line":285},[52,1853,1854],{"class":103},"wb.add_named_style(amount)\n",[52,1856,1857,1860,1862],{"class":54,"line":343},[52,1858,1859],{"class":103},"start ",[52,1861,174],{"class":99},[52,1863,1179],{"class":103},[52,1865,1866,1868,1870,1872,1875,1877],{"class":54,"line":385},[52,1867,217],{"class":99},[52,1869,1201],{"class":103},[52,1871,223],{"class":99},[52,1873,1874],{"class":103}," ws[",[52,1876,232],{"class":139},[52,1878,1159],{"class":103},[52,1880,1881,1884,1886],{"class":54,"line":427},[52,1882,1883],{"class":103},"    cell.style ",[52,1885,174],{"class":99},[52,1887,1888],{"class":62}," \"header\"\n",[52,1890,1891,1893,1895,1897,1899,1901,1903,1906],{"class":54,"line":443},[52,1892,217],{"class":99},[52,1894,432],{"class":103},[52,1896,223],{"class":99},[52,1898,684],{"class":103},[52,1900,291],{"class":62},[52,1902,200],{"class":103},[52,1904,1905],{"class":62},"\"D\"",[52,1907,240],{"class":103},[52,1909,1910,1912,1914,1916,1918,1920,1922,1924,1926,1929,1931,1934,1936,1938,1941,1944,1946,1949,1951,1953,1955,1957,1959,1961,1963],{"class":54,"line":454},[52,1911,993],{"class":99},[52,1913,348],{"class":103},[52,1915,223],{"class":99},[52,1917,353],{"class":103},[52,1919,356],{"class":302},[52,1921,174],{"class":99},[52,1923,361],{"class":139},[52,1925,200],{"class":103},[52,1927,1928],{"class":302},"max_row",[52,1930,174],{"class":99},[52,1932,1933],{"class":103},"ws.max_row, ",[52,1935,366],{"class":302},[52,1937,174],{"class":99},[52,1939,1940],{"class":139},"ord",[52,1942,1943],{"class":103},"(col) ",[52,1945,1378],{"class":99},[52,1947,1948],{"class":139}," 64",[52,1950,200],{"class":103},[52,1952,376],{"class":302},[52,1954,174],{"class":99},[52,1956,1940],{"class":139},[52,1958,1943],{"class":103},[52,1960,1378],{"class":99},[52,1962,1948],{"class":139},[52,1964,240],{"class":103},[52,1966,1967,1970,1972],{"class":54,"line":465},[52,1968,1969],{"class":103},"        cell.style ",[52,1971,174],{"class":99},[52,1973,1364],{"class":62},[52,1975,1976,1979,1981,1984],{"class":54,"line":470},[52,1977,1978],{"class":103},"    ws.column_dimensions[col].number_format ",[52,1980,174],{"class":99},[52,1982,1983],{"class":62}," \"#,##0.00\"",[52,1985,1987],{"class":1986},"s-wDw","      # for rows added later in Excel\n",[52,1989,1990,1993,1995],{"class":54,"line":519},[52,1991,1992],{"class":103},"ws.freeze_panes ",[52,1994,174],{"class":99},[52,1996,1997],{"class":62}," \"A2\"\n",[52,1999,2000,2002,2005],{"class":54,"line":581},[52,2001,457],{"class":103},[52,2003,2004],{"class":62},"\"report.xlsx\"",[52,2006,340],{"class":103},[52,2008,2009,2011,2013,2015,2018,2020,2023,2025,2028,2031,2033,2036,2038,2041,2043,2046,2049,2051,2054,2056,2058,2060,2062,2064],{"class":54,"line":603},[52,2010,713],{"class":139},[52,2012,229],{"class":103},[52,2014,249],{"class":99},[52,2016,2017],{"class":62},"\"styled ",[52,2019,256],{"class":255},[52,2021,2022],{"class":103},"ws.max_row ",[52,2024,1378],{"class":99},[52,2026,2027],{"class":139}," 1",[52,2029,2030],{"class":99},":,",[52,2032,262],{"class":255},[52,2034,2035],{"class":62}," rows in ",[52,2037,256],{"class":255},[52,2039,2040],{"class":103},"time.perf_counter() ",[52,2042,1378],{"class":99},[52,2044,2045],{"class":103}," start",[52,2047,2048],{"class":99},":.2f",[52,2050,262],{"class":255},[52,2052,2053],{"class":62},"s | cell formats: ",[52,2055,256],{"class":255},[52,2057,1458],{"class":139},[52,2059,1461],{"class":103},[52,2061,262],{"class":255},[52,2063,265],{"class":62},[52,2065,340],{"class":103},[10,2067,2068,2069,2072,2073,2076,2077,2080,2081,2083,2084,36],{},"The header row and two amount columns are styled through named styles in a fraction of a second, and the amount columns also carry a column-level number format so a value typed below the data in Excel is formatted the same way. Iterating with ",[19,2070,2071],{},"iter_rows"," over just the needed columns and rows avoids touching cells that do not need styling — and avoids ",[14,2074,2075],{},"creating"," cells: accessing ",[19,2078,2079],{},"ws[\"B30000\"]"," on a 20,000-row sheet creates an empty cell, which then counts towards ",[19,2082,1928],{},". When even this is too slow — millions of cells — writing the report with XlsxWriter's column formats, applied as the data is written, is the faster route, covered in ",[32,2085,2087],{"href":2086},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-a-million-rows-to-excel-with-xlsxwriter-constant-memory\u002F","Write a Million Rows to Excel with xlsxwriter constant_memory",[818,2089,827,2094,827,2097,827,2100,827,2103,827,2108,827,2116,827,2122,827,2127,827,2132,827,2137,827,2140,827,2146,827,2151,827,2154,827,2157,827,2160,827,2163,827,2169,827,2174,827,2177,827,2181,827,2184,827,2187,827,2193,827,2198],{"viewBox":2090,"role":821,"ariaLabelledBy":2091,"xmlns":825,"style":826},"4 0 752 125",[2092,2093],"sc-pattern-t","sc-pattern-d",[829,2095,2096],{"id":2092},"Styling a large report efficiently",[833,2098,2099],{"id":2093},"Register named styles once, style the header row by name, loop over only the used range of the columns that need styling with iter_rows, add column-level formats for rows people will add later, and freeze the header.",[837,2101],{"x":839,"y":840,"width":841,"height":2102,"fill":843},"125",[837,2104],{"x":846,"y":847,"width":2105,"height":2106,"rx":2107,"fill":1596,"stroke":1597,"style":852},"153.0","93.0","12",[854,2109,2111],{"transform":2110},"translate(84.5,29.0) scale(1.000)",[858,2112],{"d":2113,"fill":861,"stroke":2114,"style":2115},"M12 3l9 5-9 5-9-5z M3 13l9 5 9-5 M3 17l9 5 9-5","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[865,2117,2121],{"x":2118,"y":2119,"style":2120},"96.5","75.5","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Register styles",[865,2123,2126],{"x":2118,"y":2124,"style":2125},"95.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","NamedStyle, once",[54,2128],{"x1":2129,"y1":2130,"x2":2131,"y2":2130,"stroke":1597,"style":852},"178.0","62.5","200.0",[2133,2134],"polygon",{"points":2135,"fill":2136},"204.0,62.5 195.0,67.5 195.0,57.5","#5b5cf0",[837,2138],{"x":2139,"y":847,"width":2105,"height":2106,"rx":2107,"fill":1568,"stroke":1569,"style":852},"209.0",[854,2141,2143],{"transform":2142},"translate(273.5,29.0) scale(1.000)",[858,2144],{"d":860,"fill":861,"stroke":2145,"style":2115},"var(--text,#172033)",[865,2147,2150],{"x":2148,"y":2119,"style":2149},"285.5","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Header row",[865,2152,2153],{"x":2148,"y":2124,"style":2125},"cell.style = 'header'",[54,2155],{"x1":2156,"y1":2130,"x2":896,"y2":2130,"stroke":1597,"style":852},"367.0",[2133,2158],{"points":2159,"fill":2136},"393.0,62.5 384.0,67.5 384.0,57.5",[837,2161],{"x":2162,"y":847,"width":2105,"height":2106,"rx":2107,"fill":897,"stroke":898,"style":852},"398.0",[854,2164,2166],{"transform":2165},"translate(462.5,29.0) scale(1.000)",[858,2167],{"d":2168,"fill":861,"stroke":905,"style":2115},"M3 5h18l-7 8v6l-4 2v-8z",[865,2170,2173],{"x":2171,"y":2119,"style":2172},"474.5","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Used range only",[865,2175,2176],{"x":2171,"y":2124,"style":2125},"iter_rows per column",[54,2178],{"x1":2179,"y1":2130,"x2":2180,"y2":2130,"stroke":1597,"style":852},"556.0","578.0",[2133,2182],{"points":2183,"fill":2136},"582.0,62.5 573.0,67.5 573.0,57.5",[837,2185],{"x":2186,"y":847,"width":2105,"height":2106,"rx":2107,"fill":850,"stroke":851,"style":852},"587.0",[854,2188,2190],{"transform":2189},"translate(651.5,29.0) scale(1.000)",[858,2191],{"d":2192,"fill":861,"stroke":862,"style":2115},"M4 5h16v15H4z M4 10h16 M8 3v4 M16 3v4",[865,2194,2197],{"x":2195,"y":2119,"style":2196},"663.5","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Column formats",[865,2199,2200],{"x":2195,"y":2124,"style":2125},"for rows added later",[38,2202,2204],{"id":2203},"common-pitfalls","Common pitfalls",[2206,2207,2208,2216,2225,2231,2237],"ul",{},[2209,2210,2211,2215],"li",{},[2212,2213,2214],"strong",{},"Expecting column styles to restyle data."," Excel applies them to new cells only; results differ by application.",[2209,2217,2218,2224],{},[2212,2219,2220,2221,2223],{},"A new ",[19,2222,25],{}," per cell."," Create it once and reuse it.",[2209,2226,2227,2230],{},[2212,2228,2229],{},"Setting font and number format separately for many cells."," A named style does both in one assignment.",[2209,2232,2233,2236],{},[2212,2234,2235],{},"Styling whole columns cell by cell to row 1,048,576."," Style the used range; it creates cells otherwise.",[2209,2238,2239,2242],{},[2212,2240,2241],{},"Style explosions from slightly different objects."," Keep a small set of shared styles.",[38,2244,2246],{"id":2245},"conclusion","Conclusion",[10,2248,2249,2250,2253,2254,2256],{},"Column and row styles in openpyxl are meant for the cells people add later — Excel does not apply them to the data you write, and LibreOffice does — so style written cells directly. Do it efficiently: create style objects once and reuse them, or register a ",[19,2251,2252],{},"NamedStyle"," and assign it by name, and limit loops to the used range with ",[19,2255,2071],{},". openpyxl de-duplicates identical styles in the saved file either way, so the gain is in run time, which on large reports is several-fold.",[38,2258,2260],{"id":2259},"frequently-asked-questions","Frequently asked questions",[10,2262,2263,2266],{},[2212,2264,2265],{},"How do I make a whole column bold in openpyxl?","\nSet the font on each cell in the used range of the column, reusing one Font object; column_dimensions styles only affect cells added later.",[10,2268,2269,2272],{},[2212,2270,2271],{},"Why doesn't column_dimensions font change my existing cells?","\nIn Excel a column style applies to cells created after the file is opened, not to cells already in it; LibreOffice also applies it to unstyled existing cells, so style data cells directly for consistent results.",[10,2274,2275,2278],{},[2212,2276,2277],{},"What is the fastest way to style many cells with openpyxl?","\nRegister a NamedStyle that combines font, fill and number format, and assign it with cell.style; reusing shared style objects is the next fastest.",[10,2280,2281,2284],{},[2212,2282,2283],{},"Does creating many Font objects make the file bigger?","\nNo. openpyxl merges identical styles when saving, so the file is the same; it only makes the script slower.",[38,2286,2288],{"id":2287},"related","Related",[2206,2290,2291,2297,2304,2311],{},[2209,2292,2293,2294,2296],{},"Up one level: ",[32,2295,35],{"href":34}," — cell styling from Python.",[2209,2298,2299,2303],{},[32,2300,2302],{"href":2301},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fapply-built-in-cell-styles-like-good-bad-and-neutral\u002F","Apply Built-In Cell Styles Like Good, Bad and Neutral"," — Excel's named styles.",[2209,2305,2306,2310],{},[32,2307,2309],{"href":2308},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fset-column-width-and-row-height-in-openpyxl\u002F","Set Column Width and Row Height in openpyxl"," — the other column dimension settings.",[2209,2312,2313,2317],{},[32,2314,2316],{"href":2315},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-large-excel-files-in-python\u002Fspeed-up-openpyxl-with-read-only-mode\u002F","Speed Up openpyxl with read_only Mode"," — performance on the reading side.",[2319,2320,2321],"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":48,"searchDepth":107,"depth":107,"links":2323},[2324,2325,2326,2327,2328,2329,2330,2331],{"id":40,"depth":107,"text":41},{"id":83,"depth":107,"text":84},{"id":929,"depth":107,"text":930},{"id":1620,"depth":107,"text":1621},{"id":2203,"depth":107,"text":2204},{"id":2245,"depth":107,"text":2246},{"id":2259,"depth":107,"text":2260},{"id":2287,"depth":107,"text":2288},"2026-10-02","Format entire columns and rows in large openpyxl workbooks without slowing the script down: what column and row styles actually do (and why they do not restyle cells that already hold data), reusing one Font object instead of creating thousands, named styles for the fastest path, styling only the used range, and checking the rendered result and the file's style count.","md",[2336,2338,2340,2342],{"q":2265,"a":2337},"Set the font on each cell in the used range of the column, reusing one Font object; column_dimensions styles only affect cells added later.",{"q":2271,"a":2339},"In Excel a column style applies to cells created after the file is opened, not to cells already in it; LibreOffice also applies it to unstyled existing cells, so style data cells directly for consistent results.",{"q":2277,"a":2341},"Register a NamedStyle that combines font, fill and number format, and assign it with cell.style; reusing shared style objects is the next fastest.",{"q":2283,"a":2343},"No. openpyxl merges identical styles when saving, so the file is the same; it only makes the script slower.","style whole columns and rows openpyxl",null,{"breadcrumb":2347},[2348,2350,2353],{"name":2349,"item":1442},"Home",{"name":2351,"item":2352},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":35,"item":34},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fstyle-whole-columns-and-rows-efficiently-with-openpyxl",{"title":5,"description":2356},"Column and row styles in openpyxl: column_dimensions and row_dimensions styles versus per-cell styling, why existing cells keep their own style, shared Font objects, NamedStyle, timing comparisons and rendered checks.","style-whole-columns-and-rows-efficiently-with-openpyxl","formatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fstyle-whole-columns-and-rows-efficiently-with-openpyxl\u002Findex",[2360,2361],"cell-styling","openpyxl","how-to","zd4JGYPsIutdcB93txRDV-ibuhcGLS0mLjc8OpXD5Jc",[2365,2369],{"title":2366,"path":2367,"stem":2368,"children":-1},"Set the Print Area and Page Setup with openpyxl","\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fset-print-area-and-page-setup-with-openpyxl","formatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fset-print-area-and-page-setup-with-openpyxl\u002Findex",{"title":2370,"path":2371,"stem":2372,"children":-1},"Wrap Text and Align Cells with openpyxl","\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fwrap-text-and-align-cells-with-openpyxl","formatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fwrap-text-and-align-cells-with-openpyxl\u002Findex",[2374,2376],{"path":2375,"title":2351},"\u002Fformatting-and-charting-excel-reports-with-python",{"path":2377,"title":35},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl",[],[2380,2383,2386,2389,2392,2395],{"path":2381,"title":2382,"kind":2362},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-rich-text-in-a-cell-with-xlsxwriter","Write Rich Text with Mixed Formats in One Cell with xlsxwriter",{"path":2384,"title":2385,"kind":2362},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl","Copy Cell Styles from One Cell to Another with openpyxl",{"path":2387,"title":2388,"kind":2362},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fauto-fit-column-widths-when-writing-with-pandas","Auto-Fit Column Widths When Writing with pandas",{"path":2390,"title":2391,"kind":2362},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fexport-a-styled-pandas-dataframe-to-excel","Export a Styled pandas DataFrame to Excel",{"path":2393,"title":2394,"kind":2362},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fgenerate-a-staff-rota-in-excel-with-python","Generate a Staff Rota in Excel with Python",{"path":2396,"title":2397,"kind":2362},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-a-table-of-contents-sheet-with-hyperlinks-in-excel","Add a Table of Contents Sheet with Hyperlinks in Excel",1790972118680]