[{"data":1,"prerenderedAt":2055},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl":2020,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl":2029,"children:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl":2034,"related:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl":2035},{"id":4,"title":5,"body":6,"dateModified":1986,"datePublished":1986,"description":1987,"extension":1988,"faq":1989,"keyword":1998,"kind":1999,"meta":2000,"navigation":217,"path":2009,"seo":2010,"slug":2013,"stem":2014,"topics":2015,"type":2018,"__hash__":2019},"docs\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl\u002Findex.md","Copy Cell Styles from One Cell to Another with openpyxl",{"type":7,"value":8,"toc":1973},"minimark",[9,19,156,161,186,189,548,552,559,712,728,732,744,783,790,872,882,1002,1006,1009,1310,1317,1321,1332,1505,1517,1521,1527,1708,1716,1831,1835,1879,1883,1893,1897,1909,1913,1919,1925,1931,1937,1941,1970],[10,11,12,13,18],"p",{},"A generated report usually inherits its look from somewhere: a template row you want new data to match, a header cell styled by a designer, the format of last month's sheet. openpyxl has no \"Format Painter\", but every piece of a cell's appearance is an attribute you can copy — font, fill, border, alignment, number format and protection. This guide, part of ",[14,15,17],"a",{"href":16},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002F","Using openpyxl for Excel File Manipulation",", shows the safe way to copy them, the shortcut that works only inside one workbook, and how to extend a template's formatting to rows that do not exist yet.",[20,21,29,30,29,34,29,38,29,46,29,56,29,63,29,68,29,72,29,78,29,83,29,86,29,90,29,93,29,95,29,99,29,102,29,105,29,110,29,114,29,118,29,121,29,124,29,128,29,131,29,135,29,138,29,143,29,148,29,151],"svg",{"viewBox":22,"role":23,"ariaLabelledBy":24,"xmlns":27,"style":28},"4 0 752 134","img",[25,26],"copy-parts-t","copy-parts-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  ",[31,32,33],"title",{"id":25},"The six attributes that make up a cell's style in openpyxl",[35,36,37],"desc",{"id":26},"A cell's appearance is the combination of font, fill, border, alignment, number format and protection. Copying a style means copying each of these six attributes from the source cell to the target cell.",[39,40],"rect",{"x":41,"y":42,"width":43,"height":44,"fill":45},"4","0","752","134","#ffffff",[39,47],{"x":48,"y":49,"width":50,"height":51,"rx":52,"fill":53,"stroke":54,"style":55},"20.0","16.0","115.2","76.5","12","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:2px",[57,58,62],"text",{"x":59,"y":60,"style":61},"77.6","41.5","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","font",[57,64,67],{"x":59,"y":65,"style":66},"61.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","bold, size,",[57,69,71],{"x":59,"y":70,"style":66},"78.5","colour",[73,74],"line",{"x1":75,"y1":76,"x2":77,"y2":76,"stroke":54,"style":55},"140.2","54.2","162.2",[79,80],"polygon",{"points":81,"fill":82},"166.2,54.2 157.2,59.2 157.2,49.2","#5b5cf0",[39,84],{"x":85,"y":49,"width":50,"height":51,"rx":52,"fill":53,"stroke":54,"style":55},"171.2",[57,87,89],{"x":88,"y":60,"style":61},"228.8","fill",[57,91,92],{"x":88,"y":65,"style":66},"background",[57,94,71],{"x":88,"y":70,"style":66},[73,96],{"x1":97,"y1":76,"x2":98,"y2":76,"stroke":54,"style":55},"291.4","313.4",[79,100],{"points":101,"fill":82},"317.4,54.2 308.4,59.2 308.4,49.2",[39,103],{"x":104,"y":49,"width":50,"height":51,"rx":52,"fill":53,"stroke":54,"style":55},"322.4",[57,106,109],{"x":107,"y":108,"style":61},"380.0","50.2","border",[57,111,113],{"x":107,"y":112,"style":66},"69.8","four sides",[73,115],{"x1":116,"y1":76,"x2":117,"y2":76,"stroke":54,"style":55},"442.6","464.6",[79,119],{"points":120,"fill":82},"468.6,54.2 459.6,59.2 459.6,49.2",[39,122],{"x":123,"y":49,"width":50,"height":51,"rx":52,"fill":53,"stroke":54,"style":55},"473.6",[57,125,127],{"x":126,"y":108,"style":61},"531.2","alignment",[57,129,130],{"x":126,"y":112,"style":66},"wrap, centre",[73,132],{"x1":133,"y1":76,"x2":134,"y2":76,"stroke":54,"style":55},"593.8","615.8",[79,136],{"points":137,"fill":82},"619.8,54.2 610.8,59.2 610.8,49.2",[39,139],{"x":140,"y":49,"width":50,"height":51,"rx":52,"fill":141,"stroke":142,"style":55},"624.8","#d9f4f1","var(--teal,#0f9488)",[57,144,147],{"x":145,"y":108,"style":146},"682.4","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","number_format",[57,149,150],{"x":145,"y":112,"style":66},"#,##0.00",[57,152,155],{"x":107,"y":153,"style":154},"114.5","font-size:12.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","protection (locked, hidden) is the sixth; conditional formatting is not part of a cell and never copies with it",[157,158,160],"h2",{"id":159},"prerequisites","Prerequisites",[162,163,168],"pre",{"className":164,"code":165,"language":166,"meta":167,"style":167},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install openpyxl\n","bash","",[169,170,171],"code",{"__ignoreMap":167},[172,173,175,179,183],"span",{"class":73,"line":174},1,[172,176,178],{"class":177},"sMTad","pip",[172,180,182],{"class":181},"srMev"," install",[172,184,185],{"class":181}," openpyxl\n",[10,187,188],{},"The examples start from a small styled source sheet — a header cell and a formatted data row, the kind of thing a template provides:",[162,190,194],{"className":191,"code":192,"language":193,"meta":167,"style":167},"language-python shiki shiki-themes github-light github-dark-high-contrast","from copy import copy\n\nfrom openpyxl import Workbook, load_workbook\nfrom openpyxl.styles import Alignment, Border, Font, PatternFill, Side\n\nwb = Workbook()\nws = wb.active\nws.title = \"Template\"\n\nws[\"A1\"] = \"Region\"\nws[\"A1\"].font = Font(bold=True, color=\"FFFFFF\")\nws[\"A1\"].fill = PatternFill(\"solid\", fgColor=\"4338CA\")\nws[\"A1\"].alignment = Alignment(horizontal=\"center\")\nws[\"A1\"].border = Border(bottom=Side(style=\"medium\", color=\"1E1B4B\"))\n\nws[\"B2\"] = 0.125\nws[\"B2\"].number_format = \"0.0%\"\nws[\"B2\"].font = Font(color=\"0B6157\")\nws[\"B2\"].border = Border(bottom=Side(style=\"thin\", color=\"CDD5E6\"))\nwb.save(\"template.xlsx\")\n","python",[169,195,196,212,219,232,245,250,262,273,284,289,306,345,375,400,443,448,463,478,500,537],{"__ignoreMap":167},[172,197,198,202,206,209],{"class":73,"line":174},[172,199,201],{"class":200},"s-kum","from",[172,203,205],{"class":204},"skGVy"," copy ",[172,207,208],{"class":200},"import",[172,210,211],{"class":204}," copy\n",[172,213,215],{"class":73,"line":214},2,[172,216,218],{"emptyLinePlaceholder":217},true,"\n",[172,220,222,224,227,229],{"class":73,"line":221},3,[172,223,201],{"class":200},[172,225,226],{"class":204}," openpyxl ",[172,228,208],{"class":200},[172,230,231],{"class":204}," Workbook, load_workbook\n",[172,233,235,237,240,242],{"class":73,"line":234},4,[172,236,201],{"class":200},[172,238,239],{"class":204}," openpyxl.styles ",[172,241,208],{"class":200},[172,243,244],{"class":204}," Alignment, Border, Font, PatternFill, Side\n",[172,246,248],{"class":73,"line":247},5,[172,249,218],{"emptyLinePlaceholder":217},[172,251,253,256,259],{"class":73,"line":252},6,[172,254,255],{"class":204},"wb ",[172,257,258],{"class":200},"=",[172,260,261],{"class":204}," Workbook()\n",[172,263,265,268,270],{"class":73,"line":264},7,[172,266,267],{"class":204},"ws ",[172,269,258],{"class":200},[172,271,272],{"class":204}," wb.active\n",[172,274,276,279,281],{"class":73,"line":275},8,[172,277,278],{"class":204},"ws.title ",[172,280,258],{"class":200},[172,282,283],{"class":181}," \"Template\"\n",[172,285,287],{"class":73,"line":286},9,[172,288,218],{"emptyLinePlaceholder":217},[172,290,292,295,298,301,303],{"class":73,"line":291},10,[172,293,294],{"class":204},"ws[",[172,296,297],{"class":181},"\"A1\"",[172,299,300],{"class":204},"] ",[172,302,258],{"class":200},[172,304,305],{"class":181}," \"Region\"\n",[172,307,309,311,313,316,318,321,325,327,331,334,337,339,342],{"class":73,"line":308},11,[172,310,294],{"class":204},[172,312,297],{"class":181},[172,314,315],{"class":204},"].font ",[172,317,258],{"class":200},[172,319,320],{"class":204}," Font(",[172,322,324],{"class":323},"sa561","bold",[172,326,258],{"class":200},[172,328,330],{"class":329},"sP0c6","True",[172,332,333],{"class":204},", ",[172,335,336],{"class":323},"color",[172,338,258],{"class":200},[172,340,341],{"class":181},"\"FFFFFF\"",[172,343,344],{"class":204},")\n",[172,346,348,350,352,355,357,360,363,365,368,370,373],{"class":73,"line":347},12,[172,349,294],{"class":204},[172,351,297],{"class":181},[172,353,354],{"class":204},"].fill ",[172,356,258],{"class":200},[172,358,359],{"class":204}," PatternFill(",[172,361,362],{"class":181},"\"solid\"",[172,364,333],{"class":204},[172,366,367],{"class":323},"fgColor",[172,369,258],{"class":200},[172,371,372],{"class":181},"\"4338CA\"",[172,374,344],{"class":204},[172,376,378,380,382,385,387,390,393,395,398],{"class":73,"line":377},13,[172,379,294],{"class":204},[172,381,297],{"class":181},[172,383,384],{"class":204},"].alignment ",[172,386,258],{"class":200},[172,388,389],{"class":204}," Alignment(",[172,391,392],{"class":323},"horizontal",[172,394,258],{"class":200},[172,396,397],{"class":181},"\"center\"",[172,399,344],{"class":204},[172,401,403,405,407,410,412,415,418,420,423,426,428,431,433,435,437,440],{"class":73,"line":402},14,[172,404,294],{"class":204},[172,406,297],{"class":181},[172,408,409],{"class":204},"].border ",[172,411,258],{"class":200},[172,413,414],{"class":204}," Border(",[172,416,417],{"class":323},"bottom",[172,419,258],{"class":200},[172,421,422],{"class":204},"Side(",[172,424,425],{"class":323},"style",[172,427,258],{"class":200},[172,429,430],{"class":181},"\"medium\"",[172,432,333],{"class":204},[172,434,336],{"class":323},[172,436,258],{"class":200},[172,438,439],{"class":181},"\"1E1B4B\"",[172,441,442],{"class":204},"))\n",[172,444,446],{"class":73,"line":445},15,[172,447,218],{"emptyLinePlaceholder":217},[172,449,451,453,456,458,460],{"class":73,"line":450},16,[172,452,294],{"class":204},[172,454,455],{"class":181},"\"B2\"",[172,457,300],{"class":204},[172,459,258],{"class":200},[172,461,462],{"class":329}," 0.125\n",[172,464,466,468,470,473,475],{"class":73,"line":465},17,[172,467,294],{"class":204},[172,469,455],{"class":181},[172,471,472],{"class":204},"].number_format ",[172,474,258],{"class":200},[172,476,477],{"class":181}," \"0.0%\"\n",[172,479,481,483,485,487,489,491,493,495,498],{"class":73,"line":480},18,[172,482,294],{"class":204},[172,484,455],{"class":181},[172,486,315],{"class":204},[172,488,258],{"class":200},[172,490,320],{"class":204},[172,492,336],{"class":323},[172,494,258],{"class":200},[172,496,497],{"class":181},"\"0B6157\"",[172,499,344],{"class":204},[172,501,503,505,507,509,511,513,515,517,519,521,523,526,528,530,532,535],{"class":73,"line":502},19,[172,504,294],{"class":204},[172,506,455],{"class":181},[172,508,409],{"class":204},[172,510,258],{"class":200},[172,512,414],{"class":204},[172,514,417],{"class":323},[172,516,258],{"class":200},[172,518,422],{"class":204},[172,520,425],{"class":323},[172,522,258],{"class":200},[172,524,525],{"class":181},"\"thin\"",[172,527,333],{"class":204},[172,529,336],{"class":323},[172,531,258],{"class":200},[172,533,534],{"class":181},"\"CDD5E6\"",[172,536,442],{"class":204},[172,538,540,543,546],{"class":73,"line":539},20,[172,541,542],{"class":204},"wb.save(",[172,544,545],{"class":181},"\"template.xlsx\"",[172,547,344],{"class":204},[157,549,551],{"id":550},"step-1-copy-a-style-attribute-by-attribute","Step 1 — Copy a style attribute by attribute",[10,553,554,555,558],{},"The dependable pattern is one helper that copies each of the six style attributes with ",[169,556,557],{},"copy()",". It works for any two cells, in the same sheet, another sheet, or another workbook:",[162,560,562],{"className":191,"code":561,"language":193,"meta":167,"style":167},"STYLE_ATTRS = (\"font\", \"fill\", \"border\", \"alignment\", \"number_format\", \"protection\")\n\ndef copy_style(source, target) -> None:\n    for attr in STYLE_ATTRS:\n        setattr(target, attr, copy(getattr(source, attr)))\n\ncopy_style(ws[\"A1\"], ws[\"B1\"])\nws[\"B1\"] = \"Share\"\nprint(ws[\"B1\"].font.b, ws[\"B1\"].fill.fgColor.rgb)   # True 004338CA\n",[169,563,564,605,609,627,643,657,661,677,690],{"__ignoreMap":167},[172,565,566,569,572,575,578,580,583,585,588,590,593,595,598,600,603],{"class":73,"line":174},[172,567,568],{"class":329},"STYLE_ATTRS",[172,570,571],{"class":200}," =",[172,573,574],{"class":204}," (",[172,576,577],{"class":181},"\"font\"",[172,579,333],{"class":204},[172,581,582],{"class":181},"\"fill\"",[172,584,333],{"class":204},[172,586,587],{"class":181},"\"border\"",[172,589,333],{"class":204},[172,591,592],{"class":181},"\"alignment\"",[172,594,333],{"class":204},[172,596,597],{"class":181},"\"number_format\"",[172,599,333],{"class":204},[172,601,602],{"class":181},"\"protection\"",[172,604,344],{"class":204},[172,606,607],{"class":73,"line":214},[172,608,218],{"emptyLinePlaceholder":217},[172,610,611,614,618,621,624],{"class":73,"line":221},[172,612,613],{"class":200},"def",[172,615,617],{"class":616},"s_Opv"," copy_style",[172,619,620],{"class":204},"(source, target) -> ",[172,622,623],{"class":329},"None",[172,625,626],{"class":204},":\n",[172,628,629,632,635,638,641],{"class":73,"line":234},[172,630,631],{"class":200},"    for",[172,633,634],{"class":204}," attr ",[172,636,637],{"class":200},"in",[172,639,640],{"class":329}," STYLE_ATTRS",[172,642,626],{"class":204},[172,644,645,648,651,654],{"class":73,"line":247},[172,646,647],{"class":329},"        setattr",[172,649,650],{"class":204},"(target, attr, copy(",[172,652,653],{"class":329},"getattr",[172,655,656],{"class":204},"(source, attr)))\n",[172,658,659],{"class":73,"line":252},[172,660,218],{"emptyLinePlaceholder":217},[172,662,663,666,668,671,674],{"class":73,"line":264},[172,664,665],{"class":204},"copy_style(ws[",[172,667,297],{"class":181},[172,669,670],{"class":204},"], ws[",[172,672,673],{"class":181},"\"B1\"",[172,675,676],{"class":204},"])\n",[172,678,679,681,683,685,687],{"class":73,"line":275},[172,680,294],{"class":204},[172,682,673],{"class":181},[172,684,300],{"class":204},[172,686,258],{"class":200},[172,688,689],{"class":181}," \"Share\"\n",[172,691,692,695,698,700,703,705,708],{"class":73,"line":286},[172,693,694],{"class":329},"print",[172,696,697],{"class":204},"(ws[",[172,699,673],{"class":181},[172,701,702],{"class":204},"].font.b, ws[",[172,704,673],{"class":181},[172,706,707],{"class":204},"].fill.fgColor.rgb)   ",[172,709,711],{"class":710},"s-wDw","# True 004338CA\n",[10,713,714,716,717,719,720,723,724,727],{},[169,715,147],{}," is a plain string, so copying it is trivial; the others are style objects that openpyxl treats as immutable and shares between cells. ",[169,718,557],{}," gives the target its own reference, which is what makes the helper safe across workbooks. To copy only part of a style — say the border but not the fill — pass a shorter tuple of attributes, or modify a copy: ",[169,721,722],{},"target.font = copy(source.font)"," followed by ",[169,725,726],{},"target.font = Font(**{...})"," is the usual way to tweak one property while keeping the rest.",[157,729,731],{"id":730},"step-2-the-_style-shortcut-and-where-it-breaks","Step 2 — The _style shortcut, and where it breaks",[10,733,734,735,738,739,743],{},"Every cell also has a private ",[169,736,737],{},"_style"," attribute: a compact record of ",[740,741,742],"em",{},"indexes"," into the workbook's shared tables of fonts, fills and borders. Copying it moves the whole style in one assignment, and inside one workbook it is safe and fast:",[162,745,747],{"className":191,"code":746,"language":193,"meta":167,"style":167},"ws[\"C1\"]._style = copy(ws[\"A1\"]._style)\nprint(ws[\"C1\"].font.b)    # True\n",[169,748,749,769],{"__ignoreMap":167},[172,750,751,753,756,759,761,764,766],{"class":73,"line":174},[172,752,294],{"class":204},[172,754,755],{"class":181},"\"C1\"",[172,757,758],{"class":204},"]._style ",[172,760,258],{"class":200},[172,762,763],{"class":204}," copy(ws[",[172,765,297],{"class":181},[172,767,768],{"class":204},"]._style)\n",[172,770,771,773,775,777,780],{"class":73,"line":214},[172,772,694],{"class":329},[172,774,697],{"class":204},[172,776,755],{"class":181},[172,778,779],{"class":204},"].font.b)    ",[172,781,782],{"class":710},"# True\n",[10,784,785,786,789],{},"Across workbooks the indexes point into a ",[740,787,788],{},"different"," set of tables, and the result depends on what the target workbook happens to contain at those positions:",[162,791,793],{"className":191,"code":792,"language":193,"meta":167,"style":167},"other = Workbook()\nother.active[\"A1\"].font = Font(italic=True)       # the target has its own style table\nother.active[\"C3\"]._style = copy(ws[\"A1\"]._style)\ncopied = other.active[\"C3\"].font\nprint(copied.b, copied.i)    # False True  \u003C- not the source font at all\n",[169,794,795,804,830,847,862],{"__ignoreMap":167},[172,796,797,800,802],{"class":73,"line":174},[172,798,799],{"class":204},"other ",[172,801,258],{"class":200},[172,803,261],{"class":204},[172,805,806,809,811,813,815,817,820,822,824,827],{"class":73,"line":214},[172,807,808],{"class":204},"other.active[",[172,810,297],{"class":181},[172,812,315],{"class":204},[172,814,258],{"class":200},[172,816,320],{"class":204},[172,818,819],{"class":323},"italic",[172,821,258],{"class":200},[172,823,330],{"class":329},[172,825,826],{"class":204},")       ",[172,828,829],{"class":710},"# the target has its own style table\n",[172,831,832,834,837,839,841,843,845],{"class":73,"line":221},[172,833,808],{"class":204},[172,835,836],{"class":181},"\"C3\"",[172,838,758],{"class":204},[172,840,258],{"class":200},[172,842,763],{"class":204},[172,844,297],{"class":181},[172,846,768],{"class":204},[172,848,849,852,854,857,859],{"class":73,"line":234},[172,850,851],{"class":204},"copied ",[172,853,258],{"class":200},[172,855,856],{"class":204}," other.active[",[172,858,836],{"class":181},[172,860,861],{"class":204},"].font\n",[172,863,864,866,869],{"class":73,"line":247},[172,865,694],{"class":329},[172,867,868],{"class":204},"(copied.b, copied.i)    ",[172,870,871],{"class":710},"# False True  \u003C- not the source font at all\n",[10,873,874,875,878,879,881],{},"No error, and a wrong result: index 1 in the source workbook's font table is the bold white header font, but index 1 in the target's table is the italic font that was added first. The copied cell comes out italic and not bold. With a target whose tables are shorter than the index, the same line fails instead with ",[169,876,877],{},"IndexError: list index out of range"," the moment the style is read. Both failures come from the same cause, and the silent one is worse, because a report with the wrong fonts looks plausible until someone compares it with the template. Use ",[169,880,737],{}," only when source and target are in the same workbook; use the attribute helper everywhere else.",[20,883,29,888,29,891,29,894,29,897,29,902,29,913,29,916,29,920,29,924,29,927,29,930,29,939,29,944,29,949,29,953,29,957,29,959,29,962,29,966,29,969,29,972,29,975,29,978,29,980,29,983,29,987,29,990,29,995,29,999],{"viewBox":884,"role":23,"ariaLabelledBy":885,"xmlns":27,"style":28},"4 0 752 238",[886,887],"copy-which-t","copy-which-d",[31,889,890],{"id":886},"Which copy technique to use",[35,892,893],{"id":887},"If source and target are in the same workbook and you need speed, copying _style is safe. If they are in different workbooks, copy each style attribute with copy. If the same style goes on many cells, register a NamedStyle and assign it by name.",[39,895],{"x":41,"y":42,"width":43,"height":896,"fill":45},"238",[39,898],{"x":899,"y":49,"width":900,"height":901,"rx":52,"fill":53,"stroke":54,"style":55},"216.3","327.4","75.5",[903,904,906],"g",{"transform":905},"translate(368.0,29.0) scale(1.000)",[907,908],"path",{"d":909,"fill":910,"stroke":911,"style":912},"M6 3h9l4 4v14H6z M15 3v4h4 M9.5 11.5l4.5 6 M14 11.5l-4.5 6","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[57,914,915],{"x":107,"y":901,"style":61},"Where are the source and target cells?",[73,917],{"x1":107,"y1":918,"x2":107,"y2":919,"stroke":54,"style":55},"91.5","111.5",[73,921],{"x1":922,"y1":919,"x2":923,"y2":919,"stroke":54,"style":55},"134.7","625.3",[73,925],{"x1":922,"y1":919,"x2":922,"y2":926,"stroke":54,"style":55},"157.5",[79,928],{"points":929,"fill":82},"134.7,161.5 129.7,152.5 139.7,152.5",[39,931],{"x":932,"y":933,"width":934,"height":935,"rx":936,"fill":45,"stroke":937,"style":938},"78.7","121.5","111.9","21.0","10","var(--line,#cdd5e6)","stroke-width:1.2px",[57,940,943],{"x":922,"y":941,"style":942},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","same workbook",[39,945],{"x":48,"y":946,"width":947,"height":948,"rx":52,"fill":141,"stroke":142,"style":55},"163.5","229.3","59.0",[57,950,952],{"x":922,"y":951,"style":146},"189.0","copy(cell._style)",[57,954,956],{"x":922,"y":955,"style":66},"208.5","fast, one assignment",[73,958],{"x1":107,"y1":919,"x2":107,"y2":926,"stroke":54,"style":55},[79,960],{"points":961,"fill":82},"380.0,161.5 375.0,152.5 385.0,152.5",[39,963],{"x":964,"y":933,"width":965,"height":935,"rx":936,"fill":45,"stroke":937,"style":938},"310.8","138.4",[57,967,968],{"x":107,"y":941,"style":942},"different workbooks",[39,970],{"x":971,"y":946,"width":947,"height":948,"rx":52,"fill":53,"stroke":54,"style":55},"265.3",[57,973,974],{"x":107,"y":951,"style":61},"copy each attribute",[57,976,977],{"x":107,"y":955,"style":66},"font fill border alignment…",[73,979],{"x1":923,"y1":919,"x2":923,"y2":926,"stroke":54,"style":55},[79,981],{"points":982,"fill":82},"625.3,161.5 620.3,152.5 630.3,152.5",[39,984],{"x":985,"y":933,"width":986,"height":935,"rx":936,"fill":45,"stroke":937,"style":938},"584.7","81.3",[57,988,989],{"x":923,"y":941,"style":942},"many cells",[39,991],{"x":992,"y":946,"width":947,"height":948,"rx":52,"fill":993,"stroke":994,"style":55},"510.7","#fdefd8","var(--gold,#b4740a)",[57,996,998],{"x":923,"y":951,"style":997},"font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","NamedStyle",[57,1000,1001],{"x":923,"y":955,"style":66},"registered once",[157,1003,1005],{"id":1004},"step-3-carry-a-template-row-down-onto-new-data","Step 3 — Carry a template row down onto new data",[10,1007,1008],{},"The most common job: a template has one formatted data row, and the script writes fifty rows of data that should all look like it. Copy the template row's style to every row you write, plus the row height:",[162,1010,1012],{"className":191,"code":1011,"language":193,"meta":167,"style":167},"def extend_row_format(ws, template_row: int, first: int, last: int) -> None:\n    height = ws.row_dimensions[template_row].height\n    for row in range(first, last + 1):\n        for col in range(1, ws.max_column + 1):\n            copy_style(ws.cell(template_row, col), ws.cell(row, col))\n        if height:\n            ws.row_dimensions[row].height = height\n\nshares = [0.125, 0.31, 0.07, 0.495]\nfor i, share in enumerate(shares, start=2):\n    ws.cell(i, 1, f\"Region {i - 1}\")\n    ws.cell(i, 2, share)\nextend_row_format(ws, template_row=2, first=3, last=len(shares) + 1)\nprint([ws.cell(r, 2).number_format for r in range(2, 6)])  # ['0.0%', '0.0%', '0.0%', '0.0%']\n",[169,1013,1014,1044,1054,1078,1105,1110,1118,1128,1132,1163,1189,1224,1233,1274],{"__ignoreMap":167},[172,1015,1016,1018,1021,1024,1027,1030,1032,1035,1037,1040,1042],{"class":73,"line":174},[172,1017,613],{"class":200},[172,1019,1020],{"class":616}," extend_row_format",[172,1022,1023],{"class":204},"(ws, template_row: ",[172,1025,1026],{"class":329},"int",[172,1028,1029],{"class":204},", first: ",[172,1031,1026],{"class":329},[172,1033,1034],{"class":204},", last: ",[172,1036,1026],{"class":329},[172,1038,1039],{"class":204},") -> ",[172,1041,623],{"class":329},[172,1043,626],{"class":204},[172,1045,1046,1049,1051],{"class":73,"line":214},[172,1047,1048],{"class":204},"    height ",[172,1050,258],{"class":200},[172,1052,1053],{"class":204}," ws.row_dimensions[template_row].height\n",[172,1055,1056,1058,1061,1063,1066,1069,1072,1075],{"class":73,"line":221},[172,1057,631],{"class":200},[172,1059,1060],{"class":204}," row ",[172,1062,637],{"class":200},[172,1064,1065],{"class":329}," range",[172,1067,1068],{"class":204},"(first, last ",[172,1070,1071],{"class":200},"+",[172,1073,1074],{"class":329}," 1",[172,1076,1077],{"class":204},"):\n",[172,1079,1080,1083,1086,1088,1090,1093,1096,1099,1101,1103],{"class":73,"line":234},[172,1081,1082],{"class":200},"        for",[172,1084,1085],{"class":204}," col ",[172,1087,637],{"class":200},[172,1089,1065],{"class":329},[172,1091,1092],{"class":204},"(",[172,1094,1095],{"class":329},"1",[172,1097,1098],{"class":204},", ws.max_column ",[172,1100,1071],{"class":200},[172,1102,1074],{"class":329},[172,1104,1077],{"class":204},[172,1106,1107],{"class":73,"line":247},[172,1108,1109],{"class":204},"            copy_style(ws.cell(template_row, col), ws.cell(row, col))\n",[172,1111,1112,1115],{"class":73,"line":252},[172,1113,1114],{"class":200},"        if",[172,1116,1117],{"class":204}," height:\n",[172,1119,1120,1123,1125],{"class":73,"line":264},[172,1121,1122],{"class":204},"            ws.row_dimensions[row].height ",[172,1124,258],{"class":200},[172,1126,1127],{"class":204}," height\n",[172,1129,1130],{"class":73,"line":275},[172,1131,218],{"emptyLinePlaceholder":217},[172,1133,1134,1137,1139,1142,1145,1147,1150,1152,1155,1157,1160],{"class":73,"line":286},[172,1135,1136],{"class":204},"shares ",[172,1138,258],{"class":200},[172,1140,1141],{"class":204}," [",[172,1143,1144],{"class":329},"0.125",[172,1146,333],{"class":204},[172,1148,1149],{"class":329},"0.31",[172,1151,333],{"class":204},[172,1153,1154],{"class":329},"0.07",[172,1156,333],{"class":204},[172,1158,1159],{"class":329},"0.495",[172,1161,1162],{"class":204},"]\n",[172,1164,1165,1168,1171,1173,1176,1179,1182,1184,1187],{"class":73,"line":291},[172,1166,1167],{"class":200},"for",[172,1169,1170],{"class":204}," i, share ",[172,1172,637],{"class":200},[172,1174,1175],{"class":329}," enumerate",[172,1177,1178],{"class":204},"(shares, ",[172,1180,1181],{"class":323},"start",[172,1183,258],{"class":200},[172,1185,1186],{"class":329},"2",[172,1188,1077],{"class":204},[172,1190,1191,1194,1196,1198,1201,1204,1208,1211,1214,1216,1219,1222],{"class":73,"line":308},[172,1192,1193],{"class":204},"    ws.cell(i, ",[172,1195,1095],{"class":329},[172,1197,333],{"class":204},[172,1199,1200],{"class":200},"f",[172,1202,1203],{"class":181},"\"Region ",[172,1205,1207],{"class":1206},"sSjpA","{",[172,1209,1210],{"class":204},"i ",[172,1212,1213],{"class":200},"-",[172,1215,1074],{"class":329},[172,1217,1218],{"class":1206},"}",[172,1220,1221],{"class":181},"\"",[172,1223,344],{"class":204},[172,1225,1226,1228,1230],{"class":73,"line":347},[172,1227,1193],{"class":204},[172,1229,1186],{"class":329},[172,1231,1232],{"class":204},", share)\n",[172,1234,1235,1238,1241,1243,1245,1247,1250,1252,1255,1257,1260,1262,1265,1268,1270,1272],{"class":73,"line":377},[172,1236,1237],{"class":204},"extend_row_format(ws, ",[172,1239,1240],{"class":323},"template_row",[172,1242,258],{"class":200},[172,1244,1186],{"class":329},[172,1246,333],{"class":204},[172,1248,1249],{"class":323},"first",[172,1251,258],{"class":200},[172,1253,1254],{"class":329},"3",[172,1256,333],{"class":204},[172,1258,1259],{"class":323},"last",[172,1261,258],{"class":200},[172,1263,1264],{"class":329},"len",[172,1266,1267],{"class":204},"(shares) ",[172,1269,1071],{"class":200},[172,1271,1074],{"class":329},[172,1273,344],{"class":204},[172,1275,1276,1278,1281,1283,1286,1288,1291,1293,1295,1297,1299,1301,1304,1307],{"class":73,"line":402},[172,1277,694],{"class":329},[172,1279,1280],{"class":204},"([ws.cell(r, ",[172,1282,1186],{"class":329},[172,1284,1285],{"class":204},").number_format ",[172,1287,1167],{"class":200},[172,1289,1290],{"class":204}," r ",[172,1292,637],{"class":200},[172,1294,1065],{"class":329},[172,1296,1092],{"class":204},[172,1298,1186],{"class":329},[172,1300,333],{"class":204},[172,1302,1303],{"class":329},"6",[172,1305,1306],{"class":204},")])  ",[172,1308,1309],{"class":710},"# ['0.0%', '0.0%', '0.0%', '0.0%']\n",[10,1311,1312,1313,1316],{},"Write the values first and the styles second, or the other way round — it does not matter, because value and style are independent. What matters is copying from the ",[740,1314,1315],{},"template"," row every time rather than from the row above, so a mistake in one row cannot cascade down the sheet.",[157,1318,1320],{"id":1319},"step-4-copy-column-widths-and-row-heights-too","Step 4 — Copy column widths and row heights too",[10,1322,1323,1324,1327,1328,1331],{},"A copied cell style does not include the width of its column or the height of its row; those live in ",[169,1325,1326],{},"column_dimensions"," and ",[169,1329,1330],{},"row_dimensions"," on the sheet. When you clone a layout onto another sheet, copy them explicitly:",[162,1333,1335],{"className":191,"code":1334,"language":193,"meta":167,"style":167},"def copy_dimensions(src_ws, dst_ws) -> None:\n    for key, dim in src_ws.column_dimensions.items():\n        dst_ws.column_dimensions[key].width = dim.width\n        dst_ws.column_dimensions[key].hidden = dim.hidden\n    for idx, dim in src_ws.row_dimensions.items():\n        if dim.height:\n            dst_ws.row_dimensions[idx].height = dim.height\n\nws.column_dimensions[\"A\"].width = 22\nreport = wb.create_sheet(\"March\")\nfor row in ws.iter_rows():\n    for cell in row:\n        target = report.cell(cell.row, cell.column, cell.value)\n        copy_style(cell, target)\ncopy_dimensions(ws, report)\nprint(report.column_dimensions[\"A\"].width)   # 22.0\n",[169,1336,1337,1351,1363,1373,1383,1395,1402,1412,1416,1432,1447,1458,1470,1480,1485,1490],{"__ignoreMap":167},[172,1338,1339,1341,1344,1347,1349],{"class":73,"line":174},[172,1340,613],{"class":200},[172,1342,1343],{"class":616}," copy_dimensions",[172,1345,1346],{"class":204},"(src_ws, dst_ws) -> ",[172,1348,623],{"class":329},[172,1350,626],{"class":204},[172,1352,1353,1355,1358,1360],{"class":73,"line":214},[172,1354,631],{"class":200},[172,1356,1357],{"class":204}," key, dim ",[172,1359,637],{"class":200},[172,1361,1362],{"class":204}," src_ws.column_dimensions.items():\n",[172,1364,1365,1368,1370],{"class":73,"line":221},[172,1366,1367],{"class":204},"        dst_ws.column_dimensions[key].width ",[172,1369,258],{"class":200},[172,1371,1372],{"class":204}," dim.width\n",[172,1374,1375,1378,1380],{"class":73,"line":234},[172,1376,1377],{"class":204},"        dst_ws.column_dimensions[key].hidden ",[172,1379,258],{"class":200},[172,1381,1382],{"class":204}," dim.hidden\n",[172,1384,1385,1387,1390,1392],{"class":73,"line":247},[172,1386,631],{"class":200},[172,1388,1389],{"class":204}," idx, dim ",[172,1391,637],{"class":200},[172,1393,1394],{"class":204}," src_ws.row_dimensions.items():\n",[172,1396,1397,1399],{"class":73,"line":252},[172,1398,1114],{"class":200},[172,1400,1401],{"class":204}," dim.height:\n",[172,1403,1404,1407,1409],{"class":73,"line":264},[172,1405,1406],{"class":204},"            dst_ws.row_dimensions[idx].height ",[172,1408,258],{"class":200},[172,1410,1411],{"class":204}," dim.height\n",[172,1413,1414],{"class":73,"line":275},[172,1415,218],{"emptyLinePlaceholder":217},[172,1417,1418,1421,1424,1427,1429],{"class":73,"line":286},[172,1419,1420],{"class":204},"ws.column_dimensions[",[172,1422,1423],{"class":181},"\"A\"",[172,1425,1426],{"class":204},"].width ",[172,1428,258],{"class":200},[172,1430,1431],{"class":329}," 22\n",[172,1433,1434,1437,1439,1442,1445],{"class":73,"line":291},[172,1435,1436],{"class":204},"report ",[172,1438,258],{"class":200},[172,1440,1441],{"class":204}," wb.create_sheet(",[172,1443,1444],{"class":181},"\"March\"",[172,1446,344],{"class":204},[172,1448,1449,1451,1453,1455],{"class":73,"line":308},[172,1450,1167],{"class":200},[172,1452,1060],{"class":204},[172,1454,637],{"class":200},[172,1456,1457],{"class":204}," ws.iter_rows():\n",[172,1459,1460,1462,1465,1467],{"class":73,"line":347},[172,1461,631],{"class":200},[172,1463,1464],{"class":204}," cell ",[172,1466,637],{"class":200},[172,1468,1469],{"class":204}," row:\n",[172,1471,1472,1475,1477],{"class":73,"line":377},[172,1473,1474],{"class":204},"        target ",[172,1476,258],{"class":200},[172,1478,1479],{"class":204}," report.cell(cell.row, cell.column, cell.value)\n",[172,1481,1482],{"class":73,"line":402},[172,1483,1484],{"class":204},"        copy_style(cell, target)\n",[172,1486,1487],{"class":73,"line":445},[172,1488,1489],{"class":204},"copy_dimensions(ws, report)\n",[172,1491,1492,1494,1497,1499,1502],{"class":73,"line":450},[172,1493,694],{"class":329},[172,1495,1496],{"class":204},"(report.column_dimensions[",[172,1498,1423],{"class":181},[172,1500,1501],{"class":204},"].width)   ",[172,1503,1504],{"class":710},"# 22.0\n",[10,1506,1507,1508,1511,1512,1516],{},"If you only need an identical copy of a sheet inside the same workbook, ",[169,1509,1510],{},"wb.copy_worksheet(ws)"," does all of this in one call — values, styles, dimensions and merged cells — and is covered in ",[14,1513,1515],{"href":1514},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-multiple-excel-sheets-in-python\u002Fcopy-a-sheet-between-excel-workbooks-with-python\u002F","Copy a Sheet Between Excel Workbooks with Python",", along with the cross-workbook case it does not handle.",[157,1518,1520],{"id":1519},"step-5-use-a-namedstyle-for-many-cells","Step 5 — Use a NamedStyle for many cells",[10,1522,1523,1524,1526],{},"When the same look goes on hundreds or thousands of cells, define it once as a ",[169,1525,998],{},", register it, and assign it by name. Every cell then points at one shared record:",[162,1528,1530],{"className":191,"code":1529,"language":193,"meta":167,"style":167},"from openpyxl.styles import NamedStyle\n\npercent_cell = NamedStyle(name=\"percent_cell\")\npercent_cell.number_format = \"0.0%\"\npercent_cell.font = Font(color=\"0B6157\")\npercent_cell.border = Border(bottom=Side(style=\"thin\", color=\"CDD5E6\"))\nwb.add_named_style(percent_cell)\n\nfor row in range(2, 1002):\n    report.cell(row, 3).style = \"percent_cell\"\n\nwb.save(\"styled_copy.xlsx\")\nprint(load_workbook(\"styled_copy.xlsx\")[\"March\"][\"C500\"].style)   # percent_cell\n",[169,1531,1532,1543,1547,1567,1576,1593,1624,1629,1633,1654,1669,1673,1682],{"__ignoreMap":167},[172,1533,1534,1536,1538,1540],{"class":73,"line":174},[172,1535,201],{"class":200},[172,1537,239],{"class":204},[172,1539,208],{"class":200},[172,1541,1542],{"class":204}," NamedStyle\n",[172,1544,1545],{"class":73,"line":214},[172,1546,218],{"emptyLinePlaceholder":217},[172,1548,1549,1552,1554,1557,1560,1562,1565],{"class":73,"line":221},[172,1550,1551],{"class":204},"percent_cell ",[172,1553,258],{"class":200},[172,1555,1556],{"class":204}," NamedStyle(",[172,1558,1559],{"class":323},"name",[172,1561,258],{"class":200},[172,1563,1564],{"class":181},"\"percent_cell\"",[172,1566,344],{"class":204},[172,1568,1569,1572,1574],{"class":73,"line":234},[172,1570,1571],{"class":204},"percent_cell.number_format ",[172,1573,258],{"class":200},[172,1575,477],{"class":181},[172,1577,1578,1581,1583,1585,1587,1589,1591],{"class":73,"line":247},[172,1579,1580],{"class":204},"percent_cell.font ",[172,1582,258],{"class":200},[172,1584,320],{"class":204},[172,1586,336],{"class":323},[172,1588,258],{"class":200},[172,1590,497],{"class":181},[172,1592,344],{"class":204},[172,1594,1595,1598,1600,1602,1604,1606,1608,1610,1612,1614,1616,1618,1620,1622],{"class":73,"line":252},[172,1596,1597],{"class":204},"percent_cell.border ",[172,1599,258],{"class":200},[172,1601,414],{"class":204},[172,1603,417],{"class":323},[172,1605,258],{"class":200},[172,1607,422],{"class":204},[172,1609,425],{"class":323},[172,1611,258],{"class":200},[172,1613,525],{"class":181},[172,1615,333],{"class":204},[172,1617,336],{"class":323},[172,1619,258],{"class":200},[172,1621,534],{"class":181},[172,1623,442],{"class":204},[172,1625,1626],{"class":73,"line":264},[172,1627,1628],{"class":204},"wb.add_named_style(percent_cell)\n",[172,1630,1631],{"class":73,"line":275},[172,1632,218],{"emptyLinePlaceholder":217},[172,1634,1635,1637,1639,1641,1643,1645,1647,1649,1652],{"class":73,"line":286},[172,1636,1167],{"class":200},[172,1638,1060],{"class":204},[172,1640,637],{"class":200},[172,1642,1065],{"class":329},[172,1644,1092],{"class":204},[172,1646,1186],{"class":329},[172,1648,333],{"class":204},[172,1650,1651],{"class":329},"1002",[172,1653,1077],{"class":204},[172,1655,1656,1659,1661,1664,1666],{"class":73,"line":291},[172,1657,1658],{"class":204},"    report.cell(row, ",[172,1660,1254],{"class":329},[172,1662,1663],{"class":204},").style ",[172,1665,258],{"class":200},[172,1667,1668],{"class":181}," \"percent_cell\"\n",[172,1670,1671],{"class":73,"line":308},[172,1672,218],{"emptyLinePlaceholder":217},[172,1674,1675,1677,1680],{"class":73,"line":347},[172,1676,542],{"class":204},[172,1678,1679],{"class":181},"\"styled_copy.xlsx\"",[172,1681,344],{"class":204},[172,1683,1684,1686,1689,1691,1694,1696,1699,1702,1705],{"class":73,"line":377},[172,1685,694],{"class":329},[172,1687,1688],{"class":204},"(load_workbook(",[172,1690,1679],{"class":181},[172,1692,1693],{"class":204},")[",[172,1695,1444],{"class":181},[172,1697,1698],{"class":204},"][",[172,1700,1701],{"class":181},"\"C500\"",[172,1703,1704],{"class":204},"].style)   ",[172,1706,1707],{"class":710},"# percent_cell\n",[10,1709,1710,1711,1715],{},"Named styles also show up in Excel's Cell Styles gallery, so whoever edits the report later can apply the same look by hand. A whole style system built this way is described in ",[14,1712,1714],{"href":1713},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fapply-a-reusable-style-theme-across-an-excel-report\u002F","Apply a Reusable Style Theme Across an Excel Report",".",[20,1717,29,1722,29,1725,29,1728,29,1731,29,1736,29,1744,29,1750,29,1756,29,1762,29,1769,29,1773,29,1778,29,1782,29,1788,29,1791,29,1798,29,1802,29,1806,29,1810,29,1815,29,1818,29,1823,29,1826],{"viewBox":1718,"role":23,"ariaLabelledBy":1719,"xmlns":27,"style":28},"4 0 752 207",[1720,1721],"copy-cost-t","copy-cost-d",[31,1723,1724],{"id":1720},"Per-cell styles versus a named style on a thousand cells",[35,1726,1727],{"id":1721},"Copying six attributes to a thousand cells stores a style reference per cell and costs six assignments each. A NamedStyle is registered once and each cell only stores its name, which is faster to apply and visible in Excel's Cell Styles gallery.",[39,1729],{"x":41,"y":42,"width":43,"height":1730,"fill":45},"207",[39,1732],{"x":48,"y":49,"width":1733,"height":1734,"rx":1735,"fill":993,"stroke":994,"style":55},"351.0","175.0","14",[903,1737,1739],{"transform":1738},"translate(182.5,29.0) scale(1.083)",[907,1740],{"d":1741,"fill":910,"stroke":1742,"style":1743},"M9 8l-4 4 4 4 M15 8l4 4-4 4","var(--gold-ink,#7a4e06)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[57,1745,1749],{"x":1746,"y":1747,"style":1748},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","copy_style() per cell",[73,1751],{"x1":1752,"y1":1753,"x2":1754,"y2":1753,"stroke":994,"style":1755},"36.0","91.0","355.0","stroke-width:1px",[57,1757,1761],{"x":1758,"y":1759,"style":1760},"60.0","111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","six assignments per cell",[903,1763,1765],{"transform":1764},"translate(38.5,99.5) scale(0.625)",[907,1766],{"d":1767,"fill":910,"stroke":994,"style":1768},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[57,1770,1772],{"x":1758,"y":1771,"style":1760},"137.0","style deduplicated on save",[903,1774,1776],{"transform":1775},"translate(38.5,125.5) scale(0.625)",[907,1777],{"d":1767,"fill":910,"stroke":994,"style":1768},[57,1779,1781],{"x":1758,"y":1780,"style":1760},"163.0","works across workbooks",[903,1783,1785],{"transform":1784},"translate(38.5,151.5) scale(0.625)",[907,1786],{"d":1787,"fill":910,"stroke":142,"style":1768},"M5 12.5l4.5 4.5L19 7",[39,1789],{"x":1790,"y":49,"width":1733,"height":1734,"rx":1735,"fill":141,"stroke":142,"style":55},"389.0",[903,1792,1794],{"transform":1793},"translate(551.5,29.0) scale(1.083)",[907,1795],{"d":1796,"fill":910,"stroke":1797,"style":1743},"M12 3l9 5-9 5-9-5z M3 13l9 5 9-5 M3 17l9 5 9-5","var(--teal-ink,#0b6157)",[57,1799,998],{"x":1800,"y":1747,"style":1801},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle",[73,1803],{"x1":1804,"y1":1753,"x2":1805,"y2":1753,"stroke":142,"style":1755},"405.0","724.0",[57,1807,1809],{"x":1808,"y":1759,"style":1760},"429.0","defined once",[903,1811,1813],{"transform":1812},"translate(407.5,99.5) scale(0.625)",[907,1814],{"d":1787,"fill":910,"stroke":142,"style":1768},[57,1816,1817],{"x":1808,"y":1771,"style":1760},"one assignment per cell",[903,1819,1821],{"transform":1820},"translate(407.5,125.5) scale(0.625)",[907,1822],{"d":1787,"fill":910,"stroke":142,"style":1768},[57,1824,1825],{"x":1808,"y":1780,"style":1760},"shows in Cell Styles gallery",[903,1827,1829],{"transform":1828},"translate(407.5,151.5) scale(0.625)",[907,1830],{"d":1787,"fill":910,"stroke":142,"style":1768},[157,1832,1834],{"id":1833},"common-pitfalls","Common pitfalls",[1836,1837,1838,1853,1859,1869],"ul",{},[1839,1840,1841,1848,1849,1852],"li",{},[1842,1843,1844,1845,1847],"strong",{},"Copying ",[169,1846,737],{}," between workbooks."," It raises ",[169,1850,1851],{},"IndexError"," or applies a wrong style. Copy attributes instead.",[1839,1854,1855,1858],{},[1842,1856,1857],{},"Forgetting that conditional formatting is separate."," It lives on the worksheet as rules over ranges; add a rule covering the new rows rather than copying cells.",[1839,1860,1861,1864,1865,1868],{},[1842,1862,1863],{},"Copying merged cells cell by cell."," Only the top-left cell of a merged range holds the value and full style; re-create the merge with ",[169,1866,1867],{},"ws.merge_cells()"," on the target.",[1839,1870,1871,1874,1875,1878],{},[1842,1872,1873],{},"Theme colours."," Some templates use theme colours (",[169,1876,1877],{},"fgColor.theme",") rather than RGB. They copy correctly within a workbook but render in the target workbook's theme, which may differ.",[157,1880,1882],{"id":1881},"performance-and-scale-notes","Performance and scale notes",[10,1884,1885,1886,1888,1889,1715],{},"Style assignment is cheap per cell but adds up: copying six attributes to 100,000 cells is 600,000 Python-level assignments and takes several seconds. openpyxl deduplicates identical styles when saving, so the file does not bloat, but the loop is still slow. For large ranges prefer a ",[169,1887,998],{},", style whole columns once in the template so new rows inherit them where Excel allows it, or generate the report with xlsxwriter, where a format object is attached at write time at no extra cost — see ",[14,1890,1892],{"href":1891},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-a-formatted-excel-report-with-xlsxwriter\u002F","Write a Formatted Excel Report with xlsxwriter",[157,1894,1896],{"id":1895},"conclusion","Conclusion",[10,1898,1899,1900,1902,1903,1905,1906,1908],{},"Copy a cell's look by copying its six style attributes with ",[169,1901,557],{}," — a small helper that works everywhere. Use ",[169,1904,737],{}," only as a fast path inside one workbook, remember that widths, heights, merges and conditional formats live on the sheet rather than the cell, and switch to a registered ",[169,1907,998],{}," when one look covers many cells. Always copy from a fixed template cell or row, never from the previous row, so the formatting stays consistent however long the report grows.",[157,1910,1912],{"id":1911},"frequently-asked-questions","Frequently asked questions",[10,1914,1915,1918],{},[1842,1916,1917],{},"Why can't I just assign target.font = source.font?","\nIn openpyxl style objects are immutable and shared, and assigning the same object works within one workbook, but copying with copy() is the documented, safe pattern — and it is required when the target lives in a different workbook.",[10,1920,1921,1924],{},[1842,1922,1923],{},"Is copying cell._style faster?","\nYes, and within one workbook it is safe, because _style holds indexes into that workbook's style tables. Across workbooks those indexes point at the wrong or missing entries, and openpyxl raises IndexError or applies the wrong format.",[10,1926,1927,1930],{},[1842,1928,1929],{},"Does copying a cell style copy conditional formatting?","\nNo. Conditional formatting rules belong to the worksheet and apply to ranges, not to individual cells. Add the rule to the new range instead.",[10,1932,1933,1936],{},[1842,1934,1935],{},"How do I copy a style to a whole range quickly?","\nCreate a NamedStyle once, register it with the workbook, and assign its name to each cell. Every cell then shares one style record, which keeps the file small and the loop fast.",[157,1938,1940],{"id":1939},"related","Related",[1836,1942,1943,1949,1956,1963],{},[1839,1944,1945,1946,1948],{},"Up one level: ",[14,1947,17],{"href":16}," — the openpyxl object model.",[1839,1950,1951,1955],{},[14,1952,1954],{"href":1953},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002F","Styling Excel Cells with openpyxl"," — building styles from scratch.",[1839,1957,1958,1962],{},[14,1959,1961],{"href":1960},"\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fpopulate-excel-template-without-losing-formatting\u002F","Populate an Excel Template Without Losing Formatting"," — where copied row formats matter most.",[1839,1964,1965,1969],{},[14,1966,1968],{"href":1967},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Funmerge-cells-and-fill-values-with-openpyxl\u002F","Unmerge Cells and Fill the Values with openpyxl"," — handling merged ranges when copying.",[425,1971,1972],{},"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 .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}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}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":167,"searchDepth":214,"depth":214,"links":1974},[1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985],{"id":159,"depth":214,"text":160},{"id":550,"depth":214,"text":551},{"id":730,"depth":214,"text":731},{"id":1004,"depth":214,"text":1005},{"id":1319,"depth":214,"text":1320},{"id":1519,"depth":214,"text":1520},{"id":1833,"depth":214,"text":1834},{"id":1881,"depth":214,"text":1882},{"id":1895,"depth":214,"text":1896},{"id":1911,"depth":214,"text":1912},{"id":1939,"depth":214,"text":1940},"2026-09-23","Copy fonts, fills, borders, alignment and number formats between cells with openpyxl — within a sheet, across sheets and between workbooks — plus column widths, row heights and whole-row formatting for new data.","md",[1990,1992,1994,1996],{"q":1917,"a":1991},"In openpyxl style objects are immutable and shared, and assigning the same object works within one workbook, but copying with copy() is the documented, safe pattern — and it is required when the target lives in a different workbook.",{"q":1923,"a":1993},"Yes, and within one workbook it is safe, because _style holds indexes into that workbook's style tables. Across workbooks those indexes point at the wrong or missing entries, and openpyxl raises IndexError or applies the wrong format.",{"q":1929,"a":1995},"No. Conditional formatting rules belong to the worksheet and apply to ranges, not to individual cells. Add the rule to the new range instead.",{"q":1935,"a":1997},"Create a NamedStyle once, register it with the workbook, and assign its name to each cell. Every cell then shares one style record, which keeps the file small and the loop fast.","copy cell styles from one cell to another with openpyxl",null,{"breadcrumb":2001},[2002,2005,2008],{"name":2003,"item":2004},"Home","\u002F",{"name":2006,"item":2007},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":17,"item":16},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl",{"title":2011,"description":2012},"Copy Cell Formatting with openpyxl (Within and Across Workbooks)","Copy a cell's style in openpyxl the right way — copy() each style attribute, why _style breaks across workbooks, named styles for reuse, and copying widths, heights and formatted template rows.","copy-cell-styles-with-openpyxl","getting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl\u002Findex",[2016,2017],"cell-styling","openpyxl","how-to","g0CZsxwebc4XGaL3zlXPz9nopQNp8zGoPQyVrcTesRg",[2021,2025],{"title":2022,"path":2023,"stem":2024,"children":-1},"Convert Excel Column Letters and Numbers in Python","\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fconvert-column-letters-and-numbers-with-openpyxl","getting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fconvert-column-letters-and-numbers-with-openpyxl\u002Findex",{"title":2026,"path":2027,"stem":2028,"children":-1},"Delete Empty Rows and Columns with openpyxl","\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fdelete-empty-rows-and-columns-with-openpyxl","getting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fdelete-empty-rows-and-columns-with-openpyxl\u002Findex",[2030,2032],{"path":2031,"title":2006},"\u002Fgetting-started-with-python-excel-automation",{"path":2033,"title":17},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation",[],[2036,2040,2043,2046,2049,2052],{"path":2037,"title":2038,"kind":2039},"\u002Fformatting-and-charting-excel-reports-with-python","Formatting and Charting Excel Reports with Python","overview",{"path":2041,"title":2042,"kind":2018},"\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":2044,"title":1954,"kind":2045},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl","guide",{"path":2047,"title":2048,"kind":2018},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fadd-alternating-row-colors-with-openpyxl","Add Alternating Row Colors with openpyxl",{"path":2050,"title":2051,"kind":2018},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fadd-borders-to-a-range-with-openpyxl","Add Borders to a Range with openpyxl",{"path":2053,"title":2054,"kind":2018},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fadd-hyperlinks-to-excel-cells-with-python","Add Hyperlinks to Excel Cells with Python",1790972069788]