[{"data":1,"prerenderedAt":1988},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl":1980},{"id":4,"title":5,"body":6,"description":1972,"extension":1973,"meta":1974,"navigation":81,"path":1975,"seo":1976,"stem":1978,"__hash__":1979},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Findex.md","Styling Excel Cells with openpyxl",{"type":7,"value":8,"toc":1958},"minimark",[9,19,24,50,53,313,317,330,518,522,540,678,682,727,912,916,926,1132,1136,1139,1345,1349,1360,1551,1555,1562,1786,1790,1797,1817,1821,1841,1861,1867,1876,1889,1893,1911,1915,1955],[10,11,12,13,18],"p",{},"A report that no one styles looks like a database dump. With openpyxl you set fonts, fills, borders, and alignment directly on cells, and because you are editing the Office Open XML file itself, those styles persist exactly as written. This page is part of ",[14,15,17],"a",{"href":16},"\u002Fformatting-and-charting-excel-reports-with-python\u002F","Formatting and Charting Excel Reports with Python",", and it walks through every styling object you reach for in a real reporting script. Each block runs in order against a sample workbook built in the first step.",[20,21,23],"h2",{"id":22},"install-and-create-a-sample-workbook","Install and create a sample workbook",[25,26,31],"pre",{"className":27,"code":28,"language":29,"meta":30,"style":30},"language-bash shiki shiki-themes github-light github-dark","pip install openpyxl\n","bash","",[32,33,34],"code",{"__ignoreMap":30},[35,36,39,43,47],"span",{"class":37,"line":38},"line",1,[35,40,42],{"class":41},"sScJk","pip",[35,44,46],{"class":45},"sZZnC"," install",[35,48,49],{"class":45}," openpyxl\n",[10,51,52],{},"Build a tiny sales sheet with a header row and a few data rows so the styling steps below have real cells to target:",[25,54,58],{"className":55,"code":56,"language":57,"meta":30,"style":30},"language-python shiki shiki-themes github-light github-dark","from openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nws.title = \"Sales\"\n\nws.append([\"Region\", \"Rep\", \"Units\", \"Revenue\"])\nfor row in [\n    [\"North\", \"Alvarez\", 120, 24000],\n    [\"South\", \"Boateng\", 95, 19000],\n    [\"East\",  \"Chen\",    140, 28000],\n    [\"West\",  \"Dubois\",  80,  16000],\n]:\n    ws.append(row)\n\nwb.save(\"styled_report.xlsx\")\nprint(\"Sample workbook created\")\n","python",[32,59,60,76,83,95,106,117,122,150,165,193,218,245,270,276,282,287,299],{"__ignoreMap":30},[35,61,62,66,70,73],{"class":37,"line":38},[35,63,65],{"class":64},"szBVR","from",[35,67,69],{"class":68},"sVt8B"," openpyxl ",[35,71,72],{"class":64},"import",[35,74,75],{"class":68}," Workbook\n",[35,77,79],{"class":37,"line":78},2,[35,80,82],{"emptyLinePlaceholder":81},true,"\n",[35,84,86,89,92],{"class":37,"line":85},3,[35,87,88],{"class":68},"wb ",[35,90,91],{"class":64},"=",[35,93,94],{"class":68}," Workbook()\n",[35,96,98,101,103],{"class":37,"line":97},4,[35,99,100],{"class":68},"ws ",[35,102,91],{"class":64},[35,104,105],{"class":68}," wb.active\n",[35,107,109,112,114],{"class":37,"line":108},5,[35,110,111],{"class":68},"ws.title ",[35,113,91],{"class":64},[35,115,116],{"class":45}," \"Sales\"\n",[35,118,120],{"class":37,"line":119},6,[35,121,82],{"emptyLinePlaceholder":81},[35,123,125,128,131,134,137,139,142,144,147],{"class":37,"line":124},7,[35,126,127],{"class":68},"ws.append([",[35,129,130],{"class":45},"\"Region\"",[35,132,133],{"class":68},", ",[35,135,136],{"class":45},"\"Rep\"",[35,138,133],{"class":68},[35,140,141],{"class":45},"\"Units\"",[35,143,133],{"class":68},[35,145,146],{"class":45},"\"Revenue\"",[35,148,149],{"class":68},"])\n",[35,151,153,156,159,162],{"class":37,"line":152},8,[35,154,155],{"class":64},"for",[35,157,158],{"class":68}," row ",[35,160,161],{"class":64},"in",[35,163,164],{"class":68}," [\n",[35,166,168,171,174,176,179,181,185,187,190],{"class":37,"line":167},9,[35,169,170],{"class":68},"    [",[35,172,173],{"class":45},"\"North\"",[35,175,133],{"class":68},[35,177,178],{"class":45},"\"Alvarez\"",[35,180,133],{"class":68},[35,182,184],{"class":183},"sj4cs","120",[35,186,133],{"class":68},[35,188,189],{"class":183},"24000",[35,191,192],{"class":68},"],\n",[35,194,196,198,201,203,206,208,211,213,216],{"class":37,"line":195},10,[35,197,170],{"class":68},[35,199,200],{"class":45},"\"South\"",[35,202,133],{"class":68},[35,204,205],{"class":45},"\"Boateng\"",[35,207,133],{"class":68},[35,209,210],{"class":183},"95",[35,212,133],{"class":68},[35,214,215],{"class":183},"19000",[35,217,192],{"class":68},[35,219,221,223,226,229,232,235,238,240,243],{"class":37,"line":220},11,[35,222,170],{"class":68},[35,224,225],{"class":45},"\"East\"",[35,227,228],{"class":68},",  ",[35,230,231],{"class":45},"\"Chen\"",[35,233,234],{"class":68},",    ",[35,236,237],{"class":183},"140",[35,239,133],{"class":68},[35,241,242],{"class":183},"28000",[35,244,192],{"class":68},[35,246,248,250,253,255,258,260,263,265,268],{"class":37,"line":247},12,[35,249,170],{"class":68},[35,251,252],{"class":45},"\"West\"",[35,254,228],{"class":68},[35,256,257],{"class":45},"\"Dubois\"",[35,259,228],{"class":68},[35,261,262],{"class":183},"80",[35,264,228],{"class":68},[35,266,267],{"class":183},"16000",[35,269,192],{"class":68},[35,271,273],{"class":37,"line":272},13,[35,274,275],{"class":68},"]:\n",[35,277,279],{"class":37,"line":278},14,[35,280,281],{"class":68},"    ws.append(row)\n",[35,283,285],{"class":37,"line":284},15,[35,286,82],{"emptyLinePlaceholder":81},[35,288,290,293,296],{"class":37,"line":289},16,[35,291,292],{"class":68},"wb.save(",[35,294,295],{"class":45},"\"styled_report.xlsx\"",[35,297,298],{"class":68},")\n",[35,300,302,305,308,311],{"class":37,"line":301},17,[35,303,304],{"class":183},"print",[35,306,307],{"class":68},"(",[35,309,310],{"class":45},"\"Sample workbook created\"",[35,312,298],{"class":68},[20,314,316],{"id":315},"font-bold-color-and-size","Font: bold, color, and size",[10,318,319,322,323,325,326,329],{},[32,320,321],{},"Font"," controls typeface, weight, size, and color. Color is an 8-digit ARGB hex string (or a 6-digit RGB string, which openpyxl pads to full opacity). Assign a fresh ",[32,324,321],{}," to a cell's ",[32,327,328],{},".font"," attribute — fonts are immutable, so you replace them rather than mutate them:",[25,331,333],{"className":55,"code":332,"language":57,"meta":30,"style":30},"from openpyxl import load_workbook\nfrom openpyxl.styles import Font\n\nwb = load_workbook(\"styled_report.xlsx\")\nws = wb[\"Sales\"]\n\nws[\"A1\"].font = Font(name=\"Calibri\", size=12, bold=True, color=\"FFFFFF\")\nws[\"D2\"].font = Font(bold=True, italic=True, color=\"2E7D32\")  # green revenue\n\nwb.save(\"styled_report.xlsx\")\nprint(\"Fonts applied\")\n",[32,334,335,346,358,362,375,390,394,451,495,499,507],{"__ignoreMap":30},[35,336,337,339,341,343],{"class":37,"line":38},[35,338,65],{"class":64},[35,340,69],{"class":68},[35,342,72],{"class":64},[35,344,345],{"class":68}," load_workbook\n",[35,347,348,350,353,355],{"class":37,"line":78},[35,349,65],{"class":64},[35,351,352],{"class":68}," openpyxl.styles ",[35,354,72],{"class":64},[35,356,357],{"class":68}," Font\n",[35,359,360],{"class":37,"line":85},[35,361,82],{"emptyLinePlaceholder":81},[35,363,364,366,368,371,373],{"class":37,"line":97},[35,365,88],{"class":68},[35,367,91],{"class":64},[35,369,370],{"class":68}," load_workbook(",[35,372,295],{"class":45},[35,374,298],{"class":68},[35,376,377,379,381,384,387],{"class":37,"line":108},[35,378,100],{"class":68},[35,380,91],{"class":64},[35,382,383],{"class":68}," wb[",[35,385,386],{"class":45},"\"Sales\"",[35,388,389],{"class":68},"]\n",[35,391,392],{"class":37,"line":119},[35,393,82],{"emptyLinePlaceholder":81},[35,395,396,399,402,405,407,410,414,416,419,421,424,426,429,431,434,436,439,441,444,446,449],{"class":37,"line":124},[35,397,398],{"class":68},"ws[",[35,400,401],{"class":45},"\"A1\"",[35,403,404],{"class":68},"].font ",[35,406,91],{"class":64},[35,408,409],{"class":68}," Font(",[35,411,413],{"class":412},"s4XuR","name",[35,415,91],{"class":64},[35,417,418],{"class":45},"\"Calibri\"",[35,420,133],{"class":68},[35,422,423],{"class":412},"size",[35,425,91],{"class":64},[35,427,428],{"class":183},"12",[35,430,133],{"class":68},[35,432,433],{"class":412},"bold",[35,435,91],{"class":64},[35,437,438],{"class":183},"True",[35,440,133],{"class":68},[35,442,443],{"class":412},"color",[35,445,91],{"class":64},[35,447,448],{"class":45},"\"FFFFFF\"",[35,450,298],{"class":68},[35,452,453,455,458,460,462,464,466,468,470,472,475,477,479,481,483,485,488,491],{"class":37,"line":152},[35,454,398],{"class":68},[35,456,457],{"class":45},"\"D2\"",[35,459,404],{"class":68},[35,461,91],{"class":64},[35,463,409],{"class":68},[35,465,433],{"class":412},[35,467,91],{"class":64},[35,469,438],{"class":183},[35,471,133],{"class":68},[35,473,474],{"class":412},"italic",[35,476,91],{"class":64},[35,478,438],{"class":183},[35,480,133],{"class":68},[35,482,443],{"class":412},[35,484,91],{"class":64},[35,486,487],{"class":45},"\"2E7D32\"",[35,489,490],{"class":68},")  ",[35,492,494],{"class":493},"sJ8bj","# green revenue\n",[35,496,497],{"class":37,"line":167},[35,498,82],{"emptyLinePlaceholder":81},[35,500,501,503,505],{"class":37,"line":195},[35,502,292],{"class":68},[35,504,295],{"class":45},[35,506,298],{"class":68},[35,508,509,511,513,516],{"class":37,"line":220},[35,510,304],{"class":183},[35,512,307],{"class":68},[35,514,515],{"class":45},"\"Fonts applied\"",[35,517,298],{"class":68},[20,519,521],{"id":520},"patternfill-cell-backgrounds","PatternFill: cell backgrounds",[10,523,524,527,528,531,532,535,536,539],{},[32,525,526],{},"PatternFill"," paints a cell's background. You must pass a ",[32,529,530],{},"fill_type"," (use ",[32,533,534],{},"\"solid\"","); without it the fill renders invisibly. ",[32,537,538],{},"fgColor"," is the visible color for a solid fill:",[25,541,543],{"className":55,"code":542,"language":57,"meta":30,"style":30},"from openpyxl import load_workbook\nfrom openpyxl.styles import PatternFill\n\nwb = load_workbook(\"styled_report.xlsx\")\nws = wb[\"Sales\"]\n\nheader_fill = PatternFill(fill_type=\"solid\", fgColor=\"4472C4\")  # blue bar\nfor cell in ws[1]:\n    cell.fill = header_fill\n\nwb.save(\"styled_report.xlsx\")\nprint(\"Header fill applied\")\n",[32,544,545,555,566,570,582,594,598,628,645,655,659,667],{"__ignoreMap":30},[35,546,547,549,551,553],{"class":37,"line":38},[35,548,65],{"class":64},[35,550,69],{"class":68},[35,552,72],{"class":64},[35,554,345],{"class":68},[35,556,557,559,561,563],{"class":37,"line":78},[35,558,65],{"class":64},[35,560,352],{"class":68},[35,562,72],{"class":64},[35,564,565],{"class":68}," PatternFill\n",[35,567,568],{"class":37,"line":85},[35,569,82],{"emptyLinePlaceholder":81},[35,571,572,574,576,578,580],{"class":37,"line":97},[35,573,88],{"class":68},[35,575,91],{"class":64},[35,577,370],{"class":68},[35,579,295],{"class":45},[35,581,298],{"class":68},[35,583,584,586,588,590,592],{"class":37,"line":108},[35,585,100],{"class":68},[35,587,91],{"class":64},[35,589,383],{"class":68},[35,591,386],{"class":45},[35,593,389],{"class":68},[35,595,596],{"class":37,"line":119},[35,597,82],{"emptyLinePlaceholder":81},[35,599,600,603,605,608,610,612,614,616,618,620,623,625],{"class":37,"line":124},[35,601,602],{"class":68},"header_fill ",[35,604,91],{"class":64},[35,606,607],{"class":68}," PatternFill(",[35,609,530],{"class":412},[35,611,91],{"class":64},[35,613,534],{"class":45},[35,615,133],{"class":68},[35,617,538],{"class":412},[35,619,91],{"class":64},[35,621,622],{"class":45},"\"4472C4\"",[35,624,490],{"class":68},[35,626,627],{"class":493},"# blue bar\n",[35,629,630,632,635,637,640,643],{"class":37,"line":152},[35,631,155],{"class":64},[35,633,634],{"class":68}," cell ",[35,636,161],{"class":64},[35,638,639],{"class":68}," ws[",[35,641,642],{"class":183},"1",[35,644,275],{"class":68},[35,646,647,650,652],{"class":37,"line":167},[35,648,649],{"class":68},"    cell.fill ",[35,651,91],{"class":64},[35,653,654],{"class":68}," header_fill\n",[35,656,657],{"class":37,"line":195},[35,658,82],{"emptyLinePlaceholder":81},[35,660,661,663,665],{"class":37,"line":220},[35,662,292],{"class":68},[35,664,295],{"class":45},[35,666,298],{"class":68},[35,668,669,671,673,676],{"class":37,"line":247},[35,670,304],{"class":183},[35,672,307],{"class":68},[35,674,675],{"class":45},"\"Header fill applied\"",[35,677,298],{"class":68},[20,679,681],{"id":680},"border-and-side-ruled-cells","Border and Side: ruled cells",[10,683,684,685,688,689,692,693,133,696,133,699,133,702,705,706,708,709,712,713,133,716,719,720,723,724,726],{},"A ",[32,686,687],{},"Border"," is built from four ",[32,690,691],{},"Side"," objects — ",[32,694,695],{},"left",[32,697,698],{},"right",[32,700,701],{},"top",[32,703,704],{},"bottom",". Each ",[32,707,691],{}," takes a ",[32,710,711],{},"style"," (such as ",[32,714,715],{},"\"thin\"",[32,717,718],{},"\"medium\"",", or ",[32,721,722],{},"\"double\"",") and a color. Define one ",[32,725,691],{}," and reuse it on all four edges for a clean box:",[25,728,730],{"className":55,"code":729,"language":57,"meta":30,"style":30},"from openpyxl import load_workbook\nfrom openpyxl.styles import Border, Side\n\nwb = load_workbook(\"styled_report.xlsx\")\nws = wb[\"Sales\"]\n\nthin = Side(style=\"thin\", color=\"999999\")\nbox = Border(left=thin, right=thin, top=thin, bottom=thin)\n\nfor row in ws[\"A1:D5\"]:\n    for cell in row:\n        cell.border = box\n\nwb.save(\"styled_report.xlsx\")\nprint(\"Borders applied\")\n",[32,731,732,742,753,757,769,781,785,812,848,852,867,879,889,893,901],{"__ignoreMap":30},[35,733,734,736,738,740],{"class":37,"line":38},[35,735,65],{"class":64},[35,737,69],{"class":68},[35,739,72],{"class":64},[35,741,345],{"class":68},[35,743,744,746,748,750],{"class":37,"line":78},[35,745,65],{"class":64},[35,747,352],{"class":68},[35,749,72],{"class":64},[35,751,752],{"class":68}," Border, Side\n",[35,754,755],{"class":37,"line":85},[35,756,82],{"emptyLinePlaceholder":81},[35,758,759,761,763,765,767],{"class":37,"line":97},[35,760,88],{"class":68},[35,762,91],{"class":64},[35,764,370],{"class":68},[35,766,295],{"class":45},[35,768,298],{"class":68},[35,770,771,773,775,777,779],{"class":37,"line":108},[35,772,100],{"class":68},[35,774,91],{"class":64},[35,776,383],{"class":68},[35,778,386],{"class":45},[35,780,389],{"class":68},[35,782,783],{"class":37,"line":119},[35,784,82],{"emptyLinePlaceholder":81},[35,786,787,790,792,795,797,799,801,803,805,807,810],{"class":37,"line":124},[35,788,789],{"class":68},"thin ",[35,791,91],{"class":64},[35,793,794],{"class":68}," Side(",[35,796,711],{"class":412},[35,798,91],{"class":64},[35,800,715],{"class":45},[35,802,133],{"class":68},[35,804,443],{"class":412},[35,806,91],{"class":64},[35,808,809],{"class":45},"\"999999\"",[35,811,298],{"class":68},[35,813,814,817,819,822,824,826,829,831,833,835,837,839,841,843,845],{"class":37,"line":152},[35,815,816],{"class":68},"box ",[35,818,91],{"class":64},[35,820,821],{"class":68}," Border(",[35,823,695],{"class":412},[35,825,91],{"class":64},[35,827,828],{"class":68},"thin, ",[35,830,698],{"class":412},[35,832,91],{"class":64},[35,834,828],{"class":68},[35,836,701],{"class":412},[35,838,91],{"class":64},[35,840,828],{"class":68},[35,842,704],{"class":412},[35,844,91],{"class":64},[35,846,847],{"class":68},"thin)\n",[35,849,850],{"class":37,"line":167},[35,851,82],{"emptyLinePlaceholder":81},[35,853,854,856,858,860,862,865],{"class":37,"line":195},[35,855,155],{"class":64},[35,857,158],{"class":68},[35,859,161],{"class":64},[35,861,639],{"class":68},[35,863,864],{"class":45},"\"A1:D5\"",[35,866,275],{"class":68},[35,868,869,872,874,876],{"class":37,"line":220},[35,870,871],{"class":64},"    for",[35,873,634],{"class":68},[35,875,161],{"class":64},[35,877,878],{"class":68}," row:\n",[35,880,881,884,886],{"class":37,"line":247},[35,882,883],{"class":68},"        cell.border ",[35,885,91],{"class":64},[35,887,888],{"class":68}," box\n",[35,890,891],{"class":37,"line":272},[35,892,82],{"emptyLinePlaceholder":81},[35,894,895,897,899],{"class":37,"line":278},[35,896,292],{"class":68},[35,898,295],{"class":45},[35,900,298],{"class":68},[35,902,903,905,907,910],{"class":37,"line":284},[35,904,304],{"class":183},[35,906,307],{"class":68},[35,908,909],{"class":45},"\"Borders applied\"",[35,911,298],{"class":68},[20,913,915],{"id":914},"alignment-wrapping-and-centering","Alignment: wrapping and centering",[10,917,918,921,922,925],{},[32,919,920],{},"Alignment"," controls horizontal and vertical placement plus text wrapping. Set ",[32,923,924],{},"wrap_text=True"," to let long values flow onto multiple lines instead of spilling over. Center the header row both ways:",[25,927,929],{"className":55,"code":928,"language":57,"meta":30,"style":30},"from openpyxl import load_workbook\nfrom openpyxl.styles import Alignment\n\nwb = load_workbook(\"styled_report.xlsx\")\nws = wb[\"Sales\"]\n\ncenter = Alignment(horizontal=\"center\", vertical=\"center\", wrap_text=True)\nfor cell in ws[1]:\n    cell.alignment = center\n\n# Right-align the numeric columns for a tidy ledger look\nright = Alignment(horizontal=\"right\")\nfor row in ws[\"C2:D5\"]:\n    for cell in row:\n        cell.alignment = right\n\nwb.save(\"styled_report.xlsx\")\nprint(\"Alignment applied\")\n",[32,930,931,941,952,956,968,980,984,1022,1036,1046,1050,1055,1073,1088,1098,1108,1112,1120],{"__ignoreMap":30},[35,932,933,935,937,939],{"class":37,"line":38},[35,934,65],{"class":64},[35,936,69],{"class":68},[35,938,72],{"class":64},[35,940,345],{"class":68},[35,942,943,945,947,949],{"class":37,"line":78},[35,944,65],{"class":64},[35,946,352],{"class":68},[35,948,72],{"class":64},[35,950,951],{"class":68}," Alignment\n",[35,953,954],{"class":37,"line":85},[35,955,82],{"emptyLinePlaceholder":81},[35,957,958,960,962,964,966],{"class":37,"line":97},[35,959,88],{"class":68},[35,961,91],{"class":64},[35,963,370],{"class":68},[35,965,295],{"class":45},[35,967,298],{"class":68},[35,969,970,972,974,976,978],{"class":37,"line":108},[35,971,100],{"class":68},[35,973,91],{"class":64},[35,975,383],{"class":68},[35,977,386],{"class":45},[35,979,389],{"class":68},[35,981,982],{"class":37,"line":119},[35,983,82],{"emptyLinePlaceholder":81},[35,985,986,989,991,994,997,999,1002,1004,1007,1009,1011,1013,1016,1018,1020],{"class":37,"line":124},[35,987,988],{"class":68},"center ",[35,990,91],{"class":64},[35,992,993],{"class":68}," Alignment(",[35,995,996],{"class":412},"horizontal",[35,998,91],{"class":64},[35,1000,1001],{"class":45},"\"center\"",[35,1003,133],{"class":68},[35,1005,1006],{"class":412},"vertical",[35,1008,91],{"class":64},[35,1010,1001],{"class":45},[35,1012,133],{"class":68},[35,1014,1015],{"class":412},"wrap_text",[35,1017,91],{"class":64},[35,1019,438],{"class":183},[35,1021,298],{"class":68},[35,1023,1024,1026,1028,1030,1032,1034],{"class":37,"line":152},[35,1025,155],{"class":64},[35,1027,634],{"class":68},[35,1029,161],{"class":64},[35,1031,639],{"class":68},[35,1033,642],{"class":183},[35,1035,275],{"class":68},[35,1037,1038,1041,1043],{"class":37,"line":167},[35,1039,1040],{"class":68},"    cell.alignment ",[35,1042,91],{"class":64},[35,1044,1045],{"class":68}," center\n",[35,1047,1048],{"class":37,"line":195},[35,1049,82],{"emptyLinePlaceholder":81},[35,1051,1052],{"class":37,"line":220},[35,1053,1054],{"class":493},"# Right-align the numeric columns for a tidy ledger look\n",[35,1056,1057,1060,1062,1064,1066,1068,1071],{"class":37,"line":247},[35,1058,1059],{"class":68},"right ",[35,1061,91],{"class":64},[35,1063,993],{"class":68},[35,1065,996],{"class":412},[35,1067,91],{"class":64},[35,1069,1070],{"class":45},"\"right\"",[35,1072,298],{"class":68},[35,1074,1075,1077,1079,1081,1083,1086],{"class":37,"line":272},[35,1076,155],{"class":64},[35,1078,158],{"class":68},[35,1080,161],{"class":64},[35,1082,639],{"class":68},[35,1084,1085],{"class":45},"\"C2:D5\"",[35,1087,275],{"class":68},[35,1089,1090,1092,1094,1096],{"class":37,"line":278},[35,1091,871],{"class":64},[35,1093,634],{"class":68},[35,1095,161],{"class":64},[35,1097,878],{"class":68},[35,1099,1100,1103,1105],{"class":37,"line":284},[35,1101,1102],{"class":68},"        cell.alignment ",[35,1104,91],{"class":64},[35,1106,1107],{"class":68}," right\n",[35,1109,1110],{"class":37,"line":289},[35,1111,82],{"emptyLinePlaceholder":81},[35,1113,1114,1116,1118],{"class":37,"line":301},[35,1115,292],{"class":68},[35,1117,295],{"class":45},[35,1119,298],{"class":68},[35,1121,1123,1125,1127,1130],{"class":37,"line":1122},18,[35,1124,304],{"class":183},[35,1126,307],{"class":68},[35,1128,1129],{"class":45},"\"Alignment applied\"",[35,1131,298],{"class":68},[20,1133,1135],{"id":1134},"style-a-header-row-in-one-loop","Style a header row in one loop",[10,1137,1138],{},"In a real generator the header is styled in a single pass that combines font, fill, and alignment. Build the style objects once, outside the loop, then apply them to every cell in row 1:",[25,1140,1142],{"className":55,"code":1141,"language":57,"meta":30,"style":30},"from openpyxl import load_workbook\nfrom openpyxl.styles import Font, PatternFill, Alignment\n\nwb = load_workbook(\"styled_report.xlsx\")\nws = wb[\"Sales\"]\n\nhead_font = Font(bold=True, color=\"FFFFFF\", size=12)\nhead_fill = PatternFill(\"solid\", fgColor=\"4472C4\")\nhead_align = Alignment(horizontal=\"center\", vertical=\"center\")\n\nfor cell in ws[1]:\n    cell.font = head_font\n    cell.fill = head_fill\n    cell.alignment = head_align\n\nwb.save(\"styled_report.xlsx\")\nprint(\"Header row styled in a loop\")\n",[32,1143,1144,1154,1165,1169,1181,1193,1197,1230,1251,1276,1280,1294,1304,1313,1322,1326,1334],{"__ignoreMap":30},[35,1145,1146,1148,1150,1152],{"class":37,"line":38},[35,1147,65],{"class":64},[35,1149,69],{"class":68},[35,1151,72],{"class":64},[35,1153,345],{"class":68},[35,1155,1156,1158,1160,1162],{"class":37,"line":78},[35,1157,65],{"class":64},[35,1159,352],{"class":68},[35,1161,72],{"class":64},[35,1163,1164],{"class":68}," Font, PatternFill, Alignment\n",[35,1166,1167],{"class":37,"line":85},[35,1168,82],{"emptyLinePlaceholder":81},[35,1170,1171,1173,1175,1177,1179],{"class":37,"line":97},[35,1172,88],{"class":68},[35,1174,91],{"class":64},[35,1176,370],{"class":68},[35,1178,295],{"class":45},[35,1180,298],{"class":68},[35,1182,1183,1185,1187,1189,1191],{"class":37,"line":108},[35,1184,100],{"class":68},[35,1186,91],{"class":64},[35,1188,383],{"class":68},[35,1190,386],{"class":45},[35,1192,389],{"class":68},[35,1194,1195],{"class":37,"line":119},[35,1196,82],{"emptyLinePlaceholder":81},[35,1198,1199,1202,1204,1206,1208,1210,1212,1214,1216,1218,1220,1222,1224,1226,1228],{"class":37,"line":124},[35,1200,1201],{"class":68},"head_font ",[35,1203,91],{"class":64},[35,1205,409],{"class":68},[35,1207,433],{"class":412},[35,1209,91],{"class":64},[35,1211,438],{"class":183},[35,1213,133],{"class":68},[35,1215,443],{"class":412},[35,1217,91],{"class":64},[35,1219,448],{"class":45},[35,1221,133],{"class":68},[35,1223,423],{"class":412},[35,1225,91],{"class":64},[35,1227,428],{"class":183},[35,1229,298],{"class":68},[35,1231,1232,1235,1237,1239,1241,1243,1245,1247,1249],{"class":37,"line":152},[35,1233,1234],{"class":68},"head_fill ",[35,1236,91],{"class":64},[35,1238,607],{"class":68},[35,1240,534],{"class":45},[35,1242,133],{"class":68},[35,1244,538],{"class":412},[35,1246,91],{"class":64},[35,1248,622],{"class":45},[35,1250,298],{"class":68},[35,1252,1253,1256,1258,1260,1262,1264,1266,1268,1270,1272,1274],{"class":37,"line":167},[35,1254,1255],{"class":68},"head_align ",[35,1257,91],{"class":64},[35,1259,993],{"class":68},[35,1261,996],{"class":412},[35,1263,91],{"class":64},[35,1265,1001],{"class":45},[35,1267,133],{"class":68},[35,1269,1006],{"class":412},[35,1271,91],{"class":64},[35,1273,1001],{"class":45},[35,1275,298],{"class":68},[35,1277,1278],{"class":37,"line":195},[35,1279,82],{"emptyLinePlaceholder":81},[35,1281,1282,1284,1286,1288,1290,1292],{"class":37,"line":220},[35,1283,155],{"class":64},[35,1285,634],{"class":68},[35,1287,161],{"class":64},[35,1289,639],{"class":68},[35,1291,642],{"class":183},[35,1293,275],{"class":68},[35,1295,1296,1299,1301],{"class":37,"line":247},[35,1297,1298],{"class":68},"    cell.font ",[35,1300,91],{"class":64},[35,1302,1303],{"class":68}," head_font\n",[35,1305,1306,1308,1310],{"class":37,"line":272},[35,1307,649],{"class":68},[35,1309,91],{"class":64},[35,1311,1312],{"class":68}," head_fill\n",[35,1314,1315,1317,1319],{"class":37,"line":278},[35,1316,1040],{"class":68},[35,1318,91],{"class":64},[35,1320,1321],{"class":68}," head_align\n",[35,1323,1324],{"class":37,"line":284},[35,1325,82],{"emptyLinePlaceholder":81},[35,1327,1328,1330,1332],{"class":37,"line":289},[35,1329,292],{"class":68},[35,1331,295],{"class":45},[35,1333,298],{"class":68},[35,1335,1336,1338,1340,1343],{"class":37,"line":301},[35,1337,304],{"class":183},[35,1339,307],{"class":68},[35,1341,1342],{"class":45},"\"Header row styled in a loop\"",[35,1344,298],{"class":68},[20,1346,1348],{"id":1347},"merge-cells-for-a-title-bar","Merge cells for a title bar",[10,1350,1351,1354,1355,1359],{},[32,1352,1353],{},"ws.merge_cells()"," joins a rectangular range into one logical cell. Set the value and styling on the ",[1356,1357,1358],"strong",{},"top-left"," cell of the range — the others are emptied. Insert a row first so the title sits above the table:",[25,1361,1363],{"className":55,"code":1362,"language":57,"meta":30,"style":30},"from openpyxl import load_workbook\nfrom openpyxl.styles import Font, Alignment\n\nwb = load_workbook(\"styled_report.xlsx\")\nws = wb[\"Sales\"]\n\nws.insert_rows(1)                      # push the table down one row\nws.merge_cells(\"A1:D1\")               # title spans all four columns\ntitle = ws[\"A1\"]\ntitle.value = \"Q3 Regional Sales\"\ntitle.font = Font(bold=True, size=14, color=\"1F2937\")\ntitle.alignment = Alignment(horizontal=\"center\", vertical=\"center\")\n\nwb.save(\"styled_report.xlsx\")\nprint(\"Title bar merged\")\n",[32,1364,1365,1375,1386,1390,1402,1414,1418,1431,1445,1458,1468,1503,1528,1532,1540],{"__ignoreMap":30},[35,1366,1367,1369,1371,1373],{"class":37,"line":38},[35,1368,65],{"class":64},[35,1370,69],{"class":68},[35,1372,72],{"class":64},[35,1374,345],{"class":68},[35,1376,1377,1379,1381,1383],{"class":37,"line":78},[35,1378,65],{"class":64},[35,1380,352],{"class":68},[35,1382,72],{"class":64},[35,1384,1385],{"class":68}," Font, Alignment\n",[35,1387,1388],{"class":37,"line":85},[35,1389,82],{"emptyLinePlaceholder":81},[35,1391,1392,1394,1396,1398,1400],{"class":37,"line":97},[35,1393,88],{"class":68},[35,1395,91],{"class":64},[35,1397,370],{"class":68},[35,1399,295],{"class":45},[35,1401,298],{"class":68},[35,1403,1404,1406,1408,1410,1412],{"class":37,"line":108},[35,1405,100],{"class":68},[35,1407,91],{"class":64},[35,1409,383],{"class":68},[35,1411,386],{"class":45},[35,1413,389],{"class":68},[35,1415,1416],{"class":37,"line":119},[35,1417,82],{"emptyLinePlaceholder":81},[35,1419,1420,1423,1425,1428],{"class":37,"line":124},[35,1421,1422],{"class":68},"ws.insert_rows(",[35,1424,642],{"class":183},[35,1426,1427],{"class":68},")                      ",[35,1429,1430],{"class":493},"# push the table down one row\n",[35,1432,1433,1436,1439,1442],{"class":37,"line":152},[35,1434,1435],{"class":68},"ws.merge_cells(",[35,1437,1438],{"class":45},"\"A1:D1\"",[35,1440,1441],{"class":68},")               ",[35,1443,1444],{"class":493},"# title spans all four columns\n",[35,1446,1447,1450,1452,1454,1456],{"class":37,"line":167},[35,1448,1449],{"class":68},"title ",[35,1451,91],{"class":64},[35,1453,639],{"class":68},[35,1455,401],{"class":45},[35,1457,389],{"class":68},[35,1459,1460,1463,1465],{"class":37,"line":195},[35,1461,1462],{"class":68},"title.value ",[35,1464,91],{"class":64},[35,1466,1467],{"class":45}," \"Q3 Regional Sales\"\n",[35,1469,1470,1473,1475,1477,1479,1481,1483,1485,1487,1489,1492,1494,1496,1498,1501],{"class":37,"line":220},[35,1471,1472],{"class":68},"title.font ",[35,1474,91],{"class":64},[35,1476,409],{"class":68},[35,1478,433],{"class":412},[35,1480,91],{"class":64},[35,1482,438],{"class":183},[35,1484,133],{"class":68},[35,1486,423],{"class":412},[35,1488,91],{"class":64},[35,1490,1491],{"class":183},"14",[35,1493,133],{"class":68},[35,1495,443],{"class":412},[35,1497,91],{"class":64},[35,1499,1500],{"class":45},"\"1F2937\"",[35,1502,298],{"class":68},[35,1504,1505,1508,1510,1512,1514,1516,1518,1520,1522,1524,1526],{"class":37,"line":247},[35,1506,1507],{"class":68},"title.alignment ",[35,1509,91],{"class":64},[35,1511,993],{"class":68},[35,1513,996],{"class":412},[35,1515,91],{"class":64},[35,1517,1001],{"class":45},[35,1519,133],{"class":68},[35,1521,1006],{"class":412},[35,1523,91],{"class":64},[35,1525,1001],{"class":45},[35,1527,298],{"class":68},[35,1529,1530],{"class":37,"line":272},[35,1531,82],{"emptyLinePlaceholder":81},[35,1533,1534,1536,1538],{"class":37,"line":278},[35,1535,292],{"class":68},[35,1537,295],{"class":45},[35,1539,298],{"class":68},[35,1541,1542,1544,1546,1549],{"class":37,"line":284},[35,1543,304],{"class":183},[35,1545,307],{"class":68},[35,1547,1548],{"class":45},"\"Title bar merged\"",[35,1550,298],{"class":68},[20,1552,1554],{"id":1553},"reuse-a-namedstyle","Reuse a NamedStyle",[10,1556,1557,1558,1561],{},"When the same combination of font, fill, border, and alignment recurs, define a ",[32,1559,1560],{},"NamedStyle"," once, register it on the workbook, then apply it by name. Excel also exposes named styles to the user, and reusing one keeps the file smaller than repeating inline styles:",[25,1563,1565],{"className":55,"code":1564,"language":57,"meta":30,"style":30},"from openpyxl import load_workbook\nfrom openpyxl.styles import NamedStyle, Font, PatternFill, Alignment\n\nwb = load_workbook(\"styled_report.xlsx\")\nws = wb[\"Sales\"]\n\nheader_style = NamedStyle(name=\"report_header\")\nheader_style.font = Font(bold=True, color=\"FFFFFF\")\nheader_style.fill = PatternFill(\"solid\", fgColor=\"305496\")\nheader_style.alignment = Alignment(horizontal=\"center\")\n\nif \"report_header\" not in wb.named_styles:\n    wb.add_named_style(header_style)\n\nfor cell in ws[2]:                     # the column-header row (row 1 is the title)\n    cell.style = \"report_header\"\n\nwb.save(\"styled_report.xlsx\")\nprint(\"NamedStyle applied\")\n",[32,1566,1567,1577,1588,1592,1604,1616,1620,1639,1664,1686,1703,1707,1724,1729,1733,1752,1762,1766,1774],{"__ignoreMap":30},[35,1568,1569,1571,1573,1575],{"class":37,"line":38},[35,1570,65],{"class":64},[35,1572,69],{"class":68},[35,1574,72],{"class":64},[35,1576,345],{"class":68},[35,1578,1579,1581,1583,1585],{"class":37,"line":78},[35,1580,65],{"class":64},[35,1582,352],{"class":68},[35,1584,72],{"class":64},[35,1586,1587],{"class":68}," NamedStyle, Font, PatternFill, Alignment\n",[35,1589,1590],{"class":37,"line":85},[35,1591,82],{"emptyLinePlaceholder":81},[35,1593,1594,1596,1598,1600,1602],{"class":37,"line":97},[35,1595,88],{"class":68},[35,1597,91],{"class":64},[35,1599,370],{"class":68},[35,1601,295],{"class":45},[35,1603,298],{"class":68},[35,1605,1606,1608,1610,1612,1614],{"class":37,"line":108},[35,1607,100],{"class":68},[35,1609,91],{"class":64},[35,1611,383],{"class":68},[35,1613,386],{"class":45},[35,1615,389],{"class":68},[35,1617,1618],{"class":37,"line":119},[35,1619,82],{"emptyLinePlaceholder":81},[35,1621,1622,1625,1627,1630,1632,1634,1637],{"class":37,"line":124},[35,1623,1624],{"class":68},"header_style ",[35,1626,91],{"class":64},[35,1628,1629],{"class":68}," NamedStyle(",[35,1631,413],{"class":412},[35,1633,91],{"class":64},[35,1635,1636],{"class":45},"\"report_header\"",[35,1638,298],{"class":68},[35,1640,1641,1644,1646,1648,1650,1652,1654,1656,1658,1660,1662],{"class":37,"line":152},[35,1642,1643],{"class":68},"header_style.font ",[35,1645,91],{"class":64},[35,1647,409],{"class":68},[35,1649,433],{"class":412},[35,1651,91],{"class":64},[35,1653,438],{"class":183},[35,1655,133],{"class":68},[35,1657,443],{"class":412},[35,1659,91],{"class":64},[35,1661,448],{"class":45},[35,1663,298],{"class":68},[35,1665,1666,1669,1671,1673,1675,1677,1679,1681,1684],{"class":37,"line":167},[35,1667,1668],{"class":68},"header_style.fill ",[35,1670,91],{"class":64},[35,1672,607],{"class":68},[35,1674,534],{"class":45},[35,1676,133],{"class":68},[35,1678,538],{"class":412},[35,1680,91],{"class":64},[35,1682,1683],{"class":45},"\"305496\"",[35,1685,298],{"class":68},[35,1687,1688,1691,1693,1695,1697,1699,1701],{"class":37,"line":195},[35,1689,1690],{"class":68},"header_style.alignment ",[35,1692,91],{"class":64},[35,1694,993],{"class":68},[35,1696,996],{"class":412},[35,1698,91],{"class":64},[35,1700,1001],{"class":45},[35,1702,298],{"class":68},[35,1704,1705],{"class":37,"line":220},[35,1706,82],{"emptyLinePlaceholder":81},[35,1708,1709,1712,1715,1718,1721],{"class":37,"line":247},[35,1710,1711],{"class":64},"if",[35,1713,1714],{"class":45}," \"report_header\"",[35,1716,1717],{"class":64}," not",[35,1719,1720],{"class":64}," in",[35,1722,1723],{"class":68}," wb.named_styles:\n",[35,1725,1726],{"class":37,"line":272},[35,1727,1728],{"class":68},"    wb.add_named_style(header_style)\n",[35,1730,1731],{"class":37,"line":278},[35,1732,82],{"emptyLinePlaceholder":81},[35,1734,1735,1737,1739,1741,1743,1746,1749],{"class":37,"line":284},[35,1736,155],{"class":64},[35,1738,634],{"class":68},[35,1740,161],{"class":64},[35,1742,639],{"class":68},[35,1744,1745],{"class":183},"2",[35,1747,1748],{"class":68},"]:                     ",[35,1750,1751],{"class":493},"# the column-header row (row 1 is the title)\n",[35,1753,1754,1757,1759],{"class":37,"line":289},[35,1755,1756],{"class":68},"    cell.style ",[35,1758,91],{"class":64},[35,1760,1761],{"class":45}," \"report_header\"\n",[35,1763,1764],{"class":37,"line":301},[35,1765,82],{"emptyLinePlaceholder":81},[35,1767,1768,1770,1772],{"class":37,"line":1122},[35,1769,292],{"class":68},[35,1771,295],{"class":45},[35,1773,298],{"class":68},[35,1775,1777,1779,1781,1784],{"class":37,"line":1776},19,[35,1778,304],{"class":183},[35,1780,307],{"class":68},[35,1782,1783],{"class":45},"\"NamedStyle applied\"",[35,1785,298],{"class":68},[20,1787,1789],{"id":1788},"why-these-styles-survive","Why these styles survive",[10,1791,1792,1793,1796],{},"openpyxl edits the workbook XML directly, so every style you set is written into the file and reopens exactly as saved. That is the key difference from ",[32,1794,1795],{},"pandas.to_excel()",", which writes plain unstyled cells (beyond a couple of header options) and discards any formatting you might expect. If you generate the data with pandas and need styling, write the values first, then reopen the file with openpyxl and apply styles — or skip pandas and build the sheet with openpyxl from the start.",[10,1798,1799,1800,1804,1805,1808,1809,1804,1813,1816],{},"For sizing and navigation, two companion pages go deeper: ",[14,1801,1803],{"href":1802},"\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"," covers ",[32,1806,1807],{},"ws.column_dimensions[...].width"," and row heights, and ",[14,1810,1812],{"href":1811},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Ffreeze-header-row-in-excel-with-openpyxl\u002F","Freeze the Header Row in Excel with openpyxl",[32,1814,1815],{},"ws.freeze_panes"," so the header stays visible while scrolling.",[20,1818,1820],{"id":1819},"frequently-asked-questions","Frequently asked questions",[10,1822,1823,1826,1827,1829,1830,1832,1833,1836,1837,1840],{},[1356,1824,1825],{},"Why does my PatternFill show up as blank?","\nYou almost certainly omitted ",[32,1828,530],{},". A ",[32,1831,526],{}," with no type renders nothing. Use ",[32,1834,1835],{},"PatternFill(\"solid\", fgColor=\"4472C4\")"," or ",[32,1838,1839],{},"PatternFill(fill_type=\"solid\", fgColor=\"4472C4\")",".",[10,1842,1843,1846,1847,133,1849,133,1852,1854,1855,1857,1858,1840],{},[1356,1844,1845],{},"Can I modify just one attribute of an existing Font?","\nNo — ",[32,1848,321],{},[32,1850,1851],{},"Fill",[32,1853,687],{},", and ",[32,1856,920],{}," are immutable. Build a new object with the attributes you want and assign it. To carry over existing values, read them off the old object first: ",[32,1859,1860],{},"Font(name=cell.font.name, bold=True)",[10,1862,1863,1866],{},[1356,1864,1865],{},"Why did my value disappear after merging cells?","\nOnly the top-left cell of a merged range keeps its value; the rest are cleared. Set the value and styling on that top-left cell, and merge before writing if order matters.",[10,1868,1869,1872,1873,1875],{},[1356,1870,1871],{},"Do styles applied with openpyxl survive a round-trip through pandas?","\nNo. ",[32,1874,1795],{}," writes plain cells and ignores prior formatting. Apply openpyxl styles as the last step, after any pandas write, so nothing overwrites them.",[10,1877,1878,1881,1882,1885,1886,1888],{},[1356,1879,1880],{},"What color format does openpyxl expect?","\nAn ARGB hex string. Pass 8 digits (",[32,1883,1884],{},"\"FF4472C4\"",") for explicit opacity, or 6 digits (",[32,1887,622],{},") and openpyxl treats it as fully opaque.",[20,1890,1892],{"id":1891},"conclusion","Conclusion",[10,1894,1895,1896,133,1898,133,1900,1902,1903,1854,1905,1907,1908,1910],{},"Styling in openpyxl comes down to four immutable objects — ",[32,1897,321],{},[32,1899,526],{},[32,1901,687],{},"\u002F",[32,1904,691],{},[32,1906,920],{}," — assigned to a cell's matching attribute. Build them once outside your loops, apply them across rows or ranges, and reach for ",[32,1909,1560],{}," when a combination repeats. Because openpyxl writes straight to the XML, the result is exactly what reopens in Excel, with none of the formatting loss you get from a plain pandas export.",[20,1912,1914],{"id":1913},"where-to-go-next","Where to go next",[1916,1917,1918,1924,1929,1934,1941,1948],"ul",{},[1919,1920,1921,1923],"li",{},[14,1922,17],{"href":16}," — the parent pillar tying styling, charts, number formats, and images together.",[1919,1925,1926,1928],{},[14,1927,1803],{"href":1802}," — size columns and rows so styled content fits.",[1919,1930,1931,1933],{},[14,1932,1812],{"href":1811}," — keep your styled header visible while scrolling.",[1919,1935,1936,1940],{},[14,1937,1939],{"href":1938},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002F","Creating Charts in Excel with openpyxl"," — turn the styled table into a chart.",[1919,1942,1943,1947],{},[14,1944,1946],{"href":1945},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002F","Applying Number and Date Formats in Excel"," — format the values inside your styled cells.",[1919,1949,1950,1954],{},[14,1951,1953],{"href":1952},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002F","Applying Conditional Formatting with openpyxl"," — let the data drive cell colors automatically.",[711,1956,1957],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":30,"searchDepth":78,"depth":78,"links":1959},[1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971],{"id":22,"depth":78,"text":23},{"id":315,"depth":78,"text":316},{"id":520,"depth":78,"text":521},{"id":680,"depth":78,"text":681},{"id":914,"depth":78,"text":915},{"id":1134,"depth":78,"text":1135},{"id":1347,"depth":78,"text":1348},{"id":1553,"depth":78,"text":1554},{"id":1788,"depth":78,"text":1789},{"id":1819,"depth":78,"text":1820},{"id":1891,"depth":78,"text":1892},{"id":1913,"depth":78,"text":1914},"Style Excel cells from Python with openpyxl: Font, PatternFill, Border, Alignment, header rows in a loop, merged titles, and reusable NamedStyles — all runnable.","md",{},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl",{"title":5,"description":1977},"Apply fonts, fills, borders, alignment, merged title bars, and reusable NamedStyles to Excel cells in Python with openpyxl. Production-ready, runnable examples.","formatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Findex","Lu84GYH0QDQmrdYcl623LwL9iOFrjHviW3NvE05bXZs",[1981,1985],{"title":1982,"path":1983,"stem":1984,"children":-1},"Add a Logo Image to an Excel Report with openpyxl","\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fadd-logo-image-to-excel-report-with-openpyxl","formatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fadd-logo-image-to-excel-report-with-openpyxl\u002Findex",{"title":1812,"path":1986,"stem":1987,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Ffreeze-header-row-in-excel-with-openpyxl","formatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Ffreeze-header-row-in-excel-with-openpyxl\u002Findex",1781773160681]