[{"data":1,"prerenderedAt":1847},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fformat-cells-in-a-live-workbook-with-xlwings":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fformat-cells-in-a-live-workbook-with-xlwings":1818,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fformat-cells-in-a-live-workbook-with-xlwings":1826,"children:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fformat-cells-in-a-live-workbook-with-xlwings":1831,"related:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fformat-cells-in-a-live-workbook-with-xlwings":1832},{"id":4,"title":5,"body":6,"dateModified":1785,"datePublished":1785,"description":1786,"extension":1787,"faq":1788,"keyword":1797,"kind":1798,"meta":1799,"navigation":106,"path":1807,"seo":1808,"slug":1811,"stem":1812,"topics":1813,"type":1816,"__hash__":1817},"docs\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fformat-cells-in-a-live-workbook-with-xlwings\u002Findex.md","Format Cells in a Live Workbook with xlwings",{"type":7,"value":8,"toc":1771},"minimark",[9,33,38,63,74,78,219,237,241,357,404,560,564,570,750,775,779,789,894,908,914,963,973,977,980,1138,1158,1249,1253,1316,1323,1533,1537,1540,1601,1618,1622,1667,1671,1706,1710,1716,1722,1728,1734,1738,1767],[10,11,12,13,17,18,21,22,26,27,32],"p",{},"openpyxl formats a ",[14,15,16],"em",{},"file",": you load it, change it, save it, and someone opens it later. xlwings formats a workbook that is ",[14,19,20],{},"open in Excel right now"," — the person watching sees the header turn bold and the totals turn green as the script runs. That makes xlwings the tool for interactive tools, buttons in a workbook, and jobs that must work through Excel itself (refreshing data connections, using Excel's own number formats and table styles). Its formatting API is small and readable for the common cases, and for everything else it hands you Excel's own object model through ",[23,24,25],"code",{},".api",". This page formats a report sheet end to end and covers the speed habits that matter, because every property you set is a round trip to Excel. It belongs to ",[28,29,31],"a",{"href":30},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002F","Automating Excel With xlwings: The Basics",".",[34,35,37],"h2",{"id":36},"prerequisites","Prerequisites",[39,40,45],"pre",{"className":41,"code":42,"language":43,"meta":44,"style":44},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install xlwings\n","bash","",[23,46,47],{"__ignoreMap":44},[48,49,52,56,60],"span",{"class":50,"line":51},"line",1,[48,53,55],{"class":54},"sMTad","pip",[48,57,59],{"class":58},"srMev"," install",[48,61,62],{"class":58}," xlwings\n",[10,64,65,66,69,70,73],{},"xlwings drives a real Excel installation, so it runs on Windows or macOS with Excel installed; the code on this page is not executed by our build, which runs on Linux, but every xlwings property used was checked against the xlwings 0.37 API. The examples assume a workbook ",[23,67,68],{},"sales_report.xlsx"," with a sheet ",[23,71,72],{},"Report"," holding a header row in A1:E1 and 500 rows of data below, as an exported report usually looks before formatting.",[34,75,77],{"id":76},"step-1-connect-and-look-at-the-range","Step 1 — Connect and look at the range",[39,79,83],{"className":80,"code":81,"language":82,"meta":44,"style":44},"language-python shiki shiki-themes github-light github-dark-high-contrast","import xlwings as xw\n\nwb = xw.Book(\"sales_report.xlsx\")          # opens it, or attaches if already open\nsheet = wb.sheets[\"Report\"]\ndata = sheet.range(\"A1\").expand()          # the contiguous block starting at A1\nheader = data.rows[0]\nbody = data.offset(1).resize(data.rows.count - 1)\nprint(data.address, header.address, body.address)\n","python",[23,84,85,101,108,130,147,167,184,210],{"__ignoreMap":44},[48,86,87,91,95,98],{"class":50,"line":51},[48,88,90],{"class":89},"s-kum","import",[48,92,94],{"class":93},"skGVy"," xlwings ",[48,96,97],{"class":89},"as",[48,99,100],{"class":93}," xw\n",[48,102,104],{"class":50,"line":103},2,[48,105,107],{"emptyLinePlaceholder":106},true,"\n",[48,109,111,114,117,120,123,126],{"class":50,"line":110},3,[48,112,113],{"class":93},"wb ",[48,115,116],{"class":89},"=",[48,118,119],{"class":93}," xw.Book(",[48,121,122],{"class":58},"\"sales_report.xlsx\"",[48,124,125],{"class":93},")          ",[48,127,129],{"class":128},"s-wDw","# opens it, or attaches if already open\n",[48,131,133,136,138,141,144],{"class":50,"line":132},4,[48,134,135],{"class":93},"sheet ",[48,137,116],{"class":89},[48,139,140],{"class":93}," wb.sheets[",[48,142,143],{"class":58},"\"Report\"",[48,145,146],{"class":93},"]\n",[48,148,150,153,155,158,161,164],{"class":50,"line":149},5,[48,151,152],{"class":93},"data ",[48,154,116],{"class":89},[48,156,157],{"class":93}," sheet.range(",[48,159,160],{"class":58},"\"A1\"",[48,162,163],{"class":93},").expand()          ",[48,165,166],{"class":128},"# the contiguous block starting at A1\n",[48,168,170,173,175,178,182],{"class":50,"line":169},6,[48,171,172],{"class":93},"header ",[48,174,116],{"class":89},[48,176,177],{"class":93}," data.rows[",[48,179,181],{"class":180},"sP0c6","0",[48,183,146],{"class":93},[48,185,187,190,192,195,198,201,204,207],{"class":50,"line":186},7,[48,188,189],{"class":93},"body ",[48,191,116],{"class":89},[48,193,194],{"class":93}," data.offset(",[48,196,197],{"class":180},"1",[48,199,200],{"class":93},").resize(data.rows.count ",[48,202,203],{"class":89},"-",[48,205,206],{"class":180}," 1",[48,208,209],{"class":93},")\n",[48,211,213,216],{"class":50,"line":212},8,[48,214,215],{"class":180},"print",[48,217,218],{"class":93},"(data.address, header.address, body.address)\n",[10,220,221,224,225,228,229,232,233,32],{},[23,222,223],{},"expand()"," grows from A1 down and right until it hits empty cells, so the code adapts when next month's report has more rows. ",[23,226,227],{},"offset"," and ",[23,230,231],{},"resize"," carve out the body below the header. Connecting to running workbooks and reading values is covered in ",[28,234,236],{"href":235},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fread-and-write-a-live-excel-workbook-with-xlwings\u002F","Read and Write a Live Excel Workbook with xlwings",[34,238,240],{"id":239},"step-2-fills-fonts-and-number-formats","Step 2 — Fills, fonts and number formats",[39,242,244],{"className":80,"code":243,"language":82,"meta":44,"style":44},"header.color = \"#4338CA\"                   # fill; also accepts (67, 56, 202)\nheader.font.bold = True\nheader.font.color = \"#FFFFFF\"\nheader.font.size = 11\n\nsheet.range(\"D2\").expand(\"down\").number_format = \"#,##0.00\"\nsheet.range(\"B2\").expand(\"down\").number_format = \"dd mmm yyyy\"\nsheet.range(\"E2\").expand(\"down\").number_format = \"0.0%\"\ndata.columns.autofit()\n",[23,245,246,259,269,279,289,293,315,333,351],{"__ignoreMap":44},[48,247,248,251,253,256],{"class":50,"line":51},[48,249,250],{"class":93},"header.color ",[48,252,116],{"class":89},[48,254,255],{"class":58}," \"#4338CA\"",[48,257,258],{"class":128},"                   # fill; also accepts (67, 56, 202)\n",[48,260,261,264,266],{"class":50,"line":103},[48,262,263],{"class":93},"header.font.bold ",[48,265,116],{"class":89},[48,267,268],{"class":180}," True\n",[48,270,271,274,276],{"class":50,"line":110},[48,272,273],{"class":93},"header.font.color ",[48,275,116],{"class":89},[48,277,278],{"class":58}," \"#FFFFFF\"\n",[48,280,281,284,286],{"class":50,"line":132},[48,282,283],{"class":93},"header.font.size ",[48,285,116],{"class":89},[48,287,288],{"class":180}," 11\n",[48,290,291],{"class":50,"line":149},[48,292,107],{"emptyLinePlaceholder":106},[48,294,295,298,301,304,307,310,312],{"class":50,"line":169},[48,296,297],{"class":93},"sheet.range(",[48,299,300],{"class":58},"\"D2\"",[48,302,303],{"class":93},").expand(",[48,305,306],{"class":58},"\"down\"",[48,308,309],{"class":93},").number_format ",[48,311,116],{"class":89},[48,313,314],{"class":58}," \"#,##0.00\"\n",[48,316,317,319,322,324,326,328,330],{"class":50,"line":186},[48,318,297],{"class":93},[48,320,321],{"class":58},"\"B2\"",[48,323,303],{"class":93},[48,325,306],{"class":58},[48,327,309],{"class":93},[48,329,116],{"class":89},[48,331,332],{"class":58}," \"dd mmm yyyy\"\n",[48,334,335,337,340,342,344,346,348],{"class":50,"line":212},[48,336,297],{"class":93},[48,338,339],{"class":58},"\"E2\"",[48,341,303],{"class":93},[48,343,306],{"class":58},[48,345,309],{"class":93},[48,347,116],{"class":89},[48,349,350],{"class":58}," \"0.0%\"\n",[48,352,354],{"class":50,"line":353},9,[48,355,356],{"class":93},"data.columns.autofit()\n",[10,358,359,362,363,366,367,370,371,374,375,374,378,374,381,228,384,387,388,391,392,395,396,387,400,403],{},[23,360,361],{},"Range.color"," sets the fill and accepts a hex string, an RGB tuple or ",[23,364,365],{},"None"," to clear it; reading it back returns a tuple. ",[23,368,369],{},"font"," exposes ",[23,372,373],{},"bold",", ",[23,376,377],{},"italic",[23,379,380],{},"color",[23,382,383],{},"size",[23,385,386],{},"name",". ",[23,389,390],{},"number_format"," takes the same codes as Excel's ",[14,393,394],{},"Format Cells"," dialog, so anything that works there works here — see ",[28,397,399],{"href":398},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fwrite-custom-number-format-codes-in-excel-with-python\u002F","Write Custom Number Format Codes in Excel with Python",[23,401,402],{},"autofit"," asks Excel itself to size the columns, which is more accurate than any estimate a file-based library can make, because Excel measures the rendered text.",[405,406,414,415,414,419,414,423,414,430,414,440,414,451,414,458,414,464,414,470,414,478,414,482,414,487,414,491,414,496,414,500,414,507,414,511,414,518,414,523,414,527,414,531,414,536,414,539,414,544,414,547,414,552,414,555],"svg",{"viewBox":407,"role":408,"ariaLabelledBy":409,"xmlns":412,"style":413},"4 0 752 233","img",[410,411],"xw-vs-op-t","xw-vs-op-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  ",[416,417,418],"title",{"id":410},"Formatting with xlwings versus openpyxl",[420,421,422],"desc",{"id":411},"xlwings formats a workbook open in Excel, changes are visible immediately, autofit is measured by Excel, and anything in Excel's object model is reachable through .api, but it needs Excel and each call is a round trip. openpyxl formats a file without Excel, runs anywhere and is fast for many cells, but cannot autofit precisely and has no access to Excel features it does not model.",[424,425],"rect",{"x":426,"y":181,"width":427,"height":428,"fill":429},"4","752","233","#ffffff",[424,431],{"x":432,"y":433,"width":434,"height":435,"rx":436,"fill":437,"stroke":438,"style":439},"20.0","16.0","351.0","201.0","14","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:2px",[441,442,444],"g",{"transform":443},"translate(182.5,29.0) scale(1.083)",[445,446],"path",{"d":447,"fill":448,"stroke":449,"style":450},"M3 5.5l8-1.2v7.2H3z M13 4l8-1.2v8.7h-8z M3 13.5h8v7.2l-8-1.2z M13 13.5h8v8.7l-8-1.2z","none","var(--brand-strong,#4338ca)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[452,453,457],"text",{"x":454,"y":455,"style":456},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","xlwings (live Excel)",[50,459],{"x1":460,"y1":461,"x2":462,"y2":461,"stroke":438,"style":463},"36.0","91.0","355.0","stroke-width:1px",[452,465,469],{"x":466,"y":467,"style":468},"60.0","111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","changes appear as the script runs",[441,471,473],{"transform":472},"translate(38.5,99.5) scale(0.625)",[445,474],{"d":475,"fill":448,"stroke":476,"style":477},"M5 12.5l4.5 4.5L19 7","var(--teal,#0f9488)","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[452,479,481],{"x":466,"y":480,"style":468},"137.0","autofit measured by Excel",[441,483,485],{"transform":484},"translate(38.5,125.5) scale(0.625)",[445,486],{"d":475,"fill":448,"stroke":476,"style":477},[452,488,490],{"x":466,"y":489,"style":468},"163.0","full object model via .api",[441,492,494],{"transform":493},"translate(38.5,151.5) scale(0.625)",[445,495],{"d":475,"fill":448,"stroke":476,"style":477},[452,497,499],{"x":466,"y":498,"style":468},"189.0","needs Excel; each call is a round trip",[441,501,503],{"transform":502},"translate(38.5,177.5) scale(0.625)",[445,504],{"d":505,"fill":448,"stroke":506,"style":477},"M6 6l12 12 M18 6L6 18","var(--accent,#f43f8f)",[424,508],{"x":509,"y":433,"width":434,"height":435,"rx":436,"fill":510,"stroke":476,"style":439},"389.0","#d9f4f1",[441,512,514],{"transform":513},"translate(551.5,29.0) scale(1.083)",[445,515],{"d":516,"fill":448,"stroke":517,"style":450},"M12 3c-4 0-4 1.6-4 3v2h4.2v1H6c-2 0-3 1.4-3 4s1 4 3 4h2v-2.6c0-1.6 1.3-2.9 2.9-2.9h4.2c1.3 0 2.4-1.1 2.4-2.4V6c0-1.6-1.8-3-5.5-3z M10 5.5h.01 M12 21c4 0 4-1.6 4-3v-2h-4.2v-1H18c2 0 3-1.4 3-4s-1-4-3-4h-2v2.6c0 1.6-1.3 2.9-2.9 2.9H8.9c-1.3 0-2.4 1.1-2.4 2.4V18c0 1.6 1.8 3 5.5 3z M14 18.5h.01","var(--teal-ink,#0b6157)",[452,519,522],{"x":520,"y":455,"style":521},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","openpyxl (file)",[50,524],{"x1":525,"y1":461,"x2":526,"y2":461,"stroke":476,"style":463},"405.0","724.0",[452,528,530],{"x":529,"y":467,"style":468},"429.0","no Excel needed, runs on servers",[441,532,534],{"transform":533},"translate(407.5,99.5) scale(0.625)",[445,535],{"d":475,"fill":448,"stroke":476,"style":477},[452,537,538],{"x":529,"y":480,"style":468},"fast for many cells",[441,540,542],{"transform":541},"translate(407.5,125.5) scale(0.625)",[445,543],{"d":475,"fill":448,"stroke":476,"style":477},[452,545,546],{"x":529,"y":489,"style":468},"no exact autofit",[441,548,550],{"transform":549},"translate(407.5,151.5) scale(0.625)",[445,551],{"d":505,"fill":448,"stroke":506,"style":477},[452,553,554],{"x":529,"y":498,"style":468},"only what openpyxl models",[441,556,558],{"transform":557},"translate(407.5,177.5) scale(0.625)",[445,559],{"d":505,"fill":448,"stroke":506,"style":477},[34,561,563],{"id":562},"step-3-borders-and-anything-else-through-api","Step 3 — Borders and anything else through .api",[10,565,566,567,569],{},"xlwings deliberately keeps its own API small. For borders, conditional formats and the rest of Excel's formatting, use ",[23,568,25],{},", which returns the underlying Excel object — the same object VBA uses:",[39,571,573],{"className":80,"code":572,"language":82,"meta":44,"style":44},"from xlwings.constants import BordersIndex, LineStyle, BorderWeight\n\nbottom = header.api.Borders(BordersIndex.xlEdgeBottom)      # Windows (COM)\nbottom.LineStyle = LineStyle.xlContinuous\nbottom.Weight = BorderWeight.xlMedium\n\ntotal_row = data.rows.count + 1\nsheet.range(f\"A{total_row}\").value = \"Total\"\nsheet.range(f\"D{total_row}\").formula = f\"=SUM(D2:D{total_row - 1})\"\nsheet.range(f\"A{total_row}:E{total_row}\").font.bold = True\n",[23,574,575,588,592,605,615,625,629,645,676,717],{"__ignoreMap":44},[48,576,577,580,583,585],{"class":50,"line":51},[48,578,579],{"class":89},"from",[48,581,582],{"class":93}," xlwings.constants ",[48,584,90],{"class":89},[48,586,587],{"class":93}," BordersIndex, LineStyle, BorderWeight\n",[48,589,590],{"class":50,"line":103},[48,591,107],{"emptyLinePlaceholder":106},[48,593,594,597,599,602],{"class":50,"line":110},[48,595,596],{"class":93},"bottom ",[48,598,116],{"class":89},[48,600,601],{"class":93}," header.api.Borders(BordersIndex.xlEdgeBottom)      ",[48,603,604],{"class":128},"# Windows (COM)\n",[48,606,607,610,612],{"class":50,"line":132},[48,608,609],{"class":93},"bottom.LineStyle ",[48,611,116],{"class":89},[48,613,614],{"class":93}," LineStyle.xlContinuous\n",[48,616,617,620,622],{"class":50,"line":149},[48,618,619],{"class":93},"bottom.Weight ",[48,621,116],{"class":89},[48,623,624],{"class":93}," BorderWeight.xlMedium\n",[48,626,627],{"class":50,"line":169},[48,628,107],{"emptyLinePlaceholder":106},[48,630,631,634,636,639,642],{"class":50,"line":186},[48,632,633],{"class":93},"total_row ",[48,635,116],{"class":89},[48,637,638],{"class":93}," data.rows.count ",[48,640,641],{"class":89},"+",[48,643,644],{"class":180}," 1\n",[48,646,647,649,652,655,659,662,665,668,671,673],{"class":50,"line":212},[48,648,297],{"class":93},[48,650,651],{"class":89},"f",[48,653,654],{"class":58},"\"A",[48,656,658],{"class":657},"sSjpA","{",[48,660,661],{"class":93},"total_row",[48,663,664],{"class":657},"}",[48,666,667],{"class":58},"\"",[48,669,670],{"class":93},").value ",[48,672,116],{"class":89},[48,674,675],{"class":58}," \"Total\"\n",[48,677,678,680,682,685,687,689,691,693,696,698,701,704,706,708,710,712,714],{"class":50,"line":353},[48,679,297],{"class":93},[48,681,651],{"class":89},[48,683,684],{"class":58},"\"D",[48,686,658],{"class":657},[48,688,661],{"class":93},[48,690,664],{"class":657},[48,692,667],{"class":58},[48,694,695],{"class":93},").formula ",[48,697,116],{"class":89},[48,699,700],{"class":89}," f",[48,702,703],{"class":58},"\"=SUM(D2:D",[48,705,658],{"class":657},[48,707,633],{"class":93},[48,709,203],{"class":89},[48,711,206],{"class":180},[48,713,664],{"class":657},[48,715,716],{"class":58},")\"\n",[48,718,720,722,724,726,728,730,732,735,737,739,741,743,746,748],{"class":50,"line":719},10,[48,721,297],{"class":93},[48,723,651],{"class":89},[48,725,654],{"class":58},[48,727,658],{"class":657},[48,729,661],{"class":93},[48,731,664],{"class":657},[48,733,734],{"class":58},":E",[48,736,658],{"class":657},[48,738,661],{"class":93},[48,740,664],{"class":657},[48,742,667],{"class":58},[48,744,745],{"class":93},").font.bold ",[48,747,116],{"class":89},[48,749,268],{"class":180},[10,751,752,755,756,759,760,763,764,768,769,771,772,774],{},[23,753,754],{},"xlwings.constants"," provides Excel's named constants (",[23,757,758],{},"xlEdgeBottom"," is 9, ",[23,761,762],{},"xlContinuous"," 1), so the code reads like the VBA it mirrors — handy when translating a recorded macro, as in ",[28,765,767],{"href":766},"\u002Fgetting-started-with-python-excel-automation\u002Fchoosing-a-python-excel-library\u002Ftranslate-common-vba-macros-to-python\u002F","Translate Common VBA Macros to Python",". The catch is portability: on Windows ",[23,770,25],{}," is Excel's COM object, on macOS it is an AppleScript bridge with different syntax, so ",[23,773,25],{}," code written on one platform usually needs adjusting for the other. Keep to xlwings' own properties where they suffice.",[34,776,778],{"id":777},"step-4-conditional-formats-and-an-excel-table","Step 4 — Conditional formats and an Excel table",[10,780,781,782,784,785,788],{},"Conditional formatting through ",[23,783,25],{}," uses Excel's ",[23,786,787],{},"FormatConditions"," collection directly (Windows):",[39,790,792],{"className":80,"code":791,"language":82,"meta":44,"style":44},"margin = sheet.range(\"E2\").expand(\"down\")\nscale = margin.api.FormatConditions.AddColorScale(3)       # three-colour scale\nnegatives = sheet.range(\"D2\").expand(\"down\").api.FormatConditions.Add(Type=1, Operator=6, Formula1=\"=0\")\nnegatives.Font.Color = 0x00009C                             # BGR: dark red text for values \u003C 0\n",[23,793,794,811,830,878],{"__ignoreMap":44},[48,795,796,799,801,803,805,807,809],{"class":50,"line":51},[48,797,798],{"class":93},"margin ",[48,800,116],{"class":89},[48,802,157],{"class":93},[48,804,339],{"class":58},[48,806,303],{"class":93},[48,808,306],{"class":58},[48,810,209],{"class":93},[48,812,813,816,818,821,824,827],{"class":50,"line":103},[48,814,815],{"class":93},"scale ",[48,817,116],{"class":89},[48,819,820],{"class":93}," margin.api.FormatConditions.AddColorScale(",[48,822,823],{"class":180},"3",[48,825,826],{"class":93},")       ",[48,828,829],{"class":128},"# three-colour scale\n",[48,831,832,835,837,839,841,843,845,848,852,854,856,858,861,863,866,868,871,873,876],{"class":50,"line":110},[48,833,834],{"class":93},"negatives ",[48,836,116],{"class":89},[48,838,157],{"class":93},[48,840,300],{"class":58},[48,842,303],{"class":93},[48,844,306],{"class":58},[48,846,847],{"class":93},").api.FormatConditions.Add(",[48,849,851],{"class":850},"sa561","Type",[48,853,116],{"class":89},[48,855,197],{"class":180},[48,857,374],{"class":93},[48,859,860],{"class":850},"Operator",[48,862,116],{"class":89},[48,864,865],{"class":180},"6",[48,867,374],{"class":93},[48,869,870],{"class":850},"Formula1",[48,872,116],{"class":89},[48,874,875],{"class":58},"\"=0\"",[48,877,209],{"class":93},[48,879,880,883,885,888,891],{"class":50,"line":132},[48,881,882],{"class":93},"negatives.Font.Color ",[48,884,116],{"class":89},[48,886,887],{"class":89}," 0x",[48,889,890],{"class":180},"00009C",[48,892,893],{"class":128},"                             # BGR: dark red text for values \u003C 0\n",[10,895,896,899,900,903,904,907],{},[23,897,898],{},"Type=1"," is a cell-value rule and ",[23,901,902],{},"Operator=6"," means \"less than\"; Excel's colour values in COM are BGR integers, so ",[23,905,906],{},"0x00009C"," is dark red. When in doubt, record a macro in Excel while applying the format and translate it.",[10,909,910,911,913],{},"Turning the range into a proper Excel table gives banding, filter buttons and a style in one call, with no ",[23,912,25],{}," needed:",[39,915,917],{"className":80,"code":916,"language":82,"meta":44,"style":44},"table = sheet.tables.add(source=data, name=\"SalesReport\", table_style_name=\"TableStyleMedium2\")\nprint(table.name, table.range.address)\n",[23,918,919,956],{"__ignoreMap":44},[48,920,921,924,926,929,932,934,937,939,941,944,946,949,951,954],{"class":50,"line":51},[48,922,923],{"class":93},"table ",[48,925,116],{"class":89},[48,927,928],{"class":93}," sheet.tables.add(",[48,930,931],{"class":850},"source",[48,933,116],{"class":89},[48,935,936],{"class":93},"data, ",[48,938,386],{"class":850},[48,940,116],{"class":89},[48,942,943],{"class":58},"\"SalesReport\"",[48,945,374],{"class":93},[48,947,948],{"class":850},"table_style_name",[48,950,116],{"class":89},[48,952,953],{"class":58},"\"TableStyleMedium2\"",[48,955,209],{"class":93},[48,957,958,960],{"class":50,"line":103},[48,959,215],{"class":180},[48,961,962],{"class":93},"(table.name, table.range.address)\n",[10,964,965,968,969,32],{},[23,966,967],{},"tables.add"," takes the source range, a table name and any built-in style name from Excel's gallery. Tables also make formulas more robust — see ",[28,970,972],{"href":971},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-excel-tables-and-autofilters-with-python\u002Fcreate-an-excel-table-with-python\u002F","Create an Excel Table with Python",[34,974,976],{"id":975},"step-5-keep-it-fast","Step 5 — Keep it fast",[10,978,979],{},"Every property assignment crosses from Python into Excel and back. Formatting 500 rows cell by cell means thousands of round trips and visible flicker; formatting the whole range at once is one call:",[39,981,983],{"className":80,"code":982,"language":82,"meta":44,"style":44},"import time\n\napp = wb.app\napp.screen_updating = False\ntry:\n    start = time.perf_counter()\n    body.font.size = 10                               # one call for the whole body\n    for i in range(1, body.rows.count, 2):            # banding: still one call per row\n        body.rows[i].color = \"#F0F4FF\"\n    print(f\"formatted in {time.perf_counter() - start:.1f} s\")\nfinally:\n    app.screen_updating = True\n",[23,984,985,992,996,1006,1016,1024,1034,1047,1078,1088,1120,1128],{"__ignoreMap":44},[48,986,987,989],{"class":50,"line":51},[48,988,90],{"class":89},[48,990,991],{"class":93}," time\n",[48,993,994],{"class":50,"line":103},[48,995,107],{"emptyLinePlaceholder":106},[48,997,998,1001,1003],{"class":50,"line":110},[48,999,1000],{"class":93},"app ",[48,1002,116],{"class":89},[48,1004,1005],{"class":93}," wb.app\n",[48,1007,1008,1011,1013],{"class":50,"line":132},[48,1009,1010],{"class":93},"app.screen_updating ",[48,1012,116],{"class":89},[48,1014,1015],{"class":180}," False\n",[48,1017,1018,1021],{"class":50,"line":149},[48,1019,1020],{"class":89},"try",[48,1022,1023],{"class":93},":\n",[48,1025,1026,1029,1031],{"class":50,"line":169},[48,1027,1028],{"class":93},"    start ",[48,1030,116],{"class":89},[48,1032,1033],{"class":93}," time.perf_counter()\n",[48,1035,1036,1039,1041,1044],{"class":50,"line":186},[48,1037,1038],{"class":93},"    body.font.size ",[48,1040,116],{"class":89},[48,1042,1043],{"class":180}," 10",[48,1045,1046],{"class":128},"                               # one call for the whole body\n",[48,1048,1049,1052,1055,1058,1061,1064,1066,1069,1072,1075],{"class":50,"line":212},[48,1050,1051],{"class":89},"    for",[48,1053,1054],{"class":93}," i ",[48,1056,1057],{"class":89},"in",[48,1059,1060],{"class":180}," range",[48,1062,1063],{"class":93},"(",[48,1065,197],{"class":180},[48,1067,1068],{"class":93},", body.rows.count, ",[48,1070,1071],{"class":180},"2",[48,1073,1074],{"class":93},"):            ",[48,1076,1077],{"class":128},"# banding: still one call per row\n",[48,1079,1080,1083,1085],{"class":50,"line":353},[48,1081,1082],{"class":93},"        body.rows[i].color ",[48,1084,116],{"class":89},[48,1086,1087],{"class":58}," \"#F0F4FF\"\n",[48,1089,1090,1093,1095,1097,1100,1102,1105,1107,1110,1113,1115,1118],{"class":50,"line":719},[48,1091,1092],{"class":180},"    print",[48,1094,1063],{"class":93},[48,1096,651],{"class":89},[48,1098,1099],{"class":58},"\"formatted in ",[48,1101,658],{"class":657},[48,1103,1104],{"class":93},"time.perf_counter() ",[48,1106,203],{"class":89},[48,1108,1109],{"class":93}," start",[48,1111,1112],{"class":89},":.1f",[48,1114,664],{"class":657},[48,1116,1117],{"class":58}," s\"",[48,1119,209],{"class":93},[48,1121,1123,1126],{"class":50,"line":1122},11,[48,1124,1125],{"class":89},"finally",[48,1127,1023],{"class":93},[48,1129,1131,1134,1136],{"class":50,"line":1130},12,[48,1132,1133],{"class":93},"    app.screen_updating ",[48,1135,116],{"class":89},[48,1137,268],{"class":180},[10,1139,1140,1141,1144,1145,1147,1148,1150,1151,1153,1154,32],{},"Turning off ",[23,1142,1143],{},"screen_updating"," stops Excel redrawing after every change, which is often the biggest single speed-up; the ",[23,1146,1020],{},"\u002F",[23,1149,1125],{}," guarantees it is turned back on even if the script fails, or the user is left with a frozen-looking window. Prefer whole-range operations, a table style or a conditional format over loops — banding via ",[23,1152,967],{}," above costs one call instead of 250. The same principle applies to reading and writing values, as measured in ",[28,1155,1157],{"href":1156},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fspeed-up-xlwings-with-bulk-reads-and-writes\u002F","Speed Up xlwings with Bulk Reads and Writes",[405,1159,414,1165,414,1168,414,1171,414,1175,414,1182,414,1188,414,1195,414,1200,414,1203,414,1207,414,1210,414,1215,414,1218,414,1222,414,1227,414,1232,414,1235,414,1239,414,1241,414,1243],{"viewBox":1160,"role":408,"ariaLabelledBy":1161,"xmlns":412,"style":1164},"4 0 744 206",[1162,1163],"xw-calls-t","xw-calls-d","width:100%;max-width:744px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[416,1166,1167],{"id":1162},"Round trips to Excel for the same formatting job",[420,1169,1170],{"id":1163},"Applying a font size to 500 data rows takes 500 calls cell-row by row, or 1 call for the whole range. Banding every other row takes 250 calls in a loop, or a single call when it comes from a table style.",[424,1172],{"x":426,"y":181,"width":1173,"height":1174,"fill":429},"744","206",[424,1176],{"x":432,"y":433,"width":1177,"height":1178,"rx":1179,"fill":1180,"stroke":1181,"style":463},"173.3","28.0","7","#e7ebef","var(--line,#cdd5e6)",[452,1183,1187],{"x":1184,"y":1185,"style":1186},"106.7","34.5","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","font size · row by row",[424,1189],{"x":1190,"y":433,"width":1191,"height":1178,"rx":1179,"fill":1192,"stroke":1193,"style":1194},"203.3","464.2","#fce9e9","var(--danger,#dc2626)","stroke-width:1.5px",[452,1196,1199],{"x":1197,"y":1185,"style":1198},"675.6","font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:start","500 calls",[424,1201],{"x":432,"y":1202,"width":1177,"height":1178,"rx":1179,"fill":1180,"stroke":1181,"style":463},"56.0",[452,1204,1206],{"x":1184,"y":1205,"style":1186},"74.5","font size · whole range",[424,1208],{"x":1190,"y":1202,"width":1209,"height":1178,"rx":1179,"fill":510,"stroke":476,"style":1194},"6.0",[452,1211,1214],{"x":1212,"y":1205,"style":1213},"217.3","font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:start","1 call",[424,1216],{"x":432,"y":1217,"width":1177,"height":1178,"rx":1179,"fill":1180,"stroke":1181,"style":463},"96.0",[452,1219,1221],{"x":1184,"y":1220,"style":1186},"114.5","banding · loop",[424,1223],{"x":1190,"y":1217,"width":1224,"height":1178,"rx":1179,"fill":1225,"stroke":1226,"style":1194},"232.1","#fdefd8","var(--gold,#b4740a)",[452,1228,1231],{"x":1229,"y":1220,"style":1230},"443.5","font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:start","250 calls",[424,1233],{"x":432,"y":1234,"width":1177,"height":1178,"rx":1179,"fill":1180,"stroke":1181,"style":463},"136.0",[452,1236,1238],{"x":1184,"y":1237,"style":1186},"154.5","banding · table style",[424,1240],{"x":1190,"y":1234,"width":1209,"height":1178,"rx":1179,"fill":510,"stroke":476,"style":1194},[452,1242,1214],{"x":1212,"y":1237,"style":1213},[452,1244,1248],{"x":1245,"y":1246,"style":1247},"380.0","186.0","font-size:12.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","Each call is a round trip from Python to Excel; fewer, larger operations are faster.",[34,1250,1252],{"id":1251},"step-6-save-and-decide-what-the-workbook-should-look-like-next-time","Step 6 — Save, and decide what the workbook should look like next time",[39,1254,1256],{"className":80,"code":1255,"language":82,"meta":44,"style":44},"sheet.activate()\nexcel = wb.app.api                                         # Windows: the Excel Application COM object\nexcel.ActiveWindow.FreezePanes = False                     # clear any existing freeze\nsheet.range(\"A2\").select()\nexcel.ActiveWindow.FreezePanes = True                      # freeze everything above row 2\nwb.save()\n",[23,1257,1258,1263,1276,1289,1299,1311],{"__ignoreMap":44},[48,1259,1260],{"class":50,"line":51},[48,1261,1262],{"class":93},"sheet.activate()\n",[48,1264,1265,1268,1270,1273],{"class":50,"line":103},[48,1266,1267],{"class":93},"excel ",[48,1269,116],{"class":89},[48,1271,1272],{"class":93}," wb.app.api                                         ",[48,1274,1275],{"class":128},"# Windows: the Excel Application COM object\n",[48,1277,1278,1281,1283,1286],{"class":50,"line":110},[48,1279,1280],{"class":93},"excel.ActiveWindow.FreezePanes ",[48,1282,116],{"class":89},[48,1284,1285],{"class":180}," False",[48,1287,1288],{"class":128},"                     # clear any existing freeze\n",[48,1290,1291,1293,1296],{"class":50,"line":132},[48,1292,297],{"class":93},[48,1294,1295],{"class":58},"\"A2\"",[48,1297,1298],{"class":93},").select()\n",[48,1300,1301,1303,1305,1308],{"class":50,"line":149},[48,1302,1280],{"class":93},[48,1304,116],{"class":89},[48,1306,1307],{"class":180}," True",[48,1309,1310],{"class":128},"                      # freeze everything above row 2\n",[48,1312,1313],{"class":50,"line":169},[48,1314,1315],{"class":93},"wb.save()\n",[10,1317,1318,1319,32],{},"Freezing panes is a window setting rather than a cell format, which is why it goes through the window object. Save when done; if the formatting is the same every month, consider putting it in a template workbook instead and letting the script only fill values — formatting that lives in the template does not need to be re-applied, and runs faster. Template filling is covered in ",[28,1320,1322],{"href":1321},"\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Ffill-excel-template-with-python-openpyxl\u002F","Fill an Excel Template with Python and openpyxl",[405,1324,414,1330,414,1333,414,1336,414,1341,414,1346,414,1350,414,1356,414,1360,414,1364,414,1368,414,1372,414,1375,414,1379,414,1383,414,1387,414,1390,414,1394,414,1396,414,1400,414,1402,414,1405,414,1407,414,1410,414,1412,414,1415,414,1417,414,1420,414,1423,414,1426,414,1428,414,1432,414,1434,414,1437,414,1439,414,1442,414,1444,414,1447,414,1449,414,1452,414,1454,414,1457,414,1459,414,1462,414,1464,414,1467,414,1469,414,1472,414,1474,414,1477,414,1479,414,1482,414,1485,414,1488,414,1490,414,1493,414,1495,414,1497,414,1499,414,1501,414,1503,414,1505,414,1507,414,1509,414,1512,414,1516,414,1518,414,1522,414,1524,414,1526,414,1528,414,1531],{"viewBox":1325,"role":408,"ariaLabelledBy":1326,"xmlns":412,"style":1329},"135 0 489 196",[1327,1328],"xw-result-t","xw-result-d","width:100%;max-width:489px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[416,1331,1332],{"id":1327},"The report sheet after formatting",[420,1334,1335],{"id":1328},"A header row with a dark indigo fill and white bold text, dates formatted as dd mmm yyyy, amounts with thousands separators and two decimals, margins as percentages, and a bold total row with a SUM formula.",[424,1337],{"x":1338,"y":181,"width":1339,"height":1340,"fill":429},"135","489","196",[424,1342],{"x":1343,"y":433,"width":1344,"height":1345,"rx":181,"fill":1180,"stroke":1181,"style":463},"151.7","32.0","24.0",[424,1347],{"x":1348,"y":433,"width":1349,"height":1345,"rx":181,"fill":1180,"stroke":1181,"style":463},"183.7","64.1",[452,1351,1355],{"x":1352,"y":1353,"style":1354},"215.7","33.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[424,1357],{"x":1358,"y":433,"width":1359,"height":1345,"rx":181,"fill":1180,"stroke":1181,"style":463},"247.8","93.3",[452,1361,1363],{"x":1362,"y":1353,"style":1354},"294.4","B",[424,1365],{"x":1366,"y":433,"width":1367,"height":1345,"rx":181,"fill":1180,"stroke":1181,"style":463},"341.1","94.3",[452,1369,1371],{"x":1370,"y":1353,"style":1354},"388.2","C",[424,1373],{"x":1374,"y":433,"width":467,"height":1345,"rx":181,"fill":1180,"stroke":1181,"style":463},"435.4",[452,1376,1378],{"x":1377,"y":1353,"style":1354},"490.9","D",[424,1380],{"x":1381,"y":433,"width":1382,"height":1345,"rx":181,"fill":1180,"stroke":1181,"style":463},"546.4","62.0",[452,1384,1386],{"x":1385,"y":1353,"style":1354},"577.4","E",[424,1388],{"x":1343,"y":1389,"width":1344,"height":1178,"rx":181,"fill":1180,"stroke":1181,"style":463},"40.0",[452,1391,197],{"x":1392,"y":1393,"style":1354},"167.7","59.0",[424,1395],{"x":1348,"y":1389,"width":1349,"height":1178,"rx":181,"fill":437,"stroke":438,"style":1194},[452,1397,1399],{"x":1352,"y":1393,"style":1398},"font-size:10.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Order",[424,1401],{"x":1358,"y":1389,"width":1359,"height":1178,"rx":181,"fill":437,"stroke":438,"style":1194},[452,1403,1404],{"x":1362,"y":1393,"style":1398},"Date",[424,1406],{"x":1366,"y":1389,"width":1367,"height":1178,"rx":181,"fill":437,"stroke":438,"style":1194},[452,1408,1409],{"x":1370,"y":1393,"style":1398},"Customer",[424,1411],{"x":1374,"y":1389,"width":467,"height":1178,"rx":181,"fill":437,"stroke":438,"style":1194},[452,1413,1414],{"x":1377,"y":1393,"style":1398},"Amount",[424,1416],{"x":1381,"y":1389,"width":1382,"height":1178,"rx":181,"fill":437,"stroke":438,"style":1194},[452,1418,1419],{"x":1385,"y":1393,"style":1398},"Margin",[424,1421],{"x":1343,"y":1422,"width":1344,"height":1178,"rx":181,"fill":1180,"stroke":1181,"style":463},"68.0",[452,1424,1071],{"x":1392,"y":1425,"style":1354},"87.0",[424,1427],{"x":1348,"y":1422,"width":1349,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1429,1431],{"x":1352,"y":1425,"style":1430},"font-size:10.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","N-1001",[424,1433],{"x":1358,"y":1422,"width":1359,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1435,1436],{"x":1362,"y":1425,"style":1430},"03 Sep 2026",[424,1438],{"x":1366,"y":1422,"width":1367,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1440,1441],{"x":1370,"y":1425,"style":1430},"Müller GmbH",[424,1443],{"x":1374,"y":1422,"width":467,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1445,1446],{"x":1377,"y":1425,"style":1430},"1,200.00",[424,1448],{"x":1381,"y":1422,"width":1382,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1450,1451],{"x":1385,"y":1425,"style":1430},"21.4%",[424,1453],{"x":1343,"y":1217,"width":1344,"height":1178,"rx":181,"fill":1180,"stroke":1181,"style":463},[452,1455,823],{"x":1392,"y":1456,"style":1354},"115.0",[424,1458],{"x":1348,"y":1217,"width":1349,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1460,1461],{"x":1352,"y":1456,"style":1430},"N-1002",[424,1463],{"x":1358,"y":1217,"width":1359,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1465,1466],{"x":1362,"y":1456,"style":1430},"04 Sep 2026",[424,1468],{"x":1366,"y":1217,"width":1367,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1470,1471],{"x":1370,"y":1456,"style":1430},"Café Señor",[424,1473],{"x":1374,"y":1217,"width":467,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1475,1476],{"x":1377,"y":1456,"style":1430},"240.00",[424,1478],{"x":1381,"y":1217,"width":1382,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1480,1481],{"x":1385,"y":1456,"style":1430},"18.7%",[424,1483],{"x":1343,"y":1484,"width":1344,"height":1178,"rx":181,"fill":1180,"stroke":1181,"style":463},"124.0",[452,1486,426],{"x":1392,"y":1487,"style":1354},"143.0",[424,1489],{"x":1348,"y":1484,"width":1349,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1491,1492],{"x":1352,"y":1487,"style":1430},"…",[424,1494],{"x":1358,"y":1484,"width":1359,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1496,1492],{"x":1362,"y":1487,"style":1430},[424,1498],{"x":1366,"y":1484,"width":1367,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1500,1492],{"x":1370,"y":1487,"style":1430},[424,1502],{"x":1374,"y":1484,"width":467,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1504,1492],{"x":1377,"y":1487,"style":1430},[424,1506],{"x":1381,"y":1484,"width":1382,"height":1178,"rx":181,"fill":429,"stroke":1181,"style":463},[452,1508,1492],{"x":1385,"y":1487,"style":1430},[424,1510],{"x":1343,"y":1511,"width":1344,"height":1178,"rx":181,"fill":1180,"stroke":1181,"style":463},"152.0",[452,1513,1515],{"x":1392,"y":1514,"style":1354},"171.0","5",[424,1517],{"x":1348,"y":1511,"width":1349,"height":1178,"rx":181,"fill":510,"stroke":476,"style":1194},[452,1519,1521],{"x":1352,"y":1514,"style":1520},"font-size:10.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Total",[424,1523],{"x":1358,"y":1511,"width":1359,"height":1178,"rx":181,"fill":510,"stroke":476,"style":1194},[424,1525],{"x":1366,"y":1511,"width":1367,"height":1178,"rx":181,"fill":510,"stroke":476,"style":1194},[424,1527],{"x":1374,"y":1511,"width":467,"height":1178,"rx":181,"fill":510,"stroke":476,"style":1194},[452,1529,1530],{"x":1377,"y":1514,"style":1520},"=SUM(D2:D501)",[424,1532],{"x":1381,"y":1511,"width":1382,"height":1178,"rx":181,"fill":510,"stroke":476,"style":1194},[34,1534,1536],{"id":1535},"step-7-make-the-formatting-repeatable","Step 7 — Make the formatting repeatable",[10,1538,1539],{},"Scripts that format a live workbook tend to run more than once — after the data is refreshed, or when someone presses the button again. Clearing the previous formatting first makes every run produce the same result instead of piling conditional formats on top of each other:",[39,1541,1543],{"className":80,"code":1542,"language":82,"meta":44,"style":44},"data.clear_formats()                                       # fills, fonts, borders, number formats\ndata.api.FormatConditions.Delete()                         # Windows: remove earlier conditional formats\nfor existing in list(sheet.tables):\n    if existing.name == \"SalesReport\":\n        existing.api.Unlist()                              # turn the old table back into a range\n",[23,1544,1545,1553,1561,1577,1593],{"__ignoreMap":44},[48,1546,1547,1550],{"class":50,"line":51},[48,1548,1549],{"class":93},"data.clear_formats()                                       ",[48,1551,1552],{"class":128},"# fills, fonts, borders, number formats\n",[48,1554,1555,1558],{"class":50,"line":103},[48,1556,1557],{"class":93},"data.api.FormatConditions.Delete()                         ",[48,1559,1560],{"class":128},"# Windows: remove earlier conditional formats\n",[48,1562,1563,1566,1569,1571,1574],{"class":50,"line":110},[48,1564,1565],{"class":89},"for",[48,1567,1568],{"class":93}," existing ",[48,1570,1057],{"class":89},[48,1572,1573],{"class":180}," list",[48,1575,1576],{"class":93},"(sheet.tables):\n",[48,1578,1579,1582,1585,1588,1591],{"class":50,"line":132},[48,1580,1581],{"class":89},"    if",[48,1583,1584],{"class":93}," existing.name ",[48,1586,1587],{"class":89},"==",[48,1589,1590],{"class":58}," \"SalesReport\"",[48,1592,1023],{"class":93},[48,1594,1595,1598],{"class":50,"line":149},[48,1596,1597],{"class":93},"        existing.api.Unlist()                              ",[48,1599,1600],{"class":128},"# turn the old table back into a range\n",[10,1602,1603,1606,1607,1610,1611,1614,1615,1617],{},[23,1604,1605],{},"clear_formats"," resets the visual formatting while keeping the values; deleting the conditional formats matters most, because ",[23,1608,1609],{},"FormatConditions.Add"," ",[14,1612,1613],{},"adds"," a rule every time and a sheet that has been formatted twenty times carries twenty identical rules. Removing the old table before ",[23,1616,967],{}," avoids an error about overlapping tables. Run the clean-up, then Steps 2–5, and the sheet looks the same no matter how often the script runs.",[34,1619,1621],{"id":1620},"common-pitfalls","Common pitfalls",[1623,1624,1625,1633,1642,1650,1659],"ul",{},[1626,1627,1628,1632],"li",{},[1629,1630,1631],"strong",{},"Formatting cell by cell."," Each assignment is a round trip; format whole ranges.",[1626,1634,1635,1638,1639,1641],{},[1629,1636,1637],{},"Leaving screen updating off."," Always restore it in a ",[23,1640,1125],{}," block.",[1626,1643,1644,1649],{},[1629,1645,1646,1648],{},[23,1647,25],{}," code across platforms."," Windows COM and macOS AppleScript differ; test on the platform users have.",[1626,1651,1652,1655,1656,1658],{},[1629,1653,1654],{},"BGR colours in COM."," Excel's COM colour integers are blue-green-red; xlwings' own ",[23,1657,380],{}," property takes RGB.",[1626,1660,1661,1610,1664,1666],{},[1629,1662,1663],{},"Formatting before writing values.",[23,1665,223],{}," stops at empty cells; write the data first, then format the range it occupies.",[34,1668,1670],{"id":1669},"conclusion","Conclusion",[10,1672,1673,1674,374,1676,374,1679,374,1682,374,1684,374,1686,1688,1689,1691,1692,1694,1695,1697,1698,1700,1701,1147,1703,1705],{},"xlwings formats a workbook live in Excel. Use its own properties — ",[23,1675,380],{},[23,1677,1678],{},"font.bold",[23,1680,1681],{},"font.color",[23,1683,390],{},[23,1685,402],{},[23,1687,967],{}," — for the common cases, and ",[23,1690,25],{}," with ",[23,1693,754],{}," for borders, conditional formats and anything else in Excel's object model, remembering that ",[23,1696,25],{}," differs between Windows and macOS. Format whole ranges rather than cells, switch ",[23,1699,1143],{}," off inside ",[23,1702,1020],{},[23,1704,1125],{},", and move formatting that never changes into a template.",[34,1707,1709],{"id":1708},"frequently-asked-questions","Frequently asked questions",[10,1711,1712,1715],{},[1629,1713,1714],{},"How do I change a cell's background colour with xlwings?","\nAssign to the range's color property: sheet.range(\"A1\").color = \"#FFF2CC\" or an RGB tuple such as (255, 242, 204). Set it to None to remove the fill.",[10,1717,1718,1721],{},[1629,1719,1720],{},"How do I make text bold or change the font colour in xlwings?","\nUse the range's font object: rng.font.bold = True, rng.font.color = \"#9C0006\", rng.font.size = 11, rng.font.name = \"Calibri\".",[10,1723,1724,1727],{},[1629,1725,1726],{},"How do I add borders with xlwings?","\nxlwings has no border property of its own, so use the Excel object model through the range's api attribute: on Windows, take the Borders item for the edge you want and set its LineStyle and Weight, using the named constants in xlwings.constants.",[10,1729,1730,1733],{},[1629,1731,1732],{},"Why is formatting with xlwings slow?","\nEvery property assignment is a call from Python into Excel. Format whole ranges instead of looping over cells, prefer table styles and conditional formats, and set app.screen_updating = False while the script runs.",[34,1735,1737],{"id":1736},"related","Related",[1623,1739,1740,1746,1753,1760],{},[1626,1741,1742,1743,1745],{},"Up one level: ",[28,1744,31],{"href":30}," — controlling Excel from Python.",[1626,1747,1748,1752],{},[28,1749,1751],{"href":1750},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002F","Styling Excel Cells with openpyxl"," — the same formatting on files.",[1626,1754,1755,1759],{},[28,1756,1758],{"href":1757},"\u002Fgetting-started-with-python-excel-automation\u002Fchoosing-a-python-excel-library\u002Fwhen-to-use-xlwings-instead-of-openpyxl\u002F","When to Use xlwings Instead of openpyxl"," — choosing between the two.",[1626,1761,1762,1766],{},[28,1763,1765],{"href":1764},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Finsert-a-matplotlib-plot-into-a-live-workbook-with-xlwings\u002F","Insert a matplotlib Plot into a Live Workbook with xlwings"," — adding pictures the same way.",[1768,1769,1770],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}",{"title":44,"searchDepth":103,"depth":103,"links":1772},[1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784],{"id":36,"depth":103,"text":37},{"id":76,"depth":103,"text":77},{"id":239,"depth":103,"text":240},{"id":562,"depth":103,"text":563},{"id":777,"depth":103,"text":778},{"id":975,"depth":103,"text":976},{"id":1251,"depth":103,"text":1252},{"id":1535,"depth":103,"text":1536},{"id":1620,"depth":103,"text":1621},{"id":1669,"depth":103,"text":1670},{"id":1708,"depth":103,"text":1709},{"id":1736,"depth":103,"text":1737},"2026-10-02","Style a workbook that is open in Excel from Python: fill colours, fonts, number formats and column widths through xlwings' own properties, borders and conditional formats through the .api escape hatch, an Excel table with a built-in style, and the screen-updating and range-at-once habits that keep formatting thousands of cells fast — plus how this differs from formatting a file with openpyxl.","md",[1789,1791,1793,1795],{"q":1714,"a":1790},"Assign to the range's color property: sheet.range(\"A1\").color = \"#FFF2CC\" or an RGB tuple such as (255, 242, 204). Set it to None to remove the fill.",{"q":1720,"a":1792},"Use the range's font object: rng.font.bold = True, rng.font.color = \"#9C0006\", rng.font.size = 11, rng.font.name = \"Calibri\".",{"q":1726,"a":1794},"xlwings has no border property of its own, so use the Excel object model through the range's api attribute: on Windows, take the Borders item for the edge you want and set its LineStyle and Weight, using the named constants in xlwings.constants.",{"q":1732,"a":1796},"Every property assignment is a call from Python into Excel. Format whole ranges instead of looping over cells, prefer table styles and conditional formats, and set app.screen_updating = False while the script runs.","format cells in a live workbook with xlwings",null,{"breadcrumb":1800},[1801,1803,1806],{"name":1802,"item":1147},"Home",{"name":1804,"item":1805},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":31,"item":30},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fformat-cells-in-a-live-workbook-with-xlwings",{"title":1809,"description":1810},"Format Excel Cells from Python with xlwings (Live Workbook)","Format an open workbook with xlwings: Range.color, font.bold\u002Fcolor\u002Fsize, number_format, autofit, borders and conditional formatting via .api and xlwings.constants, tables.add with a style, screen_updating for speed, and xlwings vs openpyxl.","format-cells-in-a-live-workbook-with-xlwings","getting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fformat-cells-in-a-live-workbook-with-xlwings\u002Findex",[1814,1815],"xlwings","cell-styling","how-to","H7rAYaRWHtep8fCeABw_z6RDyC7BNpvhgBbMXFcAJVc",[1819,1823],{"title":1820,"path":1821,"stem":1822,"children":-1},"Control How xlwings Converts DataFrames and Ranges","\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fcontrol-how-xlwings-converts-dataframes-and-ranges","getting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fcontrol-how-xlwings-converts-dataframes-and-ranges\u002Findex",{"title":1765,"path":1824,"stem":1825,"children":-1},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Finsert-a-matplotlib-plot-into-a-live-workbook-with-xlwings","getting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Finsert-a-matplotlib-plot-into-a-live-workbook-with-xlwings\u002Findex",[1827,1829],{"path":1828,"title":31},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics",{"path":1830,"title":1804},"\u002Fgetting-started-with-python-excel-automation",[],[1833,1836,1839,1843,1844,1845],{"path":1834,"title":1835,"kind":1816},"\u002Fautomating-reporting-workflows\u002Ftesting-and-packaging-excel-automation-scripts\u002Ftest-win32com-and-xlwings-code-without-excel","Test win32com and xlwings Code Without Excel",{"path":1837,"title":1838,"kind":1816},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fautomate-excel-on-macos-with-python","Automate Excel on macOS with Python",{"path":1840,"title":1841,"kind":1842},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fxlwings-vs-pywin32-for-excel-automation","xlwings vs pywin32 for Excel Automation","compare",{"path":1821,"title":1820,"kind":1816},{"path":1824,"title":1765,"kind":1816},{"path":1846,"title":236,"kind":1816},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fread-and-write-a-live-excel-workbook-with-xlwings",1790972056958]