[{"data":1,"prerenderedAt":1718},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-dates-in-excel-cells-with-python":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-dates-in-excel-cells-with-python":1711},{"id":4,"title":5,"body":6,"dateModified":1689,"datePublished":1689,"description":1690,"extension":1691,"faq":1692,"meta":1703,"navigation":264,"path":1704,"seo":1705,"slug":1707,"stem":1708,"type":1709,"__hash__":1710},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-dates-in-excel-cells-with-python\u002Findex.md","Format Dates in Excel Cells with Python",{"type":7,"value":8,"toc":1670},"minimark",[9,37,162,167,191,205,209,223,452,461,465,490,665,682,686,692,914,918,930,1113,1141,1145,1163,1387,1399,1403,1510,1514,1529,1533,1538,1549,1553,1567,1571,1578,1582,1601,1605,1623,1627,1641,1645,1666],[10,11,12,13,17,18,22,23,26,27,30,31,36],"p",{},"Excel stores a date as a number — a serial count of days from a base date — and displays it through a format. If you write a ",[14,15,16],"em",{},"string"," like ",[19,20,21],"code",{},"\"2024-03-09\"",", Excel keeps text and cannot reformat it, sort it as a date, or do date math on it. The fix is to write a real Python ",[19,24,25],{},"date","\u002F",[19,28,29],{},"datetime"," so Excel stores a true serial, then set the display code. This guide, part of ",[32,33,35],"a",{"href":34},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002F","Applying Number and Date Formats in Excel",", is fully runnable.",[38,39,47,48,47,52,47,56,47,66,47,73,47,78,47,86,47,90,47,94,47,98,47,102,47,107,47,113,47,116,47,121,47,124,47,130,47,136,47,141,47,145,47,149,47,154,47,158],"svg",{"viewBox":40,"role":41,"ariaLabelledBy":42,"xmlns":45,"style":46},"0 0 760 230","img",[43,44],"dt-t","dt-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:760px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[49,50,51],"title",{"id":43},"A Python date is stored as an Excel serial and displayed through a format code",[53,54,55],"desc",{"id":44},"A Python date object is stored as an Excel serial number, then rendered two ways depending on the chosen display format code.",[57,58],"rect",{"x":59,"y":60,"width":61,"height":62,"rx":63,"fill":64,"stroke":65},"20","86","170","58","12","var(--surface-muted,#eef2ff)","var(--line,#cdd5e6)",[67,68,72],"text",{"x":69,"y":70,"style":71},"105","74","font-size:12px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","Python date",[67,74,77],{"x":69,"y":75,"style":76},"122","font-size:14px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","date(2024,1,5)",[79,80],"line",{"x1":81,"y1":82,"x2":83,"y2":82,"stroke":84,"style":85},"192","115","266","var(--brand,#5b5cf0)","stroke-width:2px",[87,88],"polygon",{"points":89,"fill":84},"266,115 256,110 256,120",[57,91],{"x":92,"y":60,"width":61,"height":62,"rx":63,"fill":84,"stroke":93},"270","var(--brand-strong,#4338ca)",[67,95,97],{"x":96,"y":70,"style":71},"355","Excel serial",[67,99,101],{"x":96,"y":82,"style":100},"font-size:18px;font-weight:700;fill:#ffffff;text-anchor:middle","45296",[67,103,106],{"x":96,"y":104,"style":105},"134","font-size:10.5px;fill:rgba(255,255,255,0.85);text-anchor:middle","days from base",[79,108],{"x1":109,"y1":110,"x2":111,"y2":70,"stroke":112,"style":85},"442","100","516","var(--teal,#0f9488)",[87,114],{"points":115,"fill":112},"516,74 505,75 509,85",[79,117],{"x1":109,"y1":118,"x2":111,"y2":119,"stroke":120,"style":85},"130","156","var(--gold,#b4740a)",[87,122],{"points":123,"fill":120},"516,156 505,145 501,156",[57,125],{"x":126,"y":127,"width":128,"height":62,"rx":63,"fill":129,"stroke":112},"520","44","220","rgba(15,148,136,0.12)",[67,131,135],{"x":132,"y":133,"style":134},"630","68","font-size:11px;fill:var(--muted,#5b6780);text-anchor:middle","\"yyyy-mm-dd\"",[67,137,140],{"x":132,"y":138,"style":139},"90","font-size:16px;font-weight:700;fill:var(--teal,#0f9488);text-anchor:middle","2024-01-05",[57,142],{"x":126,"y":143,"width":128,"height":62,"rx":63,"fill":144,"stroke":120},"128","rgba(180,116,10,0.12)",[67,146,148],{"x":132,"y":147,"style":134},"152","\"mmm d, yyyy\"",[67,150,153],{"x":132,"y":151,"style":152},"174","font-size:16px;font-weight:700;fill:var(--gold,#b4740a);text-anchor:middle","Jan 5, 2024",[67,155,157],{"x":96,"y":156,"style":134},"172","number_format",[67,159,161],{"x":96,"y":160,"style":134},"190","picks the look",[163,164,166],"h2",{"id":165},"prerequisites-and-install","Prerequisites and install",[168,169,174],"pre",{"className":170,"code":171,"language":172,"meta":173,"style":173},"language-bash shiki shiki-themes github-light github-dark","pip install openpyxl\n","bash","",[19,175,176],{"__ignoreMap":173},[177,178,180,184,188],"span",{"class":79,"line":179},1,[177,181,183],{"class":182},"sScJk","pip",[177,185,187],{"class":186},"sZZnC"," install",[177,189,190],{"class":186}," openpyxl\n",[10,192,193,194,197,198,200,201,204],{},"For the pandas section: ",[19,195,196],{},"pip install pandas openpyxl",". The standard-library ",[19,199,29],{}," module is all you need for the core examples. ",[19,202,203],{},"openpyxl"," does not require Excel.",[163,206,208],{"id":207},"step-1-write-a-real-date-so-excel-stores-a-serial","Step 1: Write a real date so Excel stores a serial",[10,210,211,212,215,216,219,220,222],{},"Assign a ",[19,213,214],{},"datetime.date"," or ",[19,217,218],{},"datetime.datetime"," object directly. ",[19,221,203],{}," converts it to Excel's serial number and applies a default date format, which you then override with your own code.",[168,224,228],{"className":225,"code":226,"language":227,"meta":173,"style":173},"language-python shiki shiki-themes github-light github-dark","from datetime import date, datetime\nfrom openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nws.append([\"Event\", \"When\"])\nws.append([\"Invoice issued\", date(2024, 3, 9)])\nws.append([\"Logged at\", datetime(2024, 3, 9, 14, 30)])\n\nws[\"B2\"].number_format = \"yyyy-mm-dd\"        # 2024-03-09\nws[\"B3\"].number_format = \"yyyy-mm-dd hh:mm\"  # 2024-03-09 14:30\n\nwb.save(\"dates_basic.xlsx\")\nprint(\"B2 is a real date:\", ws[\"B2\"].value)  # datetime.date(2024, 3, 9)\n","python",[19,229,230,246,259,266,278,289,307,335,368,373,394,412,417,429],{"__ignoreMap":173},[177,231,232,236,240,243],{"class":79,"line":179},[177,233,235],{"class":234},"szBVR","from",[177,237,239],{"class":238},"sVt8B"," datetime ",[177,241,242],{"class":234},"import",[177,244,245],{"class":238}," date, datetime\n",[177,247,249,251,254,256],{"class":79,"line":248},2,[177,250,235],{"class":234},[177,252,253],{"class":238}," openpyxl ",[177,255,242],{"class":234},[177,257,258],{"class":238}," Workbook\n",[177,260,262],{"class":79,"line":261},3,[177,263,265],{"emptyLinePlaceholder":264},true,"\n",[177,267,269,272,275],{"class":79,"line":268},4,[177,270,271],{"class":238},"wb ",[177,273,274],{"class":234},"=",[177,276,277],{"class":238}," Workbook()\n",[177,279,281,284,286],{"class":79,"line":280},5,[177,282,283],{"class":238},"ws ",[177,285,274],{"class":234},[177,287,288],{"class":238}," wb.active\n",[177,290,292,295,298,301,304],{"class":79,"line":291},6,[177,293,294],{"class":238},"ws.append([",[177,296,297],{"class":186},"\"Event\"",[177,299,300],{"class":238},", ",[177,302,303],{"class":186},"\"When\"",[177,305,306],{"class":238},"])\n",[177,308,310,312,315,318,322,324,327,329,332],{"class":79,"line":309},7,[177,311,294],{"class":238},[177,313,314],{"class":186},"\"Invoice issued\"",[177,316,317],{"class":238},", date(",[177,319,321],{"class":320},"sj4cs","2024",[177,323,300],{"class":238},[177,325,326],{"class":320},"3",[177,328,300],{"class":238},[177,330,331],{"class":320},"9",[177,333,334],{"class":238},")])\n",[177,336,338,340,343,346,348,350,352,354,356,358,361,363,366],{"class":79,"line":337},8,[177,339,294],{"class":238},[177,341,342],{"class":186},"\"Logged at\"",[177,344,345],{"class":238},", datetime(",[177,347,321],{"class":320},[177,349,300],{"class":238},[177,351,326],{"class":320},[177,353,300],{"class":238},[177,355,331],{"class":320},[177,357,300],{"class":238},[177,359,360],{"class":320},"14",[177,362,300],{"class":238},[177,364,365],{"class":320},"30",[177,367,334],{"class":238},[177,369,371],{"class":79,"line":370},9,[177,372,265],{"emptyLinePlaceholder":264},[177,374,376,379,382,385,387,390],{"class":79,"line":375},10,[177,377,378],{"class":238},"ws[",[177,380,381],{"class":186},"\"B2\"",[177,383,384],{"class":238},"].number_format ",[177,386,274],{"class":234},[177,388,389],{"class":186}," \"yyyy-mm-dd\"",[177,391,393],{"class":392},"sJ8bj","        # 2024-03-09\n",[177,395,397,399,402,404,406,409],{"class":79,"line":396},11,[177,398,378],{"class":238},[177,400,401],{"class":186},"\"B3\"",[177,403,384],{"class":238},[177,405,274],{"class":234},[177,407,408],{"class":186}," \"yyyy-mm-dd hh:mm\"",[177,410,411],{"class":392},"  # 2024-03-09 14:30\n",[177,413,415],{"class":79,"line":414},12,[177,416,265],{"emptyLinePlaceholder":264},[177,418,420,423,426],{"class":79,"line":419},13,[177,421,422],{"class":238},"wb.save(",[177,424,425],{"class":186},"\"dates_basic.xlsx\"",[177,427,428],{"class":238},")\n",[177,430,432,435,438,441,444,446,449],{"class":79,"line":431},14,[177,433,434],{"class":320},"print",[177,436,437],{"class":238},"(",[177,439,440],{"class":186},"\"B2 is a real date:\"",[177,442,443],{"class":238},", ws[",[177,445,381],{"class":186},[177,447,448],{"class":238},"].value)  ",[177,450,451],{"class":392},"# datetime.date(2024, 3, 9)\n",[10,453,454,457,458,460],{},[19,455,456],{},"ws[\"B2\"].value"," round-trips as a ",[19,459,25],{}," object, proving Excel holds a serial, not text.",[163,462,464],{"id":463},"step-2-choose-a-display-layout","Step 2: Choose a display layout",[10,466,467,468,26,471,474,475,26,478,481,482,485,486,489],{},"The same stored date can render many ways. Pick a code and assign it. ",[19,469,470],{},"m",[19,472,473],{},"d"," are unpadded, ",[19,476,477],{},"mm",[19,479,480],{},"dd"," are zero-padded, ",[19,483,484],{},"mmm"," is the short month name, and ",[19,487,488],{},"yyyy"," is the four-digit year.",[168,491,493],{"className":225,"code":492,"language":227,"meta":173,"style":173},"from datetime import date\nfrom openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nd = date(2024, 3, 9)\nfor row, code in enumerate([\"yyyy-mm-dd\", \"mmm d, yyyy\", \"dd\u002Fmm\u002Fyyyy\", \"d mmmm yyyy\"], start=1):\n    ws.cell(row=row, column=1, value=d).number_format = code\n\nwb.save(\"dates_layouts.xlsx\")\nprint(\"Same date serial, four display codes\")\n",[19,494,495,506,516,520,528,536,558,606,641,645,654],{"__ignoreMap":173},[177,496,497,499,501,503],{"class":79,"line":179},[177,498,235],{"class":234},[177,500,239],{"class":238},[177,502,242],{"class":234},[177,504,505],{"class":238}," date\n",[177,507,508,510,512,514],{"class":79,"line":248},[177,509,235],{"class":234},[177,511,253],{"class":238},[177,513,242],{"class":234},[177,515,258],{"class":238},[177,517,518],{"class":79,"line":261},[177,519,265],{"emptyLinePlaceholder":264},[177,521,522,524,526],{"class":79,"line":268},[177,523,271],{"class":238},[177,525,274],{"class":234},[177,527,277],{"class":238},[177,529,530,532,534],{"class":79,"line":280},[177,531,283],{"class":238},[177,533,274],{"class":234},[177,535,288],{"class":238},[177,537,538,541,543,546,548,550,552,554,556],{"class":79,"line":291},[177,539,540],{"class":238},"d ",[177,542,274],{"class":234},[177,544,545],{"class":238}," date(",[177,547,321],{"class":320},[177,549,300],{"class":238},[177,551,326],{"class":320},[177,553,300],{"class":238},[177,555,331],{"class":320},[177,557,428],{"class":238},[177,559,560,563,566,569,572,575,577,579,581,583,586,588,591,594,598,600,603],{"class":79,"line":309},[177,561,562],{"class":234},"for",[177,564,565],{"class":238}," row, code ",[177,567,568],{"class":234},"in",[177,570,571],{"class":320}," enumerate",[177,573,574],{"class":238},"([",[177,576,135],{"class":186},[177,578,300],{"class":238},[177,580,148],{"class":186},[177,582,300],{"class":238},[177,584,585],{"class":186},"\"dd\u002Fmm\u002Fyyyy\"",[177,587,300],{"class":238},[177,589,590],{"class":186},"\"d mmmm yyyy\"",[177,592,593],{"class":238},"], ",[177,595,597],{"class":596},"s4XuR","start",[177,599,274],{"class":234},[177,601,602],{"class":320},"1",[177,604,605],{"class":238},"):\n",[177,607,608,611,614,616,619,622,624,626,628,631,633,636,638],{"class":79,"line":337},[177,609,610],{"class":238},"    ws.cell(",[177,612,613],{"class":596},"row",[177,615,274],{"class":234},[177,617,618],{"class":238},"row, ",[177,620,621],{"class":596},"column",[177,623,274],{"class":234},[177,625,602],{"class":320},[177,627,300],{"class":238},[177,629,630],{"class":596},"value",[177,632,274],{"class":234},[177,634,635],{"class":238},"d).number_format ",[177,637,274],{"class":234},[177,639,640],{"class":238}," code\n",[177,642,643],{"class":79,"line":370},[177,644,265],{"emptyLinePlaceholder":264},[177,646,647,649,652],{"class":79,"line":375},[177,648,422],{"class":238},[177,650,651],{"class":186},"\"dates_layouts.xlsx\"",[177,653,428],{"class":238},[177,655,656,658,660,663],{"class":79,"line":396},[177,657,434],{"class":320},[177,659,437],{"class":238},[177,661,662],{"class":186},"\"Same date serial, four display codes\"",[177,664,428],{"class":238},[10,666,667,668,300,671,300,674,677,678,681],{},"This writes ",[19,669,670],{},"2024-03-09",[19,672,673],{},"Mar 9, 2024",[19,675,676],{},"09\u002F03\u002F2024",", and ",[19,679,680],{},"9 March 2024"," — all from the identical stored value.",[163,683,685],{"id":684},"step-3-format-a-date-column-across-rows","Step 3: Format a date column across rows",[10,687,688,689,691],{},"Loop the date column and set one code on each data cell, skipping the header. Because every cell holds a real ",[19,690,25],{},", the format simply changes presentation.",[168,693,695],{"className":225,"code":694,"language":227,"meta":173,"style":173},"from datetime import date\nfrom openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\nws.append([\"Invoice\", \"Due\"])\nfor n, d in [(\"INV-001\", date(2024, 1, 31)),\n             (\"INV-002\", date(2024, 2, 29)),\n             (\"INV-003\", date(2024, 3, 15))]:\n    ws.append([n, d])\n\nfor cell in ws[\"B\"][1:]:               # column B, skip header\n    cell.number_format = \"mmm d, yyyy\"\n\nwb.save(\"dates_column.xlsx\")\nprint(\"Formatted\", ws.max_row - 1, \"due dates\")\n",[19,696,697,707,717,721,729,737,751,782,806,829,834,838,864,874,878,888],{"__ignoreMap":173},[177,698,699,701,703,705],{"class":79,"line":179},[177,700,235],{"class":234},[177,702,239],{"class":238},[177,704,242],{"class":234},[177,706,505],{"class":238},[177,708,709,711,713,715],{"class":79,"line":248},[177,710,235],{"class":234},[177,712,253],{"class":238},[177,714,242],{"class":234},[177,716,258],{"class":238},[177,718,719],{"class":79,"line":261},[177,720,265],{"emptyLinePlaceholder":264},[177,722,723,725,727],{"class":79,"line":268},[177,724,271],{"class":238},[177,726,274],{"class":234},[177,728,277],{"class":238},[177,730,731,733,735],{"class":79,"line":280},[177,732,283],{"class":238},[177,734,274],{"class":234},[177,736,288],{"class":238},[177,738,739,741,744,746,749],{"class":79,"line":291},[177,740,294],{"class":238},[177,742,743],{"class":186},"\"Invoice\"",[177,745,300],{"class":238},[177,747,748],{"class":186},"\"Due\"",[177,750,306],{"class":238},[177,752,753,755,758,760,763,766,768,770,772,774,776,779],{"class":79,"line":309},[177,754,562],{"class":234},[177,756,757],{"class":238}," n, d ",[177,759,568],{"class":234},[177,761,762],{"class":238}," [(",[177,764,765],{"class":186},"\"INV-001\"",[177,767,317],{"class":238},[177,769,321],{"class":320},[177,771,300],{"class":238},[177,773,602],{"class":320},[177,775,300],{"class":238},[177,777,778],{"class":320},"31",[177,780,781],{"class":238},")),\n",[177,783,784,787,790,792,794,796,799,801,804],{"class":79,"line":337},[177,785,786],{"class":238},"             (",[177,788,789],{"class":186},"\"INV-002\"",[177,791,317],{"class":238},[177,793,321],{"class":320},[177,795,300],{"class":238},[177,797,798],{"class":320},"2",[177,800,300],{"class":238},[177,802,803],{"class":320},"29",[177,805,781],{"class":238},[177,807,808,810,813,815,817,819,821,823,826],{"class":79,"line":370},[177,809,786],{"class":238},[177,811,812],{"class":186},"\"INV-003\"",[177,814,317],{"class":238},[177,816,321],{"class":320},[177,818,300],{"class":238},[177,820,326],{"class":320},[177,822,300],{"class":238},[177,824,825],{"class":320},"15",[177,827,828],{"class":238},"))]:\n",[177,830,831],{"class":79,"line":375},[177,832,833],{"class":238},"    ws.append([n, d])\n",[177,835,836],{"class":79,"line":396},[177,837,265],{"emptyLinePlaceholder":264},[177,839,840,842,845,847,850,853,856,858,861],{"class":79,"line":414},[177,841,562],{"class":234},[177,843,844],{"class":238}," cell ",[177,846,568],{"class":234},[177,848,849],{"class":238}," ws[",[177,851,852],{"class":186},"\"B\"",[177,854,855],{"class":238},"][",[177,857,602],{"class":320},[177,859,860],{"class":238},":]:               ",[177,862,863],{"class":392},"# column B, skip header\n",[177,865,866,869,871],{"class":79,"line":419},[177,867,868],{"class":238},"    cell.number_format ",[177,870,274],{"class":234},[177,872,873],{"class":186}," \"mmm d, yyyy\"\n",[177,875,876],{"class":79,"line":431},[177,877,265],{"emptyLinePlaceholder":264},[177,879,881,883,886],{"class":79,"line":880},15,[177,882,422],{"class":238},[177,884,885],{"class":186},"\"dates_column.xlsx\"",[177,887,428],{"class":238},[177,889,891,893,895,898,901,904,907,909,912],{"class":79,"line":890},16,[177,892,434],{"class":320},[177,894,437],{"class":238},[177,896,897],{"class":186},"\"Formatted\"",[177,899,900],{"class":238},", ws.max_row ",[177,902,903],{"class":234},"-",[177,905,906],{"class":320}," 1",[177,908,300],{"class":238},[177,910,911],{"class":186},"\"due dates\"",[177,913,428],{"class":238},[163,915,917],{"id":916},"why-a-string-date-cannot-be-reformatted","Why a string date cannot be reformatted",[10,919,920,921,923,924,926,927,929],{},"If a cell holds the text ",[19,922,21],{},", applying a date ",[19,925,157],{}," does nothing — there is no serial to reformat. Excel treats text as text. Detect and fix this by parsing the string back into a ",[19,928,25],{}," before writing.",[168,931,933],{"className":225,"code":932,"language":227,"meta":173,"style":173},"from datetime import datetime\nfrom openpyxl import Workbook\n\nwb = Workbook()\nws = wb.active\n\nws[\"A1\"] = \"2024-03-09\"                          # text — a date format would be ignored\nws[\"A2\"] = datetime.strptime(\"2024-03-09\", \"%Y-%m-%d\").date()  # real date\nws[\"A2\"].number_format = \"mmm d, yyyy\"\n\nprint(\"A1 type:\", type(ws[\"A1\"].value).__name__)  # str\nprint(\"A2 type:\", type(ws[\"A2\"].value).__name__)  # date\nwb.save(\"dates_text_vs_real.xlsx\")\n",[19,934,935,946,956,960,968,976,980,998,1031,1043,1047,1078,1104],{"__ignoreMap":173},[177,936,937,939,941,943],{"class":79,"line":179},[177,938,235],{"class":234},[177,940,239],{"class":238},[177,942,242],{"class":234},[177,944,945],{"class":238}," datetime\n",[177,947,948,950,952,954],{"class":79,"line":248},[177,949,235],{"class":234},[177,951,253],{"class":238},[177,953,242],{"class":234},[177,955,258],{"class":238},[177,957,958],{"class":79,"line":261},[177,959,265],{"emptyLinePlaceholder":264},[177,961,962,964,966],{"class":79,"line":268},[177,963,271],{"class":238},[177,965,274],{"class":234},[177,967,277],{"class":238},[177,969,970,972,974],{"class":79,"line":280},[177,971,283],{"class":238},[177,973,274],{"class":234},[177,975,288],{"class":238},[177,977,978],{"class":79,"line":291},[177,979,265],{"emptyLinePlaceholder":264},[177,981,982,984,987,990,992,995],{"class":79,"line":309},[177,983,378],{"class":238},[177,985,986],{"class":186},"\"A1\"",[177,988,989],{"class":238},"] ",[177,991,274],{"class":234},[177,993,994],{"class":186}," \"2024-03-09\"",[177,996,997],{"class":392},"                          # text — a date format would be ignored\n",[177,999,1000,1002,1005,1007,1009,1012,1014,1016,1019,1022,1025,1028],{"class":79,"line":337},[177,1001,378],{"class":238},[177,1003,1004],{"class":186},"\"A2\"",[177,1006,989],{"class":238},[177,1008,274],{"class":234},[177,1010,1011],{"class":238}," datetime.strptime(",[177,1013,21],{"class":186},[177,1015,300],{"class":238},[177,1017,1018],{"class":186},"\"%Y-%m-",[177,1020,1021],{"class":320},"%d",[177,1023,1024],{"class":186},"\"",[177,1026,1027],{"class":238},").date()  ",[177,1029,1030],{"class":392},"# real date\n",[177,1032,1033,1035,1037,1039,1041],{"class":79,"line":370},[177,1034,378],{"class":238},[177,1036,1004],{"class":186},[177,1038,384],{"class":238},[177,1040,274],{"class":234},[177,1042,873],{"class":186},[177,1044,1045],{"class":79,"line":375},[177,1046,265],{"emptyLinePlaceholder":264},[177,1048,1049,1051,1053,1056,1058,1061,1064,1066,1069,1072,1075],{"class":79,"line":396},[177,1050,434],{"class":320},[177,1052,437],{"class":238},[177,1054,1055],{"class":186},"\"A1 type:\"",[177,1057,300],{"class":238},[177,1059,1060],{"class":320},"type",[177,1062,1063],{"class":238},"(ws[",[177,1065,986],{"class":186},[177,1067,1068],{"class":238},"].value).",[177,1070,1071],{"class":320},"__name__",[177,1073,1074],{"class":238},")  ",[177,1076,1077],{"class":392},"# str\n",[177,1079,1080,1082,1084,1087,1089,1091,1093,1095,1097,1099,1101],{"class":79,"line":414},[177,1081,434],{"class":320},[177,1083,437],{"class":238},[177,1085,1086],{"class":186},"\"A2 type:\"",[177,1088,300],{"class":238},[177,1090,1060],{"class":320},[177,1092,1063],{"class":238},[177,1094,1004],{"class":186},[177,1096,1068],{"class":238},[177,1098,1071],{"class":320},[177,1100,1074],{"class":238},[177,1102,1103],{"class":392},"# date\n",[177,1105,1106,1108,1111],{"class":79,"line":419},[177,1107,422],{"class":238},[177,1109,1110],{"class":186},"\"dates_text_vs_real.xlsx\"",[177,1112,428],{"class":238},[10,1114,1115,1118,1119,1122,1123,1126,1127,1129,1130,1132,1133,1136,1137,1140],{},[19,1116,1117],{},"A1"," stays a ",[19,1120,1121],{},"str","; ",[19,1124,1125],{},"A2"," is a real ",[19,1128,25],{}," that now displays as ",[19,1131,673],{},". Always parse incoming string dates with ",[19,1134,1135],{},"datetime.strptime"," (or ",[19,1138,1139],{},"pandas.to_datetime",") before writing.",[163,1142,1144],{"id":1143},"handling-pandas-datetime-columns-on-export","Handling pandas datetime columns on export",[10,1146,1147,1148,1151,1152,1155,1156,1158,1159,1162],{},"pandas writes proper datetime cells when the column dtype is ",[19,1149,1150],{},"datetime64",", so the values arrive as real serials. But ",[19,1153,1154],{},"to_excel"," applies a default format; reopen with ",[19,1157,203],{}," to set your own. If your column is still strings, convert it with ",[19,1160,1161],{},"pd.to_datetime"," first.",[168,1164,1166],{"className":225,"code":1165,"language":227,"meta":173,"style":173},"import pandas as pd\nfrom openpyxl import load_workbook\n\ndf = pd.DataFrame({\n    \"Invoice\": [\"INV-001\", \"INV-002\"],\n    \"Due\": [\"2024-01-31\", \"2024-02-29\"],     # strings on purpose\n})\ndf[\"Due\"] = pd.to_datetime(df[\"Due\"])         # convert to real datetimes\ndf.to_excel(\"pandas_dates.xlsx\", index=False, sheet_name=\"Invoices\")\n\nwb = load_workbook(\"pandas_dates.xlsx\")\nws = wb[\"Invoices\"]\nfor cell in ws[\"B\"][1:]:                       # Due is column B\n    cell.number_format = \"dd\u002Fmm\u002Fyyyy\"\n\nwb.save(\"pandas_dates.xlsx\")\nprint(\"Converted, exported, and reformatted the Due column\")\n",[19,1167,1168,1181,1192,1196,1206,1223,1244,1249,1271,1301,1305,1318,1332,1354,1363,1367,1375],{"__ignoreMap":173},[177,1169,1170,1172,1175,1178],{"class":79,"line":179},[177,1171,242],{"class":234},[177,1173,1174],{"class":238}," pandas ",[177,1176,1177],{"class":234},"as",[177,1179,1180],{"class":238}," pd\n",[177,1182,1183,1185,1187,1189],{"class":79,"line":248},[177,1184,235],{"class":234},[177,1186,253],{"class":238},[177,1188,242],{"class":234},[177,1190,1191],{"class":238}," load_workbook\n",[177,1193,1194],{"class":79,"line":261},[177,1195,265],{"emptyLinePlaceholder":264},[177,1197,1198,1201,1203],{"class":79,"line":268},[177,1199,1200],{"class":238},"df ",[177,1202,274],{"class":234},[177,1204,1205],{"class":238}," pd.DataFrame({\n",[177,1207,1208,1211,1214,1216,1218,1220],{"class":79,"line":280},[177,1209,1210],{"class":186},"    \"Invoice\"",[177,1212,1213],{"class":238},": [",[177,1215,765],{"class":186},[177,1217,300],{"class":238},[177,1219,789],{"class":186},[177,1221,1222],{"class":238},"],\n",[177,1224,1225,1228,1230,1233,1235,1238,1241],{"class":79,"line":291},[177,1226,1227],{"class":186},"    \"Due\"",[177,1229,1213],{"class":238},[177,1231,1232],{"class":186},"\"2024-01-31\"",[177,1234,300],{"class":238},[177,1236,1237],{"class":186},"\"2024-02-29\"",[177,1239,1240],{"class":238},"],     ",[177,1242,1243],{"class":392},"# strings on purpose\n",[177,1245,1246],{"class":79,"line":309},[177,1247,1248],{"class":238},"})\n",[177,1250,1251,1254,1256,1258,1260,1263,1265,1268],{"class":79,"line":337},[177,1252,1253],{"class":238},"df[",[177,1255,748],{"class":186},[177,1257,989],{"class":238},[177,1259,274],{"class":234},[177,1261,1262],{"class":238}," pd.to_datetime(df[",[177,1264,748],{"class":186},[177,1266,1267],{"class":238},"])         ",[177,1269,1270],{"class":392},"# convert to real datetimes\n",[177,1272,1273,1276,1279,1281,1284,1286,1289,1291,1294,1296,1299],{"class":79,"line":370},[177,1274,1275],{"class":238},"df.to_excel(",[177,1277,1278],{"class":186},"\"pandas_dates.xlsx\"",[177,1280,300],{"class":238},[177,1282,1283],{"class":596},"index",[177,1285,274],{"class":234},[177,1287,1288],{"class":320},"False",[177,1290,300],{"class":238},[177,1292,1293],{"class":596},"sheet_name",[177,1295,274],{"class":234},[177,1297,1298],{"class":186},"\"Invoices\"",[177,1300,428],{"class":238},[177,1302,1303],{"class":79,"line":375},[177,1304,265],{"emptyLinePlaceholder":264},[177,1306,1307,1309,1311,1314,1316],{"class":79,"line":396},[177,1308,271],{"class":238},[177,1310,274],{"class":234},[177,1312,1313],{"class":238}," load_workbook(",[177,1315,1278],{"class":186},[177,1317,428],{"class":238},[177,1319,1320,1322,1324,1327,1329],{"class":79,"line":414},[177,1321,283],{"class":238},[177,1323,274],{"class":234},[177,1325,1326],{"class":238}," wb[",[177,1328,1298],{"class":186},[177,1330,1331],{"class":238},"]\n",[177,1333,1334,1336,1338,1340,1342,1344,1346,1348,1351],{"class":79,"line":419},[177,1335,562],{"class":234},[177,1337,844],{"class":238},[177,1339,568],{"class":234},[177,1341,849],{"class":238},[177,1343,852],{"class":186},[177,1345,855],{"class":238},[177,1347,602],{"class":320},[177,1349,1350],{"class":238},":]:                       ",[177,1352,1353],{"class":392},"# Due is column B\n",[177,1355,1356,1358,1360],{"class":79,"line":431},[177,1357,868],{"class":238},[177,1359,274],{"class":234},[177,1361,1362],{"class":186}," \"dd\u002Fmm\u002Fyyyy\"\n",[177,1364,1365],{"class":79,"line":880},[177,1366,265],{"emptyLinePlaceholder":264},[177,1368,1369,1371,1373],{"class":79,"line":890},[177,1370,422],{"class":238},[177,1372,1278],{"class":186},[177,1374,428],{"class":238},[177,1376,1378,1380,1382,1385],{"class":79,"line":1377},17,[177,1379,434],{"class":320},[177,1381,437],{"class":238},[177,1383,1384],{"class":186},"\"Converted, exported, and reformatted the Due column\"",[177,1386,428],{"class":238},[10,1388,1389,1390,1393,1394,1398],{},"Exporting with ",[19,1391,1392],{},"index=False"," keeps the date column at B; see ",[32,1395,1397],{"href":1396},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fwrite-pandas-dataframe-to-excel-without-index\u002F","Write a Pandas DataFrame to Excel Without the Index",".",[163,1400,1402],{"id":1401},"common-pitfalls","Common pitfalls",[1404,1405,1406,1422],"table",{},[1407,1408,1409],"thead",{},[1410,1411,1412,1416,1419],"tr",{},[1413,1414,1415],"th",{},"Symptom",[1413,1417,1418],{},"Cause",[1413,1420,1421],{},"Fix",[1423,1424,1425,1442,1458,1481,1499],"tbody",{},[1410,1426,1427,1431,1434],{},[1428,1429,1430],"td",{},"Date format ignored",[1428,1432,1433],{},"Cell holds a string, not a date serial",[1428,1435,1436,1437,26,1439,1441],{},"Parse with ",[19,1438,1135],{},[19,1440,1161],{}," before writing",[1410,1443,1444,1447,1450],{},[1428,1445,1446],{},"Cannot sort or filter as dates",[1428,1448,1449],{},"Values are text",[1428,1451,1452,1453,26,1455,1457],{},"Convert to real ",[19,1454,25],{},[19,1456,29],{}," objects",[1410,1459,1460,1463,1471],{},[1428,1461,1462],{},"Time component shows when you want a date",[1428,1464,1465,1466,1468,1469],{},"Wrote a ",[19,1467,29],{},", not a ",[19,1470,25],{},[1428,1472,1473,1474,1477,1478],{},"Use ",[19,1475,1476],{},"dt.date()",", or a date-only code like ",[19,1479,1480],{},"yyyy-mm-dd",[1410,1482,1483,1489,1492],{},[1428,1484,1485,1488],{},[19,1486,1487],{},"ValueError"," writing a tz-aware datetime",[1428,1490,1491],{},"Excel has no timezone concept",[1428,1493,1494,1495,1498],{},"Strip tzinfo: ",[19,1496,1497],{},"dt.replace(tzinfo=None)"," (after converting to your target zone)",[1410,1500,1501,1504,1507],{},[1428,1502,1503],{},"Off-by-one near early-1900 dates",[1428,1505,1506],{},"Excel's 1900 leap-year quirk",[1428,1508,1509],{},"Avoid pre-1900 dates; modern dates are unaffected",[163,1511,1513],{"id":1512},"a-note-on-timezones-and-the-1900-quirk","A note on timezones and the 1900 quirk",[10,1515,1516,1517,1519,1520,1522,1523,1525,1526,1528],{},"Excel dates are timezone-naive: there is no UTC offset stored. Convert a timezone-aware ",[19,1518,29],{}," to your intended zone first, then strip the tzinfo with ",[19,1521,1497],{}," before writing, or ",[19,1524,203],{}," raises a ",[19,1527,1487],{},". Separately, Excel intentionally treats 1900 as a leap year (a legacy bug it keeps for compatibility), so serials before March 1900 can be off by a day. This never affects ordinary modern reporting dates — it is only a concern for historical data reaching back over a century.",[163,1530,1532],{"id":1531},"frequently-asked-questions","Frequently asked questions",[1534,1535,1537],"h3",{"id":1536},"why-does-my-date-format-do-nothing","Why does my date format do nothing?",[10,1539,1540,1541,1543,1544,26,1546,1548],{},"The cell holds a string. A date ",[19,1542,157],{}," only formats a stored date serial. Parse the string into a ",[19,1545,25],{},[19,1547,29],{}," object first, then write it.",[1534,1550,1552],{"id":1551},"how-do-i-store-a-real-date-instead-of-text","How do I store a real date instead of text?",[10,1554,211,1555,215,1557,1559,1560,1562,1563,1566],{},[19,1556,214],{},[19,1558,218],{}," object to the cell. ",[19,1561,203],{}," converts it to Excel's serial number automatically; ",[19,1564,1565],{},"cell.value"," reads back as a date object.",[1534,1568,1570],{"id":1569},"how-do-i-show-a-date-as-ddmmyyyy","How do I show a date as dd\u002Fmm\u002Fyyyy?",[10,1572,1573,1574,1577],{},"Set ",[19,1575,1576],{},"cell.number_format = \"dd\u002Fmm\u002Fyyyy\"",". The format controls layout only; the stored serial is identical regardless of which code you choose.",[1534,1579,1581],{"id":1580},"why-does-my-date-include-a-time-of-0000","Why does my date include a time of 00:00?",[10,1583,1584,1585,1587,1588,1590,1591,1594,1595,1597,1598,1398],{},"You wrote a ",[19,1586,29],{}," with no time, or used a code that includes hours. Use a ",[19,1589,25],{}," object, call ",[19,1592,1593],{},".date()"," on a ",[19,1596,29],{},", or pick a date-only code like ",[19,1599,1600],{},"mmm d, yyyy",[1534,1602,1604],{"id":1603},"how-do-i-format-dates-from-a-pandas-dataframe","How do I format dates from a pandas DataFrame?",[10,1606,1607,1608,1610,1611,1613,1614,1616,1617,1619,1620,1622],{},"Ensure the column is ",[19,1609,1150],{}," (convert with ",[19,1612,1161],{},"), export with ",[19,1615,1154],{},", then reopen with ",[19,1618,203],{}," and set ",[19,1621,157],{}," on the date column.",[163,1624,1626],{"id":1625},"conclusion","Conclusion",[10,1628,1629,1630,26,1632,1634,1635,215,1638,1640],{},"Correct Excel dates are two layers: a real ",[19,1631,25],{},[19,1633,29],{}," value Excel stores as a serial, and a display code on top. Always write objects, never pre-formatted strings — a text date cannot be reformatted, sorted, or computed. Parse incoming strings with ",[19,1636,1637],{},"strptime",[19,1639,1161],{},", strip timezones, and the format codes do the rest.",[163,1642,1644],{"id":1643},"where-to-go-next","Where to go next",[1646,1647,1648,1654,1661],"ul",{},[1649,1650,1651,1653],"li",{},[32,1652,35],{"href":34}," — the parent cluster: separators, percentages, and the format-code reference table.",[1649,1655,1656,1660],{},[32,1657,1659],{"href":1658},"\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"," — the currency companion to this guide.",[1649,1662,1663,1665],{},[32,1664,1397],{"href":1396}," — keep your date column in the right place after export.",[1667,1668,1669],"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}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":173,"searchDepth":248,"depth":248,"links":1671},[1672,1673,1674,1675,1676,1677,1678,1679,1680,1687,1688],{"id":165,"depth":248,"text":166},{"id":207,"depth":248,"text":208},{"id":463,"depth":248,"text":464},{"id":684,"depth":248,"text":685},{"id":916,"depth":248,"text":917},{"id":1143,"depth":248,"text":1144},{"id":1401,"depth":248,"text":1402},{"id":1512,"depth":248,"text":1513},{"id":1531,"depth":248,"text":1532,"children":1681},[1682,1683,1684,1685,1686],{"id":1536,"depth":261,"text":1537},{"id":1551,"depth":261,"text":1552},{"id":1569,"depth":261,"text":1570},{"id":1580,"depth":261,"text":1581},{"id":1603,"depth":261,"text":1604},{"id":1625,"depth":248,"text":1626},{"id":1643,"depth":248,"text":1644},"2026-06-18","Format dates in Excel cells with openpyxl: write real datetime objects so Excel stores a date serial, then apply yyyy-mm-dd, mmm d yyyy, or dd\u002Fmm\u002Fyyyy display codes.","md",[1693,1695,1697,1699,1701],{"q":1537,"a":1694},"The cell holds a string. A date number_format only formats a stored date serial. Parse the string into a date\u002Fdatetime object first, then write it.",{"q":1552,"a":1696},"Assign a datetime.date or datetime.datetime object to the cell. openpyxl converts it to Excel's serial number automatically; cell.value reads back as a date object.",{"q":1570,"a":1698},"Set cell.number_format = \"dd\u002Fmm\u002Fyyyy\". The format controls layout only; the stored serial is identical regardless of which code you choose.",{"q":1581,"a":1700},"You wrote a datetime with no time, or used a code that includes hours. Use a date object, call .date() on a datetime, or pick a date-only code like mmm d, yyyy.",{"q":1604,"a":1702},"Ensure the column is datetime64 (convert with pd.to_datetime), export with to_excel, then reopen with openpyxl and set number_format on the date column.",{},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-dates-in-excel-cells-with-python",{"title":5,"description":1706},"Step-by-step openpyxl date formatting: store real date serials from datetime objects, apply ISO and locale layouts, fix text dates, and format pandas datetime columns.","format-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","long_tail","IOmUwivts8zJmbZm-VSReZwdKcdTn5IWaOnIocb0V3M",[1712,1715],{"title":35,"path":1713,"stem":1714,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Findex",{"title":1659,"path":1716,"stem":1717,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-excel-cells-as-currency-with-python","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-excel-cells-as-currency-with-python\u002Findex",1781795518821]