[{"data":1,"prerenderedAt":1874},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel":1841,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel":1850,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel":1855,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel":1856},{"id":4,"title":5,"body":6,"dateModified":1807,"datePublished":1807,"description":1808,"extension":1809,"faq":1810,"keyword":1819,"kind":1820,"meta":1821,"navigation":251,"path":1830,"seo":1831,"slug":1834,"stem":1835,"topics":1836,"type":1839,"__hash__":1840},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel\u002Findex.md","Format Numbers in Thousands and Millions in Excel with Python",{"type":7,"value":8,"toc":1793},"minimark",[9,24,179,184,216,220,223,465,476,480,490,627,630,769,773,776,866,875,879,882,949,962,966,972,1154,1161,1300,1304,1311,1538,1545,1549,1552,1669,1676,1680,1713,1717,1720,1724,1730,1736,1750,1756,1760,1789],[10,11,12,13,18,19,23],"p",{},"A finance pack with revenue written as 1,234,567.00 and 987,654.00 is hard to scan; the same figures as 1.2M and 1.0M, or as 1,235 and 988 under a heading \"€ thousands\", are read in a glance. Excel can do this purely in the display — the cell keeps 1,234,567 for every formula — through a detail of number formats: commas after the last digit scale the value. This guide, part of ",[14,15,17],"a",{"href":16},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002F","Applying Number and Date Formats in Excel",", applies thousands and millions formats from Python and covers the places they surprise people: negatives, small values and totals. The general format-code syntax is covered in ",[14,20,22],{"href":21},"\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",".",[25,26,34,35,34,39,34,43,34,51,34,59,34,66,34,73,34,76,34,80,34,83,34,87,34,92,34,98,34,100,34,105,34,107,34,110,34,112,34,114,34,117,34,121,34,123,34,127,34,129,34,132,34,134,34,136,34,139,34,143,34,145,34,149,34,151,34,154,34,156,34,158,34,161,34,165,34,167,34,171,34,173,34,175,34,177],"svg",{"viewBox":27,"role":28,"ariaLabelledBy":29,"xmlns":32,"style":33},"4 0 752 208","img",[30,31],"km-codes-t","km-codes-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  ",[36,37,38],"title",{"id":30},"The same values under three formats",[40,41,42],"desc",{"id":31},"With the format",[44,45],"rect",{"x":46,"y":47,"width":48,"height":49,"fill":50},"4","0","752","208","#ffffff",[44,52],{"x":53,"y":54,"width":55,"height":56,"rx":47,"fill":50,"stroke":57,"style":58},"20.0","16.0","92.4","40.0","var(--line,#cdd5e6)","stroke-width:1px",[44,60],{"x":61,"y":54,"width":62,"height":56,"rx":47,"fill":63,"stroke":64,"style":65},"112.4","209.2","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:1.2px",[67,68,72],"text",{"x":69,"y":70,"style":71},"217.0","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","#,##0,\"K\"",[44,74],{"x":75,"y":54,"width":62,"height":56,"rx":47,"fill":63,"stroke":64,"style":65},"321.6",[67,77,79],{"x":78,"y":70,"style":71},"426.2","#,##0.0,,\"M\"",[44,81],{"x":82,"y":54,"width":62,"height":56,"rx":47,"fill":63,"stroke":64,"style":65},"530.8",[67,84,86],{"x":85,"y":70,"style":71},"635.4","auto K\u002FM",[44,88],{"x":53,"y":89,"width":55,"height":90,"rx":47,"fill":91,"stroke":57,"style":58},"56.0","34.0","#e7ebef",[67,93,97],{"x":94,"y":95,"style":96},"32.0","78.0","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start","1,234,567",[44,99],{"x":61,"y":89,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,101,104],{"x":69,"y":102,"style":103},"77.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","1,235K",[44,106],{"x":75,"y":89,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,108,109],{"x":78,"y":102,"style":103},"1.2M",[44,111],{"x":82,"y":89,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,113,109],{"x":85,"y":102,"style":103},[44,115],{"x":53,"y":116,"width":55,"height":90,"rx":47,"fill":91,"stroke":57,"style":58},"90.0",[67,118,120],{"x":94,"y":119,"style":96},"112.0","987,654",[44,122],{"x":61,"y":116,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,124,126],{"x":69,"y":125,"style":103},"111.0","988K",[44,128],{"x":75,"y":116,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,130,131],{"x":78,"y":125,"style":103},"1.0M",[44,133],{"x":82,"y":116,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,135,126],{"x":85,"y":125,"style":103},[44,137],{"x":53,"y":138,"width":55,"height":90,"rx":47,"fill":91,"stroke":57,"style":58},"124.0",[67,140,142],{"x":94,"y":141,"style":96},"146.0","45,210",[44,144],{"x":61,"y":138,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,146,148],{"x":69,"y":147,"style":103},"145.0","45K",[44,150],{"x":75,"y":138,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,152,153],{"x":78,"y":147,"style":103},"0.0M",[44,155],{"x":82,"y":138,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,157,148],{"x":85,"y":147,"style":103},[44,159],{"x":53,"y":160,"width":55,"height":90,"rx":47,"fill":91,"stroke":57,"style":58},"158.0",[67,162,164],{"x":94,"y":163,"style":96},"180.0","812",[44,166],{"x":61,"y":160,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,168,170],{"x":69,"y":169,"style":103},"179.0","1K",[44,172],{"x":75,"y":160,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,174,153],{"x":78,"y":169,"style":103},[44,176],{"x":82,"y":160,"width":62,"height":90,"rx":47,"fill":50,"stroke":57,"style":58},[67,178,164],{"x":85,"y":169,"style":103},[180,181,183],"h2",{"id":182},"prerequisites","Prerequisites",[185,186,191],"pre",{"className":187,"code":188,"language":189,"meta":190,"style":190},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install openpyxl pandas xlsxwriter\n","bash","",[192,193,194],"code",{"__ignoreMap":190},[195,196,199,203,207,210,213],"span",{"class":197,"line":198},"line",1,[195,200,202],{"class":201},"sMTad","pip",[195,204,206],{"class":205},"srMev"," install",[195,208,209],{"class":205}," openpyxl",[195,211,212],{"class":205}," pandas",[195,214,215],{"class":205}," xlsxwriter\n",[180,217,219],{"id":218},"step-1-scale-with-trailing-commas","Step 1 — Scale with trailing commas",[10,221,222],{},"A comma between digit placeholders is the thousands separator; a comma after the last placeholder divides the display by 1,000. Two commas divide by a million:",[185,224,228],{"className":225,"code":226,"language":227,"meta":190,"style":190},"language-python shiki shiki-themes github-light github-dark-high-contrast","from openpyxl import Workbook\n\nvalues = [1234567, 987654, 45210, 812, -1234567]\nwb = Workbook()\nws = wb.active\nws.append([\"Revenue\", \"In K\", \"In M\"])\nfor v in values:\n    ws.append([v, v, v])\nfor row in ws.iter_rows(min_row=2):\n    row[0].number_format = \"#,##0\"\n    row[1].number_format = '#,##0,\"K\"'\n    row[2].number_format = '#,##0.0,,\"M\"'\nwb.save(\"scaled.xlsx\")\nprint(ws[\"B2\"].value, ws[\"B2\"].number_format)       # 1234567 #,##0,\"K\"\n","python",[192,229,230,246,253,294,305,316,338,353,359,384,400,415,429,441],{"__ignoreMap":190},[195,231,232,236,240,243],{"class":197,"line":198},[195,233,235],{"class":234},"s-kum","from",[195,237,239],{"class":238},"skGVy"," openpyxl ",[195,241,242],{"class":234},"import",[195,244,245],{"class":238}," Workbook\n",[195,247,249],{"class":197,"line":248},2,[195,250,252],{"emptyLinePlaceholder":251},true,"\n",[195,254,256,259,262,265,269,272,275,277,280,282,284,286,289,291],{"class":197,"line":255},3,[195,257,258],{"class":238},"values ",[195,260,261],{"class":234},"=",[195,263,264],{"class":238}," [",[195,266,268],{"class":267},"sP0c6","1234567",[195,270,271],{"class":238},", ",[195,273,274],{"class":267},"987654",[195,276,271],{"class":238},[195,278,279],{"class":267},"45210",[195,281,271],{"class":238},[195,283,164],{"class":267},[195,285,271],{"class":238},[195,287,288],{"class":234},"-",[195,290,268],{"class":267},[195,292,293],{"class":238},"]\n",[195,295,297,300,302],{"class":197,"line":296},4,[195,298,299],{"class":238},"wb ",[195,301,261],{"class":234},[195,303,304],{"class":238}," Workbook()\n",[195,306,308,311,313],{"class":197,"line":307},5,[195,309,310],{"class":238},"ws ",[195,312,261],{"class":234},[195,314,315],{"class":238}," wb.active\n",[195,317,319,322,325,327,330,332,335],{"class":197,"line":318},6,[195,320,321],{"class":238},"ws.append([",[195,323,324],{"class":205},"\"Revenue\"",[195,326,271],{"class":238},[195,328,329],{"class":205},"\"In K\"",[195,331,271],{"class":238},[195,333,334],{"class":205},"\"In M\"",[195,336,337],{"class":238},"])\n",[195,339,341,344,347,350],{"class":197,"line":340},7,[195,342,343],{"class":234},"for",[195,345,346],{"class":238}," v ",[195,348,349],{"class":234},"in",[195,351,352],{"class":238}," values:\n",[195,354,356],{"class":197,"line":355},8,[195,357,358],{"class":238},"    ws.append([v, v, v])\n",[195,360,362,364,367,369,372,376,378,381],{"class":197,"line":361},9,[195,363,343],{"class":234},[195,365,366],{"class":238}," row ",[195,368,349],{"class":234},[195,370,371],{"class":238}," ws.iter_rows(",[195,373,375],{"class":374},"sa561","min_row",[195,377,261],{"class":234},[195,379,380],{"class":267},"2",[195,382,383],{"class":238},"):\n",[195,385,387,390,392,395,397],{"class":197,"line":386},10,[195,388,389],{"class":238},"    row[",[195,391,47],{"class":267},[195,393,394],{"class":238},"].number_format ",[195,396,261],{"class":234},[195,398,399],{"class":205}," \"#,##0\"\n",[195,401,403,405,408,410,412],{"class":197,"line":402},11,[195,404,389],{"class":238},[195,406,407],{"class":267},"1",[195,409,394],{"class":238},[195,411,261],{"class":234},[195,413,414],{"class":205}," '#,##0,\"K\"'\n",[195,416,418,420,422,424,426],{"class":197,"line":417},12,[195,419,389],{"class":238},[195,421,380],{"class":267},[195,423,394],{"class":238},[195,425,261],{"class":234},[195,427,428],{"class":205}," '#,##0.0,,\"M\"'\n",[195,430,432,435,438],{"class":197,"line":431},13,[195,433,434],{"class":238},"wb.save(",[195,436,437],{"class":205},"\"scaled.xlsx\"",[195,439,440],{"class":238},")\n",[195,442,444,447,450,453,456,458,461],{"class":197,"line":443},14,[195,445,446],{"class":267},"print",[195,448,449],{"class":238},"(ws[",[195,451,452],{"class":205},"\"B2\"",[195,454,455],{"class":238},"].value, ws[",[195,457,452],{"class":205},[195,459,460],{"class":238},"].number_format)       ",[195,462,464],{"class":463},"s-wDw","# 1234567 #,##0,\"K\"\n",[10,466,467,468,471,472,475],{},"Rendered, row 2 reads 1,234,567 — 1,235K — 1.2M, and the stored value in every cell is still 1234567. The text after the number must be quoted; a bare ",[192,469,470],{},"K"," would be read as part of the code. Because the value is untouched, ",[192,473,474],{},"SUM",", charts and pivot tables all use the full figure.",[180,477,479],{"id":478},"step-2-put-the-unit-in-the-header-or-in-the-cell","Step 2 — Put the unit in the header or in the cell",[10,481,482,483,485,486,489],{},"There are two conventions, and a report should use one. A suffix in every cell — ",[192,484,109],{}," — is self-explanatory when figures are quoted out of context. A unit in the header — \"Revenue (€ thousands)\" with plain ",[192,487,488],{},"#,##0,"," in the cells — is the finance convention: cleaner columns, and the unit is stated once:",[185,491,493],{"className":225,"code":492,"language":227,"meta":190,"style":190},"ws2 = wb.create_sheet(\"Pack\")\nws2.append([\"Region\", \"Revenue (€ thousands)\"])\nfor region, value in [(\"North\", 1234567), (\"South\", 987654), (\"East\", 45210)]:\n    ws2.append([region, value])\nfor (cell,) in ws2.iter_rows(min_row=2, min_col=2, max_col=2):\n    cell.number_format = \"#,##0,\"\nwb.save(\"scaled.xlsx\")\n",[192,494,495,510,525,566,571,609,619],{"__ignoreMap":190},[195,496,497,500,502,505,508],{"class":197,"line":198},[195,498,499],{"class":238},"ws2 ",[195,501,261],{"class":234},[195,503,504],{"class":238}," wb.create_sheet(",[195,506,507],{"class":205},"\"Pack\"",[195,509,440],{"class":238},[195,511,512,515,518,520,523],{"class":197,"line":248},[195,513,514],{"class":238},"ws2.append([",[195,516,517],{"class":205},"\"Region\"",[195,519,271],{"class":238},[195,521,522],{"class":205},"\"Revenue (€ thousands)\"",[195,524,337],{"class":238},[195,526,527,529,532,534,537,540,542,544,547,550,552,554,556,559,561,563],{"class":197,"line":255},[195,528,343],{"class":234},[195,530,531],{"class":238}," region, value ",[195,533,349],{"class":234},[195,535,536],{"class":238}," [(",[195,538,539],{"class":205},"\"North\"",[195,541,271],{"class":238},[195,543,268],{"class":267},[195,545,546],{"class":238},"), (",[195,548,549],{"class":205},"\"South\"",[195,551,271],{"class":238},[195,553,274],{"class":267},[195,555,546],{"class":238},[195,557,558],{"class":205},"\"East\"",[195,560,271],{"class":238},[195,562,279],{"class":267},[195,564,565],{"class":238},")]:\n",[195,567,568],{"class":197,"line":296},[195,569,570],{"class":238},"    ws2.append([region, value])\n",[195,572,573,575,578,580,583,585,587,589,591,594,596,598,600,603,605,607],{"class":197,"line":307},[195,574,343],{"class":234},[195,576,577],{"class":238}," (cell,) ",[195,579,349],{"class":234},[195,581,582],{"class":238}," ws2.iter_rows(",[195,584,375],{"class":374},[195,586,261],{"class":234},[195,588,380],{"class":267},[195,590,271],{"class":238},[195,592,593],{"class":374},"min_col",[195,595,261],{"class":234},[195,597,380],{"class":267},[195,599,271],{"class":238},[195,601,602],{"class":374},"max_col",[195,604,261],{"class":234},[195,606,380],{"class":267},[195,608,383],{"class":238},[195,610,611,614,616],{"class":197,"line":318},[195,612,613],{"class":238},"    cell.number_format ",[195,615,261],{"class":234},[195,617,618],{"class":205}," \"#,##0,\"\n",[195,620,621,623,625],{"class":197,"line":340},[195,622,434],{"class":238},[195,624,437],{"class":205},[195,626,440],{"class":238},[10,628,629],{},"Whichever you choose, keep it consistent across sheets: a pack where one table is in thousands and the next in millions, both unlabelled, invites a factor-of-a-thousand misreading.",[25,631,34,636,34,639,34,642,34,645,34,651,34,662,34,667,34,672,34,677,34,685,34,689,34,694,34,698,34,705,34,709,34,716,34,720,34,727,34,732,34,736,34,740,34,745,34,748,34,753,34,756,34,761,34,764],{"viewBox":632,"role":28,"ariaLabelledBy":633,"xmlns":32,"style":33},"4 0 752 233",[634,635],"km-unit-t","km-unit-d",[36,637,638],{"id":634},"Unit in every cell or unit in the header",[40,640,641],{"id":635},"A suffix in every cell, such as 1.2M, is clear when a single figure is copied elsewhere but adds clutter to dense tables. A unit in the header, such as Revenue in euro thousands with plain scaled numbers, keeps tables clean and is the usual finance convention, but a copied number loses its unit.",[44,643],{"x":46,"y":47,"width":48,"height":644,"fill":50},"233",[44,646],{"x":53,"y":54,"width":647,"height":648,"rx":649,"fill":63,"stroke":64,"style":650},"351.0","201.0","14","stroke-width:2px",[652,653,655],"g",{"transform":654},"translate(182.5,29.0) scale(1.083)",[656,657],"path",{"d":658,"fill":659,"stroke":660,"style":661},"M5 9h14 M4 15h14 M10 4l-2 16 M16 4l-2 16","none","var(--brand-strong,#4338ca)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[67,663,666],{"x":664,"y":95,"style":665},"195.5","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Suffix: 1.2M",[197,668],{"x1":669,"y1":670,"x2":671,"y2":670,"stroke":64,"style":58},"36.0","91.0","355.0",[67,673,676],{"x":674,"y":125,"style":675},"60.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","each figure explains itself",[652,678,680],{"transform":679},"translate(38.5,99.5) scale(0.625)",[656,681],{"d":682,"fill":659,"stroke":683,"style":684},"M5 12.5l4.5 4.5L19 7","var(--teal,#0f9488)","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[67,686,688],{"x":674,"y":687,"style":675},"137.0","good for dashboards and cards",[652,690,692],{"transform":691},"translate(38.5,125.5) scale(0.625)",[656,693],{"d":682,"fill":659,"stroke":683,"style":684},[67,695,697],{"x":674,"y":696,"style":675},"163.0","clutter in dense tables",[652,699,701],{"transform":700},"translate(38.5,151.5) scale(0.625)",[656,702],{"d":703,"fill":659,"stroke":704,"style":684},"M6 6l12 12 M18 6L6 18","var(--accent,#f43f8f)",[67,706,708],{"x":674,"y":707,"style":675},"189.0","one unit per cell",[652,710,712],{"transform":711},"translate(38.5,177.5) scale(0.625)",[656,713],{"d":714,"fill":659,"stroke":715,"style":684},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","var(--gold,#b4740a)",[44,717],{"x":718,"y":54,"width":647,"height":648,"rx":649,"fill":719,"stroke":683,"style":650},"389.0","#d9f4f1",[652,721,723],{"transform":722},"translate(551.5,29.0) scale(1.083)",[656,724],{"d":725,"fill":659,"stroke":726,"style":661},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14","var(--teal-ink,#0b6157)",[67,728,731],{"x":729,"y":95,"style":730},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Header: (€ thousands)",[197,733],{"x1":734,"y1":670,"x2":735,"y2":670,"stroke":683,"style":58},"405.0","724.0",[67,737,739],{"x":738,"y":125,"style":675},"429.0","clean columns",[652,741,743],{"transform":742},"translate(407.5,99.5) scale(0.625)",[656,744],{"d":682,"fill":659,"stroke":683,"style":684},[67,746,747],{"x":738,"y":687,"style":675},"finance convention",[652,749,751],{"transform":750},"translate(407.5,125.5) scale(0.625)",[656,752],{"d":682,"fill":659,"stroke":683,"style":684},[67,754,755],{"x":738,"y":696,"style":675},"copied figures lose the unit",[652,757,759],{"transform":758},"translate(407.5,151.5) scale(0.625)",[656,760],{"d":703,"fill":659,"stroke":704,"style":684},[67,762,763],{"x":738,"y":707,"style":675},"label every table",[652,765,767],{"transform":766},"translate(407.5,177.5) scale(0.625)",[656,768],{"d":714,"fill":659,"stroke":715,"style":684},[180,770,772],{"id":771},"step-3-auto-switching-between-k-and-m","Step 3 — Auto-switching between K and M",[10,774,775],{},"Number formats can have conditions in square brackets, which lets one format show large values in millions and smaller ones in thousands:",[185,777,779],{"className":225,"code":778,"language":227,"meta":190,"style":190},"AUTO = '[>=1000000]#,##0.0,,\"M\";[>=1000]#,##0,\"K\";0'\nws3 = wb.create_sheet(\"Auto\")\nfor v in [1234567, 987654, 45210, 812]:\n    ws3.append([v])\nfor (cell,) in ws3.iter_rows():\n    cell.number_format = AUTO\nwb.save(\"scaled.xlsx\")\n",[192,780,781,792,806,833,838,849,858],{"__ignoreMap":190},[195,782,783,786,789],{"class":197,"line":198},[195,784,785],{"class":267},"AUTO",[195,787,788],{"class":234}," =",[195,790,791],{"class":205}," '[>=1000000]#,##0.0,,\"M\";[>=1000]#,##0,\"K\";0'\n",[195,793,794,797,799,801,804],{"class":197,"line":248},[195,795,796],{"class":238},"ws3 ",[195,798,261],{"class":234},[195,800,504],{"class":238},[195,802,803],{"class":205},"\"Auto\"",[195,805,440],{"class":238},[195,807,808,810,812,814,816,818,820,822,824,826,828,830],{"class":197,"line":255},[195,809,343],{"class":234},[195,811,346],{"class":238},[195,813,349],{"class":234},[195,815,264],{"class":238},[195,817,268],{"class":267},[195,819,271],{"class":238},[195,821,274],{"class":267},[195,823,271],{"class":238},[195,825,279],{"class":267},[195,827,271],{"class":238},[195,829,164],{"class":267},[195,831,832],{"class":238},"]:\n",[195,834,835],{"class":197,"line":296},[195,836,837],{"class":238},"    ws3.append([v])\n",[195,839,840,842,844,846],{"class":197,"line":307},[195,841,343],{"class":234},[195,843,577],{"class":238},[195,845,349],{"class":234},[195,847,848],{"class":238}," ws3.iter_rows():\n",[195,850,851,853,855],{"class":197,"line":318},[195,852,613],{"class":238},[195,854,261],{"class":234},[195,856,857],{"class":267}," AUTO\n",[195,859,860,862,864],{"class":197,"line":340},[195,861,434],{"class":238},[195,863,437],{"class":205},[195,865,440],{"class":238},[10,867,868,869,871,872,874],{},"The four values display as 1.2M, 988K, 45K and 812. The catch is that a format allows at most two conditions plus a final section, and the final section catches everything else — including negative numbers. Rendered in LibreOffice, −1,234,567 falls into that last ",[192,870,47],{}," section and shows as an unscaled ",[192,873,268],{},", with no sign. Use auto-switching only for columns that cannot be negative, such as counts and gross sales; for anything that can go below zero, pick one scale per column.",[180,876,878],{"id":877},"step-4-negatives-and-small-values","Step 4 — Negatives and small values",[10,880,881],{},"With a single scale, a two-section format handles negatives explicitly — here in red parentheses, the finance convention:",[185,883,885],{"className":225,"code":884,"language":227,"meta":190,"style":190},"SIGNED_M = '#,##0.0,,\"M\";[Red](#,##0.0,,\"M\")'\nfor (cell,) in ws.iter_rows(min_row=2, min_col=3, max_col=3):\n    cell.number_format = SIGNED_M\nwb.save(\"scaled.xlsx\")\n",[192,886,887,897,932,941],{"__ignoreMap":190},[195,888,889,892,894],{"class":197,"line":198},[195,890,891],{"class":267},"SIGNED_M",[195,893,788],{"class":234},[195,895,896],{"class":205}," '#,##0.0,,\"M\";[Red](#,##0.0,,\"M\")'\n",[195,898,899,901,903,905,907,909,911,913,915,917,919,922,924,926,928,930],{"class":197,"line":248},[195,900,343],{"class":234},[195,902,577],{"class":238},[195,904,349],{"class":234},[195,906,371],{"class":238},[195,908,375],{"class":374},[195,910,261],{"class":234},[195,912,380],{"class":267},[195,914,271],{"class":238},[195,916,593],{"class":374},[195,918,261],{"class":234},[195,920,921],{"class":267},"3",[195,923,271],{"class":238},[195,925,602],{"class":374},[195,927,261],{"class":234},[195,929,921],{"class":267},[195,931,383],{"class":238},[195,933,934,936,938],{"class":197,"line":255},[195,935,613],{"class":238},[195,937,261],{"class":234},[195,939,940],{"class":267}," SIGNED_M\n",[195,942,943,945,947],{"class":197,"line":296},[195,944,434],{"class":238},[195,946,437],{"class":205},[195,948,440],{"class":238},[10,950,951,952,954,955,957,958,23],{},"−1,234,567 now reads (1.2M) in red. The other trap is at the small end: 45,210 in millions with one decimal is ",[192,953,153],{},", and 812 is ",[192,956,153],{}," too — the figure is not zero, it is just too small for the scale. If a column mixes magnitudes that widely, show it in thousands, add a decimal, or split the small items into an \"other\" line. Red parentheses and their variants are covered in detail in ",[14,959,961],{"href":960},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fshow-negative-numbers-in-red-with-parentheses\u002F","Show Negative Numbers in Red with Parentheses in Excel",[180,963,965],{"id":964},"step-5-the-total-that-does-not-add-up","Step 5 — The total that does not add up",[10,967,968,969,971],{},"Scaled display rounds each cell independently, while a ",[192,970,474],{}," works on the full values. Two cells of 1,449,000 display as 1.4M each, and their total of 2,898,000 displays as 2.9M. Readers notice:",[185,973,975],{"className":225,"code":974,"language":227,"meta":190,"style":190},"ws4 = wb.create_sheet(\"Totals\")\nws4.append([\"Item\", \"Amount\"])\nws4.append([\"A\", 1449000])\nws4.append([\"B\", 1449000])\nws4.append([\"Total\", \"=SUM(B2:B3)\"])\nfor (cell,) in ws4.iter_rows(min_row=2, min_col=2, max_col=2):\n    cell.number_format = '#,##0.0,,\"M\"'\nwb.save(\"scaled.xlsx\")\nprint(round(1449000 \u002F 1e6, 1) * 2, round(2898000 \u002F 1e6, 1))   # 2.8 2.9\n",[192,976,977,991,1006,1020,1033,1047,1082,1090,1098],{"__ignoreMap":190},[195,978,979,982,984,986,989],{"class":197,"line":198},[195,980,981],{"class":238},"ws4 ",[195,983,261],{"class":234},[195,985,504],{"class":238},[195,987,988],{"class":205},"\"Totals\"",[195,990,440],{"class":238},[195,992,993,996,999,1001,1004],{"class":197,"line":248},[195,994,995],{"class":238},"ws4.append([",[195,997,998],{"class":205},"\"Item\"",[195,1000,271],{"class":238},[195,1002,1003],{"class":205},"\"Amount\"",[195,1005,337],{"class":238},[195,1007,1008,1010,1013,1015,1018],{"class":197,"line":255},[195,1009,995],{"class":238},[195,1011,1012],{"class":205},"\"A\"",[195,1014,271],{"class":238},[195,1016,1017],{"class":267},"1449000",[195,1019,337],{"class":238},[195,1021,1022,1024,1027,1029,1031],{"class":197,"line":296},[195,1023,995],{"class":238},[195,1025,1026],{"class":205},"\"B\"",[195,1028,271],{"class":238},[195,1030,1017],{"class":267},[195,1032,337],{"class":238},[195,1034,1035,1037,1040,1042,1045],{"class":197,"line":307},[195,1036,995],{"class":238},[195,1038,1039],{"class":205},"\"Total\"",[195,1041,271],{"class":238},[195,1043,1044],{"class":205},"\"=SUM(B2:B3)\"",[195,1046,337],{"class":238},[195,1048,1049,1051,1053,1055,1058,1060,1062,1064,1066,1068,1070,1072,1074,1076,1078,1080],{"class":197,"line":318},[195,1050,343],{"class":234},[195,1052,577],{"class":238},[195,1054,349],{"class":234},[195,1056,1057],{"class":238}," ws4.iter_rows(",[195,1059,375],{"class":374},[195,1061,261],{"class":234},[195,1063,380],{"class":267},[195,1065,271],{"class":238},[195,1067,593],{"class":374},[195,1069,261],{"class":234},[195,1071,380],{"class":267},[195,1073,271],{"class":238},[195,1075,602],{"class":374},[195,1077,261],{"class":234},[195,1079,380],{"class":267},[195,1081,383],{"class":238},[195,1083,1084,1086,1088],{"class":197,"line":340},[195,1085,613],{"class":238},[195,1087,261],{"class":234},[195,1089,428],{"class":205},[195,1091,1092,1094,1096],{"class":197,"line":355},[195,1093,434],{"class":238},[195,1095,437],{"class":205},[195,1097,440],{"class":238},[195,1099,1100,1102,1105,1108,1110,1112,1115,1118,1120,1122,1125,1128,1131,1133,1135,1137,1140,1142,1144,1146,1148,1151],{"class":197,"line":361},[195,1101,446],{"class":267},[195,1103,1104],{"class":238},"(",[195,1106,1107],{"class":267},"round",[195,1109,1104],{"class":238},[195,1111,1017],{"class":267},[195,1113,1114],{"class":234}," \u002F",[195,1116,1117],{"class":267}," 1e6",[195,1119,271],{"class":238},[195,1121,407],{"class":267},[195,1123,1124],{"class":238},") ",[195,1126,1127],{"class":234},"*",[195,1129,1130],{"class":267}," 2",[195,1132,271],{"class":238},[195,1134,1107],{"class":267},[195,1136,1104],{"class":238},[195,1138,1139],{"class":267},"2898000",[195,1141,1114],{"class":234},[195,1143,1117],{"class":267},[195,1145,271],{"class":238},[195,1147,407],{"class":267},[195,1149,1150],{"class":238},"))   ",[195,1152,1153],{"class":463},"# 2.8 2.9\n",[10,1155,1156,1157,23],{},"There are three honest responses. Add a footnote — \"figures may not add due to rounding\" — which is standard in published accounts. Show one more decimal, which usually makes the effect disappear. Or, when the report must add up visually, round the stored values in Python before writing and sum those — accepting that the total now differs slightly from the true one. The last option changes the data, so choose it deliberately; rounding rules are covered in ",[14,1158,1160],{"href":1159},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fmatch-excel-rounding-in-pandas\u002F","Match Excel Rounding in pandas",[25,1162,34,1168,34,1171,34,1174,34,1179,34,1183,34,1187,34,1193,34,1197,34,1201,34,1205,34,1209,34,1212,34,1216,34,1218,34,1222,34,1224,34,1227,34,1229,34,1232,34,1235,34,1238,34,1240,34,1243,34,1245,34,1248,34,1250,34,1253,34,1256,34,1259,34,1261,34,1263,34,1265,34,1267,34,1269,34,1271,34,1273,34,1276,34,1278,34,1281,34,1285,34,1289,34,1291,34,1294],{"viewBox":1163,"role":28,"ariaLabelledBy":1164,"xmlns":32,"style":1167},"210 0 340 194",[1165,1166],"km-totals-t","km-totals-d","width:100%;max-width:340px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[36,1169,1170],{"id":1165},"Rounded parts and an unrounded total",[40,1172,1173],{"id":1166},"Items A and B each hold 1,449,000 and display as 1.4M. The total formula sums the full values, 2,898,000, and displays 2.9M, so the displayed parts appear to add up to 2.8M while the total says 2.9M.",[44,1175],{"x":1176,"y":47,"width":1177,"height":1178,"fill":50},"210","340","194",[44,1180],{"x":1181,"y":54,"width":94,"height":1182,"rx":47,"fill":91,"stroke":57,"style":58},"254.6","24.0",[44,1184],{"x":1185,"y":54,"width":1186,"height":1182,"rx":47,"fill":91,"stroke":57,"style":58},"286.6","55.5",[67,1188,1192],{"x":1189,"y":1190,"style":1191},"314.3","33.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[44,1194],{"x":1195,"y":54,"width":1196,"height":1182,"rx":47,"fill":91,"stroke":57,"style":58},"342.1","73.0",[67,1198,1200],{"x":1199,"y":1190,"style":1191},"378.5","B",[44,1202],{"x":1203,"y":54,"width":1204,"height":1182,"rx":47,"fill":91,"stroke":57,"style":58},"415.0","90.4",[67,1206,1208],{"x":1207,"y":1190,"style":1191},"460.2","C",[44,1210],{"x":1181,"y":56,"width":94,"height":1211,"rx":47,"fill":91,"stroke":57,"style":58},"28.0",[67,1213,407],{"x":1214,"y":1215,"style":1191},"270.6","59.0",[44,1217],{"x":1185,"y":56,"width":1186,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1219,1221],{"x":1189,"y":1215,"style":1220},"font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Item",[44,1223],{"x":1195,"y":56,"width":1196,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1225,1226],{"x":1199,"y":1215,"style":1220},"Amount",[44,1228],{"x":1203,"y":56,"width":1204,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1230,1231],{"x":1207,"y":1215,"style":1220},"stored",[44,1233],{"x":1181,"y":1234,"width":94,"height":1211,"rx":47,"fill":91,"stroke":57,"style":58},"68.0",[67,1236,380],{"x":1214,"y":1237,"style":1191},"87.0",[44,1239],{"x":1185,"y":1234,"width":1186,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1241,1192],{"x":1189,"y":1237,"style":1242},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle",[44,1244],{"x":1195,"y":1234,"width":1196,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1246,1247],{"x":1199,"y":1237,"style":1242},"1.4M",[44,1249],{"x":1203,"y":1234,"width":1204,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1251,1252],{"x":1207,"y":1237,"style":1242},"1,449,000",[44,1254],{"x":1181,"y":1255,"width":94,"height":1211,"rx":47,"fill":91,"stroke":57,"style":58},"96.0",[67,1257,921],{"x":1214,"y":1258,"style":1191},"115.0",[44,1260],{"x":1185,"y":1255,"width":1186,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1262,1200],{"x":1189,"y":1258,"style":1242},[44,1264],{"x":1195,"y":1255,"width":1196,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1266,1247],{"x":1199,"y":1258,"style":1242},[44,1268],{"x":1203,"y":1255,"width":1204,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1270,1252],{"x":1207,"y":1258,"style":1242},[44,1272],{"x":1181,"y":138,"width":94,"height":1211,"rx":47,"fill":91,"stroke":57,"style":58},[67,1274,46],{"x":1214,"y":1275,"style":1191},"143.0",[44,1277],{"x":1185,"y":138,"width":1186,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1279,1280],{"x":1189,"y":1275,"style":1242},"Total",[44,1282],{"x":1195,"y":138,"width":1196,"height":1211,"rx":47,"fill":1283,"stroke":715,"style":1284},"#fdefd8","stroke-width:1.5px",[67,1286,1288],{"x":1199,"y":1275,"style":1287},"font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","2.9M",[44,1290],{"x":1203,"y":138,"width":1204,"height":1211,"rx":47,"fill":50,"stroke":57,"style":58},[67,1292,1293],{"x":1207,"y":1275,"style":1242},"2,898,000",[67,1295,1299],{"x":1296,"y":1297,"style":1298},"380.0","174.0","font-size:12.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","the total is right; the parts are rounded for display",[180,1301,1303],{"id":1302},"step-6-the-same-formats-from-pandas-with-xlsxwriter","Step 6 — The same formats from pandas with XlsxWriter",[10,1305,1306,1307,1310],{},"When the report is written from a DataFrame, set the format per column with XlsxWriter's ",[192,1308,1309],{},"set_column",", which applies it without touching each cell:",[185,1312,1314],{"className":225,"code":1313,"language":227,"meta":190,"style":190},"import pandas as pd\n\ndf = pd.DataFrame({\"Region\": [\"North\", \"South\", \"East\"], \"Revenue\": [1234567, 987654, 45210],\n                   \"Change\": [150300, -48200, 2100]})\nwith pd.ExcelWriter(\"pack.xlsx\", engine=\"xlsxwriter\") as writer:\n    df.to_excel(writer, sheet_name=\"Pack\", index=False)\n    book, sheet = writer.book, writer.sheets[\"Pack\"]\n    sheet.set_column(\"B:B\", 14, book.add_format({\"num_format\": '#,##0,\"K\"'}))\n    sheet.set_column(\"C:C\", 14, book.add_format({\"num_format\": '#,##0,\"K\";[Red](#,##0,\"K\")'}))\nprint(pd.read_excel(\"pack.xlsx\")[\"Revenue\"].tolist())      # [1234567, 987654, 45210]\n",[192,1315,1316,1329,1333,1378,1403,1431,1455,1469,1496,1518],{"__ignoreMap":190},[195,1317,1318,1320,1323,1326],{"class":197,"line":198},[195,1319,242],{"class":234},[195,1321,1322],{"class":238}," pandas ",[195,1324,1325],{"class":234},"as",[195,1327,1328],{"class":238}," pd\n",[195,1330,1331],{"class":197,"line":248},[195,1332,252],{"emptyLinePlaceholder":251},[195,1334,1335,1338,1340,1343,1345,1348,1350,1352,1354,1356,1358,1361,1363,1365,1367,1369,1371,1373,1375],{"class":197,"line":255},[195,1336,1337],{"class":238},"df ",[195,1339,261],{"class":234},[195,1341,1342],{"class":238}," pd.DataFrame({",[195,1344,517],{"class":205},[195,1346,1347],{"class":238},": [",[195,1349,539],{"class":205},[195,1351,271],{"class":238},[195,1353,549],{"class":205},[195,1355,271],{"class":238},[195,1357,558],{"class":205},[195,1359,1360],{"class":238},"], ",[195,1362,324],{"class":205},[195,1364,1347],{"class":238},[195,1366,268],{"class":267},[195,1368,271],{"class":238},[195,1370,274],{"class":267},[195,1372,271],{"class":238},[195,1374,279],{"class":267},[195,1376,1377],{"class":238},"],\n",[195,1379,1380,1383,1385,1388,1390,1392,1395,1397,1400],{"class":197,"line":296},[195,1381,1382],{"class":205},"                   \"Change\"",[195,1384,1347],{"class":238},[195,1386,1387],{"class":267},"150300",[195,1389,271],{"class":238},[195,1391,288],{"class":234},[195,1393,1394],{"class":267},"48200",[195,1396,271],{"class":238},[195,1398,1399],{"class":267},"2100",[195,1401,1402],{"class":238},"]})\n",[195,1404,1405,1408,1411,1414,1416,1419,1421,1424,1426,1428],{"class":197,"line":307},[195,1406,1407],{"class":234},"with",[195,1409,1410],{"class":238}," pd.ExcelWriter(",[195,1412,1413],{"class":205},"\"pack.xlsx\"",[195,1415,271],{"class":238},[195,1417,1418],{"class":374},"engine",[195,1420,261],{"class":234},[195,1422,1423],{"class":205},"\"xlsxwriter\"",[195,1425,1124],{"class":238},[195,1427,1325],{"class":234},[195,1429,1430],{"class":238}," writer:\n",[195,1432,1433,1436,1439,1441,1443,1445,1448,1450,1453],{"class":197,"line":318},[195,1434,1435],{"class":238},"    df.to_excel(writer, ",[195,1437,1438],{"class":374},"sheet_name",[195,1440,261],{"class":234},[195,1442,507],{"class":205},[195,1444,271],{"class":238},[195,1446,1447],{"class":374},"index",[195,1449,261],{"class":234},[195,1451,1452],{"class":267},"False",[195,1454,440],{"class":238},[195,1456,1457,1460,1462,1465,1467],{"class":197,"line":340},[195,1458,1459],{"class":238},"    book, sheet ",[195,1461,261],{"class":234},[195,1463,1464],{"class":238}," writer.book, writer.sheets[",[195,1466,507],{"class":205},[195,1468,293],{"class":238},[195,1470,1471,1474,1477,1479,1481,1484,1487,1490,1493],{"class":197,"line":355},[195,1472,1473],{"class":238},"    sheet.set_column(",[195,1475,1476],{"class":205},"\"B:B\"",[195,1478,271],{"class":238},[195,1480,649],{"class":267},[195,1482,1483],{"class":238},", book.add_format({",[195,1485,1486],{"class":205},"\"num_format\"",[195,1488,1489],{"class":238},": ",[195,1491,1492],{"class":205},"'#,##0,\"K\"'",[195,1494,1495],{"class":238},"}))\n",[195,1497,1498,1500,1503,1505,1507,1509,1511,1513,1516],{"class":197,"line":361},[195,1499,1473],{"class":238},[195,1501,1502],{"class":205},"\"C:C\"",[195,1504,271],{"class":238},[195,1506,649],{"class":267},[195,1508,1483],{"class":238},[195,1510,1486],{"class":205},[195,1512,1489],{"class":238},[195,1514,1515],{"class":205},"'#,##0,\"K\";[Red](#,##0,\"K\")'",[195,1517,1495],{"class":238},[195,1519,1520,1522,1525,1527,1530,1532,1535],{"class":197,"line":386},[195,1521,446],{"class":267},[195,1523,1524],{"class":238},"(pd.read_excel(",[195,1526,1413],{"class":205},[195,1528,1529],{"class":238},")[",[195,1531,324],{"class":205},[195,1533,1534],{"class":238},"].tolist())      ",[195,1536,1537],{"class":463},"# [1234567, 987654, 45210]\n",[10,1539,1540,1541,23],{},"Reading the file back returns the full values, confirming that only the display changed. To check what readers will actually see, export the displayed text — covered in ",[14,1542,1544],{"href":1543},"\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",[180,1546,1548],{"id":1547},"step-7-check-what-readers-will-see","Step 7 — Check what readers will see",[10,1550,1551],{},"Format codes are easy to get subtly wrong, and openpyxl only stores them — it never shows the result. LibreOffice can export every sheet as CSV with the text as displayed, which turns \"does it look right?\" into something a script can check:",[185,1553,1555],{"className":225,"code":1554,"language":227,"meta":190,"style":190},"import subprocess\n\nsubprocess.run([\"soffice\", \"--headless\", \"--convert-to\",\n                \"csv:Text - txt - csv (StarCalc):44,34,76,1,,0,false,true,true,false,false,-1\",\n                \"scaled.xlsx\"], check=True, capture_output=True, timeout=120)\nprint(open(\"scaled-Totals.csv\").read())\n# Item,Amount\n# A,1.4M\n# B,1.4M\n# Total,2.9M\n",[192,1556,1557,1564,1568,1589,1596,1632,1649,1654,1659,1664],{"__ignoreMap":190},[195,1558,1559,1561],{"class":197,"line":198},[195,1560,242],{"class":234},[195,1562,1563],{"class":238}," subprocess\n",[195,1565,1566],{"class":197,"line":248},[195,1567,252],{"emptyLinePlaceholder":251},[195,1569,1570,1573,1576,1578,1581,1583,1586],{"class":197,"line":255},[195,1571,1572],{"class":238},"subprocess.run([",[195,1574,1575],{"class":205},"\"soffice\"",[195,1577,271],{"class":238},[195,1579,1580],{"class":205},"\"--headless\"",[195,1582,271],{"class":238},[195,1584,1585],{"class":205},"\"--convert-to\"",[195,1587,1588],{"class":238},",\n",[195,1590,1591,1594],{"class":197,"line":296},[195,1592,1593],{"class":205},"                \"csv:Text - txt - csv (StarCalc):44,34,76,1,,0,false,true,true,false,false,-1\"",[195,1595,1588],{"class":238},[195,1597,1598,1601,1603,1606,1608,1611,1613,1616,1618,1620,1622,1625,1627,1630],{"class":197,"line":307},[195,1599,1600],{"class":205},"                \"scaled.xlsx\"",[195,1602,1360],{"class":238},[195,1604,1605],{"class":374},"check",[195,1607,261],{"class":234},[195,1609,1610],{"class":267},"True",[195,1612,271],{"class":238},[195,1614,1615],{"class":374},"capture_output",[195,1617,261],{"class":234},[195,1619,1610],{"class":267},[195,1621,271],{"class":238},[195,1623,1624],{"class":374},"timeout",[195,1626,261],{"class":234},[195,1628,1629],{"class":267},"120",[195,1631,440],{"class":238},[195,1633,1634,1636,1638,1641,1643,1646],{"class":197,"line":318},[195,1635,446],{"class":267},[195,1637,1104],{"class":238},[195,1639,1640],{"class":267},"open",[195,1642,1104],{"class":238},[195,1644,1645],{"class":205},"\"scaled-Totals.csv\"",[195,1647,1648],{"class":238},").read())\n",[195,1650,1651],{"class":197,"line":340},[195,1652,1653],{"class":463},"# Item,Amount\n",[195,1655,1656],{"class":197,"line":355},[195,1657,1658],{"class":463},"# A,1.4M\n",[195,1660,1661],{"class":197,"line":361},[195,1662,1663],{"class":463},"# B,1.4M\n",[195,1665,1666],{"class":197,"line":386},[195,1667,1668],{"class":463},"# Total,2.9M\n",[10,1670,1671,1672,1675],{},"The long filter string asks for comma-separated output of the formatted text, one file per sheet (the final ",[192,1673,1674],{},"-1","). Every value shown in this guide was checked this way. Put a few such assertions in the report's tests — \"revenue for North shows as 1,235\" — and a format change that breaks the display fails the build instead of reaching readers.",[180,1677,1679],{"id":1678},"common-pitfalls","Common pitfalls",[1681,1682,1683,1695,1701,1707],"ul",{},[1684,1685,1686,1690,1691,1694],"li",{},[1687,1688,1689],"strong",{},"Dividing in Python."," Writing ",[192,1692,1693],{},"value \u002F 1000"," changes the data; every formula that uses the cell is then off by a factor of a thousand. Scale in the format.",[1684,1696,1697,1700],{},[1687,1698,1699],{},"Locale expectations."," Format codes are stored with a comma as the thousands separator and a point as the decimal. Excel displays them in the reader's locale, so a German reader sees 1.234K — the code itself should not be localised.",[1684,1702,1703,1706],{},[1687,1704,1705],{},"Charts inherit the format."," A chart built from a scaled column shows axis labels in the same format when it links to the source format, which is usually what you want; if the axis shows full numbers, set the axis number format to match.",[1684,1708,1709,1712],{},[1687,1710,1711],{},"Scaling percentages or ratios."," Trailing commas apply to any number; putting a thousands format on a ratio column shows 0K everywhere.",[180,1714,1716],{"id":1715},"conclusion","Conclusion",[10,1718,1719],{},"Trailing commas in a number format scale the display by thousands or millions while the cell keeps its full value. Choose one convention — suffix in the cell or unit in the header — use two-section formats for columns that can be negative, keep auto-switching K\u002FM formats for positive-only data, watch for small values that round to zero, and explain or eliminate totals that do not add up visually.",[180,1721,1723],{"id":1722},"frequently-asked-questions","Frequently asked questions",[10,1725,1726,1729],{},[1687,1727,1728],{},"How do I show numbers in thousands in Excel without dividing them?","\nAdd a comma after the last digit placeholder in the number format, such as #,##0,. Each trailing comma divides the displayed value by 1,000 while the cell keeps the full number for formulas.",[10,1731,1732,1735],{},[1687,1733,1734],{},"How do I show millions with one decimal and an M?","\nUse #,##0.0,,\"M\". Two trailing commas divide by a million, .0 keeps one decimal and the quoted M is shown as text after the number.",[10,1737,1738,1741,1742,1745,1746,1749],{},[1687,1739,1740],{},"Can one format switch between K and M automatically?","\nYes, with conditional sections such as ",[195,1743,1744],{},">=1000000","#,##0.0,,\"M\";",[195,1747,1748],{},">=1000","#,##0,\"K\";0, but only for positive numbers — a format allows two conditions, so there is no section left for negatives. Use one scale per column when values can be negative.",[10,1751,1752,1755],{},[1687,1753,1754],{},"Why don't the displayed values add up to the displayed total?","\nEach cell is rounded for display on its own, while the total is calculated from the unrounded values. 1.4M plus 1.4M can show a total of 2.9M. Say so in a note, or round the stored values if the report must add up visually.",[180,1757,1759],{"id":1758},"related","Related",[1681,1761,1762,1768,1775,1782],{},[1684,1763,1764,1765,1767],{},"Up one level: ",[14,1766,17],{"href":16}," — number and date formatting.",[1684,1769,1770,1774],{},[14,1771,1773],{"href":1772},"\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 accounting layout.",[1684,1776,1777,1781],{},[14,1778,1780],{"href":1779},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-as-percentages-in-excel-with-python\u002F","Format Numbers as Percentages in Excel with Python"," — another display-only scale.",[1684,1783,1784,1788],{},[14,1785,1787],{"href":1786},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-a-kpi-summary-block-to-an-excel-dashboard\u002F","Add a KPI Summary Block to an Excel Dashboard"," — where compact figures matter most.",[1790,1791,1792],"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}",{"title":190,"searchDepth":248,"depth":248,"links":1794},[1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806],{"id":182,"depth":248,"text":183},{"id":218,"depth":248,"text":219},{"id":478,"depth":248,"text":479},{"id":771,"depth":248,"text":772},{"id":877,"depth":248,"text":878},{"id":964,"depth":248,"text":965},{"id":1302,"depth":248,"text":1303},{"id":1547,"depth":248,"text":1548},{"id":1678,"depth":248,"text":1679},{"id":1715,"depth":248,"text":1716},{"id":1722,"depth":248,"text":1723},{"id":1758,"depth":248,"text":1759},"2026-09-23","Show 1,234,567 as 1,235K or 1.2M in an Excel report without changing the stored value — scaling commas in number formats, units in headers or suffixes, auto-switching K and M with conditional sections, negatives and small values, and totals that seem not to add up.","md",[1811,1813,1815,1817],{"q":1728,"a":1812},"Add a comma after the last digit placeholder in the number format, such as #,##0,. Each trailing comma divides the displayed value by 1,000 while the cell keeps the full number for formulas.",{"q":1734,"a":1814},"Use #,##0.0,,\"M\". Two trailing commas divide by a million, .0 keeps one decimal and the quoted M is shown as text after the number.",{"q":1740,"a":1816},"Yes, with conditional sections such as [>=1000000]#,##0.0,,\"M\";[>=1000]#,##0,\"K\";0, but only for positive numbers — a format allows two conditions, so there is no section left for negatives. Use one scale per column when values can be negative.",{"q":1754,"a":1818},"Each cell is rounded for display on its own, while the total is calculated from the unrounded values. 1.4M plus 1.4M can show a total of 2.9M. Say so in a note, or round the stored values if the report must add up visually.","format numbers in thousands and millions in excel with python",null,{"breadcrumb":1822},[1823,1826,1829],{"name":1824,"item":1825},"Home","\u002F",{"name":1827,"item":1828},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":17,"item":16},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel",{"title":1832,"description":1833},"Format Numbers in Thousands and Millions in Excel (Python)","Display Excel numbers in thousands or millions with openpyxl and xlsxwriter — #,##0, and #,##0.0,, codes, K and M suffixes, conditional K\u002FM formats and their limits, negative values, small values that round to zero and checking the displayed text.","format-numbers-in-thousands-and-millions-in-excel","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel\u002Findex",[1837,1838],"number-formats","openpyxl","how-to","PvcGEOjhP_lgs5ddkvwEI-KZcnKLnzz8FgX-kZBhN4k",[1842,1846],{"title":1843,"path":1844,"stem":1845,"children":-1},"Format Numbers in Lakhs and Crores in Excel","\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-lakhs-and-crores-in-excel","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-lakhs-and-crores-in-excel\u002Findex",{"title":1847,"path":1848,"stem":1849,"children":-1},"Format ZIP Codes and IDs with Leading Zeros in Excel","\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros\u002Findex",[1851,1853],{"path":1852,"title":17},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel",{"path":1854,"title":1827},"\u002Fformatting-and-charting-excel-reports-with-python",[],[1857,1860,1863,1866,1868,1871],{"path":1858,"title":1859,"kind":1839},"\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":1861,"title":1862,"kind":1839},"\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":1864,"title":1865,"kind":1839},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fexcel-text-function-equivalent-in-pandas","Excel TEXT Function Equivalent in pandas",{"path":1867,"title":1160,"kind":1839},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fmatch-excel-rounding-in-pandas",{"path":1869,"title":1870,"kind":1839},"\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":1872,"title":1873,"kind":1839},"\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",1790972107095]