[{"data":1,"prerenderedAt":2139},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-negative-numbers-in-red-with-parentheses":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-negative-numbers-in-red-with-parentheses":2107,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-negative-numbers-in-red-with-parentheses":2115,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-negative-numbers-in-red-with-parentheses":2120,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-negative-numbers-in-red-with-parentheses":2121},{"id":4,"title":5,"body":6,"dateModified":2073,"datePublished":2073,"description":2074,"extension":2075,"faq":2076,"keyword":2085,"kind":2086,"meta":2087,"navigation":289,"path":2096,"seo":2097,"slug":2100,"stem":2101,"topics":2102,"type":2105,"__hash__":2106},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-negative-numbers-in-red-with-parentheses\u002Findex.md","Show Negative Numbers in Red with Parentheses in Excel",{"type":7,"value":8,"toc":2059},"minimark",[9,33,218,223,254,258,261,501,520,524,540,624,640,765,769,775,976,997,1001,1004,1143,1184,1188,1195,1272,1287,1433,1437,1440,1743,1753,1757,1760,1914,1921,1925,1968,1972,1987,1991,2004,2010,2016,2022,2026,2055],[10,11,12,13,17,18,21,22,27,28,32],"p",{},"In financial reports a negative number is written in parentheses, often in red: ",[14,15,16],"code",{},"(1,235)"," rather than ",[14,19,20],{},"-1,235",". The convention exists because a minus sign is easy to miss in a column of figures, while brackets and colour are not — and brackets still work when the report is printed in black and white. Excel produces this with a number format, so the cell still holds −1234.5 for every formula. This guide, part of ",[23,24,26],"a",{"href":25},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002F","Applying Number and Date Formats in Excel",", builds the formats from Python, explains the alignment characters that make them look right, and covers the edge cases. The general structure of format codes is covered in ",[23,29,31],{"href":30},"\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",".",[34,35,43,44,43,48,43,52,43,60,43,69,43,73,43,80,43,84,43,88,43,92,43,96,43,100,43,105,43,107,43,111,43,113,43,116,43,118,43,121,43,124,43,128,43,130,43,134,43,136,43,139,43,141,43,144,43,147,43,151,43,153,43,156,43,158,43,161,43,166,43,169,43,172,43,176,43,178,43,181,43,183,43,185,43,187,43,190,43,193,43,197,43,199,43,202,43,204,43,207,43,209,43,212],"svg",{"viewBox":36,"role":37,"ariaLabelledBy":38,"xmlns":41,"style":42},"159 0 441 222","img",[39,40],"ng-sheet-t","ng-sheet-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:441px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[45,46,47],"title",{"id":39},"A variance column with parenthesised negatives",[49,50,51],"desc",{"id":40},"Revenue variance values of 1,235, negative 1,235, zero and 48,200 are displayed as 1,235, a red (1,235), a dash and 48,200. The positives carry a trailing space so their last digit lines up with the last digit of the negatives inside the parentheses.",[53,54],"rect",{"x":55,"y":56,"width":57,"height":58,"fill":59},"159","0","441","222","#ffffff",[53,61],{"x":62,"y":63,"width":64,"height":65,"rx":56,"fill":66,"stroke":67,"style":68},"255.8","16.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)","stroke-width:1px",[53,70],{"x":71,"y":63,"width":72,"height":65,"rx":56,"fill":66,"stroke":67,"style":68},"287.8","60.3",[74,75,79],"text",{"x":76,"y":77,"style":78},"318.0","33.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[53,81],{"x":82,"y":63,"width":83,"height":65,"rx":56,"fill":66,"stroke":67,"style":68},"348.1","72.0",[74,85,87],{"x":86,"y":77,"style":78},"384.1","B",[53,89],{"x":90,"y":63,"width":91,"height":65,"rx":56,"fill":66,"stroke":67,"style":68},"420.1","84.1",[74,93,95],{"x":94,"y":77,"style":78},"462.1","C",[53,97],{"x":62,"y":98,"width":64,"height":99,"rx":56,"fill":66,"stroke":67,"style":68},"40.0","28.0",[74,101,104],{"x":102,"y":103,"style":78},"271.8","59.0","1",[53,106],{"x":71,"y":98,"width":72,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,108,110],{"x":76,"y":103,"style":109},"font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Line",[53,112],{"x":82,"y":98,"width":83,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,114,115],{"x":86,"y":103,"style":109},"stored",[53,117],{"x":90,"y":98,"width":91,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,119,120],{"x":94,"y":103,"style":109},"displayed",[53,122],{"x":62,"y":123,"width":64,"height":99,"rx":56,"fill":66,"stroke":67,"style":68},"68.0",[74,125,127],{"x":102,"y":126,"style":78},"87.0","2",[53,129],{"x":71,"y":123,"width":72,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,131,133],{"x":76,"y":126,"style":132},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","North",[53,135],{"x":82,"y":123,"width":83,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,137,138],{"x":86,"y":126,"style":132},"1234.5",[53,140],{"x":90,"y":123,"width":91,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,142,143],{"x":94,"y":126,"style":132},"1,235␠",[53,145],{"x":62,"y":146,"width":64,"height":99,"rx":56,"fill":66,"stroke":67,"style":68},"96.0",[74,148,150],{"x":102,"y":149,"style":78},"115.0","3",[53,152],{"x":71,"y":146,"width":72,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,154,155],{"x":76,"y":149,"style":132},"South",[53,157],{"x":82,"y":146,"width":83,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,159,160],{"x":86,"y":149,"style":132},"-1234.5",[53,162],{"x":90,"y":146,"width":91,"height":99,"rx":56,"fill":163,"stroke":164,"style":165},"#fee8f2","var(--accent,#f43f8f)","stroke-width:1.5px",[74,167,16],{"x":94,"y":149,"style":168},"font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle",[53,170],{"x":62,"y":171,"width":64,"height":99,"rx":56,"fill":66,"stroke":67,"style":68},"124.0",[74,173,175],{"x":102,"y":174,"style":78},"143.0","4",[53,177],{"x":71,"y":171,"width":72,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,179,180],{"x":76,"y":174,"style":132},"East",[53,182],{"x":82,"y":171,"width":83,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,184,56],{"x":86,"y":174,"style":132},[53,186],{"x":90,"y":171,"width":91,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,188,189],{"x":94,"y":174,"style":132},"–␠",[53,191],{"x":62,"y":192,"width":64,"height":99,"rx":56,"fill":66,"stroke":67,"style":68},"152.0",[74,194,196],{"x":102,"y":195,"style":78},"171.0","5",[53,198],{"x":71,"y":192,"width":72,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,200,201],{"x":76,"y":195,"style":132},"West",[53,203],{"x":82,"y":192,"width":83,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,205,206],{"x":86,"y":195,"style":132},"48200",[53,208],{"x":90,"y":192,"width":91,"height":99,"rx":56,"fill":59,"stroke":67,"style":68},[74,210,211],{"x":94,"y":195,"style":132},"48,200␠",[74,213,217],{"x":214,"y":215,"style":216},"380.0","202.0","font-size:12.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","the ␠ marks the space that _) reserves for the missing parenthesis",[219,220,222],"h2",{"id":221},"prerequisites","Prerequisites",[224,225,230],"pre",{"className":226,"code":227,"language":228,"meta":229,"style":229},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install openpyxl pandas xlsxwriter\n","bash","",[14,231,232],{"__ignoreMap":229},[233,234,237,241,245,248,251],"span",{"class":235,"line":236},"line",1,[233,238,240],{"class":239},"sMTad","pip",[233,242,244],{"class":243},"srMev"," install",[233,246,247],{"class":243}," openpyxl",[233,249,250],{"class":243}," pandas",[233,252,253],{"class":243}," xlsxwriter\n",[219,255,257],{"id":256},"step-1-the-two-section-format","Step 1 — The two-section format",[10,259,260],{},"A number format has up to four sections separated by semicolons — positive; negative; zero; text. For red parenthesised negatives you need the first two:",[224,262,266],{"className":263,"code":264,"language":265,"meta":229,"style":229},"language-python shiki shiki-themes github-light github-dark-high-contrast","from openpyxl import Workbook\n\nRED_PARENS = \"#,##0_);[Red](#,##0)\"\n\nwb = Workbook()\nws = wb.active\nws.append([\"Line\", \"Variance\"])\nfor line, value in [(\"North\", 1234.5), (\"South\", -1234.5), (\"East\", 0), (\"West\", 48200)]:\n    ws.append([line, value])\nfor (cell,) in ws.iter_rows(min_row=2, min_col=2, max_col=2):\n    cell.number_format = RED_PARENS\nwb.save(\"variance.xlsx\")\nprint(ws[\"B3\"].value, ws[\"B3\"].number_format)       # -1234.5 #,##0_);[Red](#,##0)\n","python",[14,267,268,284,291,304,309,321,332,350,406,412,454,465,477],{"__ignoreMap":229},[233,269,270,274,278,281],{"class":235,"line":236},[233,271,273],{"class":272},"s-kum","from",[233,275,277],{"class":276},"skGVy"," openpyxl ",[233,279,280],{"class":272},"import",[233,282,283],{"class":276}," Workbook\n",[233,285,287],{"class":235,"line":286},2,[233,288,290],{"emptyLinePlaceholder":289},true,"\n",[233,292,294,298,301],{"class":235,"line":293},3,[233,295,297],{"class":296},"sP0c6","RED_PARENS",[233,299,300],{"class":272}," =",[233,302,303],{"class":243}," \"#,##0_);[Red](#,##0)\"\n",[233,305,307],{"class":235,"line":306},4,[233,308,290],{"emptyLinePlaceholder":289},[233,310,312,315,318],{"class":235,"line":311},5,[233,313,314],{"class":276},"wb ",[233,316,317],{"class":272},"=",[233,319,320],{"class":276}," Workbook()\n",[233,322,324,327,329],{"class":235,"line":323},6,[233,325,326],{"class":276},"ws ",[233,328,317],{"class":272},[233,330,331],{"class":276}," wb.active\n",[233,333,335,338,341,344,347],{"class":235,"line":334},7,[233,336,337],{"class":276},"ws.append([",[233,339,340],{"class":243},"\"Line\"",[233,342,343],{"class":276},", ",[233,345,346],{"class":243},"\"Variance\"",[233,348,349],{"class":276},"])\n",[233,351,353,356,359,362,365,368,370,372,375,378,380,383,385,387,390,392,394,396,399,401,403],{"class":235,"line":352},8,[233,354,355],{"class":272},"for",[233,357,358],{"class":276}," line, value ",[233,360,361],{"class":272},"in",[233,363,364],{"class":276}," [(",[233,366,367],{"class":243},"\"North\"",[233,369,343],{"class":276},[233,371,138],{"class":296},[233,373,374],{"class":276},"), (",[233,376,377],{"class":243},"\"South\"",[233,379,343],{"class":276},[233,381,382],{"class":272},"-",[233,384,138],{"class":296},[233,386,374],{"class":276},[233,388,389],{"class":243},"\"East\"",[233,391,343],{"class":276},[233,393,56],{"class":296},[233,395,374],{"class":276},[233,397,398],{"class":243},"\"West\"",[233,400,343],{"class":276},[233,402,206],{"class":296},[233,404,405],{"class":276},")]:\n",[233,407,409],{"class":235,"line":408},9,[233,410,411],{"class":276},"    ws.append([line, value])\n",[233,413,415,417,420,422,425,429,431,433,435,438,440,442,444,447,449,451],{"class":235,"line":414},10,[233,416,355],{"class":272},[233,418,419],{"class":276}," (cell,) ",[233,421,361],{"class":272},[233,423,424],{"class":276}," ws.iter_rows(",[233,426,428],{"class":427},"sa561","min_row",[233,430,317],{"class":272},[233,432,127],{"class":296},[233,434,343],{"class":276},[233,436,437],{"class":427},"min_col",[233,439,317],{"class":272},[233,441,127],{"class":296},[233,443,343],{"class":276},[233,445,446],{"class":427},"max_col",[233,448,317],{"class":272},[233,450,127],{"class":296},[233,452,453],{"class":276},"):\n",[233,455,457,460,462],{"class":235,"line":456},11,[233,458,459],{"class":276},"    cell.number_format ",[233,461,317],{"class":272},[233,463,464],{"class":296}," RED_PARENS\n",[233,466,468,471,474],{"class":235,"line":467},12,[233,469,470],{"class":276},"wb.save(",[233,472,473],{"class":243},"\"variance.xlsx\"",[233,475,476],{"class":276},")\n",[233,478,480,483,486,489,492,494,497],{"class":235,"line":479},13,[233,481,482],{"class":296},"print",[233,484,485],{"class":276},"(ws[",[233,487,488],{"class":243},"\"B3\"",[233,490,491],{"class":276},"].value, ws[",[233,493,488],{"class":243},[233,495,496],{"class":276},"].number_format)       ",[233,498,500],{"class":499},"s-wDw","# -1234.5 #,##0_);[Red](#,##0)\n",[10,502,503,504,507,508,343,511,513,514,516,517,32],{},"The negative section supplies its own parentheses, so no minus sign appears — the section is used because the value is negative, and the sign is implied. ",[14,505,506],{},"[Red]"," at the start of the section colours it. The stored value stays −1234.5; rendering the file gives ",[14,509,510],{},"1,235",[14,512,16],{}," in red, ",[14,515,56],{}," and ",[14,518,519],{},"48,200",[219,521,523],{"id":522},"step-2-why-the-_-matters","Step 2 — Why the _) matters",[10,525,526,529,530,532,533,536,537,539],{},[14,527,528],{},"_)"," in the positive section inserts a space exactly as wide as a closing parenthesis. Without it, the last digit of ",[14,531,510],{}," sits under the ",[14,534,535],{},")"," of ",[14,538,16],{}," instead of under its last digit, and a column of mixed signs looks ragged:",[224,541,543],{"className":263,"code":542,"language":265,"meta":229,"style":229},"for fmt in [\"#,##0;[Red](#,##0)\", RED_PARENS]:\n    print(f\"{fmt!r:26} positive ends with a pad: {fmt.split(';')[0].endswith('_)')}\")\n",[14,544,545,567],{"__ignoreMap":229},[233,546,547,549,552,554,557,560,562,564],{"class":235,"line":236},[233,548,355],{"class":272},[233,550,551],{"class":276}," fmt ",[233,553,361],{"class":272},[233,555,556],{"class":276}," [",[233,558,559],{"class":243},"\"#,##0;[Red](#,##0)\"",[233,561,343],{"class":276},[233,563,297],{"class":296},[233,565,566],{"class":276},"]:\n",[233,568,569,572,575,578,581,585,588,591,594,597,599,602,605,608,610,613,616,618,620,622],{"class":235,"line":286},[233,570,571],{"class":296},"    print",[233,573,574],{"class":276},"(",[233,576,577],{"class":272},"f",[233,579,580],{"class":243},"\"",[233,582,584],{"class":583},"sSjpA","{",[233,586,587],{"class":276},"fmt",[233,589,590],{"class":272},"!r:26",[233,592,593],{"class":583},"}",[233,595,596],{"class":243}," positive ends with a pad: ",[233,598,584],{"class":583},[233,600,601],{"class":276},"fmt.split(",[233,603,604],{"class":243},"';'",[233,606,607],{"class":276},")[",[233,609,56],{"class":296},[233,611,612],{"class":276},"].endswith(",[233,614,615],{"class":243},"'_)'",[233,617,535],{"class":276},[233,619,593],{"class":583},[233,621,580],{"class":243},[233,623,476],{"class":276},[10,625,626,627,629,630,632,633,635,636,639],{},"Exporting the rendered sheet as text shows the effect directly: with ",[14,628,528],{},", the positive ",[14,631,510],{}," is followed by a space, so it right-aligns with ",[14,634,16],{},". The pad is invisible on screen, which is why it is so often left out — the ragged edge only becomes obvious once a long column mixes positive and negative values. The underscore works with any character — ",[14,637,638],{},"_-"," reserves the width of a minus sign — which is how Excel's own accounting formats keep columns straight.",[34,641,43,647,43,650,43,653,43,657,43,666,43,677,43,683,43,688,43,694,43,701,43,705,43,710,43,714,43,719,43,724,43,731,43,736,43,740,43,744,43,749,43,752,43,757,43,760],{"viewBox":642,"role":37,"ariaLabelledBy":643,"xmlns":41,"style":646},"4 0 752 207",[644,645],"ng-align-t","ng-align-d","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[45,648,649],{"id":644},"Positive numbers with and without the _) pad",[49,651,652],{"id":645},"Without the pad, positive numbers end one character further right than the last digit of parenthesised negatives, so digits do not line up. With the _) pad, positives end with a space the width of a parenthesis and every digit column aligns.",[53,654],{"x":175,"y":56,"width":655,"height":656,"fill":59},"752","207",[53,658],{"x":659,"y":63,"width":660,"height":661,"rx":662,"fill":663,"stroke":664,"style":665},"20.0","351.0","175.0","14","#fdefd8","var(--gold,#b4740a)","stroke-width:2px",[667,668,670],"g",{"transform":669},"translate(182.5,29.0) scale(1.083)",[671,672],"path",{"d":673,"fill":674,"stroke":675,"style":676},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","none","var(--gold-ink,#7a4e06)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[74,678,682],{"x":679,"y":680,"style":681},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","#,##0;[Red](#,##0)",[235,684],{"x1":685,"y1":686,"x2":687,"y2":686,"stroke":664,"style":68},"36.0","91.0","355.0",[74,689,693],{"x":690,"y":691,"style":692},"60.0","111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","1,235 ends under the )",[667,695,697],{"transform":696},"translate(38.5,99.5) scale(0.625)",[671,698],{"d":699,"fill":674,"stroke":164,"style":700},"M6 6l12 12 M18 6L6 18","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[74,702,704],{"x":690,"y":703,"style":692},"137.0","digit columns drift",[667,706,708],{"transform":707},"translate(38.5,125.5) scale(0.625)",[671,709],{"d":699,"fill":674,"stroke":164,"style":700},[74,711,713],{"x":690,"y":712,"style":692},"163.0","looks ragged in long lists",[667,715,717],{"transform":716},"translate(38.5,151.5) scale(0.625)",[671,718],{"d":673,"fill":674,"stroke":664,"style":700},[53,720],{"x":721,"y":63,"width":660,"height":661,"rx":662,"fill":722,"stroke":723,"style":665},"389.0","#d9f4f1","var(--teal,#0f9488)",[667,725,727],{"transform":726},"translate(551.5,29.0) scale(1.083)",[671,728],{"d":729,"fill":674,"stroke":730,"style":676},"M5 12.5l4.5 4.5L19 7","var(--teal-ink,#0b6157)",[74,732,735],{"x":733,"y":680,"style":734},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","#,##0_);[Red](#,##0)",[235,737],{"x1":738,"y1":686,"x2":739,"y2":686,"stroke":723,"style":68},"405.0","724.0",[74,741,743],{"x":742,"y":691,"style":692},"429.0","1,235 ends under the 5",[667,745,747],{"transform":746},"translate(407.5,99.5) scale(0.625)",[671,748],{"d":729,"fill":674,"stroke":723,"style":700},[74,750,751],{"x":742,"y":703,"style":692},"digits line up",[667,753,755],{"transform":754},"translate(407.5,125.5) scale(0.625)",[671,756],{"d":729,"fill":674,"stroke":723,"style":700},[74,758,759],{"x":742,"y":712,"style":692},"Excel's own built-ins do this",[667,761,763],{"transform":762},"translate(407.5,151.5) scale(0.625)",[671,764],{"d":729,"fill":674,"stroke":723,"style":700},[219,766,768],{"id":767},"step-3-zeros-currency-and-the-accounting-layout","Step 3 — Zeros, currency and the accounting layout",[10,770,771,772,774],{},"Add a third section for zero — a dash reads better than ",[14,773,56],{}," in financial tables — and put currency inside the format so it sits inside the parentheses too:",[224,776,778],{"className":263,"code":777,"language":265,"meta":229,"style":229},"FORMATS = {\n    \"with dash for zero\": '#,##0_);[Red](#,##0);\"–\"_)',\n    \"currency, 2 dp\": '\"€\"#,##0.00_);[Red](\"€\"#,##0.00)',\n    \"accounting\": '_(\"€\"* #,##0.00_);_(\"€\"* (#,##0.00);_(\"€\"* \"-\"??_);_(@_)',\n}\nws2 = wb.create_sheet(\"Formats\")\nws2.append([\"value\", *FORMATS])\nfor value in [1234.5, -1234.5, 0]:\n    ws2.append([value, *[value] * len(FORMATS)])\nfor row in ws2.iter_rows(min_row=2):\n    for cell, fmt in zip(row[1:], FORMATS.values()):\n        cell.number_format = fmt\nwb.save(\"variance.xlsx\")\n",[14,779,780,790,804,816,828,833,848,865,890,912,932,958,968],{"__ignoreMap":229},[233,781,782,785,787],{"class":235,"line":236},[233,783,784],{"class":296},"FORMATS",[233,786,300],{"class":272},[233,788,789],{"class":276}," {\n",[233,791,792,795,798,801],{"class":235,"line":286},[233,793,794],{"class":243},"    \"with dash for zero\"",[233,796,797],{"class":276},": ",[233,799,800],{"class":243},"'#,##0_);[Red](#,##0);\"–\"_)'",[233,802,803],{"class":276},",\n",[233,805,806,809,811,814],{"class":235,"line":293},[233,807,808],{"class":243},"    \"currency, 2 dp\"",[233,810,797],{"class":276},[233,812,813],{"class":243},"'\"€\"#,##0.00_);[Red](\"€\"#,##0.00)'",[233,815,803],{"class":276},[233,817,818,821,823,826],{"class":235,"line":306},[233,819,820],{"class":243},"    \"accounting\"",[233,822,797],{"class":276},[233,824,825],{"class":243},"'_(\"€\"* #,##0.00_);_(\"€\"* (#,##0.00);_(\"€\"* \"-\"??_);_(@_)'",[233,827,803],{"class":276},[233,829,830],{"class":235,"line":311},[233,831,832],{"class":276},"}\n",[233,834,835,838,840,843,846],{"class":235,"line":323},[233,836,837],{"class":276},"ws2 ",[233,839,317],{"class":272},[233,841,842],{"class":276}," wb.create_sheet(",[233,844,845],{"class":243},"\"Formats\"",[233,847,476],{"class":276},[233,849,850,853,856,858,861,863],{"class":235,"line":334},[233,851,852],{"class":276},"ws2.append([",[233,854,855],{"class":243},"\"value\"",[233,857,343],{"class":276},[233,859,860],{"class":272},"*",[233,862,784],{"class":296},[233,864,349],{"class":276},[233,866,867,869,872,874,876,878,880,882,884,886,888],{"class":235,"line":352},[233,868,355],{"class":272},[233,870,871],{"class":276}," value ",[233,873,361],{"class":272},[233,875,556],{"class":276},[233,877,138],{"class":296},[233,879,343],{"class":276},[233,881,382],{"class":272},[233,883,138],{"class":296},[233,885,343],{"class":276},[233,887,56],{"class":296},[233,889,566],{"class":276},[233,891,892,895,897,900,902,905,907,909],{"class":235,"line":408},[233,893,894],{"class":276},"    ws2.append([value, ",[233,896,860],{"class":272},[233,898,899],{"class":276},"[value] ",[233,901,860],{"class":272},[233,903,904],{"class":296}," len",[233,906,574],{"class":276},[233,908,784],{"class":296},[233,910,911],{"class":276},")])\n",[233,913,914,916,919,921,924,926,928,930],{"class":235,"line":414},[233,915,355],{"class":272},[233,917,918],{"class":276}," row ",[233,920,361],{"class":272},[233,922,923],{"class":276}," ws2.iter_rows(",[233,925,428],{"class":427},[233,927,317],{"class":272},[233,929,127],{"class":296},[233,931,453],{"class":276},[233,933,934,937,940,942,945,948,950,953,955],{"class":235,"line":456},[233,935,936],{"class":272},"    for",[233,938,939],{"class":276}," cell, fmt ",[233,941,361],{"class":272},[233,943,944],{"class":296}," zip",[233,946,947],{"class":276},"(row[",[233,949,104],{"class":296},[233,951,952],{"class":276},":], ",[233,954,784],{"class":296},[233,956,957],{"class":276},".values()):\n",[233,959,960,963,965],{"class":235,"line":467},[233,961,962],{"class":276},"        cell.number_format ",[233,964,317],{"class":272},[233,966,967],{"class":276}," fmt\n",[233,969,970,972,974],{"class":235,"line":479},[233,971,470],{"class":276},[233,973,473],{"class":243},[233,975,476],{"class":276},[10,977,978,979,982,983,986,987,990,991,516,993,996],{},"The accounting layout adds two more tricks: ",[14,980,981],{},"* "," repeats a space to fill the cell, which pushes the currency symbol to the left edge while the number stays right-aligned, and the fourth section ",[14,984,985],{},"_(@_)"," pads text so labels in the same column line up too. openpyxl also knows Excel's built-in versions by number — ",[14,988,989],{},"BUILTIN_FORMATS[38]"," is ",[14,992,735],{},[14,994,995],{},"[40]"," the two-decimal variant — which Excel shows under their localised names in the Format Cells dialog.",[219,998,1000],{"id":999},"step-4-when-negative-is-good","Step 4 — When negative is good",[10,1002,1003],{},"For a cost variance, spending less than budget is good, so the colours should be reversed: overspend in red, underspend in green. Colours are per section, so swap them:",[224,1005,1007],{"className":263,"code":1006,"language":265,"meta":229,"style":229},"COST = '[Red]#,##0_);[Color10](#,##0);\"–\"_)'\nws[\"C1\"] = \"Cost variance\"\nfor row, value in zip(range(2, 6), [1200, -800, 0, 300]):\n    ws[f\"C{row}\"] = value\n    ws[f\"C{row}\"].number_format = COST\nwb.save(\"variance.xlsx\")\n",[14,1008,1009,1019,1035,1085,1111,1135],{"__ignoreMap":229},[233,1010,1011,1014,1016],{"class":235,"line":236},[233,1012,1013],{"class":296},"COST",[233,1015,300],{"class":272},[233,1017,1018],{"class":243}," '[Red]#,##0_);[Color10](#,##0);\"–\"_)'\n",[233,1020,1021,1024,1027,1030,1032],{"class":235,"line":286},[233,1022,1023],{"class":276},"ws[",[233,1025,1026],{"class":243},"\"C1\"",[233,1028,1029],{"class":276},"] ",[233,1031,317],{"class":272},[233,1033,1034],{"class":243}," \"Cost variance\"\n",[233,1036,1037,1039,1042,1044,1046,1048,1051,1053,1055,1057,1060,1063,1066,1068,1070,1073,1075,1077,1079,1082],{"class":235,"line":293},[233,1038,355],{"class":272},[233,1040,1041],{"class":276}," row, value ",[233,1043,361],{"class":272},[233,1045,944],{"class":296},[233,1047,574],{"class":276},[233,1049,1050],{"class":296},"range",[233,1052,574],{"class":276},[233,1054,127],{"class":296},[233,1056,343],{"class":276},[233,1058,1059],{"class":296},"6",[233,1061,1062],{"class":276},"), [",[233,1064,1065],{"class":296},"1200",[233,1067,343],{"class":276},[233,1069,382],{"class":272},[233,1071,1072],{"class":296},"800",[233,1074,343],{"class":276},[233,1076,56],{"class":296},[233,1078,343],{"class":276},[233,1080,1081],{"class":296},"300",[233,1083,1084],{"class":276},"]):\n",[233,1086,1087,1090,1092,1095,1097,1100,1102,1104,1106,1108],{"class":235,"line":306},[233,1088,1089],{"class":276},"    ws[",[233,1091,577],{"class":272},[233,1093,1094],{"class":243},"\"C",[233,1096,584],{"class":583},[233,1098,1099],{"class":276},"row",[233,1101,593],{"class":583},[233,1103,580],{"class":243},[233,1105,1029],{"class":276},[233,1107,317],{"class":272},[233,1109,1110],{"class":276}," value\n",[233,1112,1113,1115,1117,1119,1121,1123,1125,1127,1130,1132],{"class":235,"line":311},[233,1114,1089],{"class":276},[233,1116,577],{"class":272},[233,1118,1094],{"class":243},[233,1120,584],{"class":583},[233,1122,1099],{"class":276},[233,1124,593],{"class":583},[233,1126,580],{"class":243},[233,1128,1129],{"class":276},"].number_format ",[233,1131,317],{"class":272},[233,1133,1134],{"class":296}," COST\n",[233,1136,1137,1139,1141],{"class":235,"line":323},[233,1138,470],{"class":276},[233,1140,473],{"class":243},[233,1142,476],{"class":276},[10,1144,1145,1148,1149,343,1152,343,1155,343,1158,343,1161,343,1164,343,1166,516,1169,1172,1173,1175,1176,1179,1180,32],{},[14,1146,1147],{},"[Color10]"," is green in Excel's default palette; the named colours are limited to ",[14,1150,1151],{},"[Black]",[14,1153,1154],{},"[Blue]",[14,1156,1157],{},"[Cyan]",[14,1159,1160],{},"[Green]",[14,1162,1163],{},"[Magenta]",[14,1165,506],{},[14,1167,1168],{},"[White]",[14,1170,1171],{},"[Yellow]",", and the bright ",[14,1174,1160],{}," is hard to read on white. When the exact shade matters — a brand red such as ",[14,1177,1178],{},"#B91C1C"," — use conditional formatting for the colour and keep the number format for the parentheses; see ",[23,1181,1183],{"href":1182},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-cells-above-a-threshold-with-openpyxl\u002F","Highlight Cells Above a Threshold with openpyxl",[219,1185,1187],{"id":1186},"step-5-the-0-trap","Step 5 — The \"(0)\" trap",[10,1189,1190,1191,1194],{},"A value of −0.4 is negative, so it uses the negative section, and with no decimals it displays as ",[14,1192,1193],{},"(0)"," — a red zero in brackets that looks like an error. It appears whenever small negative remainders survive a calculation:",[224,1196,1198],{"className":263,"code":1197,"language":265,"meta":229,"style":229},"ws[\"B7\"] = -0.4\nws[\"B7\"].number_format = RED_PARENS                  # displays (0)\ncleaned = round(-0.4) + 0.0                          # round in Python before writing\nprint(cleaned)                                       # 0.0\n",[14,1199,1200,1217,1233,1262],{"__ignoreMap":229},[233,1201,1202,1204,1207,1209,1211,1214],{"class":235,"line":236},[233,1203,1023],{"class":276},[233,1205,1206],{"class":243},"\"B7\"",[233,1208,1029],{"class":276},[233,1210,317],{"class":272},[233,1212,1213],{"class":272}," -",[233,1215,1216],{"class":296},"0.4\n",[233,1218,1219,1221,1223,1225,1227,1230],{"class":235,"line":286},[233,1220,1023],{"class":276},[233,1222,1206],{"class":243},[233,1224,1129],{"class":276},[233,1226,317],{"class":272},[233,1228,1229],{"class":296}," RED_PARENS",[233,1231,1232],{"class":499},"                  # displays (0)\n",[233,1234,1235,1238,1240,1243,1245,1247,1250,1253,1256,1259],{"class":235,"line":293},[233,1236,1237],{"class":276},"cleaned ",[233,1239,317],{"class":272},[233,1241,1242],{"class":296}," round",[233,1244,574],{"class":276},[233,1246,382],{"class":272},[233,1248,1249],{"class":296},"0.4",[233,1251,1252],{"class":276},") ",[233,1254,1255],{"class":272},"+",[233,1257,1258],{"class":296}," 0.0",[233,1260,1261],{"class":499},"                          # round in Python before writing\n",[233,1263,1264,1266,1269],{"class":235,"line":306},[233,1265,482],{"class":296},[233,1267,1268],{"class":276},"(cleaned)                                       ",[233,1270,1271],{"class":499},"# 0.0\n",[10,1273,1274,1275,1278,1279,1282,1283,32],{},"Round the stored values to the precision you display before writing — adding ",[14,1276,1277],{},"0.0"," turns Python's negative zero into a plain zero — or show one more decimal so ",[14,1280,1281],{},"(0.4)"," is honest. Rounding that matches Excel's rules is covered in ",[23,1284,1286],{"href":1285},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fmatch-excel-rounding-in-pandas\u002F","Match Excel Rounding in pandas",[34,1288,43,1293,43,1296,43,1299,43,1302,43,1310,43,1318,43,1322,43,1326,43,1330,43,1333,43,1338,43,1346,43,1351,43,1355,43,1360,43,1365,43,1368,43,1371,43,1375,43,1378,43,1381,43,1385,43,1388,43,1391,43,1394,43,1398,43,1401,43,1404,43,1408,43,1411,43,1413,43,1416,43,1420,43,1423,43,1426,43,1430],{"viewBox":1289,"role":37,"ariaLabelledBy":1290,"xmlns":41,"style":646},"4 0 752 238",[1291,1292],"ng-choose-t","ng-choose-d",[45,1294,1295],{"id":1291},"Choosing the negative format",[49,1297,1298],{"id":1292},"For general financial figures use red parentheses with the _) pad. For printed or colour-blind-friendly reports keep parentheses without relying on colour. For costs where negative is good, reverse the colours. When an exact brand colour is needed, use conditional formatting for colour and the number format for parentheses.",[53,1300],{"x":175,"y":56,"width":655,"height":1301,"fill":59},"238",[53,1303],{"x":1304,"y":63,"width":1305,"height":1306,"rx":1307,"fill":1308,"stroke":1309,"style":665},"187.1","385.8","75.5","12","#f0f4ff","var(--brand,#5b5cf0)",[667,1311,1313],{"transform":1312},"translate(368.0,29.0) scale(1.000)",[671,1314],{"d":1315,"fill":674,"stroke":1316,"style":1317},"M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z M12 9a3 3 0 1 0 .01 0z","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[74,1319,1321],{"x":214,"y":1306,"style":1320},"font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","What should a negative number communicate?",[235,1323],{"x1":214,"y1":1324,"x2":214,"y2":1325,"stroke":1309,"style":665},"91.5","111.5",[235,1327],{"x1":1328,"y1":1325,"x2":1329,"y2":1325,"stroke":1309,"style":665},"104.0","656.0",[235,1331],{"x1":1328,"y1":1325,"x2":1328,"y2":1332,"stroke":1309,"style":665},"157.5",[1334,1335],"polygon",{"points":1336,"fill":1337},"104.0,161.5 99.0,152.5 109.0,152.5","#5b5cf0",[53,1339],{"x":1340,"y":1341,"width":1342,"height":1343,"rx":1344,"fill":59,"stroke":67,"style":1345},"35.6","121.5","136.8","21.0","10","stroke-width:1.2px",[74,1347,1350],{"x":1328,"y":1348,"style":1349},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","bad, general figures",[53,1352],{"x":659,"y":1353,"width":1354,"height":103,"rx":1307,"fill":163,"stroke":164,"style":665},"163.5","168.0",[74,1356,1359],{"x":1328,"y":1357,"style":1358},"189.0","font-size:13.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","_);[Red](…)",[74,1361,1364],{"x":1328,"y":1362,"style":1363},"208.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","finance default",[235,1366],{"x1":1367,"y1":1325,"x2":1367,"y2":1332,"stroke":1309,"style":665},"288.0",[1334,1369],{"points":1370,"fill":1337},"288.0,161.5 283.0,152.5 293.0,152.5",[53,1372],{"x":1373,"y":1341,"width":1374,"height":1343,"rx":1344,"fill":59,"stroke":67,"style":1345},"212.4","151.1",[74,1376,1377],{"x":1367,"y":1348,"style":1349},"printed or colour-blind",[53,1379],{"x":1380,"y":1353,"width":1354,"height":103,"rx":1307,"fill":66,"stroke":67,"style":665},"204.0",[74,1382,1384],{"x":1367,"y":1357,"style":1383},"font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","parentheses only",[74,1386,1387],{"x":1367,"y":1362,"style":1363},"_);(…)",[235,1389],{"x1":1390,"y1":1325,"x2":1390,"y2":1332,"stroke":1309,"style":665},"472.0",[1334,1392],{"points":1393,"fill":1337},"472.0,161.5 467.0,152.5 477.0,152.5",[53,1395],{"x":1396,"y":1341,"width":1397,"height":1343,"rx":1344,"fill":59,"stroke":67,"style":1345},"425.8","92.5",[74,1399,1400],{"x":1390,"y":1348,"style":1349},"good (costs)",[53,1402],{"x":1403,"y":1353,"width":1354,"height":103,"rx":1307,"fill":722,"stroke":723,"style":665},"388.0",[74,1405,1407],{"x":1390,"y":1357,"style":1406},"font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","reversed colours",[74,1409,1410],{"x":1390,"y":1362,"style":1363},"[Red]…;[Color10](…)",[235,1412],{"x1":1329,"y1":1325,"x2":1329,"y2":1332,"stroke":1309,"style":665},[1334,1414],{"points":1415,"fill":1337},"656.0,161.5 651.0,152.5 661.0,152.5",[53,1417],{"x":1418,"y":1341,"width":1419,"height":1343,"rx":1344,"fill":59,"stroke":67,"style":1345},"586.8","138.4",[74,1421,1422],{"x":1329,"y":1348,"style":1349},"exact colour needed",[53,1424],{"x":1425,"y":1353,"width":1354,"height":103,"rx":1307,"fill":663,"stroke":664,"style":665},"572.0",[74,1427,1429],{"x":1329,"y":1357,"style":1428},"font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","conditional format",[74,1431,1432],{"x":1329,"y":1362,"style":1363},"+ parentheses",[219,1434,1436],{"id":1435},"step-6-from-pandas-with-xlsxwriter-and-back-again","Step 6 — From pandas with XlsxWriter, and back again",[10,1438,1439],{},"With XlsxWriter, create the format once and apply it to whole columns:",[224,1441,1443],{"className":263,"code":1442,"language":265,"meta":229,"style":229},"import pandas as pd\n\ndf = pd.DataFrame({\"Line\": [\"North\", \"South\", \"East\"], \"Variance\": [1234.5, -1234.5, 0]})\nwith pd.ExcelWriter(\"variance_pd.xlsx\", engine=\"xlsxwriter\") as writer:\n    df.to_excel(writer, sheet_name=\"Variance\", index=False)\n    fmt = writer.book.add_format({\"num_format\": '#,##0_);[Red](#,##0);\"–\"_)'})\n    writer.sheets[\"Variance\"].set_column(\"B:B\", 12, fmt)\n\ntext = pd.Series([\"1,235\", \"(1,235)\", \"–\", \"(48,200.50)\"])\nparsed = pd.to_numeric(text.str.replace(\",\", \"\").str.replace(r\"^\\((.*)\\)$\", r\"-\\1\", regex=True)\n                       .replace(\"–\", \"0\"), errors=\"coerce\")\nprint(parsed.tolist())                               # [1235.0, -1235.0, 0.0, -48200.5]\n",[14,1444,1445,1458,1462,1509,1537,1561,1581,1601,1605,1635,1708,1733],{"__ignoreMap":229},[233,1446,1447,1449,1452,1455],{"class":235,"line":236},[233,1448,280],{"class":272},[233,1450,1451],{"class":276}," pandas ",[233,1453,1454],{"class":272},"as",[233,1456,1457],{"class":276}," pd\n",[233,1459,1460],{"class":235,"line":286},[233,1461,290],{"emptyLinePlaceholder":289},[233,1463,1464,1467,1469,1472,1474,1477,1479,1481,1483,1485,1487,1490,1492,1494,1496,1498,1500,1502,1504,1506],{"class":235,"line":293},[233,1465,1466],{"class":276},"df ",[233,1468,317],{"class":272},[233,1470,1471],{"class":276}," pd.DataFrame({",[233,1473,340],{"class":243},[233,1475,1476],{"class":276},": [",[233,1478,367],{"class":243},[233,1480,343],{"class":276},[233,1482,377],{"class":243},[233,1484,343],{"class":276},[233,1486,389],{"class":243},[233,1488,1489],{"class":276},"], ",[233,1491,346],{"class":243},[233,1493,1476],{"class":276},[233,1495,138],{"class":296},[233,1497,343],{"class":276},[233,1499,382],{"class":272},[233,1501,138],{"class":296},[233,1503,343],{"class":276},[233,1505,56],{"class":296},[233,1507,1508],{"class":276},"]})\n",[233,1510,1511,1514,1517,1520,1522,1525,1527,1530,1532,1534],{"class":235,"line":306},[233,1512,1513],{"class":272},"with",[233,1515,1516],{"class":276}," pd.ExcelWriter(",[233,1518,1519],{"class":243},"\"variance_pd.xlsx\"",[233,1521,343],{"class":276},[233,1523,1524],{"class":427},"engine",[233,1526,317],{"class":272},[233,1528,1529],{"class":243},"\"xlsxwriter\"",[233,1531,1252],{"class":276},[233,1533,1454],{"class":272},[233,1535,1536],{"class":276}," writer:\n",[233,1538,1539,1542,1545,1547,1549,1551,1554,1556,1559],{"class":235,"line":311},[233,1540,1541],{"class":276},"    df.to_excel(writer, ",[233,1543,1544],{"class":427},"sheet_name",[233,1546,317],{"class":272},[233,1548,346],{"class":243},[233,1550,343],{"class":276},[233,1552,1553],{"class":427},"index",[233,1555,317],{"class":272},[233,1557,1558],{"class":296},"False",[233,1560,476],{"class":276},[233,1562,1563,1566,1568,1571,1574,1576,1578],{"class":235,"line":323},[233,1564,1565],{"class":276},"    fmt ",[233,1567,317],{"class":272},[233,1569,1570],{"class":276}," writer.book.add_format({",[233,1572,1573],{"class":243},"\"num_format\"",[233,1575,797],{"class":276},[233,1577,800],{"class":243},[233,1579,1580],{"class":276},"})\n",[233,1582,1583,1586,1588,1591,1594,1596,1598],{"class":235,"line":334},[233,1584,1585],{"class":276},"    writer.sheets[",[233,1587,346],{"class":243},[233,1589,1590],{"class":276},"].set_column(",[233,1592,1593],{"class":243},"\"B:B\"",[233,1595,343],{"class":276},[233,1597,1307],{"class":296},[233,1599,1600],{"class":276},", fmt)\n",[233,1602,1603],{"class":235,"line":352},[233,1604,290],{"emptyLinePlaceholder":289},[233,1606,1607,1610,1612,1615,1618,1620,1623,1625,1628,1630,1633],{"class":235,"line":408},[233,1608,1609],{"class":276},"text ",[233,1611,317],{"class":272},[233,1613,1614],{"class":276}," pd.Series([",[233,1616,1617],{"class":243},"\"1,235\"",[233,1619,343],{"class":276},[233,1621,1622],{"class":243},"\"(1,235)\"",[233,1624,343],{"class":276},[233,1626,1627],{"class":243},"\"–\"",[233,1629,343],{"class":276},[233,1631,1632],{"class":243},"\"(48,200.50)\"",[233,1634,349],{"class":276},[233,1636,1637,1640,1642,1645,1648,1650,1653,1656,1659,1661,1664,1668,1671,1673,1675,1678,1681,1683,1685,1687,1690,1694,1696,1698,1701,1703,1706],{"class":235,"line":414},[233,1638,1639],{"class":276},"parsed ",[233,1641,317],{"class":272},[233,1643,1644],{"class":276}," pd.to_numeric(text.str.replace(",[233,1646,1647],{"class":243},"\",\"",[233,1649,343],{"class":276},[233,1651,1652],{"class":243},"\"\"",[233,1654,1655],{"class":276},").str.replace(",[233,1657,1658],{"class":272},"r",[233,1660,580],{"class":243},[233,1662,1663],{"class":296},"^",[233,1665,1667],{"class":1666},"s_b0D","\\(",[233,1669,1670],{"class":296},"(.",[233,1672,860],{"class":272},[233,1674,535],{"class":296},[233,1676,1677],{"class":1666},"\\)",[233,1679,1680],{"class":296},"$",[233,1682,580],{"class":243},[233,1684,343],{"class":276},[233,1686,1658],{"class":272},[233,1688,1689],{"class":243},"\"-",[233,1691,1693],{"class":1692},"sx1sP","\\1",[233,1695,580],{"class":243},[233,1697,343],{"class":276},[233,1699,1700],{"class":427},"regex",[233,1702,317],{"class":272},[233,1704,1705],{"class":296},"True",[233,1707,476],{"class":276},[233,1709,1710,1713,1715,1717,1720,1723,1726,1728,1731],{"class":235,"line":456},[233,1711,1712],{"class":276},"                       .replace(",[233,1714,1627],{"class":243},[233,1716,343],{"class":276},[233,1718,1719],{"class":243},"\"0\"",[233,1721,1722],{"class":276},"), ",[233,1724,1725],{"class":427},"errors",[233,1727,317],{"class":272},[233,1729,1730],{"class":243},"\"coerce\"",[233,1732,476],{"class":276},[233,1734,1735,1737,1740],{"class":235,"line":467},[233,1736,482],{"class":296},[233,1738,1739],{"class":276},"(parsed.tolist())                               ",[233,1741,1742],{"class":499},"# [1235.0, -1235.0, 0.0, -48200.5]\n",[10,1744,1745,1746,1748,1749,32],{},"The second half handles the reverse problem: exports and PDFs converted to Excel often contain the displayed text, ",[14,1747,16],{},", rather than the number. Strip separators, turn surrounding parentheses into a leading minus and convert. More on text that should be numbers in ",[23,1750,1752],{"href":1751},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fconvert-excel-text-columns-to-numbers-with-pandas\u002F","Convert Excel Text Columns to Numbers with pandas",[219,1754,1756],{"id":1755},"step-7-one-named-style-for-the-whole-report","Step 7 — One named style for the whole report",[10,1758,1759],{},"A report with a dozen variance columns should not repeat the format string a dozen times. Register it once as a named style; every cell that uses the style shares the definition, and it appears in Excel's Cell Styles gallery so readers can apply it to their own additions:",[224,1761,1763],{"className":263,"code":1762,"language":265,"meta":229,"style":229},"from openpyxl.styles import Alignment, NamedStyle\n\nvariance_style = NamedStyle(name=\"Variance\", number_format='#,##0_);[Red](#,##0);\"–\"_)',\n                            alignment=Alignment(horizontal=\"right\"))\nwb.add_named_style(variance_style)\nfor (cell,) in ws.iter_rows(min_row=2, max_row=5, min_col=2, max_col=2):\n    cell.style = \"Variance\"\nwb.save(\"variance.xlsx\")\nprint(ws[\"B3\"].style, ws[\"B3\"].number_format)       # Variance #,##0_);[Red](#,##0);\"–\"_)\n",[14,1764,1765,1777,1781,1809,1830,1835,1878,1888,1896],{"__ignoreMap":229},[233,1766,1767,1769,1772,1774],{"class":235,"line":236},[233,1768,273],{"class":272},[233,1770,1771],{"class":276}," openpyxl.styles ",[233,1773,280],{"class":272},[233,1775,1776],{"class":276}," Alignment, NamedStyle\n",[233,1778,1779],{"class":235,"line":286},[233,1780,290],{"emptyLinePlaceholder":289},[233,1782,1783,1786,1788,1791,1794,1796,1798,1800,1803,1805,1807],{"class":235,"line":293},[233,1784,1785],{"class":276},"variance_style ",[233,1787,317],{"class":272},[233,1789,1790],{"class":276}," NamedStyle(",[233,1792,1793],{"class":427},"name",[233,1795,317],{"class":272},[233,1797,346],{"class":243},[233,1799,343],{"class":276},[233,1801,1802],{"class":427},"number_format",[233,1804,317],{"class":272},[233,1806,800],{"class":243},[233,1808,803],{"class":276},[233,1810,1811,1814,1816,1819,1822,1824,1827],{"class":235,"line":306},[233,1812,1813],{"class":427},"                            alignment",[233,1815,317],{"class":272},[233,1817,1818],{"class":276},"Alignment(",[233,1820,1821],{"class":427},"horizontal",[233,1823,317],{"class":272},[233,1825,1826],{"class":243},"\"right\"",[233,1828,1829],{"class":276},"))\n",[233,1831,1832],{"class":235,"line":311},[233,1833,1834],{"class":276},"wb.add_named_style(variance_style)\n",[233,1836,1837,1839,1841,1843,1845,1847,1849,1851,1853,1856,1858,1860,1862,1864,1866,1868,1870,1872,1874,1876],{"class":235,"line":323},[233,1838,355],{"class":272},[233,1840,419],{"class":276},[233,1842,361],{"class":272},[233,1844,424],{"class":276},[233,1846,428],{"class":427},[233,1848,317],{"class":272},[233,1850,127],{"class":296},[233,1852,343],{"class":276},[233,1854,1855],{"class":427},"max_row",[233,1857,317],{"class":272},[233,1859,196],{"class":296},[233,1861,343],{"class":276},[233,1863,437],{"class":427},[233,1865,317],{"class":272},[233,1867,127],{"class":296},[233,1869,343],{"class":276},[233,1871,446],{"class":427},[233,1873,317],{"class":272},[233,1875,127],{"class":296},[233,1877,453],{"class":276},[233,1879,1880,1883,1885],{"class":235,"line":334},[233,1881,1882],{"class":276},"    cell.style ",[233,1884,317],{"class":272},[233,1886,1887],{"class":243}," \"Variance\"\n",[233,1889,1890,1892,1894],{"class":235,"line":352},[233,1891,470],{"class":276},[233,1893,473],{"class":243},[233,1895,476],{"class":276},[233,1897,1898,1900,1902,1904,1907,1909,1911],{"class":235,"line":408},[233,1899,482],{"class":296},[233,1901,485],{"class":276},[233,1903,488],{"class":243},[233,1905,1906],{"class":276},"].style, ws[",[233,1908,488],{"class":243},[233,1910,496],{"class":276},[233,1912,1913],{"class":499},"# Variance #,##0_);[Red](#,##0);\"–\"_)\n",[10,1915,1916,1917,32],{},"Changing the variance convention later — adding a decimal, switching to accounting layout — is then a one-line edit in the script that builds the style. Named styles and the alternative of copying styles between cells are compared in ",[23,1918,1920],{"href":1919},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl\u002F","Copy Cell Styles from One Cell to Another with openpyxl",[219,1922,1924],{"id":1923},"common-pitfalls","Common pitfalls",[1926,1927,1928,1944,1950,1956,1962],"ul",{},[1929,1930,1931,1935,1936,1939,1940,1943],"li",{},[1932,1933,1934],"strong",{},"A minus sign inside the negative section."," ",[14,1937,1938],{},"#,##0;[Red](-#,##0)"," shows ",[14,1941,1942],{},"(-1,235)"," — the section already implies the sign.",[1929,1945,1946,1949],{},[1932,1947,1948],{},"Formats on text."," A number stored as text ignores its number format entirely. Write real numbers.",[1929,1951,1952,1955],{},[1932,1953,1954],{},"Totals that change sign."," A total row using the same format flips to red parentheses when the sum goes negative — which is correct, but readers scanning for red may take a small negative total for an error. Label total rows clearly.",[1929,1957,1958,1961],{},[1932,1959,1960],{},"Different conventions per team."," Some teams expect a leading minus, others parentheses. Agree the convention for a report pack once and apply it through one named style.",[1929,1963,1964,1967],{},[1932,1965,1966],{},"Relying on colour alone."," Red and green are indistinguishable for many readers and vanish in print. Parentheses carry the meaning; colour reinforces it.",[219,1969,1971],{"id":1970},"conclusion","Conclusion",[10,1973,1974,1975,1977,1978,1980,1981,1983,1984,1986],{},"Red parenthesised negatives are a number format, not a change to the data: ",[14,1976,735],{}," with ",[14,1979,528],{}," padding the positives so every digit lines up. Add a dash for zero, put currency symbols inside the format, reverse the colours where negative is good, and round values before writing so small negatives do not show as ",[14,1982,1193],{},". When text like ",[14,1985,16],{}," arrives from elsewhere, convert it back to a signed number before calculating.",[219,1988,1990],{"id":1989},"frequently-asked-questions","Frequently asked questions",[10,1992,1993,1996,1997,2000,2001,2003],{},[1932,1994,1995],{},"What number format shows negatives in red parentheses?","\nUse a two-section number format: #,##0_); for positives, then ",[233,1998,1999],{},"Red"," followed by (#,##0) for negatives, written together with no space. ",[233,2002,1999],{}," colours the text and the parentheses replace the minus sign; the _) in the first section leaves room so positives line up with negatives. Add .00 in both sections for two decimals.",[10,2005,2006,2009],{},[1932,2007,2008],{},"What does _) do in a number format?","\nIt adds a space as wide as a closing parenthesis after positive numbers, so positives line up with negatives that end in \")\". Without it, the digits of positive and negative numbers are offset by one character.",[10,2011,2012,2015],{},[1932,2013,2014],{},"Why does a small negative number show as (0)?","\nA value such as -0.4 is negative, so it uses the negative section, and rounding to whole numbers displays 0 inside parentheses. Round the stored values before writing, or show a decimal.",[10,2017,2018,2021],{},[1932,2019,2020],{},"How do I turn \"(1,234)\" text back into a number in Python?","\nStrip thousands separators, replace the surrounding parentheses with a leading minus sign, and convert with pd.to_numeric. A regular expression such as ^((.*))$ captures the inner value.",[219,2023,2025],{"id":2024},"related","Related",[1926,2027,2028,2034,2041,2048],{},[1929,2029,2030,2031,2033],{},"Up one level: ",[23,2032,26],{"href":25}," — number and date formatting.",[1929,2035,2036,2040],{},[23,2037,2039],{"href":2038},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel\u002F","Format Numbers in Thousands and Millions in Excel with Python"," — scaled figures with the same negative styles.",[1929,2042,2043,2047],{},[23,2044,2046],{"href":2045},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-excel-cells-as-currency-with-python\u002F","Format Excel Cells as Currency with Python"," — currency symbols and placement.",[1929,2049,2050,2054],{},[23,2051,2053],{"href":2052},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fread-cell-values-as-displayed-in-excel\u002F","Read Cell Values as Displayed in Excel with Python"," — checking what readers see.",[2056,2057,2058],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s_b0D, html code.shiki .s_b0D{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold}html pre.shiki code .sx1sP, html code.shiki .sx1sP{--shiki-default:#22863A;--shiki-dark:#72F088}",{"title":229,"searchDepth":286,"depth":286,"links":2060},[2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072],{"id":221,"depth":286,"text":222},{"id":256,"depth":286,"text":257},{"id":522,"depth":286,"text":523},{"id":767,"depth":286,"text":768},{"id":999,"depth":286,"text":1000},{"id":1186,"depth":286,"text":1187},{"id":1435,"depth":286,"text":1436},{"id":1755,"depth":286,"text":1756},{"id":1923,"depth":286,"text":1924},{"id":1970,"depth":286,"text":1971},{"id":1989,"depth":286,"text":1990},{"id":2024,"depth":286,"text":2025},"2026-09-23","Format negatives the way finance readers expect — (1,235) in red, aligned with the positives above them — from Python with openpyxl or XlsxWriter. Covers the _) alignment trick, zero as a dash, currency and accounting layouts, reversed colours for costs, the \"(0)\" trap and parsing parentheses back into numbers.","md",[2077,2079,2081,2083],{"q":1995,"a":2078},"Use a two-section number format: #,##0_); for positives, then [Red] followed by (#,##0) for negatives, written together with no space. [Red] colours the text and the parentheses replace the minus sign; the _) in the first section leaves room so positives line up with negatives. Add .00 in both sections for two decimals.",{"q":2008,"a":2080},"It adds a space as wide as a closing parenthesis after positive numbers, so positives line up with negatives that end in \")\". Without it, the digits of positive and negative numbers are offset by one character.",{"q":2014,"a":2082},"A value such as -0.4 is negative, so it uses the negative section, and rounding to whole numbers displays 0 inside parentheses. Round the stored values before writing, or show a decimal.",{"q":2020,"a":2084},"Strip thousands separators, replace the surrounding parentheses with a leading minus sign, and convert with pd.to_numeric. A regular expression such as ^\\((.*)\\)$ captures the inner value.","show negative numbers in red with parentheses in excel",null,{"breadcrumb":2088},[2089,2092,2095],{"name":2090,"item":2091},"Home","\u002F",{"name":2093,"item":2094},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":26,"item":25},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-negative-numbers-in-red-with-parentheses",{"title":2098,"description":2099},"Show Negative Numbers in Red with Parentheses in Excel (Python)","Excel number formats for red parenthesised negatives from Python — #,##0_);[Red](#,##0), built-in formats 37–40, accounting alignment, zero dashes, green-for-good cost columns, values that display as (0), XlsxWriter formats and reading \"(1,234)\" back as -1234.","show-negative-numbers-in-red-with-parentheses","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-negative-numbers-in-red-with-parentheses\u002Findex",[2103,2104],"number-formats","openpyxl","how-to","Wks80za8Mr0Z1HGfnpuiZ-4NtI1auFIlKOPQYT6eXQ0",[2108,2111],{"title":2053,"path":2109,"stem":2110,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fread-cell-values-as-displayed-in-excel","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fread-cell-values-as-displayed-in-excel\u002Findex",{"title":2112,"path":2113,"stem":2114,"children":-1},"Show Units Like kg or Hours with Number Formats","\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-units-like-kg-or-hours-with-number-formats","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-units-like-kg-or-hours-with-number-formats\u002Findex",[2116,2118],{"path":2117,"title":26},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel",{"path":2119,"title":2093},"\u002Fformatting-and-charting-excel-reports-with-python",[],[2122,2125,2128,2131,2133,2136],{"path":2123,"title":2124,"kind":2105},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fconvert-currency-strings-to-numbers-with-pandas","Convert Currency Strings Like \"$1,234.56\" and \"(500)\" to Numbers with pandas",{"path":2126,"title":2127,"kind":2105},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fconvert-percentage-strings-to-numbers-with-pandas","Convert Percentage Strings Like \"12.5%\" to Numbers with pandas",{"path":2129,"title":2130,"kind":2105},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fexcel-text-function-equivalent-in-pandas","Excel TEXT Function Equivalent in pandas",{"path":2132,"title":1286,"kind":2105},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fmatch-excel-rounding-in-pandas",{"path":2134,"title":2135,"kind":2105},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-excel-time-values-and-durations","Convert Excel Time Values and Durations in Python",{"path":2137,"title":2138,"kind":2105},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-variance-arrows-and-trend-indicators-to-a-dashboard","Add Variance Arrows and Trend Indicators to a Dashboard",1790972107206]