[{"data":1,"prerenderedAt":1589},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel":1582},{"id":4,"title":5,"body":6,"description":1573,"extension":1574,"meta":1575,"navigation":127,"path":1576,"seo":1577,"stem":1580,"__hash__":1581},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Findex.md","Applying Number and Date Formats in Excel",{"type":7,"value":8,"toc":1554},"minimark",[9,33,38,63,76,80,99,246,261,265,280,424,432,436,461,605,615,619,626,776,792,796,809,986,989,993,1007,1186,1197,1201,1420,1424,1429,1436,1440,1452,1456,1473,1477,1491,1495,1500,1504,1515,1519,1550],[10,11,12,13,17,18,22,23,28,29,32],"p",{},"When a report looks wrong, the value is usually fine and the ",[14,15,16],"em",{},"display"," is off. In Excel, every cell holds a raw value and a separate display format. ",[19,20,21],"code",{},"cell.number_format"," controls only the display — it never changes the number underneath. This guide, part of ",[24,25,27],"a",{"href":26},"\u002Fformatting-and-charting-excel-reports-with-python\u002F","Formatting and Charting Excel Reports with Python",", shows how to apply currency, separators, percentages, red negatives, and dates with ",[19,30,31],{},"openpyxl",". Every snippet builds its own sample workbook so you can run them in order.",[34,35,37],"h2",{"id":36},"install-openpyxl","Install openpyxl",[39,40,45],"pre",{"className":41,"code":42,"language":43,"meta":44,"style":44},"language-bash shiki shiki-themes github-light github-dark","pip install openpyxl\n","bash","",[19,46,47],{"__ignoreMap":44},[48,49,52,56,60],"span",{"class":50,"line":51},"line",1,[48,53,55],{"class":54},"sScJk","pip",[48,57,59],{"class":58},"sZZnC"," install",[48,61,62],{"class":58}," openpyxl\n",[10,64,65,67,68,71,72,75],{},[19,66,31],{}," writes ",[19,69,70],{},".xlsx","\u002F",[19,73,74],{},".xlsm"," without Excel installed and runs on Windows, macOS, and Linux.",[34,77,79],{"id":78},"number-format-is-display-only","Number format is display-only",[10,81,82,83,86,87,90,91,94,95,98],{},"Setting ",[19,84,85],{},"number_format"," changes how a value ",[14,88,89],{},"looks",", not what it ",[14,92,93],{},"is",". A cell formatted as currency still holds the plain float, so formulas, sorts, and exports see the original number. Confirm it yourself: write a value, format it, then read ",[19,96,97],{},".value"," back — it is unchanged.",[39,100,104],{"className":101,"code":102,"language":103,"meta":44,"style":44},"language-python shiki shiki-themes github-light github-dark","from openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nws[\"A1\"] = 1234.5\nws[\"A1\"].number_format = \"$#,##0.00\"   # displays as $1,234.50\n\nprint(\"Stored value:\", ws[\"A1\"].value)        # 1234.5\nprint(\"Display code: \", ws[\"A1\"].number_format)\nwb.save(\"number_format_basics.xlsx\")\n","python",[19,105,106,122,129,141,152,170,189,194,217,234],{"__ignoreMap":44},[48,107,108,112,116,119],{"class":50,"line":51},[48,109,111],{"class":110},"szBVR","from",[48,113,115],{"class":114},"sVt8B"," openpyxl ",[48,117,118],{"class":110},"import",[48,120,121],{"class":114}," Workbook\n",[48,123,125],{"class":50,"line":124},2,[48,126,128],{"emptyLinePlaceholder":127},true,"\n",[48,130,132,135,138],{"class":50,"line":131},3,[48,133,134],{"class":114},"wb ",[48,136,137],{"class":110},"=",[48,139,140],{"class":114}," Workbook()\n",[48,142,144,147,149],{"class":50,"line":143},4,[48,145,146],{"class":114},"ws ",[48,148,137],{"class":110},[48,150,151],{"class":114}," wb.active\n",[48,153,155,158,161,164,166],{"class":50,"line":154},5,[48,156,157],{"class":114},"ws[",[48,159,160],{"class":58},"\"A1\"",[48,162,163],{"class":114},"] ",[48,165,137],{"class":110},[48,167,169],{"class":168},"sj4cs"," 1234.5\n",[48,171,173,175,177,180,182,185],{"class":50,"line":172},6,[48,174,157],{"class":114},[48,176,160],{"class":58},[48,178,179],{"class":114},"].number_format ",[48,181,137],{"class":110},[48,183,184],{"class":58}," \"$#,##0.00\"",[48,186,188],{"class":187},"sJ8bj","   # displays as $1,234.50\n",[48,190,192],{"class":50,"line":191},7,[48,193,128],{"emptyLinePlaceholder":127},[48,195,197,200,203,206,209,211,214],{"class":50,"line":196},8,[48,198,199],{"class":168},"print",[48,201,202],{"class":114},"(",[48,204,205],{"class":58},"\"Stored value:\"",[48,207,208],{"class":114},", ws[",[48,210,160],{"class":58},[48,212,213],{"class":114},"].value)        ",[48,215,216],{"class":187},"# 1234.5\n",[48,218,220,222,224,227,229,231],{"class":50,"line":219},9,[48,221,199],{"class":168},[48,223,202],{"class":114},[48,225,226],{"class":58},"\"Display code: \"",[48,228,208],{"class":114},[48,230,160],{"class":58},[48,232,233],{"class":114},"].number_format)\n",[48,235,237,240,243],{"class":50,"line":236},10,[48,238,239],{"class":114},"wb.save(",[48,241,242],{"class":58},"\"number_format_basics.xlsx\"",[48,244,245],{"class":114},")\n",[10,247,248,249,252,253,256,257,260],{},"The stored value prints ",[19,250,251],{},"1234.5"," even though Excel will render ",[19,254,255],{},"$1,234.50",". Because the format is cosmetic, the cell must already contain a real number for the format to mean anything — a text string like ",[19,258,259],{},"\"1234.5\""," will not pick up a currency format.",[34,262,264],{"id":263},"currency-and-thousands-separators","Currency and thousands separators",[10,266,267,268,271,272,275,276,279],{},"The placeholder ",[19,269,270],{},"#"," shows a digit only when present; ",[19,273,274],{},"0"," forces a digit. Group thousands with a comma and fix two decimals with ",[19,277,278],{},"0.00",". Drop the currency symbol for a plain grouped integer.",[39,281,283],{"className":101,"code":282,"language":103,"meta":44,"style":44},"from openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nws.append([\"Item\", \"Amount\"])\nws.append([\"Revenue\", 1234567.5])\nws.append([\"Units\", 42000])\n\nws[\"B2\"].number_format = \"$#,##0.00\"   # $1,234,567.50\nws[\"B3\"].number_format = \"#,##0\"       # 42,000\n\nwb.save(\"currency_and_separators.xlsx\")\nprint(\"Formatted currency and a grouped integer\")\n",[19,284,285,295,299,307,315,332,346,360,364,380,397,402,412],{"__ignoreMap":44},[48,286,287,289,291,293],{"class":50,"line":51},[48,288,111],{"class":110},[48,290,115],{"class":114},[48,292,118],{"class":110},[48,294,121],{"class":114},[48,296,297],{"class":50,"line":124},[48,298,128],{"emptyLinePlaceholder":127},[48,300,301,303,305],{"class":50,"line":131},[48,302,134],{"class":114},[48,304,137],{"class":110},[48,306,140],{"class":114},[48,308,309,311,313],{"class":50,"line":143},[48,310,146],{"class":114},[48,312,137],{"class":110},[48,314,151],{"class":114},[48,316,317,320,323,326,329],{"class":50,"line":154},[48,318,319],{"class":114},"ws.append([",[48,321,322],{"class":58},"\"Item\"",[48,324,325],{"class":114},", ",[48,327,328],{"class":58},"\"Amount\"",[48,330,331],{"class":114},"])\n",[48,333,334,336,339,341,344],{"class":50,"line":172},[48,335,319],{"class":114},[48,337,338],{"class":58},"\"Revenue\"",[48,340,325],{"class":114},[48,342,343],{"class":168},"1234567.5",[48,345,331],{"class":114},[48,347,348,350,353,355,358],{"class":50,"line":191},[48,349,319],{"class":114},[48,351,352],{"class":58},"\"Units\"",[48,354,325],{"class":114},[48,356,357],{"class":168},"42000",[48,359,331],{"class":114},[48,361,362],{"class":50,"line":196},[48,363,128],{"emptyLinePlaceholder":127},[48,365,366,368,371,373,375,377],{"class":50,"line":219},[48,367,157],{"class":114},[48,369,370],{"class":58},"\"B2\"",[48,372,179],{"class":114},[48,374,137],{"class":110},[48,376,184],{"class":58},[48,378,379],{"class":187},"   # $1,234,567.50\n",[48,381,382,384,387,389,391,394],{"class":50,"line":236},[48,383,157],{"class":114},[48,385,386],{"class":58},"\"B3\"",[48,388,179],{"class":114},[48,390,137],{"class":110},[48,392,393],{"class":58}," \"#,##0\"",[48,395,396],{"class":187},"       # 42,000\n",[48,398,400],{"class":50,"line":399},11,[48,401,128],{"emptyLinePlaceholder":127},[48,403,405,407,410],{"class":50,"line":404},12,[48,406,239],{"class":114},[48,408,409],{"class":58},"\"currency_and_separators.xlsx\"",[48,411,245],{"class":114},[48,413,415,417,419,422],{"class":50,"line":414},13,[48,416,199],{"class":168},[48,418,202],{"class":114},[48,420,421],{"class":58},"\"Formatted currency and a grouped integer\"",[48,423,245],{"class":114},[10,425,426,427,431],{},"For a deep dive on symbols, accounting parentheses, and whole-column currency, see ",[24,428,430],{"href":429},"\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",".",[34,433,435],{"id":434},"percentages-store-the-ratio-not-the-integer","Percentages: store the ratio, not the integer",[10,437,438,439,442,443,446,447,450,451,454,455,457,458,431],{},"The ",[19,440,441],{},"%"," format code multiplies the stored value by 100 for display and appends a percent sign. So a cell showing ",[19,444,445],{},"25.0%"," must store ",[19,448,449],{},"0.25",", not ",[19,452,453],{},"25",". Store the raw ratio and let the format do the conversion — storing ",[19,456,453],{}," would render as ",[19,459,460],{},"2500.0%",[39,462,464],{"className":101,"code":463,"language":103,"meta":44,"style":44},"from openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nws.append([\"Metric\", \"Rate\"])\nws.append([\"Conversion\", 0.25])\nws.append([\"Churn\", 0.073])\n\nws[\"B2\"].number_format = \"0.0%\"    # 25.0%\nws[\"B3\"].number_format = \"0.00%\"   # 7.30%\n\nprint(\"B2 stored value:\", ws[\"B2\"].value)   # 0.25, not 25\nwb.save(\"percentages.xlsx\")\n",[19,465,466,476,480,488,496,510,523,537,541,557,573,577,596],{"__ignoreMap":44},[48,467,468,470,472,474],{"class":50,"line":51},[48,469,111],{"class":110},[48,471,115],{"class":114},[48,473,118],{"class":110},[48,475,121],{"class":114},[48,477,478],{"class":50,"line":124},[48,479,128],{"emptyLinePlaceholder":127},[48,481,482,484,486],{"class":50,"line":131},[48,483,134],{"class":114},[48,485,137],{"class":110},[48,487,140],{"class":114},[48,489,490,492,494],{"class":50,"line":143},[48,491,146],{"class":114},[48,493,137],{"class":110},[48,495,151],{"class":114},[48,497,498,500,503,505,508],{"class":50,"line":154},[48,499,319],{"class":114},[48,501,502],{"class":58},"\"Metric\"",[48,504,325],{"class":114},[48,506,507],{"class":58},"\"Rate\"",[48,509,331],{"class":114},[48,511,512,514,517,519,521],{"class":50,"line":172},[48,513,319],{"class":114},[48,515,516],{"class":58},"\"Conversion\"",[48,518,325],{"class":114},[48,520,449],{"class":168},[48,522,331],{"class":114},[48,524,525,527,530,532,535],{"class":50,"line":191},[48,526,319],{"class":114},[48,528,529],{"class":58},"\"Churn\"",[48,531,325],{"class":114},[48,533,534],{"class":168},"0.073",[48,536,331],{"class":114},[48,538,539],{"class":50,"line":196},[48,540,128],{"emptyLinePlaceholder":127},[48,542,543,545,547,549,551,554],{"class":50,"line":219},[48,544,157],{"class":114},[48,546,370],{"class":58},[48,548,179],{"class":114},[48,550,137],{"class":110},[48,552,553],{"class":58}," \"0.0%\"",[48,555,556],{"class":187},"    # 25.0%\n",[48,558,559,561,563,565,567,570],{"class":50,"line":236},[48,560,157],{"class":114},[48,562,386],{"class":58},[48,564,179],{"class":114},[48,566,137],{"class":110},[48,568,569],{"class":58}," \"0.00%\"",[48,571,572],{"class":187},"   # 7.30%\n",[48,574,575],{"class":50,"line":399},[48,576,128],{"emptyLinePlaceholder":127},[48,578,579,581,583,586,588,590,593],{"class":50,"line":404},[48,580,199],{"class":168},[48,582,202],{"class":114},[48,584,585],{"class":58},"\"B2 stored value:\"",[48,587,208],{"class":114},[48,589,370],{"class":58},[48,591,592],{"class":114},"].value)   ",[48,594,595],{"class":187},"# 0.25, not 25\n",[48,597,598,600,603],{"class":50,"line":414},[48,599,239],{"class":114},[48,601,602],{"class":58},"\"percentages.xlsx\"",[48,604,245],{"class":114},[10,606,607,608,610,611,614],{},"The stored value stays ",[19,609,449],{},", so a ",[19,612,613],{},"=SUM()"," or a downstream pandas read gets the true ratio.",[34,616,618],{"id":617},"show-negatives-in-red","Show negatives in red",[10,620,621,622,625],{},"A format string can carry up to four sections separated by semicolons: positive; negative; zero; text. Supply a negative section to style losses. Wrap a section in ",[19,623,624],{},"[Red]"," to color it, and use parentheses instead of a minus sign for an accounting look.",[39,627,629],{"className":101,"code":628,"language":103,"meta":44,"style":44},"from openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nws.append([\"Account\", \"Balance\"])\nws.append([\"Operating\", 8200.40])\nws.append([\"Overdraft\", -1530.75])\n\nred_neg = \"$#,##0.00;[Red]($#,##0.00)\"\nws[\"B2\"].number_format = red_neg     # $8,200.40\nws[\"B3\"].number_format = red_neg     # ($1,530.75) in red\n\nwb.save(\"red_negatives.xlsx\")\nprint(\"Applied positive\u002Fnegative two-section format\")\n",[19,630,631,641,645,653,661,675,689,706,710,720,736,751,755,764],{"__ignoreMap":44},[48,632,633,635,637,639],{"class":50,"line":51},[48,634,111],{"class":110},[48,636,115],{"class":114},[48,638,118],{"class":110},[48,640,121],{"class":114},[48,642,643],{"class":50,"line":124},[48,644,128],{"emptyLinePlaceholder":127},[48,646,647,649,651],{"class":50,"line":131},[48,648,134],{"class":114},[48,650,137],{"class":110},[48,652,140],{"class":114},[48,654,655,657,659],{"class":50,"line":143},[48,656,146],{"class":114},[48,658,137],{"class":110},[48,660,151],{"class":114},[48,662,663,665,668,670,673],{"class":50,"line":154},[48,664,319],{"class":114},[48,666,667],{"class":58},"\"Account\"",[48,669,325],{"class":114},[48,671,672],{"class":58},"\"Balance\"",[48,674,331],{"class":114},[48,676,677,679,682,684,687],{"class":50,"line":172},[48,678,319],{"class":114},[48,680,681],{"class":58},"\"Operating\"",[48,683,325],{"class":114},[48,685,686],{"class":168},"8200.40",[48,688,331],{"class":114},[48,690,691,693,696,698,701,704],{"class":50,"line":191},[48,692,319],{"class":114},[48,694,695],{"class":58},"\"Overdraft\"",[48,697,325],{"class":114},[48,699,700],{"class":110},"-",[48,702,703],{"class":168},"1530.75",[48,705,331],{"class":114},[48,707,708],{"class":50,"line":196},[48,709,128],{"emptyLinePlaceholder":127},[48,711,712,715,717],{"class":50,"line":219},[48,713,714],{"class":114},"red_neg ",[48,716,137],{"class":110},[48,718,719],{"class":58}," \"$#,##0.00;[Red]($#,##0.00)\"\n",[48,721,722,724,726,728,730,733],{"class":50,"line":236},[48,723,157],{"class":114},[48,725,370],{"class":58},[48,727,179],{"class":114},[48,729,137],{"class":110},[48,731,732],{"class":114}," red_neg     ",[48,734,735],{"class":187},"# $8,200.40\n",[48,737,738,740,742,744,746,748],{"class":50,"line":399},[48,739,157],{"class":114},[48,741,386],{"class":58},[48,743,179],{"class":114},[48,745,137],{"class":110},[48,747,732],{"class":114},[48,749,750],{"class":187},"# ($1,530.75) in red\n",[48,752,753],{"class":50,"line":404},[48,754,128],{"emptyLinePlaceholder":127},[48,756,757,759,762],{"class":50,"line":414},[48,758,239],{"class":114},[48,760,761],{"class":58},"\"red_negatives.xlsx\"",[48,763,245],{"class":114},[48,765,767,769,771,774],{"class":50,"line":766},14,[48,768,199],{"class":168},[48,770,202],{"class":114},[48,772,773],{"class":58},"\"Applied positive\u002Fnegative two-section format\"",[48,775,245],{"class":114},[10,777,778,779,781,782,785,786,789,790,431],{},"The positive ",[19,780,686],{}," shows normally; the negative ",[19,783,784],{},"-1530.75"," displays as a red ",[19,787,788],{},"($1,530.75)",". The underlying value remains ",[19,791,784],{},[34,793,795],{"id":794},"apply-a-format-down-a-whole-column","Apply a format down a whole column",[10,797,798,799,801,802,805,806,431],{},"Reports format an entire column, not single cells. Iterate the column and set ",[19,800,85],{}," on each data cell, skipping the header. ",[19,803,804],{},"ws[\"B\"]"," yields every cell in column B top to bottom; slice off the header with ",[19,807,808],{},"[1:]",[39,810,812],{"className":101,"code":811,"language":103,"meta":44,"style":44},"from openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nws.append([\"Region\", \"Revenue\"])\nfor region, value in [(\"North\", 23990.5), (\"South\", 12475.0), (\"West\", 15992.2)]:\n    ws.append([region, value])\n\nfor cell in ws[\"B\"][1:]:           # column B, skip the header\n    cell.number_format = \"$#,##0.00\"\n\nwb.save(\"format_column.xlsx\")\nprint(\"Formatted\", ws.max_row - 1, \"revenue cells\")\n",[19,813,814,824,828,836,844,857,903,908,912,939,949,953,962],{"__ignoreMap":44},[48,815,816,818,820,822],{"class":50,"line":51},[48,817,111],{"class":110},[48,819,115],{"class":114},[48,821,118],{"class":110},[48,823,121],{"class":114},[48,825,826],{"class":50,"line":124},[48,827,128],{"emptyLinePlaceholder":127},[48,829,830,832,834],{"class":50,"line":131},[48,831,134],{"class":114},[48,833,137],{"class":110},[48,835,140],{"class":114},[48,837,838,840,842],{"class":50,"line":143},[48,839,146],{"class":114},[48,841,137],{"class":110},[48,843,151],{"class":114},[48,845,846,848,851,853,855],{"class":50,"line":154},[48,847,319],{"class":114},[48,849,850],{"class":58},"\"Region\"",[48,852,325],{"class":114},[48,854,338],{"class":58},[48,856,331],{"class":114},[48,858,859,862,865,868,871,874,876,879,882,885,887,890,892,895,897,900],{"class":50,"line":172},[48,860,861],{"class":110},"for",[48,863,864],{"class":114}," region, value ",[48,866,867],{"class":110},"in",[48,869,870],{"class":114}," [(",[48,872,873],{"class":58},"\"North\"",[48,875,325],{"class":114},[48,877,878],{"class":168},"23990.5",[48,880,881],{"class":114},"), (",[48,883,884],{"class":58},"\"South\"",[48,886,325],{"class":114},[48,888,889],{"class":168},"12475.0",[48,891,881],{"class":114},[48,893,894],{"class":58},"\"West\"",[48,896,325],{"class":114},[48,898,899],{"class":168},"15992.2",[48,901,902],{"class":114},")]:\n",[48,904,905],{"class":50,"line":191},[48,906,907],{"class":114},"    ws.append([region, value])\n",[48,909,910],{"class":50,"line":196},[48,911,128],{"emptyLinePlaceholder":127},[48,913,914,916,919,921,924,927,930,933,936],{"class":50,"line":219},[48,915,861],{"class":110},[48,917,918],{"class":114}," cell ",[48,920,867],{"class":110},[48,922,923],{"class":114}," ws[",[48,925,926],{"class":58},"\"B\"",[48,928,929],{"class":114},"][",[48,931,932],{"class":168},"1",[48,934,935],{"class":114},":]:           ",[48,937,938],{"class":187},"# column B, skip the header\n",[48,940,941,944,946],{"class":50,"line":236},[48,942,943],{"class":114},"    cell.number_format ",[48,945,137],{"class":110},[48,947,948],{"class":58}," \"$#,##0.00\"\n",[48,950,951],{"class":50,"line":399},[48,952,128],{"emptyLinePlaceholder":127},[48,954,955,957,960],{"class":50,"line":404},[48,956,239],{"class":114},[48,958,959],{"class":58},"\"format_column.xlsx\"",[48,961,245],{"class":114},[48,963,964,966,968,971,974,976,979,981,984],{"class":50,"line":414},[48,965,199],{"class":168},[48,967,202],{"class":114},[48,969,970],{"class":58},"\"Formatted\"",[48,972,973],{"class":114},", ws.max_row ",[48,975,700],{"class":110},[48,977,978],{"class":168}," 1",[48,980,325],{"class":114},[48,982,983],{"class":58},"\"revenue cells\"",[48,985,245],{"class":114},[10,987,988],{},"Formatting an empty cell is harmless — the format simply applies once a value lands there — so you can format a few rows past the current data if more is coming.",[34,990,992],{"id":991},"date-and-time-formats","Date and time formats",[10,994,995,996,999,1000,1003,1004,1006],{},"Dates need a real Python ",[19,997,998],{},"datetime.date"," or ",[19,1001,1002],{},"datetime.datetime"," so Excel stores a true date serial number. Then ",[19,1005,85],{}," controls the rendered layout. Write the object directly; do not pre-format it into a string, or Excel treats it as text and cannot reformat it.",[39,1008,1010],{"className":101,"code":1009,"language":103,"meta":44,"style":44},"from datetime import date, datetime\nfrom openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nws.append([\"Event\", \"When\"])\nws.append([\"Invoice\", date(2024, 3, 9)])\nws.append([\"Logged\", datetime(2024, 3, 9, 14, 30)])\n\nws[\"B2\"].number_format = \"yyyy-mm-dd\"          # 2024-03-09\nws[\"B3\"].number_format = \"mmm d, yyyy h:mm\"    # Mar 9, 2024 14:30\n\nwb.save(\"date_formats.xlsx\")\nprint(\"Wrote real date serials with display formats\")\n",[19,1011,1012,1024,1034,1038,1046,1054,1068,1094,1126,1130,1146,1162,1166,1175],{"__ignoreMap":44},[48,1013,1014,1016,1019,1021],{"class":50,"line":51},[48,1015,111],{"class":110},[48,1017,1018],{"class":114}," datetime ",[48,1020,118],{"class":110},[48,1022,1023],{"class":114}," date, datetime\n",[48,1025,1026,1028,1030,1032],{"class":50,"line":124},[48,1027,111],{"class":110},[48,1029,115],{"class":114},[48,1031,118],{"class":110},[48,1033,121],{"class":114},[48,1035,1036],{"class":50,"line":131},[48,1037,128],{"emptyLinePlaceholder":127},[48,1039,1040,1042,1044],{"class":50,"line":143},[48,1041,134],{"class":114},[48,1043,137],{"class":110},[48,1045,140],{"class":114},[48,1047,1048,1050,1052],{"class":50,"line":154},[48,1049,146],{"class":114},[48,1051,137],{"class":110},[48,1053,151],{"class":114},[48,1055,1056,1058,1061,1063,1066],{"class":50,"line":172},[48,1057,319],{"class":114},[48,1059,1060],{"class":58},"\"Event\"",[48,1062,325],{"class":114},[48,1064,1065],{"class":58},"\"When\"",[48,1067,331],{"class":114},[48,1069,1070,1072,1075,1078,1081,1083,1086,1088,1091],{"class":50,"line":191},[48,1071,319],{"class":114},[48,1073,1074],{"class":58},"\"Invoice\"",[48,1076,1077],{"class":114},", date(",[48,1079,1080],{"class":168},"2024",[48,1082,325],{"class":114},[48,1084,1085],{"class":168},"3",[48,1087,325],{"class":114},[48,1089,1090],{"class":168},"9",[48,1092,1093],{"class":114},")])\n",[48,1095,1096,1098,1101,1104,1106,1108,1110,1112,1114,1116,1119,1121,1124],{"class":50,"line":196},[48,1097,319],{"class":114},[48,1099,1100],{"class":58},"\"Logged\"",[48,1102,1103],{"class":114},", datetime(",[48,1105,1080],{"class":168},[48,1107,325],{"class":114},[48,1109,1085],{"class":168},[48,1111,325],{"class":114},[48,1113,1090],{"class":168},[48,1115,325],{"class":114},[48,1117,1118],{"class":168},"14",[48,1120,325],{"class":114},[48,1122,1123],{"class":168},"30",[48,1125,1093],{"class":114},[48,1127,1128],{"class":50,"line":219},[48,1129,128],{"emptyLinePlaceholder":127},[48,1131,1132,1134,1136,1138,1140,1143],{"class":50,"line":236},[48,1133,157],{"class":114},[48,1135,370],{"class":58},[48,1137,179],{"class":114},[48,1139,137],{"class":110},[48,1141,1142],{"class":58}," \"yyyy-mm-dd\"",[48,1144,1145],{"class":187},"          # 2024-03-09\n",[48,1147,1148,1150,1152,1154,1156,1159],{"class":50,"line":399},[48,1149,157],{"class":114},[48,1151,386],{"class":58},[48,1153,179],{"class":114},[48,1155,137],{"class":110},[48,1157,1158],{"class":58}," \"mmm d, yyyy h:mm\"",[48,1160,1161],{"class":187},"    # Mar 9, 2024 14:30\n",[48,1163,1164],{"class":50,"line":404},[48,1165,128],{"emptyLinePlaceholder":127},[48,1167,1168,1170,1173],{"class":50,"line":414},[48,1169,239],{"class":114},[48,1171,1172],{"class":58},"\"date_formats.xlsx\"",[48,1174,245],{"class":114},[48,1176,1177,1179,1181,1184],{"class":50,"line":766},[48,1178,199],{"class":168},[48,1180,202],{"class":114},[48,1182,1183],{"class":58},"\"Wrote real date serials with display formats\"",[48,1185,245],{"class":114},[10,1187,1188,1189,1192,1193,431],{},"For string-to-date pitfalls, locale layouts like ",[19,1190,1191],{},"dd\u002Fmm\u002Fyyyy",", and pandas datetime columns, read ",[24,1194,1196],{"href":1195},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-dates-in-excel-cells-with-python\u002F","Format Dates in Excel Cells with Python",[34,1198,1200],{"id":1199},"common-number-format-codes","Common number-format codes",[1202,1203,1204,1223],"table",{},[1205,1206,1207],"thead",{},[1208,1209,1210,1214,1220],"tr",{},[1211,1212,1213],"th",{},"Code",[1211,1215,1216,1217,1219],{},"Displays ",[19,1218,251],{}," as",[1211,1221,1222],{},"Use for",[1224,1225,1226,1242,1257,1271,1286,1303,1321,1336,1354,1371,1387,1405],"tbody",{},[1208,1227,1228,1234,1239],{},[1229,1230,1231],"td",{},[19,1232,1233],{},"#,##0",[1229,1235,1236],{},[19,1237,1238],{},"1,235",[1229,1240,1241],{},"Grouped integers, counts",[1208,1243,1244,1249,1254],{},[1229,1245,1246],{},[19,1247,1248],{},"#,##0.00",[1229,1250,1251],{},[19,1252,1253],{},"1,234.50",[1229,1255,1256],{},"Fixed two-decimal numbers",[1208,1258,1259,1264,1268],{},[1229,1260,1261],{},[19,1262,1263],{},"$#,##0.00",[1229,1265,1266],{},[19,1267,255],{},[1229,1269,1270],{},"US-dollar currency",[1208,1272,1273,1278,1283],{},[1229,1274,1275],{},[19,1276,1277],{},"€#,##0.00",[1229,1279,1280],{},[19,1281,1282],{},"€1,234.50",[1229,1284,1285],{},"Euro currency",[1208,1287,1288,1293,1300],{},[1229,1289,1290],{},[19,1291,1292],{},"0.0%",[1229,1294,202,1295,1297,1298],{},[19,1296,449],{}," →) ",[19,1299,445],{},[1229,1301,1302],{},"Percentages from a ratio",[1208,1304,1305,1310,1318],{},[1229,1306,1307],{},[19,1308,1309],{},"#,##0.00;[Red](#,##0.00)",[1229,1311,1312,1314,1315],{},[19,1313,1253],{}," \u002F red ",[19,1316,1317],{},"(…)",[1229,1319,1320],{},"Red, parenthesized negatives",[1208,1322,1323,1328,1333],{},[1229,1324,1325],{},[19,1326,1327],{},"0.00E+00",[1229,1329,1330],{},[19,1331,1332],{},"1.23E+03",[1229,1334,1335],{},"Scientific notation",[1208,1337,1338,1343,1351],{},[1229,1339,1340],{},[19,1341,1342],{},"yyyy-mm-dd",[1229,1344,202,1345,1297,1348],{},[19,1346,1347],{},"date",[19,1349,1350],{},"2024-03-09",[1229,1352,1353],{},"ISO dates",[1208,1355,1356,1361,1368],{},[1229,1357,1358],{},[19,1359,1360],{},"mmm d, yyyy",[1229,1362,202,1363,1297,1365],{},[19,1364,1347],{},[19,1366,1367],{},"Mar 9, 2024",[1229,1369,1370],{},"Readable dates",[1208,1372,1373,1377,1384],{},[1229,1374,1375],{},[19,1376,1191],{},[1229,1378,202,1379,1297,1381],{},[19,1380,1347],{},[19,1382,1383],{},"09\u002F03\u002F2024",[1229,1385,1386],{},"Day-first dates",[1208,1388,1389,1394,1402],{},[1229,1390,1391],{},[19,1392,1393],{},"h:mm:ss",[1229,1395,202,1396,1297,1399],{},[19,1397,1398],{},"time",[19,1400,1401],{},"14:30:00",[1229,1403,1404],{},"Times",[1208,1406,1407,1412,1417],{},[1229,1408,1409],{},[19,1410,1411],{},"@",[1229,1413,1414,1416],{},[19,1415,251],{}," (as text)",[1229,1418,1419],{},"Force text display",[34,1421,1423],{"id":1422},"frequently-asked-questions","Frequently asked questions",[1425,1426,1428],"h3",{"id":1427},"does-number_format-change-the-cells-value","Does number_format change the cell's value?",[10,1430,1431,1432,1435],{},"No. It only changes the display. ",[19,1433,1434],{},"cell.value"," returns the same number you stored, and formulas operate on that raw value. This is the single most important rule when debugging a \"wrong\" report.",[1425,1437,1439],{"id":1438},"why-does-my-percentage-show-as-2500","Why does my percentage show as 2500%?",[10,1441,1442,1443,1445,1446,1448,1449,1451],{},"You stored ",[19,1444,453],{}," instead of ",[19,1447,449],{},". The ",[19,1450,441],{}," code multiplies by 100 for display, so store the ratio. Divide integer percentages by 100 before writing.",[1425,1453,1455],{"id":1454},"why-is-my-currency-format-being-ignored","Why is my currency format being ignored?",[10,1457,1458,1459,1461,1462,999,1465,1468,1469,1472],{},"The cell almost certainly holds text, not a number. A value like ",[19,1460,259],{}," (a string) will not format as currency. Write a real ",[19,1463,1464],{},"int",[19,1466,1467],{},"float",", or convert with ",[19,1470,1471],{},"float(value)"," before assigning.",[1425,1474,1476],{"id":1475},"can-i-reuse-one-format-across-many-cells","Can I reuse one format across many cells?",[10,1478,1479,1480,1482,1483,1486,1487,431],{},"Yes — assigning the same string to many cells' ",[19,1481,85],{}," is cheap. For richer reuse, wrap a format in a ",[19,1484,1485],{},"NamedStyle"," and apply the style by name; see ",[24,1488,1490],{"href":1489},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002F","Styling Excel Cells with openpyxl",[1425,1492,1494],{"id":1493},"do-these-codes-match-excels-format-cells-dialog","Do these codes match Excel's Format Cells dialog?",[10,1496,1497,1498,431],{},"Yes. The strings are the same custom format codes Excel shows under Format Cells → Custom. Anything you can type there, you can assign to ",[19,1499,85],{},[34,1501,1503],{"id":1502},"conclusion","Conclusion",[10,1505,1506,1508,1509,71,1511,1514],{},[19,1507,85],{}," is a display layer over an unchanged value. Store real numbers and real ",[19,1510,1347],{},[19,1512,1513],{},"datetime"," objects, then choose a format code for presentation. Keep ratios as ratios for percentages, supply a negative section for red losses, and loop a column to format a report in one pass. Because formatting never mutates the value, your formulas and exports stay correct no matter how the cells look.",[34,1516,1518],{"id":1517},"where-to-go-next","Where to go next",[1520,1521,1522,1528,1533,1538,1543],"ul",{},[1523,1524,1525,1527],"li",{},[24,1526,27],{"href":26}," — the parent pillar covering visual report polish end to end.",[1523,1529,1530,1532],{},[24,1531,430],{"href":429}," — symbols, accounting parentheses, and whole-column currency.",[1523,1534,1535,1537],{},[24,1536,1196],{"href":1195}," — real date serials and pandas datetime export.",[1523,1539,1540,1542],{},[24,1541,1490],{"href":1489}," — fonts, fills, borders, and reusable named styles.",[1523,1544,1545,1549],{},[24,1546,1548],{"href":1547},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002F","Creating Charts in Excel with openpyxl"," — turn formatted tables into native Excel charts.",[1551,1552,1553],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":44,"searchDepth":124,"depth":124,"links":1555},[1556,1557,1558,1559,1560,1561,1562,1563,1564,1571,1572],{"id":36,"depth":124,"text":37},{"id":78,"depth":124,"text":79},{"id":263,"depth":124,"text":264},{"id":434,"depth":124,"text":435},{"id":617,"depth":124,"text":618},{"id":794,"depth":124,"text":795},{"id":991,"depth":124,"text":992},{"id":1199,"depth":124,"text":1200},{"id":1422,"depth":124,"text":1423,"children":1565},[1566,1567,1568,1569,1570],{"id":1427,"depth":131,"text":1428},{"id":1438,"depth":131,"text":1439},{"id":1454,"depth":131,"text":1455},{"id":1475,"depth":131,"text":1476},{"id":1493,"depth":131,"text":1494},{"id":1502,"depth":124,"text":1503},{"id":1517,"depth":124,"text":1518},"Format numbers, currency, percentages, and dates in Excel from Python with openpyxl number_format codes — display-only formatting that never alters the stored value.","md",{},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel",{"title":1578,"description":1579},"Number and Date Formats in Excel with Python","Use openpyxl number_format codes to show currency, thousands separators, percentages, negatives in red, and dates — without touching the underlying cell value.","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Findex","AUcnxBBCuzG89TYvt1AjJhgPPh0fZMCd4qO1tQSXlU4",[1583,1586],{"title":27,"path":1584,"stem":1585,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python","formatting-and-charting-excel-reports-with-python\u002Findex",{"title":1196,"path":1587,"stem":1588,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-dates-in-excel-cells-with-python","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-dates-in-excel-cells-with-python\u002Findex",1781773160681]