[{"data":1,"prerenderedAt":3142},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates":3134},{"id":4,"title":5,"body":6,"dateModified":132,"datePublished":132,"description":3112,"extension":3113,"faq":3114,"meta":3125,"navigation":200,"path":3126,"seo":3127,"slug":3130,"stem":3131,"type":3132,"__hash__":3133},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates\u002Findex.md","Fix Excel Serial Numbers Showing Instead of Dates",{"type":7,"value":8,"toc":3100},"minimark",[9,31,133,138,169,172,254,274,278,284,446,462,878,881,993,1016,1020,1027,1201,1211,1214,1385,1399,1403,1406,1522,1525,2101,2104,2108,2116,2352,2363,2367,2504,2508,2617,2624,2630,2797,2800,2942,2953,2957,2981,2985,2997,3016,3032,3041,3051,3055,3096],[10,11,12,13,17,18,17,21,24,25,30],"p",{},"You open the workbook your script produced and the date column reads ",[14,15,16],"code",{},"45292",", ",[14,19,20],{},"45293",[14,22,23],{},"45294",". Nothing is broken — those are the right values. Excel stores every date as a count of days and decides at display time whether to render that number as a date, and your cells are missing the instruction that makes it do so. This guide fixes it three ways: at write time with openpyxl, at write time through pandas, and as a repair pass over a workbook you already have. It builds on the storage model explained in ",[26,27,29],"a",{"href":28},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002F","Working with Dates and Times in Excel Data",".",[32,33,42,43,42,47,42,51,42,58,42,68,42,75,42,80,42,92,42,102,42,110,42,116,42,120,42,125,42,130],"svg",{"viewBox":34,"role":35,"ariaLabel":36,"ariaLabelledBy":37,"xmlns":40,"style":41},"0 0 800 216","img","The same stored value 46249 rendered two ways: with the General number format it shows as 46249, and with the yyyy-mm-dd format it shows as 2026-08-15. Only the format differs.",[38,39],"serfix-t","serfix-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:800px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[44,45,46],"title",{"id":38},"Same value, two number formats, two very different cells",[48,49,50],"desc",{"id":39},"A single stored value of 46249 branches to two rendered cells. Under the General number format Excel displays the bare number 46249, which is what users report as a bug. Under the yyyy-mm-dd number format the identical value displays as 2026-08-15. The data is untouched in both cases; only the display instruction differs.",[52,53],"rect",{"x":54,"y":54,"width":55,"height":56,"fill":57},"0","800","216","#ffffff",[52,59],{"x":60,"y":61,"width":62,"height":63,"rx":64,"fill":65,"stroke":66,"style":67},"288","18","224","58","13","#ebebfd","var(--brand,#5b5cf0)","stroke-width:2px",[69,70,74],"text",{"x":71,"y":72,"style":73},"400","42","font-size:11px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","stored in the cell",[69,76,79],{"x":71,"y":77,"style":78},"66","font-size:19px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","46249",[81,82,84,85,84,89,42],"g",{"stroke":66,"style":67,"fill":83},"none","\n    ",[86,87],"path",{"d":88},"M400 76 V 98 H 180 V 122",[86,90],{"d":91},"M400 76 V 98 H 620 V 122",[81,93,84,95,84,99,42],{"fill":94},"#5b5cf0",[96,97],"polygon",{"points":98},"180,130 173,118 187,118",[96,100],{"points":101},"620,130 613,118 627,118",[52,103],{"x":104,"y":105,"width":106,"height":107,"rx":64,"fill":108,"stroke":109,"style":67},"34","130","292","70","#fee8f2","var(--accent,#f43f8f)",[69,111,115],{"x":112,"y":113,"style":114},"180","154","font-size:11.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","number_format = \"General\"",[69,117,79],{"x":112,"y":118,"style":119},"182","font-size:17px;font-weight:700;fill:var(--text,#172033);text-anchor:middle",[52,121],{"x":122,"y":105,"width":106,"height":107,"rx":64,"fill":123,"stroke":124,"style":67},"474","#d9f4f1","var(--teal,#0f9488)",[69,126,129],{"x":127,"y":113,"style":128},"620","font-size:11.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","number_format = \"yyyy-mm-dd\"",[69,131,132],{"x":127,"y":118,"style":119},"2026-08-15",[134,135,137],"h2",{"id":136},"prerequisites","Prerequisites",[139,140,145],"pre",{"className":141,"code":142,"language":143,"meta":144,"style":144},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl xlsxwriter\n","bash","",[14,146,147],{"__ignoreMap":144},[148,149,152,156,160,163,166],"span",{"class":150,"line":151},"line",1,[148,153,155],{"class":154},"sMTad","pip",[148,157,159],{"class":158},"srMev"," install",[148,161,162],{"class":158}," pandas",[148,164,165],{"class":158}," openpyxl",[148,167,168],{"class":158}," xlsxwriter\n",[10,170,171],{},"Before fixing anything, confirm which of two situations you are in, because they need different fixes:",[139,173,177],{"className":174,"code":175,"language":176,"meta":144,"style":144},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\ndf = pd.read_excel(\"report.xlsx\")\nprint(df[\"invoice_date\"].dtype)\nprint(df[\"invoice_date\"].head(3).tolist())\n","python",[14,178,179,195,202,220,236],{"__ignoreMap":144},[148,180,181,185,189,192],{"class":150,"line":151},[148,182,184],{"class":183},"s-kum","import",[148,186,188],{"class":187},"skGVy"," pandas ",[148,190,191],{"class":183},"as",[148,193,194],{"class":187}," pd\n",[148,196,198],{"class":150,"line":197},2,[148,199,201],{"emptyLinePlaceholder":200},true,"\n",[148,203,205,208,211,214,217],{"class":150,"line":204},3,[148,206,207],{"class":187},"df ",[148,209,210],{"class":183},"=",[148,212,213],{"class":187}," pd.read_excel(",[148,215,216],{"class":158},"\"report.xlsx\"",[148,218,219],{"class":187},")\n",[148,221,223,227,230,233],{"class":150,"line":222},4,[148,224,226],{"class":225},"sP0c6","print",[148,228,229],{"class":187},"(df[",[148,231,232],{"class":158},"\"invoice_date\"",[148,234,235],{"class":187},"].dtype)\n",[148,237,239,241,243,245,248,251],{"class":150,"line":238},5,[148,240,226],{"class":225},[148,242,229],{"class":187},[148,244,232],{"class":158},[148,246,247],{"class":187},"].head(",[148,249,250],{"class":225},"3",[148,252,253],{"class":187},").tolist())\n",[10,255,256,257,260,261,265,266,269,270,273],{},"If the dtype is ",[14,258,259],{},"datetime64[ns]",", the ",[262,263,264],"strong",{},"data is fine and only the display is wrong"," — go to Step 1. If the dtype is ",[14,267,268],{},"int64"," or ",[14,271,272],{},"float64"," and the values look like five-digit numbers, the column is genuinely numeric and needs converting first — go to Step 4.",[134,275,277],{"id":276},"step-1-set-the-number-format-with-openpyxl","Step 1 — Set the number format with openpyxl",[10,279,280,283],{},[14,281,282],{},"number_format"," is a per-cell attribute holding an Excel format string. Setting it is the entire fix:",[139,285,287],{"className":174,"code":286,"language":176,"meta":144,"style":144},"from datetime import date\nfrom openpyxl import load_workbook\n\nwb = load_workbook(\"report.xlsx\")\nws = wb[\"Sheet1\"]\n\n# Column B holds dates; skip the header row.\nfor row in ws.iter_rows(min_row=2, min_col=2, max_col=2):\n    for cell in row:\n        cell.number_format = \"yyyy-mm-dd\"\n\nwb.save(\"report_fixed.xlsx\")\n",[14,288,289,302,314,318,332,348,353,360,405,419,430,435],{"__ignoreMap":144},[148,290,291,294,297,299],{"class":150,"line":151},[148,292,293],{"class":183},"from",[148,295,296],{"class":187}," datetime ",[148,298,184],{"class":183},[148,300,301],{"class":187}," date\n",[148,303,304,306,309,311],{"class":150,"line":197},[148,305,293],{"class":183},[148,307,308],{"class":187}," openpyxl ",[148,310,184],{"class":183},[148,312,313],{"class":187}," load_workbook\n",[148,315,316],{"class":150,"line":204},[148,317,201],{"emptyLinePlaceholder":200},[148,319,320,323,325,328,330],{"class":150,"line":222},[148,321,322],{"class":187},"wb ",[148,324,210],{"class":183},[148,326,327],{"class":187}," load_workbook(",[148,329,216],{"class":158},[148,331,219],{"class":187},[148,333,334,337,339,342,345],{"class":150,"line":238},[148,335,336],{"class":187},"ws ",[148,338,210],{"class":183},[148,340,341],{"class":187}," wb[",[148,343,344],{"class":158},"\"Sheet1\"",[148,346,347],{"class":187},"]\n",[148,349,351],{"class":150,"line":350},6,[148,352,201],{"emptyLinePlaceholder":200},[148,354,356],{"class":150,"line":355},7,[148,357,359],{"class":358},"s-wDw","# Column B holds dates; skip the header row.\n",[148,361,363,366,369,372,375,379,381,384,386,389,391,393,395,398,400,402],{"class":150,"line":362},8,[148,364,365],{"class":183},"for",[148,367,368],{"class":187}," row ",[148,370,371],{"class":183},"in",[148,373,374],{"class":187}," ws.iter_rows(",[148,376,378],{"class":377},"sa561","min_row",[148,380,210],{"class":183},[148,382,383],{"class":225},"2",[148,385,17],{"class":187},[148,387,388],{"class":377},"min_col",[148,390,210],{"class":183},[148,392,383],{"class":225},[148,394,17],{"class":187},[148,396,397],{"class":377},"max_col",[148,399,210],{"class":183},[148,401,383],{"class":225},[148,403,404],{"class":187},"):\n",[148,406,408,411,414,416],{"class":150,"line":407},9,[148,409,410],{"class":183},"    for",[148,412,413],{"class":187}," cell ",[148,415,371],{"class":183},[148,417,418],{"class":187}," row:\n",[148,420,422,425,427],{"class":150,"line":421},10,[148,423,424],{"class":187},"        cell.number_format ",[148,426,210],{"class":183},[148,428,429],{"class":158}," \"yyyy-mm-dd\"\n",[148,431,433],{"class":150,"line":432},11,[148,434,201],{"emptyLinePlaceholder":200},[148,436,438,441,444],{"class":150,"line":437},12,[148,439,440],{"class":187},"wb.save(",[148,442,443],{"class":158},"\"report_fixed.xlsx\"",[148,445,219],{"class":187},[10,447,448,449,452,453,456,457,461],{},"Two refinements make this robust in a real script. First, find the column by header name rather than hard-coding ",[14,450,451],{},"B",", so an inserted column does not silently misformat a different field. Second, widen the column — a date in a narrow column displays as ",[14,454,455],{},"#####",", which people report as a ",[458,459,460],"em",{},"different"," bug:",[139,463,465],{"className":174,"code":464,"language":176,"meta":144,"style":144},"from openpyxl import load_workbook\nfrom openpyxl.utils import get_column_letter\n\nDATE_FORMATS = {\n    \"invoice_date\": \"yyyy-mm-dd\",\n    \"due_date\": \"yyyy-mm-dd\",\n    \"processed_at\": \"yyyy-mm-dd hh:mm\",\n}\n\ndef format_date_columns(path, dest, sheet=None, widths=True):\n    \"\"\"Apply date number formats to columns identified by their header.\"\"\"\n    wb = load_workbook(path)\n    ws = wb[sheet] if sheet else wb.active\n\n    headers = {\n        str(c.value).strip(): c.column\n        for c in ws[1] if c.value is not None\n    }\n\n    applied = []\n    for name, fmt in DATE_FORMATS.items():\n        col = headers.get(name)\n        if col is None:\n            continue\n        for (cell,) in ws.iter_rows(min_row=2, min_col=col, max_col=col):\n            cell.number_format = fmt\n        if widths:\n            # Leave room, or Excel renders ##### instead of the date.\n            ws.column_dimensions[get_column_letter(col)].width = len(fmt) + 4\n        applied.append(name)\n\n    wb.save(dest)\n    return applied\n\nprint(\"formatted:\", format_date_columns(\"report.xlsx\", \"report_fixed.xlsx\"))\n",[14,466,467,477,489,493,504,518,529,541,546,550,577,582,592,615,620,630,639,673,679,684,695,711,722,739,745,779,790,798,804,824,830,835,841,850,855],{"__ignoreMap":144},[148,468,469,471,473,475],{"class":150,"line":151},[148,470,293],{"class":183},[148,472,308],{"class":187},[148,474,184],{"class":183},[148,476,313],{"class":187},[148,478,479,481,484,486],{"class":150,"line":197},[148,480,293],{"class":183},[148,482,483],{"class":187}," openpyxl.utils ",[148,485,184],{"class":183},[148,487,488],{"class":187}," get_column_letter\n",[148,490,491],{"class":150,"line":204},[148,492,201],{"emptyLinePlaceholder":200},[148,494,495,498,501],{"class":150,"line":222},[148,496,497],{"class":225},"DATE_FORMATS",[148,499,500],{"class":183}," =",[148,502,503],{"class":187}," {\n",[148,505,506,509,512,515],{"class":150,"line":238},[148,507,508],{"class":158},"    \"invoice_date\"",[148,510,511],{"class":187},": ",[148,513,514],{"class":158},"\"yyyy-mm-dd\"",[148,516,517],{"class":187},",\n",[148,519,520,523,525,527],{"class":150,"line":350},[148,521,522],{"class":158},"    \"due_date\"",[148,524,511],{"class":187},[148,526,514],{"class":158},[148,528,517],{"class":187},[148,530,531,534,536,539],{"class":150,"line":355},[148,532,533],{"class":158},"    \"processed_at\"",[148,535,511],{"class":187},[148,537,538],{"class":158},"\"yyyy-mm-dd hh:mm\"",[148,540,517],{"class":187},[148,542,543],{"class":150,"line":362},[148,544,545],{"class":187},"}\n",[148,547,548],{"class":150,"line":407},[148,549,201],{"emptyLinePlaceholder":200},[148,551,552,555,559,562,564,567,570,572,575],{"class":150,"line":421},[148,553,554],{"class":183},"def",[148,556,558],{"class":557},"s_Opv"," format_date_columns",[148,560,561],{"class":187},"(path, dest, sheet",[148,563,210],{"class":183},[148,565,566],{"class":225},"None",[148,568,569],{"class":187},", widths",[148,571,210],{"class":183},[148,573,574],{"class":225},"True",[148,576,404],{"class":187},[148,578,579],{"class":150,"line":432},[148,580,581],{"class":158},"    \"\"\"Apply date number formats to columns identified by their header.\"\"\"\n",[148,583,584,587,589],{"class":150,"line":437},[148,585,586],{"class":187},"    wb ",[148,588,210],{"class":183},[148,590,591],{"class":187}," load_workbook(path)\n",[148,593,595,598,600,603,606,609,612],{"class":150,"line":594},13,[148,596,597],{"class":187},"    ws ",[148,599,210],{"class":183},[148,601,602],{"class":187}," wb[sheet] ",[148,604,605],{"class":183},"if",[148,607,608],{"class":187}," sheet ",[148,610,611],{"class":183},"else",[148,613,614],{"class":187}," wb.active\n",[148,616,618],{"class":150,"line":617},14,[148,619,201],{"emptyLinePlaceholder":200},[148,621,623,626,628],{"class":150,"line":622},15,[148,624,625],{"class":187},"    headers ",[148,627,210],{"class":183},[148,629,503],{"class":187},[148,631,633,636],{"class":150,"line":632},16,[148,634,635],{"class":225},"        str",[148,637,638],{"class":187},"(c.value).strip(): c.column\n",[148,640,642,645,648,650,653,656,659,661,664,667,670],{"class":150,"line":641},17,[148,643,644],{"class":183},"        for",[148,646,647],{"class":187}," c ",[148,649,371],{"class":183},[148,651,652],{"class":187}," ws[",[148,654,655],{"class":225},"1",[148,657,658],{"class":187},"] ",[148,660,605],{"class":183},[148,662,663],{"class":187}," c.value ",[148,665,666],{"class":183},"is",[148,668,669],{"class":183}," not",[148,671,672],{"class":225}," None\n",[148,674,676],{"class":150,"line":675},18,[148,677,678],{"class":187},"    }\n",[148,680,682],{"class":150,"line":681},19,[148,683,201],{"emptyLinePlaceholder":200},[148,685,687,690,692],{"class":150,"line":686},20,[148,688,689],{"class":187},"    applied ",[148,691,210],{"class":183},[148,693,694],{"class":187}," []\n",[148,696,698,700,703,705,708],{"class":150,"line":697},21,[148,699,410],{"class":183},[148,701,702],{"class":187}," name, fmt ",[148,704,371],{"class":183},[148,706,707],{"class":225}," DATE_FORMATS",[148,709,710],{"class":187},".items():\n",[148,712,714,717,719],{"class":150,"line":713},22,[148,715,716],{"class":187},"        col ",[148,718,210],{"class":183},[148,720,721],{"class":187}," headers.get(name)\n",[148,723,725,728,731,733,736],{"class":150,"line":724},23,[148,726,727],{"class":183},"        if",[148,729,730],{"class":187}," col ",[148,732,666],{"class":183},[148,734,735],{"class":225}," None",[148,737,738],{"class":187},":\n",[148,740,742],{"class":150,"line":741},24,[148,743,744],{"class":183},"            continue\n",[148,746,748,750,753,755,757,759,761,763,765,767,769,772,774,776],{"class":150,"line":747},25,[148,749,644],{"class":183},[148,751,752],{"class":187}," (cell,) ",[148,754,371],{"class":183},[148,756,374],{"class":187},[148,758,378],{"class":377},[148,760,210],{"class":183},[148,762,383],{"class":225},[148,764,17],{"class":187},[148,766,388],{"class":377},[148,768,210],{"class":183},[148,770,771],{"class":187},"col, ",[148,773,397],{"class":377},[148,775,210],{"class":183},[148,777,778],{"class":187},"col):\n",[148,780,782,785,787],{"class":150,"line":781},26,[148,783,784],{"class":187},"            cell.number_format ",[148,786,210],{"class":183},[148,788,789],{"class":187}," fmt\n",[148,791,793,795],{"class":150,"line":792},27,[148,794,727],{"class":183},[148,796,797],{"class":187}," widths:\n",[148,799,801],{"class":150,"line":800},28,[148,802,803],{"class":358},"            # Leave room, or Excel renders ##### instead of the date.\n",[148,805,807,810,812,815,818,821],{"class":150,"line":806},29,[148,808,809],{"class":187},"            ws.column_dimensions[get_column_letter(col)].width ",[148,811,210],{"class":183},[148,813,814],{"class":225}," len",[148,816,817],{"class":187},"(fmt) ",[148,819,820],{"class":183},"+",[148,822,823],{"class":225}," 4\n",[148,825,827],{"class":150,"line":826},30,[148,828,829],{"class":187},"        applied.append(name)\n",[148,831,833],{"class":150,"line":832},31,[148,834,201],{"emptyLinePlaceholder":200},[148,836,838],{"class":150,"line":837},32,[148,839,840],{"class":187},"    wb.save(dest)\n",[148,842,844,847],{"class":150,"line":843},33,[148,845,846],{"class":183},"    return",[148,848,849],{"class":187}," applied\n",[148,851,853],{"class":150,"line":852},34,[148,854,201],{"emptyLinePlaceholder":200},[148,856,858,860,863,866,869,871,873,875],{"class":150,"line":857},35,[148,859,226],{"class":225},[148,861,862],{"class":187},"(",[148,864,865],{"class":158},"\"formatted:\"",[148,867,868],{"class":187},", format_date_columns(",[148,870,216],{"class":158},[148,872,17],{"class":187},[148,874,443],{"class":158},[148,876,877],{"class":187},"))\n",[10,879,880],{},"The format strings you will reach for most:",[882,883,884,900],"table",{},[885,886,887],"thead",{},[888,889,890,894,897],"tr",{},[891,892,893],"th",{},"Format string",[891,895,896],{},"Renders as",[891,898,899],{},"Use for",[901,902,903,918,933,948,963,978],"tbody",{},[888,904,905,911,915],{},[906,907,908],"td",{},[14,909,910],{},"yyyy-mm-dd",[906,912,913],{},[14,914,132],{},[906,916,917],{},"Dates in any report crossing regions",[888,919,920,925,930],{},[906,921,922],{},[14,923,924],{},"yyyy-mm-dd hh:mm",[906,926,927],{},[14,928,929],{},"2026-08-15 18:04",[906,931,932],{},"Timestamps",[888,934,935,940,945],{},[906,936,937],{},[14,938,939],{},"dd mmm yyyy",[906,941,942],{},[14,943,944],{},"15 Aug 2026",[906,946,947],{},"Human-facing summaries",[888,949,950,955,960],{},[906,951,952],{},[14,953,954],{},"mmm yyyy",[906,956,957],{},[14,958,959],{},"Aug 2026",[906,961,962],{},"Month labels on a period column",[888,964,965,970,975],{},[906,966,967],{},[14,968,969],{},"[h]:mm",[906,971,972],{},[14,973,974],{},"32:15",[906,976,977],{},"Durations over 24 hours",[888,979,980,985,990],{},[906,981,982],{},[14,983,984],{},"hh:mm:ss",[906,986,987],{},[14,988,989],{},"18:04:32",[906,991,992],{},"Time of day only",[10,994,995,996,999,1000,1003,1004,1007,1008,1011,1012,1015],{},"Note that ",[14,997,998],{},"mm"," means ",[458,1001,1002],{},"months"," after a date part and ",[458,1005,1006],{},"minutes"," after an hour part — ",[14,1009,1010],{},"hh:mm"," is minutes, ",[14,1013,1014],{},"yyyy-mm"," is months. Getting that wrong produces a cell showing the month number where you wanted minutes, which is a genuinely confusing bug to read.",[134,1017,1019],{"id":1018},"step-2-format-at-write-time-through-pandas","Step 2 — Format at write time through pandas",[10,1021,1022,1023,1026],{},"If your script writes the workbook, fix it there and skip the repair pass entirely. ",[14,1024,1025],{},"ExcelWriter"," takes workbook-wide defaults:",[139,1028,1030],{"className":174,"code":1029,"language":176,"meta":144,"style":144},"import pandas as pd\n\ndf = pd.DataFrame({\n    \"order\": [1001, 1002],\n    \"invoice_date\": pd.to_datetime([\"2026-08-15\", \"2026-08-16\"]),\n    \"processed_at\": pd.to_datetime([\"2026-08-15 18:04\", \"2026-08-16 09:12\"]),\n})\n\nwith pd.ExcelWriter(\n    \"orders.xlsx\",\n    engine=\"xlsxwriter\",\n    date_format=\"yyyy-mm-dd\",\n    datetime_format=\"yyyy-mm-dd hh:mm\",\n) as writer:\n    df.to_excel(writer, sheet_name=\"Orders\", index=False)\n",[14,1031,1032,1042,1046,1055,1074,1092,1108,1113,1117,1125,1132,1144,1155,1166,1176],{"__ignoreMap":144},[148,1033,1034,1036,1038,1040],{"class":150,"line":151},[148,1035,184],{"class":183},[148,1037,188],{"class":187},[148,1039,191],{"class":183},[148,1041,194],{"class":187},[148,1043,1044],{"class":150,"line":197},[148,1045,201],{"emptyLinePlaceholder":200},[148,1047,1048,1050,1052],{"class":150,"line":204},[148,1049,207],{"class":187},[148,1051,210],{"class":183},[148,1053,1054],{"class":187}," pd.DataFrame({\n",[148,1056,1057,1060,1063,1066,1068,1071],{"class":150,"line":222},[148,1058,1059],{"class":158},"    \"order\"",[148,1061,1062],{"class":187},": [",[148,1064,1065],{"class":225},"1001",[148,1067,17],{"class":187},[148,1069,1070],{"class":225},"1002",[148,1072,1073],{"class":187},"],\n",[148,1075,1076,1078,1081,1084,1086,1089],{"class":150,"line":238},[148,1077,508],{"class":158},[148,1079,1080],{"class":187},": pd.to_datetime([",[148,1082,1083],{"class":158},"\"2026-08-15\"",[148,1085,17],{"class":187},[148,1087,1088],{"class":158},"\"2026-08-16\"",[148,1090,1091],{"class":187},"]),\n",[148,1093,1094,1096,1098,1101,1103,1106],{"class":150,"line":350},[148,1095,533],{"class":158},[148,1097,1080],{"class":187},[148,1099,1100],{"class":158},"\"2026-08-15 18:04\"",[148,1102,17],{"class":187},[148,1104,1105],{"class":158},"\"2026-08-16 09:12\"",[148,1107,1091],{"class":187},[148,1109,1110],{"class":150,"line":355},[148,1111,1112],{"class":187},"})\n",[148,1114,1115],{"class":150,"line":362},[148,1116,201],{"emptyLinePlaceholder":200},[148,1118,1119,1122],{"class":150,"line":407},[148,1120,1121],{"class":183},"with",[148,1123,1124],{"class":187}," pd.ExcelWriter(\n",[148,1126,1127,1130],{"class":150,"line":421},[148,1128,1129],{"class":158},"    \"orders.xlsx\"",[148,1131,517],{"class":187},[148,1133,1134,1137,1139,1142],{"class":150,"line":432},[148,1135,1136],{"class":377},"    engine",[148,1138,210],{"class":183},[148,1140,1141],{"class":158},"\"xlsxwriter\"",[148,1143,517],{"class":187},[148,1145,1146,1149,1151,1153],{"class":150,"line":437},[148,1147,1148],{"class":377},"    date_format",[148,1150,210],{"class":183},[148,1152,514],{"class":158},[148,1154,517],{"class":187},[148,1156,1157,1160,1162,1164],{"class":150,"line":594},[148,1158,1159],{"class":377},"    datetime_format",[148,1161,210],{"class":183},[148,1163,538],{"class":158},[148,1165,517],{"class":187},[148,1167,1168,1171,1173],{"class":150,"line":617},[148,1169,1170],{"class":187},") ",[148,1172,191],{"class":183},[148,1174,1175],{"class":187}," writer:\n",[148,1177,1178,1181,1184,1186,1189,1191,1194,1196,1199],{"class":150,"line":622},[148,1179,1180],{"class":187},"    df.to_excel(writer, ",[148,1182,1183],{"class":377},"sheet_name",[148,1185,210],{"class":183},[148,1187,1188],{"class":158},"\"Orders\"",[148,1190,17],{"class":187},[148,1192,1193],{"class":377},"index",[148,1195,210],{"class":183},[148,1197,1198],{"class":225},"False",[148,1200,219],{"class":187},[10,1202,1203,1206,1207,1210],{},[14,1204,1205],{},"date_format"," applies to date-only values and ",[14,1208,1209],{},"datetime_format"," to values carrying a time. Both work with the openpyxl engine as well.",[10,1212,1213],{},"For per-column control — different formats on different columns, plus widths — drop to the xlsxwriter objects the writer exposes:",[139,1215,1217],{"className":174,"code":1216,"language":176,"meta":144,"style":144},"import pandas as pd\n\nwith pd.ExcelWriter(\"orders.xlsx\", engine=\"xlsxwriter\") as writer:\n    df.to_excel(writer, sheet_name=\"Orders\", index=False)\n\n    book = writer.book\n    sheet = writer.sheets[\"Orders\"]\n\n    day = book.add_format({\"num_format\": \"yyyy-mm-dd\"})\n    stamp = book.add_format({\"num_format\": \"yyyy-mm-dd hh:mm\"})\n\n    # set_column formats a whole column in one call — no per-cell loop.\n    sheet.set_column(\"B:B\", 13, day)\n    sheet.set_column(\"C:C\", 19, stamp)\n",[14,1218,1219,1229,1233,1258,1278,1282,1292,1306,1310,1329,1346,1350,1355,1370],{"__ignoreMap":144},[148,1220,1221,1223,1225,1227],{"class":150,"line":151},[148,1222,184],{"class":183},[148,1224,188],{"class":187},[148,1226,191],{"class":183},[148,1228,194],{"class":187},[148,1230,1231],{"class":150,"line":197},[148,1232,201],{"emptyLinePlaceholder":200},[148,1234,1235,1237,1240,1243,1245,1248,1250,1252,1254,1256],{"class":150,"line":204},[148,1236,1121],{"class":183},[148,1238,1239],{"class":187}," pd.ExcelWriter(",[148,1241,1242],{"class":158},"\"orders.xlsx\"",[148,1244,17],{"class":187},[148,1246,1247],{"class":377},"engine",[148,1249,210],{"class":183},[148,1251,1141],{"class":158},[148,1253,1170],{"class":187},[148,1255,191],{"class":183},[148,1257,1175],{"class":187},[148,1259,1260,1262,1264,1266,1268,1270,1272,1274,1276],{"class":150,"line":222},[148,1261,1180],{"class":187},[148,1263,1183],{"class":377},[148,1265,210],{"class":183},[148,1267,1188],{"class":158},[148,1269,17],{"class":187},[148,1271,1193],{"class":377},[148,1273,210],{"class":183},[148,1275,1198],{"class":225},[148,1277,219],{"class":187},[148,1279,1280],{"class":150,"line":238},[148,1281,201],{"emptyLinePlaceholder":200},[148,1283,1284,1287,1289],{"class":150,"line":350},[148,1285,1286],{"class":187},"    book ",[148,1288,210],{"class":183},[148,1290,1291],{"class":187}," writer.book\n",[148,1293,1294,1297,1299,1302,1304],{"class":150,"line":355},[148,1295,1296],{"class":187},"    sheet ",[148,1298,210],{"class":183},[148,1300,1301],{"class":187}," writer.sheets[",[148,1303,1188],{"class":158},[148,1305,347],{"class":187},[148,1307,1308],{"class":150,"line":362},[148,1309,201],{"emptyLinePlaceholder":200},[148,1311,1312,1315,1317,1320,1323,1325,1327],{"class":150,"line":407},[148,1313,1314],{"class":187},"    day ",[148,1316,210],{"class":183},[148,1318,1319],{"class":187}," book.add_format({",[148,1321,1322],{"class":158},"\"num_format\"",[148,1324,511],{"class":187},[148,1326,514],{"class":158},[148,1328,1112],{"class":187},[148,1330,1331,1334,1336,1338,1340,1342,1344],{"class":150,"line":421},[148,1332,1333],{"class":187},"    stamp ",[148,1335,210],{"class":183},[148,1337,1319],{"class":187},[148,1339,1322],{"class":158},[148,1341,511],{"class":187},[148,1343,538],{"class":158},[148,1345,1112],{"class":187},[148,1347,1348],{"class":150,"line":432},[148,1349,201],{"emptyLinePlaceholder":200},[148,1351,1352],{"class":150,"line":437},[148,1353,1354],{"class":358},"    # set_column formats a whole column in one call — no per-cell loop.\n",[148,1356,1357,1360,1363,1365,1367],{"class":150,"line":594},[148,1358,1359],{"class":187},"    sheet.set_column(",[148,1361,1362],{"class":158},"\"B:B\"",[148,1364,17],{"class":187},[148,1366,64],{"class":225},[148,1368,1369],{"class":187},", day)\n",[148,1371,1372,1374,1377,1379,1382],{"class":150,"line":617},[148,1373,1359],{"class":187},[148,1375,1376],{"class":158},"\"C:C\"",[148,1378,17],{"class":187},[148,1380,1381],{"class":225},"19",[148,1383,1384],{"class":187},", stamp)\n",[10,1386,1387,1388,1391,1392,1395,1396,1398],{},"One trap with pandas: ",[14,1389,1390],{},"to_excel"," ",[262,1393,1394],{},"replaces"," the target sheet rather than merging into it. Formatting applied to a sheet before a later ",[14,1397,1390],{}," call is discarded. Format after writing, never before.",[134,1400,1402],{"id":1401},"step-3-repair-a-workbook-you-did-not-write","Step 3 — Repair a workbook you did not write",[10,1404,1405],{},"Sometimes the file arrives already broken and you do not control the producer. A repair pass can find the date columns itself, by testing whether the values sit in a plausible date range:",[32,1407,42,1413,42,1416,42,1419,42,1422,42,1431,42,1437,42,1442,42,1447,42,1450,42,1455,42,1461,42,1466,42,1470,42,1474,42,1477,42,1482,42,1487,42,1490,42,1493,42,1497,42,1501,42,1504,42,1508,42,1511,42,1514,42,1518],{"viewBox":1408,"role":35,"ariaLabel":1409,"ariaLabelledBy":1410,"xmlns":40,"style":41},"0 50 800 180","Repair heuristic: for each column, check that the values are numeric, that they fall inside a plausible serial range, and that the header name suggests a date before applying a date format.",[1411,1412],"repair-t","repair-d",[44,1414,1415],{"id":1411},"Three tests before reformatting a column as a date",[48,1417,1418],{"id":1412},"A column must pass three gates before the repair pass changes its format. First, the values must be numeric rather than text. Second, they must fall inside a plausible serial window of roughly 20000 to 60000, covering 1954 to 2064. Third, the header name should contain a date-like word such as date, day, at or on. Passing all three applies the format; failing any one leaves the column untouched.",[52,1420],{"x":54,"y":1421,"width":55,"height":112,"fill":57},"50",[52,1423],{"x":1424,"y":1425,"width":1426,"height":1427,"rx":1428,"fill":1429,"stroke":1430,"style":67},"16","80","140","62","12","#f0f2f5","var(--line,#cdd5e6)",[69,1432,1436],{"x":1433,"y":1434,"style":1435},"86","108","font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","a column",[69,1438,1441],{"x":1433,"y":1439,"style":1440},"128","font-size:10.5px;fill:var(--muted,#5b6780);text-anchor:middle","of unknown type",[150,1443],{"x1":1444,"y1":1445,"x2":1446,"y2":1445,"stroke":1430,"style":67},"156","111","188",[96,1448],{"points":1449,"fill":94},"196,111 184,105 184,117",[52,1451],{"x":1452,"y":77,"width":1453,"height":1454,"rx":1428,"fill":65,"stroke":66,"style":67},"204","152","90",[69,1456,1460],{"x":1457,"y":1458,"style":1459},"280","92","font-size:11.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","1 · numeric?",[69,1462,1465],{"x":1457,"y":1463,"style":1464},"118","font-size:10.5px;fill:var(--text,#172033);text-anchor:middle","not text, not blank",[69,1467,1469],{"x":1457,"y":1468,"style":1440},"138","int or float cells",[150,1471],{"x1":1472,"y1":1445,"x2":1473,"y2":1445,"stroke":66,"style":67},"356","388",[96,1475],{"points":1476,"fill":94},"396,111 384,105 384,117",[52,1478],{"x":1479,"y":77,"width":1453,"height":1454,"rx":1428,"fill":1480,"stroke":1481,"style":67},"404","#fdefd8","var(--gold,#b4740a)",[69,1483,1486],{"x":1484,"y":1458,"style":1485},"480","font-size:11.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","2 · in range?",[69,1488,1489],{"x":1484,"y":1463,"style":1464},"20000 to 60000",[69,1491,1492],{"x":1484,"y":1468,"style":1440},"about 1954 to 2064",[150,1494],{"x1":1495,"y1":1445,"x2":1496,"y2":1445,"stroke":1481,"style":67},"556","588",[96,1498],{"points":1499,"fill":1500},"596,111 584,105 584,117","#b4740a",[52,1502],{"x":1503,"y":77,"width":112,"height":1454,"rx":1428,"fill":123,"stroke":124,"style":67},"604",[69,1505,1507],{"x":1506,"y":1458,"style":128},"694","3 · named like a date?",[69,1509,1510],{"x":1506,"y":1463,"style":1464},"date, day, _at, _on",[69,1512,1513],{"x":1506,"y":1468,"style":1440},"stops false positives",[69,1515,1517],{"x":71,"y":1516,"style":114},"192","all three pass → apply the format · any one fails → leave it alone",[69,1519,1521],{"x":71,"y":1520,"style":1440},"212","a quantity column of 45,000 units would pass tests 1 and 2 but not 3",[10,1523,1524],{},"The third gate matters. Without it, a column of order quantities that happens to sit between 20,000 and 60,000 gets reformatted as dates — a repair that makes the file worse:",[139,1526,1528],{"className":174,"code":1527,"language":176,"meta":144,"style":144},"import re\nfrom openpyxl import load_workbook\nfrom openpyxl.utils import get_column_letter\n\nDATE_NAME = re.compile(r\"(date|day|_at$|_on$|timestamp)\", re.I)\nPLAUSIBLE = range(20_000, 60_001)      # roughly 1954 to 2064\n\ndef repair_date_formats(path, dest, fmt=\"yyyy-mm-dd\", sample=200):\n    \"\"\"Find numeric columns that are really dates and give them a date format.\"\"\"\n    wb = load_workbook(path)\n    fixed = []\n\n    for ws in wb.worksheets:\n        headers = {c.column: str(c.value or \"\").strip() for c in ws[1]}\n\n        for col, name in headers.items():\n            if not DATE_NAME.search(name):\n                continue                         # gate 3\n\n            values, numeric = 0, 0\n            for (cell,) in ws.iter_rows(min_row=2, max_row=1 + sample,\n                                        min_col=col, max_col=col):\n                if cell.value is None:\n                    continue\n                values += 1\n                if isinstance(cell.value, (int, float)) \\\n                        and int(cell.value) in PLAUSIBLE:\n                    numeric += 1                 # gates 1 and 2\n\n            # Require a clear majority, so one stray number cannot trigger it.\n            if values and numeric \u002F values > 0.9:\n                for (cell,) in ws.iter_rows(min_row=2, min_col=col, max_col=col):\n                    cell.number_format = fmt\n                ws.column_dimensions[get_column_letter(col)].width = len(fmt) + 4\n                fixed.append(f\"{ws.title}!{name}\")\n\n    wb.save(dest)\n    return fixed\n\nprint(\"repaired:\", repair_date_formats(\"broken.xlsx\", \"repaired.xlsx\"))\n",[14,1529,1530,1537,1547,1557,1561,1616,1642,1646,1670,1675,1683,1692,1696,1708,1746,1750,1762,1775,1783,1787,1802,1834,1849,1863,1868,1879,1900,1918,1931,1935,1940,1966,1997,2006,2021,2055,2060,2065,2073,2078],{"__ignoreMap":144},[148,1531,1532,1534],{"class":150,"line":151},[148,1533,184],{"class":183},[148,1535,1536],{"class":187}," re\n",[148,1538,1539,1541,1543,1545],{"class":150,"line":197},[148,1540,293],{"class":183},[148,1542,308],{"class":187},[148,1544,184],{"class":183},[148,1546,313],{"class":187},[148,1548,1549,1551,1553,1555],{"class":150,"line":204},[148,1550,293],{"class":183},[148,1552,483],{"class":187},[148,1554,184],{"class":183},[148,1556,488],{"class":187},[148,1558,1559],{"class":150,"line":222},[148,1560,201],{"emptyLinePlaceholder":200},[148,1562,1563,1566,1568,1571,1574,1577,1579,1582,1585,1588,1590,1593,1596,1598,1601,1603,1605,1608,1611,1613],{"class":150,"line":238},[148,1564,1565],{"class":225},"DATE_NAME",[148,1567,500],{"class":183},[148,1569,1570],{"class":187}," re.compile(",[148,1572,1573],{"class":183},"r",[148,1575,1576],{"class":158},"\"",[148,1578,862],{"class":225},[148,1580,1581],{"class":158},"date",[148,1583,1584],{"class":183},"|",[148,1586,1587],{"class":158},"day",[148,1589,1584],{"class":183},[148,1591,1592],{"class":158},"_at",[148,1594,1595],{"class":225},"$",[148,1597,1584],{"class":183},[148,1599,1600],{"class":158},"_on",[148,1602,1595],{"class":225},[148,1604,1584],{"class":183},[148,1606,1607],{"class":158},"timestamp",[148,1609,1610],{"class":225},")",[148,1612,1576],{"class":158},[148,1614,1615],{"class":187},", re.I)\n",[148,1617,1618,1621,1623,1626,1628,1631,1633,1636,1639],{"class":150,"line":350},[148,1619,1620],{"class":225},"PLAUSIBLE",[148,1622,500],{"class":183},[148,1624,1625],{"class":225}," range",[148,1627,862],{"class":187},[148,1629,1630],{"class":225},"20_000",[148,1632,17],{"class":187},[148,1634,1635],{"class":225},"60_001",[148,1637,1638],{"class":187},")      ",[148,1640,1641],{"class":358},"# roughly 1954 to 2064\n",[148,1643,1644],{"class":150,"line":355},[148,1645,201],{"emptyLinePlaceholder":200},[148,1647,1648,1650,1653,1656,1658,1660,1663,1665,1668],{"class":150,"line":362},[148,1649,554],{"class":183},[148,1651,1652],{"class":557}," repair_date_formats",[148,1654,1655],{"class":187},"(path, dest, fmt",[148,1657,210],{"class":183},[148,1659,514],{"class":158},[148,1661,1662],{"class":187},", sample",[148,1664,210],{"class":183},[148,1666,1667],{"class":225},"200",[148,1669,404],{"class":187},[148,1671,1672],{"class":150,"line":407},[148,1673,1674],{"class":158},"    \"\"\"Find numeric columns that are really dates and give them a date format.\"\"\"\n",[148,1676,1677,1679,1681],{"class":150,"line":421},[148,1678,586],{"class":187},[148,1680,210],{"class":183},[148,1682,591],{"class":187},[148,1684,1685,1688,1690],{"class":150,"line":432},[148,1686,1687],{"class":187},"    fixed ",[148,1689,210],{"class":183},[148,1691,694],{"class":187},[148,1693,1694],{"class":150,"line":437},[148,1695,201],{"emptyLinePlaceholder":200},[148,1697,1698,1700,1703,1705],{"class":150,"line":594},[148,1699,410],{"class":183},[148,1701,1702],{"class":187}," ws ",[148,1704,371],{"class":183},[148,1706,1707],{"class":187}," wb.worksheets:\n",[148,1709,1710,1713,1715,1718,1721,1724,1727,1730,1733,1735,1737,1739,1741,1743],{"class":150,"line":617},[148,1711,1712],{"class":187},"        headers ",[148,1714,210],{"class":183},[148,1716,1717],{"class":187}," {c.column: ",[148,1719,1720],{"class":225},"str",[148,1722,1723],{"class":187},"(c.value ",[148,1725,1726],{"class":183},"or",[148,1728,1729],{"class":158}," \"\"",[148,1731,1732],{"class":187},").strip() ",[148,1734,365],{"class":183},[148,1736,647],{"class":187},[148,1738,371],{"class":183},[148,1740,652],{"class":187},[148,1742,655],{"class":225},[148,1744,1745],{"class":187},"]}\n",[148,1747,1748],{"class":150,"line":622},[148,1749,201],{"emptyLinePlaceholder":200},[148,1751,1752,1754,1757,1759],{"class":150,"line":632},[148,1753,644],{"class":183},[148,1755,1756],{"class":187}," col, name ",[148,1758,371],{"class":183},[148,1760,1761],{"class":187}," headers.items():\n",[148,1763,1764,1767,1769,1772],{"class":150,"line":641},[148,1765,1766],{"class":183},"            if",[148,1768,669],{"class":183},[148,1770,1771],{"class":225}," DATE_NAME",[148,1773,1774],{"class":187},".search(name):\n",[148,1776,1777,1780],{"class":150,"line":675},[148,1778,1779],{"class":183},"                continue",[148,1781,1782],{"class":358},"                         # gate 3\n",[148,1784,1785],{"class":150,"line":681},[148,1786,201],{"emptyLinePlaceholder":200},[148,1788,1789,1792,1794,1797,1799],{"class":150,"line":686},[148,1790,1791],{"class":187},"            values, numeric ",[148,1793,210],{"class":183},[148,1795,1796],{"class":225}," 0",[148,1798,17],{"class":187},[148,1800,1801],{"class":225},"0\n",[148,1803,1804,1807,1809,1811,1813,1815,1817,1819,1821,1824,1826,1828,1831],{"class":150,"line":697},[148,1805,1806],{"class":183},"            for",[148,1808,752],{"class":187},[148,1810,371],{"class":183},[148,1812,374],{"class":187},[148,1814,378],{"class":377},[148,1816,210],{"class":183},[148,1818,383],{"class":225},[148,1820,17],{"class":187},[148,1822,1823],{"class":377},"max_row",[148,1825,210],{"class":183},[148,1827,655],{"class":225},[148,1829,1830],{"class":183}," +",[148,1832,1833],{"class":187}," sample,\n",[148,1835,1836,1839,1841,1843,1845,1847],{"class":150,"line":713},[148,1837,1838],{"class":377},"                                        min_col",[148,1840,210],{"class":183},[148,1842,771],{"class":187},[148,1844,397],{"class":377},[148,1846,210],{"class":183},[148,1848,778],{"class":187},[148,1850,1851,1854,1857,1859,1861],{"class":150,"line":724},[148,1852,1853],{"class":183},"                if",[148,1855,1856],{"class":187}," cell.value ",[148,1858,666],{"class":183},[148,1860,735],{"class":225},[148,1862,738],{"class":187},[148,1864,1865],{"class":150,"line":741},[148,1866,1867],{"class":183},"                    continue\n",[148,1869,1870,1873,1876],{"class":150,"line":747},[148,1871,1872],{"class":187},"                values ",[148,1874,1875],{"class":183},"+=",[148,1877,1878],{"class":225}," 1\n",[148,1880,1881,1883,1886,1889,1892,1894,1897],{"class":150,"line":781},[148,1882,1853],{"class":183},[148,1884,1885],{"class":225}," isinstance",[148,1887,1888],{"class":187},"(cell.value, (",[148,1890,1891],{"class":225},"int",[148,1893,17],{"class":187},[148,1895,1896],{"class":225},"float",[148,1898,1899],{"class":187},")) \\\n",[148,1901,1902,1905,1908,1911,1913,1916],{"class":150,"line":792},[148,1903,1904],{"class":183},"                        and",[148,1906,1907],{"class":225}," int",[148,1909,1910],{"class":187},"(cell.value) ",[148,1912,371],{"class":183},[148,1914,1915],{"class":225}," PLAUSIBLE",[148,1917,738],{"class":187},[148,1919,1920,1923,1925,1928],{"class":150,"line":800},[148,1921,1922],{"class":187},"                    numeric ",[148,1924,1875],{"class":183},[148,1926,1927],{"class":225}," 1",[148,1929,1930],{"class":358},"                 # gates 1 and 2\n",[148,1932,1933],{"class":150,"line":806},[148,1934,201],{"emptyLinePlaceholder":200},[148,1936,1937],{"class":150,"line":826},[148,1938,1939],{"class":358},"            # Require a clear majority, so one stray number cannot trigger it.\n",[148,1941,1942,1944,1947,1950,1953,1956,1958,1961,1964],{"class":150,"line":832},[148,1943,1766],{"class":183},[148,1945,1946],{"class":187}," values ",[148,1948,1949],{"class":183},"and",[148,1951,1952],{"class":187}," numeric ",[148,1954,1955],{"class":183},"\u002F",[148,1957,1946],{"class":187},[148,1959,1960],{"class":183},">",[148,1962,1963],{"class":225}," 0.9",[148,1965,738],{"class":187},[148,1967,1968,1971,1973,1975,1977,1979,1981,1983,1985,1987,1989,1991,1993,1995],{"class":150,"line":837},[148,1969,1970],{"class":183},"                for",[148,1972,752],{"class":187},[148,1974,371],{"class":183},[148,1976,374],{"class":187},[148,1978,378],{"class":377},[148,1980,210],{"class":183},[148,1982,383],{"class":225},[148,1984,17],{"class":187},[148,1986,388],{"class":377},[148,1988,210],{"class":183},[148,1990,771],{"class":187},[148,1992,397],{"class":377},[148,1994,210],{"class":183},[148,1996,778],{"class":187},[148,1998,1999,2002,2004],{"class":150,"line":843},[148,2000,2001],{"class":187},"                    cell.number_format ",[148,2003,210],{"class":183},[148,2005,789],{"class":187},[148,2007,2008,2011,2013,2015,2017,2019],{"class":150,"line":852},[148,2009,2010],{"class":187},"                ws.column_dimensions[get_column_letter(col)].width ",[148,2012,210],{"class":183},[148,2014,814],{"class":225},[148,2016,817],{"class":187},[148,2018,820],{"class":183},[148,2020,823],{"class":225},[148,2022,2023,2026,2029,2031,2035,2038,2041,2044,2046,2049,2051,2053],{"class":150,"line":857},[148,2024,2025],{"class":187},"                fixed.append(",[148,2027,2028],{"class":183},"f",[148,2030,1576],{"class":158},[148,2032,2034],{"class":2033},"sSjpA","{",[148,2036,2037],{"class":187},"ws.title",[148,2039,2040],{"class":2033},"}",[148,2042,2043],{"class":158},"!",[148,2045,2034],{"class":2033},[148,2047,2048],{"class":187},"name",[148,2050,2040],{"class":2033},[148,2052,1576],{"class":158},[148,2054,219],{"class":187},[148,2056,2058],{"class":150,"line":2057},36,[148,2059,201],{"emptyLinePlaceholder":200},[148,2061,2063],{"class":150,"line":2062},37,[148,2064,840],{"class":187},[148,2066,2068,2070],{"class":150,"line":2067},38,[148,2069,846],{"class":183},[148,2071,2072],{"class":187}," fixed\n",[148,2074,2076],{"class":150,"line":2075},39,[148,2077,201],{"emptyLinePlaceholder":200},[148,2079,2081,2083,2085,2088,2091,2094,2096,2099],{"class":150,"line":2080},40,[148,2082,226],{"class":225},[148,2084,862],{"class":187},[148,2086,2087],{"class":158},"\"repaired:\"",[148,2089,2090],{"class":187},", repair_date_formats(",[148,2092,2093],{"class":158},"\"broken.xlsx\"",[148,2095,17],{"class":187},[148,2097,2098],{"class":158},"\"repaired.xlsx\"",[148,2100,877],{"class":187},[10,2102,2103],{},"Returning the list of what it changed — rather than silently rewriting the file — is what makes this safe to run unattended. Log it, and a surprising result is visible instead of buried.",[134,2105,2107],{"id":2106},"step-4-when-the-values-really-are-numbers","Step 4 — When the values really are numbers",[10,2109,2110,2111,269,2113,2115],{},"If pandas reports ",[14,2112,268],{},[14,2114,272],{},", a number format alone is only half a fix: Excel will display dates, but the column stays numeric to every Python reader. Convert the values, then write and format:",[139,2117,2119],{"className":174,"code":2118,"language":176,"meta":144,"style":144},"import pandas as pd\n\ndf = pd.read_excel(\"report.xlsx\")\n\n# Guard against nonsense before converting.\nplausible = df[\"invoice_date\"].between(20_000, 60_000)\nif not plausible.all():\n    print(f\"{(~plausible).sum()} values outside the plausible serial range\")\n\ndf.loc[plausible, \"invoice_date\"] = pd.to_datetime(\n    df.loc[plausible, \"invoice_date\"], unit=\"D\", origin=\"1899-12-30\"\n)\ndf[\"invoice_date\"] = pd.to_datetime(df[\"invoice_date\"], errors=\"coerce\")\n\nwith pd.ExcelWriter(\"report_fixed.xlsx\", engine=\"xlsxwriter\",\n                    date_format=\"yyyy-mm-dd\") as writer:\n    df.to_excel(writer, sheet_name=\"Orders\", index=False)\n",[14,2120,2121,2131,2135,2147,2151,2156,2180,2189,2217,2221,2235,2263,2267,2295,2299,2317,2332],{"__ignoreMap":144},[148,2122,2123,2125,2127,2129],{"class":150,"line":151},[148,2124,184],{"class":183},[148,2126,188],{"class":187},[148,2128,191],{"class":183},[148,2130,194],{"class":187},[148,2132,2133],{"class":150,"line":197},[148,2134,201],{"emptyLinePlaceholder":200},[148,2136,2137,2139,2141,2143,2145],{"class":150,"line":204},[148,2138,207],{"class":187},[148,2140,210],{"class":183},[148,2142,213],{"class":187},[148,2144,216],{"class":158},[148,2146,219],{"class":187},[148,2148,2149],{"class":150,"line":222},[148,2150,201],{"emptyLinePlaceholder":200},[148,2152,2153],{"class":150,"line":238},[148,2154,2155],{"class":358},"# Guard against nonsense before converting.\n",[148,2157,2158,2161,2163,2166,2168,2171,2173,2175,2178],{"class":150,"line":350},[148,2159,2160],{"class":187},"plausible ",[148,2162,210],{"class":183},[148,2164,2165],{"class":187}," df[",[148,2167,232],{"class":158},[148,2169,2170],{"class":187},"].between(",[148,2172,1630],{"class":225},[148,2174,17],{"class":187},[148,2176,2177],{"class":225},"60_000",[148,2179,219],{"class":187},[148,2181,2182,2184,2186],{"class":150,"line":355},[148,2183,605],{"class":183},[148,2185,669],{"class":183},[148,2187,2188],{"class":187}," plausible.all():\n",[148,2190,2191,2194,2196,2198,2200,2202,2204,2207,2210,2212,2215],{"class":150,"line":362},[148,2192,2193],{"class":225},"    print",[148,2195,862],{"class":187},[148,2197,2028],{"class":183},[148,2199,1576],{"class":158},[148,2201,2034],{"class":2033},[148,2203,862],{"class":187},[148,2205,2206],{"class":183},"~",[148,2208,2209],{"class":187},"plausible).sum()",[148,2211,2040],{"class":2033},[148,2213,2214],{"class":158}," values outside the plausible serial range\"",[148,2216,219],{"class":187},[148,2218,2219],{"class":150,"line":407},[148,2220,201],{"emptyLinePlaceholder":200},[148,2222,2223,2226,2228,2230,2232],{"class":150,"line":421},[148,2224,2225],{"class":187},"df.loc[plausible, ",[148,2227,232],{"class":158},[148,2229,658],{"class":187},[148,2231,210],{"class":183},[148,2233,2234],{"class":187}," pd.to_datetime(\n",[148,2236,2237,2240,2242,2245,2248,2250,2253,2255,2258,2260],{"class":150,"line":432},[148,2238,2239],{"class":187},"    df.loc[plausible, ",[148,2241,232],{"class":158},[148,2243,2244],{"class":187},"], ",[148,2246,2247],{"class":377},"unit",[148,2249,210],{"class":183},[148,2251,2252],{"class":158},"\"D\"",[148,2254,17],{"class":187},[148,2256,2257],{"class":377},"origin",[148,2259,210],{"class":183},[148,2261,2262],{"class":158},"\"1899-12-30\"\n",[148,2264,2265],{"class":150,"line":437},[148,2266,219],{"class":187},[148,2268,2269,2272,2274,2276,2278,2281,2283,2285,2288,2290,2293],{"class":150,"line":594},[148,2270,2271],{"class":187},"df[",[148,2273,232],{"class":158},[148,2275,658],{"class":187},[148,2277,210],{"class":183},[148,2279,2280],{"class":187}," pd.to_datetime(df[",[148,2282,232],{"class":158},[148,2284,2244],{"class":187},[148,2286,2287],{"class":377},"errors",[148,2289,210],{"class":183},[148,2291,2292],{"class":158},"\"coerce\"",[148,2294,219],{"class":187},[148,2296,2297],{"class":150,"line":617},[148,2298,201],{"emptyLinePlaceholder":200},[148,2300,2301,2303,2305,2307,2309,2311,2313,2315],{"class":150,"line":622},[148,2302,1121],{"class":183},[148,2304,1239],{"class":187},[148,2306,443],{"class":158},[148,2308,17],{"class":187},[148,2310,1247],{"class":377},[148,2312,210],{"class":183},[148,2314,1141],{"class":158},[148,2316,517],{"class":187},[148,2318,2319,2322,2324,2326,2328,2330],{"class":150,"line":632},[148,2320,2321],{"class":377},"                    date_format",[148,2323,210],{"class":183},[148,2325,514],{"class":158},[148,2327,1170],{"class":187},[148,2329,191],{"class":183},[148,2331,1175],{"class":187},[148,2333,2334,2336,2338,2340,2342,2344,2346,2348,2350],{"class":150,"line":641},[148,2335,1180],{"class":187},[148,2337,1183],{"class":377},[148,2339,210],{"class":183},[148,2341,1188],{"class":158},[148,2343,17],{"class":187},[148,2345,1193],{"class":377},[148,2347,210],{"class":183},[148,2349,1198],{"class":225},[148,2351,219],{"class":187},[10,2353,2354,2355,2358,2359,2362],{},"The ",[14,2356,2357],{},"1899-12-30"," origin is not arbitrary — it cancels Excel's 1900 leap-year bug, as explained in the ",[26,2360,2361],{"href":28},"parent topic",". Anchoring at 1900-01-01 leaves every date one day late.",[134,2364,2366],{"id":2365},"common-pitfalls-and-fixes","Common pitfalls and fixes",[882,2368,2369,2382],{},[885,2370,2371],{},[888,2372,2373,2376,2379],{},[891,2374,2375],{},"Symptom",[891,2377,2378],{},"Cause",[891,2380,2381],{},"Fix",[901,2383,2384,2400,2415,2431,2450,2463,2478,2489],{},[888,2385,2386,2391,2394],{},[906,2387,2388,2389],{},"Cell shows ",[14,2390,16],{},[906,2392,2393],{},"No date number format",[906,2395,2396,2397,30],{},"Set ",[14,2398,2399],{},"cell.number_format = \"yyyy-mm-dd\"",[888,2401,2402,2406,2409],{},[906,2403,2388,2404],{},[14,2405,455],{},[906,2407,2408],{},"Column too narrow for the formatted date",[906,2410,2411,2412,30],{},"Widen with ",[14,2413,2414],{},"column_dimensions[...].width",[888,2416,2417,2420,2425],{},[906,2418,2419],{},"Format vanished after a pandas write",[906,2421,2422,2424],{},[14,2423,1390],{}," replaced the sheet",[906,2426,2427,2428,2430],{},"Format after writing, or via ",[14,2429,1025],{}," arguments.",[888,2432,2433,2436,2441],{},[906,2434,2435],{},"Month shown where minutes expected",[906,2437,2438,2440],{},[14,2439,998],{}," after a date part means months",[906,2442,2443,2444,2446,2447,2449],{},"Use ",[14,2445,1010],{}," for time, ",[14,2448,1014],{}," for year-month.",[888,2451,2452,2455,2458],{},[906,2453,2454],{},"Every date one day late",[906,2456,2457],{},"Origin anchored at 1900-01-01",[906,2459,2443,2460,30],{},[14,2461,2462],{},"origin=\"1899-12-30\"",[888,2464,2465,2468,2474],{},[906,2466,2467],{},"Duration of 32 hours shows as 8:00",[906,2469,2470,2473],{},[14,2471,2472],{},"hh"," wraps at 24",[906,2475,2443,2476,30],{},[14,2477,969],{},[888,2479,2480,2483,2486],{},[906,2481,2482],{},"A quantity column became dates",[906,2484,2485],{},"Repair heuristic too loose",[906,2487,2488],{},"Require a date-like header name as well.",[888,2490,2491,2494,2497],{},[906,2492,2493],{},"Format applied but pandas still sees numbers",[906,2495,2496],{},"Values never converted",[906,2498,2499,2500,2503],{},"Convert with ",[14,2501,2502],{},"to_datetime"," before writing.",[134,2505,2507],{"id":2506},"performance-and-scale-notes","Performance and scale notes",[32,2509,42,2515,42,2518,42,2521,42,2524,42,2530,42,2535,42,2540,42,2544,42,2551,42,2554,42,2559,42,2564,42,2567,42,2571,42,2574,42,2577,42,2580,42,2583,42,2587,42,2590,42,2593,42,2598,42,2601,42,2604,42,2607,42,2610,42,2614],{"viewBox":2510,"role":35,"ariaLabel":2511,"ariaLabelledBy":2512,"xmlns":40,"style":41},"0 0 800 226","Three ways to apply a date format at increasing scale: per-cell assignment, a shared named style, and a single set_column call that is independent of row count.",[2513,2514],"fmtscale-t","fmtscale-d",[44,2516,2517],{"id":2513},"Three ways to apply a date format, and how each scales",[48,2519,2520],{"id":2514},"Three approaches side by side. Assigning number_format per cell creates or looks up a style entry for every cell, so cost grows with row count and can approach Excel's ceiling of roughly sixty-four thousand distinct formats. A shared NamedStyle assigned to each cell still loops but reuses one style entry. xlsxwriter's set_column applies one format to the whole column in a single call, so the cost is constant regardless of how many rows there are.",[52,2522],{"x":54,"y":54,"width":55,"height":2523,"fill":57},"226",[52,2525],{"x":2526,"y":2527,"width":2528,"height":2529,"rx":2526,"fill":108,"stroke":109,"style":67},"14","24","248","176",[69,2531,2534],{"x":1468,"y":2532,"style":2533},"52","font-size:12.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","per-cell assignment",[69,2536,2539],{"x":1468,"y":2537,"style":2538},"82","font-size:11px;fill:var(--text,#172033);text-anchor:middle","cell.number_format = \"...\"",[69,2541,2543],{"x":1468,"y":1434,"style":2542},"font-size:11px;fill:var(--muted,#5b6780);text-anchor:middle","a style lookup per cell",[52,2545],{"x":2546,"y":2547,"width":2548,"height":2549,"rx":2550,"fill":57,"stroke":109},"40","124","196","20","5",[52,2552],{"x":2546,"y":2547,"width":1446,"height":2549,"rx":2550,"fill":2553},"#f43f8f",[69,2555,2558],{"x":1468,"y":2556,"style":2557},"166","font-size:11px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","cost grows with rows",[69,2560,2563],{"x":1468,"y":2561,"style":2562},"186","font-size:10px;fill:var(--muted,#5b6780);text-anchor:middle","can hit the 64k format ceiling",[52,2565],{"x":2566,"y":2527,"width":2528,"height":2529,"rx":2526,"fill":1480,"stroke":1481,"style":67},"276",[69,2568,2570],{"x":71,"y":2532,"style":2569},"font-size:12.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","one shared NamedStyle",[69,2572,2573],{"x":71,"y":2537,"style":2538},"cell.style = \"iso_date\"",[69,2575,2576],{"x":71,"y":1434,"style":2542},"still a loop, one style",[52,2578],{"x":2579,"y":2547,"width":2548,"height":2549,"rx":2550,"fill":57,"stroke":1481},"302",[52,2581],{"x":2579,"y":2547,"width":2582,"height":2549,"rx":2550,"fill":1500},"104",[69,2584,2586],{"x":71,"y":2556,"style":2585},"font-size:11px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","no format explosion",[69,2588,2589],{"x":71,"y":2561,"style":2562},"loop cost remains",[52,2591],{"x":2592,"y":2527,"width":2528,"height":2529,"rx":2526,"fill":123,"stroke":124,"style":67},"538",[69,2594,2597],{"x":2595,"y":2532,"style":2596},"662","font-size:12.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","set_column",[69,2599,2600],{"x":2595,"y":2537,"style":2538},"sheet.set_column(\"B:B\", w, f)",[69,2602,2603],{"x":2595,"y":1434,"style":2542},"one call, whole column",[52,2605],{"x":2606,"y":2547,"width":2548,"height":2549,"rx":2550,"fill":57,"stroke":124},"564",[52,2608],{"x":2606,"y":2547,"width":1424,"height":2549,"rx":2550,"fill":2609},"#0f9488",[69,2611,2613],{"x":2595,"y":2556,"style":2612},"font-size:11px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","constant cost",[69,2615,2616],{"x":2595,"y":2561,"style":2562},"independent of row count",[10,2618,2619,2620,2623],{},"Per-cell formatting is the slow path. Each ",[14,2621,2622],{},"cell.number_format = ..."," assignment in openpyxl creates or looks up a style entry, and on a column of half a million rows that adds real time and memory.",[10,2625,2626,2627,2629],{},"Two faster routes. With xlsxwriter, ",[14,2628,2597],{}," applies one format to an entire column in a single call, independent of row count:",[139,2631,2633],{"className":174,"code":2632,"language":176,"meta":144,"style":144},"import pandas as pd\n\nbig = pd.DataFrame({\n    \"id\": range(500_000),\n    \"invoice_date\": pd.date_range(\"2024-01-01\", periods=500_000, freq=\"min\"),\n})\n\nwith pd.ExcelWriter(\"big.xlsx\", engine=\"xlsxwriter\") as writer:\n    big.to_excel(writer, sheet_name=\"Data\", index=False)\n    fmt = writer.book.add_format({\"num_format\": \"yyyy-mm-dd hh:mm\"})\n    writer.sheets[\"Data\"].set_column(\"B:B\", 19, fmt)\n",[14,2634,2635,2645,2649,2658,2676,2707,2711,2715,2738,2760,2778],{"__ignoreMap":144},[148,2636,2637,2639,2641,2643],{"class":150,"line":151},[148,2638,184],{"class":183},[148,2640,188],{"class":187},[148,2642,191],{"class":183},[148,2644,194],{"class":187},[148,2646,2647],{"class":150,"line":197},[148,2648,201],{"emptyLinePlaceholder":200},[148,2650,2651,2654,2656],{"class":150,"line":204},[148,2652,2653],{"class":187},"big ",[148,2655,210],{"class":183},[148,2657,1054],{"class":187},[148,2659,2660,2663,2665,2668,2670,2673],{"class":150,"line":222},[148,2661,2662],{"class":158},"    \"id\"",[148,2664,511],{"class":187},[148,2666,2667],{"class":225},"range",[148,2669,862],{"class":187},[148,2671,2672],{"class":225},"500_000",[148,2674,2675],{"class":187},"),\n",[148,2677,2678,2680,2683,2686,2688,2691,2693,2695,2697,2700,2702,2705],{"class":150,"line":238},[148,2679,508],{"class":158},[148,2681,2682],{"class":187},": pd.date_range(",[148,2684,2685],{"class":158},"\"2024-01-01\"",[148,2687,17],{"class":187},[148,2689,2690],{"class":377},"periods",[148,2692,210],{"class":183},[148,2694,2672],{"class":225},[148,2696,17],{"class":187},[148,2698,2699],{"class":377},"freq",[148,2701,210],{"class":183},[148,2703,2704],{"class":158},"\"min\"",[148,2706,2675],{"class":187},[148,2708,2709],{"class":150,"line":350},[148,2710,1112],{"class":187},[148,2712,2713],{"class":150,"line":355},[148,2714,201],{"emptyLinePlaceholder":200},[148,2716,2717,2719,2721,2724,2726,2728,2730,2732,2734,2736],{"class":150,"line":362},[148,2718,1121],{"class":183},[148,2720,1239],{"class":187},[148,2722,2723],{"class":158},"\"big.xlsx\"",[148,2725,17],{"class":187},[148,2727,1247],{"class":377},[148,2729,210],{"class":183},[148,2731,1141],{"class":158},[148,2733,1170],{"class":187},[148,2735,191],{"class":183},[148,2737,1175],{"class":187},[148,2739,2740,2743,2745,2747,2750,2752,2754,2756,2758],{"class":150,"line":407},[148,2741,2742],{"class":187},"    big.to_excel(writer, ",[148,2744,1183],{"class":377},[148,2746,210],{"class":183},[148,2748,2749],{"class":158},"\"Data\"",[148,2751,17],{"class":187},[148,2753,1193],{"class":377},[148,2755,210],{"class":183},[148,2757,1198],{"class":225},[148,2759,219],{"class":187},[148,2761,2762,2765,2767,2770,2772,2774,2776],{"class":150,"line":421},[148,2763,2764],{"class":187},"    fmt ",[148,2766,210],{"class":183},[148,2768,2769],{"class":187}," writer.book.add_format({",[148,2771,1322],{"class":158},[148,2773,511],{"class":187},[148,2775,538],{"class":158},[148,2777,1112],{"class":187},[148,2779,2780,2783,2785,2788,2790,2792,2794],{"class":150,"line":432},[148,2781,2782],{"class":187},"    writer.sheets[",[148,2784,2749],{"class":158},[148,2786,2787],{"class":187},"].set_column(",[148,2789,1362],{"class":158},[148,2791,17],{"class":187},[148,2793,1381],{"class":225},[148,2795,2796],{"class":187},", fmt)\n",[10,2798,2799],{},"With openpyxl, define the style once and reuse the object rather than assigning a fresh string per cell — Excel caps a workbook at roughly 64,000 distinct cell formats, and a loop that creates a new one each iteration will eventually hit it:",[139,2801,2803],{"className":174,"code":2802,"language":176,"meta":144,"style":144},"from openpyxl.styles import NamedStyle\nfrom openpyxl import load_workbook\n\ndate_style = NamedStyle(name=\"iso_date\", number_format=\"yyyy-mm-dd\")\n\nwb = load_workbook(\"report.xlsx\")\nwb.add_named_style(date_style)\nws = wb.active\nfor (cell,) in ws.iter_rows(min_row=2, min_col=2, max_col=2):\n    cell.style = \"iso_date\"      # one shared style, not one per cell\nwb.save(\"report_fixed.xlsx\")\n",[14,2804,2805,2817,2827,2831,2858,2862,2874,2879,2887,2921,2934],{"__ignoreMap":144},[148,2806,2807,2809,2812,2814],{"class":150,"line":151},[148,2808,293],{"class":183},[148,2810,2811],{"class":187}," openpyxl.styles ",[148,2813,184],{"class":183},[148,2815,2816],{"class":187}," NamedStyle\n",[148,2818,2819,2821,2823,2825],{"class":150,"line":197},[148,2820,293],{"class":183},[148,2822,308],{"class":187},[148,2824,184],{"class":183},[148,2826,313],{"class":187},[148,2828,2829],{"class":150,"line":204},[148,2830,201],{"emptyLinePlaceholder":200},[148,2832,2833,2836,2838,2841,2843,2845,2848,2850,2852,2854,2856],{"class":150,"line":222},[148,2834,2835],{"class":187},"date_style ",[148,2837,210],{"class":183},[148,2839,2840],{"class":187}," NamedStyle(",[148,2842,2048],{"class":377},[148,2844,210],{"class":183},[148,2846,2847],{"class":158},"\"iso_date\"",[148,2849,17],{"class":187},[148,2851,282],{"class":377},[148,2853,210],{"class":183},[148,2855,514],{"class":158},[148,2857,219],{"class":187},[148,2859,2860],{"class":150,"line":238},[148,2861,201],{"emptyLinePlaceholder":200},[148,2863,2864,2866,2868,2870,2872],{"class":150,"line":350},[148,2865,322],{"class":187},[148,2867,210],{"class":183},[148,2869,327],{"class":187},[148,2871,216],{"class":158},[148,2873,219],{"class":187},[148,2875,2876],{"class":150,"line":355},[148,2877,2878],{"class":187},"wb.add_named_style(date_style)\n",[148,2880,2881,2883,2885],{"class":150,"line":362},[148,2882,336],{"class":187},[148,2884,210],{"class":183},[148,2886,614],{"class":187},[148,2888,2889,2891,2893,2895,2897,2899,2901,2903,2905,2907,2909,2911,2913,2915,2917,2919],{"class":150,"line":407},[148,2890,365],{"class":183},[148,2892,752],{"class":187},[148,2894,371],{"class":183},[148,2896,374],{"class":187},[148,2898,378],{"class":377},[148,2900,210],{"class":183},[148,2902,383],{"class":225},[148,2904,17],{"class":187},[148,2906,388],{"class":377},[148,2908,210],{"class":183},[148,2910,383],{"class":225},[148,2912,17],{"class":187},[148,2914,397],{"class":377},[148,2916,210],{"class":183},[148,2918,383],{"class":225},[148,2920,404],{"class":187},[148,2922,2923,2926,2928,2931],{"class":150,"line":421},[148,2924,2925],{"class":187},"    cell.style ",[148,2927,210],{"class":183},[148,2929,2930],{"class":158}," \"iso_date\"",[148,2932,2933],{"class":358},"      # one shared style, not one per cell\n",[148,2935,2936,2938,2940],{"class":150,"line":432},[148,2937,440],{"class":187},[148,2939,443],{"class":158},[148,2941,219],{"class":187},[10,2943,2944,2945,2947,2948,2952],{},"For genuinely large workbooks, the cheapest fix of all is not to create the problem: write with the correct ",[14,2946,1205],{}," in the first place, using the streaming approach in ",[26,2949,2951],{"href":2950},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-large-excel-files-in-python\u002Fwrite-large-dataframes-to-excel-with-write-only-mode\u002F","writing large DataFrames with write-only mode",", and no repair pass is ever needed.",[134,2954,2956],{"id":2955},"conclusion","Conclusion",[10,2958,2959,2960,2962,2963,2965,2966,2968,2969,2971,2972,2974,2975,2977,2978,2980],{},"A cell showing ",[14,2961,16],{}," is a display problem, not a data problem. Set ",[14,2964,282],{}," on the cell with openpyxl, or ",[14,2967,1205],{}," and ",[14,2970,1209],{}," on a pandas ",[14,2973,1025],{},", and the same value renders as a date. Widen the column so it does not turn into ",[14,2976,455],{},". If the column is genuinely numeric rather than a formatted date, convert it with the ",[14,2979,2357],{}," origin before writing. And for repair passes over files you did not create, require a date-like header name as well as a plausible value range, so a column of quantities never gets reformatted as dates.",[134,2982,2984],{"id":2983},"frequently-asked-questions","Frequently asked questions",[10,2986,2987,2993,2994,2996],{},[262,2988,2989,2990,2992],{},"Is my data wrong when Excel shows ",[14,2991,16],{},"?","\nNo. The value is correct — 45292 is Excel's internal representation of 1 January 2024. Only the cell's display format is missing, so setting ",[14,2995,282],{}," on the cell fixes it without touching the data.",[10,2998,2999,3002,3004,3005,3007,3008,3011,3012,3015],{},[262,3000,3001],{},"Which number format string should I use?",[14,3003,514],{}," for an unambiguous date, ",[14,3006,538],{}," when the time matters, and ",[14,3009,3010],{},"\"[h]:mm\""," for durations. Avoid locale-dependent forms like ",[14,3013,3014],{},"\"mm\u002Fdd\u002Fyyyy\""," in reports that cross borders.",[10,3017,3018,3021,3023,3024,2968,3026,3028,3029,3031],{},[262,3019,3020],{},"Why did my format disappear after pandas wrote the file?",[14,3022,1390],{}," replaces the sheet rather than merging into it, so formatting applied beforehand is lost. Set ",[14,3025,1205],{},[14,3027,1209],{}," on the ",[14,3030,1025],{}," instead, or apply the formats after writing.",[10,3033,3034,3037,3038,3040],{},[262,3035,3036],{},"Do I have to format every cell individually?","\nNo. Set the format once per column by iterating that column's cells with openpyxl, or use xlsxwriter's ",[14,3039,2597],{},", which applies one format to a whole column in a single call.",[10,3042,3043,3046,3047,3050],{},[262,3044,3045],{},"What if the values really are numbers rather than dates?","\nConvert them first with ",[14,3048,3049],{},"pd.to_datetime(col, unit=\"D\", origin=\"1899-12-30\")",", then write and format. A number format alone will make Excel display a plausible date, but the column will still be numeric to pandas.",[134,3052,3054],{"id":3053},"related","Related",[3056,3057,3058,3065,3072,3079,3089],"ul",{},[3059,3060,3061,3062,3064],"li",{},"Up to the parent: ",[26,3063,29],{"href":28}," — the serial model behind this whole problem.",[3059,3066,3067,3071],{},[26,3068,3070],{"href":3069},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fparse-excel-dates-into-python-datetimes-with-pandas\u002F","Parse Excel Dates into Python datetimes with pandas"," — the reading side of the same boundary.",[3059,3073,3074,3078],{},[26,3075,3077],{"href":3076},"\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"," — the wider vocabulary of Excel format strings.",[3059,3080,3081,3085,3086,3088],{},[26,3082,3084],{"href":3083},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fset-column-width-and-row-height-in-openpyxl\u002F","Set Column Width and Row Height in openpyxl"," — fixing the ",[14,3087,455],{}," half of the problem.",[3059,3090,3091,3095],{},[26,3092,3094],{"href":3093},"\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 same mechanism applied to money.",[3097,3098,3099],"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 .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":144,"searchDepth":197,"depth":197,"links":3101},[3102,3103,3104,3105,3106,3107,3108,3109,3110,3111],{"id":136,"depth":197,"text":137},{"id":276,"depth":197,"text":277},{"id":1018,"depth":197,"text":1019},{"id":1401,"depth":197,"text":1402},{"id":2106,"depth":197,"text":2107},{"id":2365,"depth":197,"text":2366},{"id":2506,"depth":197,"text":2507},{"id":2955,"depth":197,"text":2956},{"id":2983,"depth":197,"text":2984},{"id":3053,"depth":197,"text":3054},"Your Excel file shows 45292 where a date should be. Fix it in Python with openpyxl number formats, pandas ExcelWriter date formats, and a repair pass for existing workbooks.","md",[3115,3118,3119,3121,3123],{"q":3116,"a":3117},"Is my data wrong when Excel shows 45292?","No. The value is correct — 45292 is Excel's internal representation of 1 January 2024. Only the cell's display format is missing, so setting number_format on the cell fixes it without touching the data.",{"q":3001,"a":910},{"q":3020,"a":3120},"to_excel replaces the sheet rather than merging into it, so formatting applied beforehand is lost. Set date_format and datetime_format on the ExcelWriter instead, or apply the formats after writing.",{"q":3036,"a":3122},"No. Set the format once per column by iterating that column's cells with openpyxl, or use xlsxwriter's set_column, which applies one format to a whole column in a single call.",{"q":3045,"a":3124},"Convert them first with pd.to_datetime(col, unit=\"D\", origin=\"1899-12-30\"), then write and format. A number format alone will make Excel display a plausible date, but the column will still be numeric to pandas.",{},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates",{"title":3128,"description":3129},"Excel Showing 45292 Instead of a Date — Python Fix","Why Excel displays a serial number instead of a date, and how to fix it from Python: set number_format in openpyxl, date_format in ExcelWriter, or repair a workbook in place.","fix-excel-serial-numbers-showing-instead-of-dates","advanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates\u002Findex","how-to","kX9p-BtRsyCQPmo-83Nu7ATdPk-eIZ1HxD4tebeN8zc",[3135,3138],{"title":29,"path":3136,"stem":3137,"children":-1},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data","advanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Findex",{"title":3139,"path":3140,"stem":3141,"children":-1},"Group Excel Rows by Month and Quarter with pandas","\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fgroup-excel-rows-by-month-and-quarter-with-pandas","advanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fgroup-excel-rows-by-month-and-quarter-with-pandas\u002Findex",1786800027129]