[{"data":1,"prerenderedAt":1904},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros":1870,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros":1879,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros":1884,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros":1885},{"id":4,"title":5,"body":6,"dateModified":1836,"datePublished":1836,"description":1837,"extension":1838,"faq":1839,"keyword":1848,"kind":1849,"meta":1850,"navigation":285,"path":1859,"seo":1860,"slug":1863,"stem":1864,"topics":1865,"type":1868,"__hash__":1869},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros\u002Findex.md","Format ZIP Codes and IDs with Leading Zeros in Excel",{"type":7,"value":8,"toc":1823},"minimark",[9,41,49,191,196,226,246,250,257,492,529,533,543,737,758,762,781,987,1003,1162,1165,1287,1291,1300,1441,1456,1460,1473,1659,1670,1674,1719,1723,1737,1741,1756,1760,1766,1776,1782,1788,1792,1819],[10,11,12,13,17,18,21,22,25,26,30,31,34,35,40],"p",{},"ZIP codes, employee numbers, account codes and part numbers are identifiers that happen to be written in digits, and many of them start with a zero. Pass them through a CSV file, a database integer column or a careless ",[14,15,16],"code",{},"read_excel",", and ",[14,19,20],{},"02134"," becomes the number ",[14,23,24],{},"2134",". When the report is written to Excel, there are two ways to get the zero back: store the code as ",[27,28,29],"strong",{},"text",", or store the number and apply a ",[27,32,33],{},"number format"," that pads it. Both look the same in the cell, and both are right in different situations. This page, part of ",[36,37,39],"a",{"href":38},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002F","Applying Number and Date Formats in Excel",", shows both with pandas, openpyxl and xlsxwriter.",[10,42,43,44,48],{},"For the reading side — stopping pandas from dropping the zeros in the first place — see ",[36,45,47],{"href":46},"\u002Fgetting-started-with-python-excel-automation\u002Freading-excel-files-with-pandas\u002Fkeep-leading-zeros-when-reading-excel-with-pandas\u002F","Keep Leading Zeros When Reading Excel with pandas",".",[50,51,59,60,59,64,59,68,59,76,59,86,59,97,59,103,59,110,59,116,59,123,59,127,59,132,59,136,59,143,59,148,59,155,59,160,59,164,59,168,59,173,59,176,59,181,59,184],"svg",{"viewBox":52,"role":53,"ariaLabelledBy":54,"xmlns":57,"style":58},"4 0 752 207","img",[55,56],"lz-choice-t","lz-choice-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[61,62,63],"title",{"id":55},"Two ways to show 02134 in a cell",[65,66,67],"desc",{"id":56},"Two panels. Stored as text: the cell holds the string 02134, keeps every digit whatever the format, sorts as text and matches other text; Excel may show a number-stored-as-text warning. Stored as a number with the format 00000: the cell holds 2134 and displays 02134, sorts numerically and can be used in arithmetic, but a lookup against text codes fails.",[69,70],"rect",{"x":71,"y":72,"width":73,"height":74,"fill":75},"4","0","752","207","#ffffff",[69,77],{"x":78,"y":79,"width":80,"height":81,"rx":82,"fill":83,"stroke":84,"style":85},"20.0","16.0","351.0","175.0","14","#d9f4f1","var(--teal,#0f9488)","stroke-width:2px",[87,88,90],"g",{"transform":89},"translate(182.5,29.0) scale(1.083)",[91,92],"path",{"d":93,"fill":94,"stroke":95,"style":96},"M5 9h14 M4 15h14 M10 4l-2 16 M16 4l-2 16","none","var(--teal-ink,#0b6157)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[29,98,102],{"x":99,"y":100,"style":101},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Text \"02134\"",[104,105],"line",{"x1":106,"y1":107,"x2":108,"y2":107,"stroke":84,"style":109},"36.0","91.0","355.0","stroke-width:1px",[29,111,115],{"x":112,"y":113,"style":114},"60.0","111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","every digit kept, always",[87,117,119],{"transform":118},"translate(38.5,99.5) scale(0.625)",[91,120],{"d":121,"fill":94,"stroke":84,"style":122},"M5 12.5l4.5 4.5L19 7","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[29,124,126],{"x":112,"y":125,"style":114},"137.0","matches other text codes",[87,128,130],{"transform":129},"translate(38.5,125.5) scale(0.625)",[91,131],{"d":121,"fill":94,"stroke":84,"style":122},[29,133,135],{"x":112,"y":134,"style":114},"163.0","number-as-text warning",[87,137,139],{"transform":138},"translate(38.5,151.5) scale(0.625)",[91,140],{"d":141,"fill":94,"stroke":142,"style":122},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","var(--gold,#b4740a)",[69,144],{"x":145,"y":79,"width":80,"height":81,"rx":82,"fill":146,"stroke":147,"style":85},"389.0","#f0f4ff","var(--brand,#5b5cf0)",[87,149,151],{"transform":150},"translate(551.5,29.0) scale(1.083)",[91,152],{"d":153,"fill":94,"stroke":154,"style":96},"M12 9a3 3 0 1 0 .01 0z M12 2.5v3 M12 18.5v3 M2.5 12h3 M18.5 12h3 M5.3 5.3l2.1 2.1 M16.6 16.6l2.1 2.1 M5.3 18.7l2.1-2.1 M16.6 7.4l2.1-2.1","var(--brand-strong,#4338ca)",[29,156,159],{"x":157,"y":100,"style":158},"564.5","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Number 2134, format 00000",[104,161],{"x1":162,"y1":107,"x2":163,"y2":107,"stroke":147,"style":109},"405.0","724.0",[29,165,167],{"x":166,"y":113,"style":114},"429.0","stays numeric",[87,169,171],{"transform":170},"translate(407.5,99.5) scale(0.625)",[91,172],{"d":121,"fill":94,"stroke":84,"style":122},[29,174,175],{"x":166,"y":125,"style":114},"sorts as a number",[87,177,179],{"transform":178},"translate(407.5,125.5) scale(0.625)",[91,180],{"d":121,"fill":94,"stroke":84,"style":122},[29,182,183],{"x":166,"y":134,"style":114},"lookups against text fail",[87,185,187],{"transform":186},"translate(407.5,151.5) scale(0.625)",[91,188],{"d":189,"fill":94,"stroke":190,"style":122},"M6 6l12 12 M18 6L6 18","var(--accent,#f43f8f)",[192,193,195],"h2",{"id":194},"prerequisites","Prerequisites",[197,198,203],"pre",{"className":199,"code":200,"language":201,"meta":202,"style":202},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl xlsxwriter\n","bash","",[14,204,205],{"__ignoreMap":202},[206,207,209,213,217,220,223],"span",{"class":104,"line":208},1,[206,210,212],{"class":211},"sMTad","pip",[206,214,216],{"class":215},"srMev"," install",[206,218,219],{"class":215}," pandas",[206,221,222],{"class":215}," openpyxl",[206,224,225],{"class":215}," xlsxwriter\n",[10,227,228,231,232,234,235,237,238,241,242,245],{},[14,229,230],{},"customers.csv"," has ZIP codes and employee numbers that were saved as plain numbers, so ",[14,233,20],{}," is now ",[14,236,24],{}," and ",[14,239,240],{},"07030"," is ",[14,243,244],{},"7030",". One customer has a 9-digit ZIP+4 code.",[192,247,249],{"id":248},"step-1-store-codes-as-text-with-zfill","Step 1 — Store codes as text with zfill",[10,251,252,253,256],{},"When a code is an identifier — nobody adds ZIP codes together — text is the robust choice. Pad each value to its fixed width with ",[14,254,255],{},"str.zfill",", and pandas writes strings as text cells:",[197,258,262],{"className":259,"code":260,"language":261,"meta":202,"style":202},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\ndf = pd.read_csv(\"customers.csv\")\nprint(df.dtypes.to_dict())\n\nout = df.copy()\nout[\"zip\"] = out[\"zip\"].astype(str).str.zfill(5)\nout[\"employee\"] = out[\"employee\"].astype(str).str.zfill(6)\nout.to_excel(\"codes_as_text.xlsx\", index=False)\n\nfrom openpyxl import load_workbook\nws = load_workbook(\"codes_as_text.xlsx\").active\nprint([(ws.cell(r, 2).value, ws.cell(r, 2).data_type) for r in range(2, 6)])\n","python",[14,263,264,280,287,305,315,320,331,364,391,414,419,433,449],{"__ignoreMap":202},[206,265,266,270,274,277],{"class":104,"line":208},[206,267,269],{"class":268},"s-kum","import",[206,271,273],{"class":272},"skGVy"," pandas ",[206,275,276],{"class":268},"as",[206,278,279],{"class":272}," pd\n",[206,281,283],{"class":104,"line":282},2,[206,284,286],{"emptyLinePlaceholder":285},true,"\n",[206,288,290,293,296,299,302],{"class":104,"line":289},3,[206,291,292],{"class":272},"df ",[206,294,295],{"class":268},"=",[206,297,298],{"class":272}," pd.read_csv(",[206,300,301],{"class":215},"\"customers.csv\"",[206,303,304],{"class":272},")\n",[206,306,308,312],{"class":104,"line":307},4,[206,309,311],{"class":310},"sP0c6","print",[206,313,314],{"class":272},"(df.dtypes.to_dict())\n",[206,316,318],{"class":104,"line":317},5,[206,319,286],{"emptyLinePlaceholder":285},[206,321,323,326,328],{"class":104,"line":322},6,[206,324,325],{"class":272},"out ",[206,327,295],{"class":268},[206,329,330],{"class":272}," df.copy()\n",[206,332,334,337,340,343,345,348,350,353,356,359,362],{"class":104,"line":333},7,[206,335,336],{"class":272},"out[",[206,338,339],{"class":215},"\"zip\"",[206,341,342],{"class":272},"] ",[206,344,295],{"class":268},[206,346,347],{"class":272}," out[",[206,349,339],{"class":215},[206,351,352],{"class":272},"].astype(",[206,354,355],{"class":310},"str",[206,357,358],{"class":272},").str.zfill(",[206,360,361],{"class":310},"5",[206,363,304],{"class":272},[206,365,367,369,372,374,376,378,380,382,384,386,389],{"class":104,"line":366},8,[206,368,336],{"class":272},[206,370,371],{"class":215},"\"employee\"",[206,373,342],{"class":272},[206,375,295],{"class":268},[206,377,347],{"class":272},[206,379,371],{"class":215},[206,381,352],{"class":272},[206,383,355],{"class":310},[206,385,358],{"class":272},[206,387,388],{"class":310},"6",[206,390,304],{"class":272},[206,392,394,397,400,403,407,409,412],{"class":104,"line":393},9,[206,395,396],{"class":272},"out.to_excel(",[206,398,399],{"class":215},"\"codes_as_text.xlsx\"",[206,401,402],{"class":272},", ",[206,404,406],{"class":405},"sa561","index",[206,408,295],{"class":268},[206,410,411],{"class":310},"False",[206,413,304],{"class":272},[206,415,417],{"class":104,"line":416},10,[206,418,286],{"emptyLinePlaceholder":285},[206,420,422,425,428,430],{"class":104,"line":421},11,[206,423,424],{"class":268},"from",[206,426,427],{"class":272}," openpyxl ",[206,429,269],{"class":268},[206,431,432],{"class":272}," load_workbook\n",[206,434,436,439,441,444,446],{"class":104,"line":435},12,[206,437,438],{"class":272},"ws ",[206,440,295],{"class":268},[206,442,443],{"class":272}," load_workbook(",[206,445,399],{"class":215},[206,447,448],{"class":272},").active\n",[206,450,452,454,457,460,463,465,468,471,474,477,480,483,485,487,489],{"class":104,"line":451},13,[206,453,311],{"class":310},[206,455,456],{"class":272},"([(ws.cell(r, ",[206,458,459],{"class":310},"2",[206,461,462],{"class":272},").value, ws.cell(r, ",[206,464,459],{"class":310},[206,466,467],{"class":272},").data_type) ",[206,469,470],{"class":268},"for",[206,472,473],{"class":272}," r ",[206,475,476],{"class":268},"in",[206,478,479],{"class":310}," range",[206,481,482],{"class":272},"(",[206,484,459],{"class":310},[206,486,402],{"class":272},[206,488,388],{"class":310},[206,490,491],{"class":272},")])\n",[10,493,494,495,402,497,402,500,502,503,506,507,510,511,515,516,519,520,524,525,528],{},"The cells hold the strings ",[14,496,20],{},[14,498,499],{},"10001",[14,501,240],{}," — data type ",[14,504,505],{},"s",", text. ",[14,508,509],{},"zfill"," pads to ",[512,513,514],"em",{},"at least"," the width, so the 9-digit ZIP+4 stays as ",[14,517,518],{},"21340042",", which is not how ZIP+4 is written; the next steps handle it. Text codes show a small green triangle in Excel, the \"number stored as text\" warning, which ",[36,521,523],{"href":522},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-number-stored-as-text-warnings-in-excel-output\u002F","Fix \"Number Stored as Text\" Warnings in Excel Output"," shows how to suppress. For template columns that people will type codes into, also set the number format to ",[14,526,527],{},"@"," — Excel's Text format — on the empty cells: a code typed into a Text-formatted cell is stored as typed, zeros included, instead of being converted to a number the moment Enter is pressed.",[192,530,532],{"id":531},"step-2-keep-numbers-and-apply-a-padding-format","Step 2 — Keep numbers and apply a padding format",[10,534,535,536,538,539,542],{},"When the column must stay numeric — a system that imports it expects numbers, or it is sorted numerically — write the numbers and give the cells a format that pads them. In a number format, ",[14,537,72],{}," is a digit that is always shown, so ",[14,540,541],{},"00000"," shows at least five digits:",[197,544,546],{"className":259,"code":545,"language":261,"meta":202,"style":202},"with pd.ExcelWriter(\"codes_as_numbers.xlsx\", engine=\"xlsxwriter\") as writer:\n    df.to_excel(writer, index=False, sheet_name=\"Customers\")\n    ws = writer.sheets[\"Customers\"]\n    zip5 = writer.book.add_format({\"num_format\": \"00000\"})\n    emp = writer.book.add_format({\"num_format\": \"000000\"})\n    ws.set_column(\"B:B\", 12, zip5)\n    ws.set_column(\"C:C\", 12, emp)\n\ncheck = load_workbook(\"codes_as_numbers.xlsx\").active\nprint([(check.cell(r, 2).value, check.cell(r, 2).number_format) for r in range(2, 6)])\n",[14,547,548,577,600,615,637,655,671,685,689,702],{"__ignoreMap":202},[206,549,550,553,556,559,561,564,566,569,572,574],{"class":104,"line":208},[206,551,552],{"class":268},"with",[206,554,555],{"class":272}," pd.ExcelWriter(",[206,557,558],{"class":215},"\"codes_as_numbers.xlsx\"",[206,560,402],{"class":272},[206,562,563],{"class":405},"engine",[206,565,295],{"class":268},[206,567,568],{"class":215},"\"xlsxwriter\"",[206,570,571],{"class":272},") ",[206,573,276],{"class":268},[206,575,576],{"class":272}," writer:\n",[206,578,579,582,584,586,588,590,593,595,598],{"class":104,"line":282},[206,580,581],{"class":272},"    df.to_excel(writer, ",[206,583,406],{"class":405},[206,585,295],{"class":268},[206,587,411],{"class":310},[206,589,402],{"class":272},[206,591,592],{"class":405},"sheet_name",[206,594,295],{"class":268},[206,596,597],{"class":215},"\"Customers\"",[206,599,304],{"class":272},[206,601,602,605,607,610,612],{"class":104,"line":289},[206,603,604],{"class":272},"    ws ",[206,606,295],{"class":268},[206,608,609],{"class":272}," writer.sheets[",[206,611,597],{"class":215},[206,613,614],{"class":272},"]\n",[206,616,617,620,622,625,628,631,634],{"class":104,"line":307},[206,618,619],{"class":272},"    zip5 ",[206,621,295],{"class":268},[206,623,624],{"class":272}," writer.book.add_format({",[206,626,627],{"class":215},"\"num_format\"",[206,629,630],{"class":272},": ",[206,632,633],{"class":215},"\"00000\"",[206,635,636],{"class":272},"})\n",[206,638,639,642,644,646,648,650,653],{"class":104,"line":317},[206,640,641],{"class":272},"    emp ",[206,643,295],{"class":268},[206,645,624],{"class":272},[206,647,627],{"class":215},[206,649,630],{"class":272},[206,651,652],{"class":215},"\"000000\"",[206,654,636],{"class":272},[206,656,657,660,663,665,668],{"class":104,"line":322},[206,658,659],{"class":272},"    ws.set_column(",[206,661,662],{"class":215},"\"B:B\"",[206,664,402],{"class":272},[206,666,667],{"class":310},"12",[206,669,670],{"class":272},", zip5)\n",[206,672,673,675,678,680,682],{"class":104,"line":333},[206,674,659],{"class":272},[206,676,677],{"class":215},"\"C:C\"",[206,679,402],{"class":272},[206,681,667],{"class":310},[206,683,684],{"class":272},", emp)\n",[206,686,687],{"class":104,"line":366},[206,688,286],{"emptyLinePlaceholder":285},[206,690,691,694,696,698,700],{"class":104,"line":393},[206,692,693],{"class":272},"check ",[206,695,295],{"class":268},[206,697,443],{"class":272},[206,699,558],{"class":215},[206,701,448],{"class":272},[206,703,704,706,709,711,714,716,719,721,723,725,727,729,731,733,735],{"class":104,"line":416},[206,705,311],{"class":310},[206,707,708],{"class":272},"([(check.cell(r, ",[206,710,459],{"class":310},[206,712,713],{"class":272},").value, check.cell(r, ",[206,715,459],{"class":310},[206,717,718],{"class":272},").number_format) ",[206,720,470],{"class":268},[206,722,473],{"class":272},[206,724,476],{"class":268},[206,726,479],{"class":310},[206,728,482],{"class":272},[206,730,459],{"class":310},[206,732,402],{"class":272},[206,734,388],{"class":310},[206,736,491],{"class":272},[10,738,739,740,402,742,402,744,746,747,402,749,402,751,753,754,757],{},"The cells hold ",[14,741,24],{},[14,743,499],{},[14,745,244],{}," as numbers and display ",[14,748,20],{},[14,750,499],{},[14,752,240],{},". Reading the file back with pandas gives the numbers, not the padded text — a number format changes only how a value is shown. In openpyxl the equivalent is ",[14,755,756],{},"cell.number_format = \"00000\""," on each cell of the column.",[192,759,761],{"id":760},"step-3-handle-zip4-and-mixed-length-columns","Step 3 — Handle ZIP+4 and mixed-length columns",[10,763,764,765,768,769,772,773,776,777,780],{},"A 9-digit ZIP+4 code is written ",[14,766,767],{},"02134-0042",". The format ",[14,770,771],{},"00000-0000"," inserts the hyphen as a literal and pads the whole value to nine digits. When one column mixes 5-digit and 9-digit codes, a ",[27,774,775],{},"conditional section"," picks the pattern by value: ",[14,778,779],{},"[\u003C=99999]"," applies the first format to values up to 99,999 and the second to everything else:",[197,782,784],{"className":259,"code":783,"language":261,"meta":202,"style":202},"from openpyxl import Workbook\n\nwb = Workbook(); ws = wb.active\nws.append([\"customer\", \"zip\"])\nfor name, code in zip(df[\"customer\"], df[\"zip\"]):\n    ws.append([name, int(code)])\nfor row in ws.iter_rows(min_row=2, min_col=2, max_col=2):\n    row[0].number_format = \"[\u003C=99999]00000;00000-0000\"\nwb.save(\"zip_plus4.xlsx\")\nprint([ws.cell(r, 2).number_format for r in range(2, 3)], [ws.cell(r, 2).value for r in range(2, 6)])\n",[14,785,786,797,801,816,831,856,867,907,922,932],{"__ignoreMap":202},[206,787,788,790,792,794],{"class":104,"line":208},[206,789,424],{"class":268},[206,791,427],{"class":272},[206,793,269],{"class":268},[206,795,796],{"class":272}," Workbook\n",[206,798,799],{"class":104,"line":282},[206,800,286],{"emptyLinePlaceholder":285},[206,802,803,806,808,811,813],{"class":104,"line":289},[206,804,805],{"class":272},"wb ",[206,807,295],{"class":268},[206,809,810],{"class":272}," Workbook(); ws ",[206,812,295],{"class":268},[206,814,815],{"class":272}," wb.active\n",[206,817,818,821,824,826,828],{"class":104,"line":307},[206,819,820],{"class":272},"ws.append([",[206,822,823],{"class":215},"\"customer\"",[206,825,402],{"class":272},[206,827,339],{"class":215},[206,829,830],{"class":272},"])\n",[206,832,833,835,838,840,843,846,848,851,853],{"class":104,"line":317},[206,834,470],{"class":268},[206,836,837],{"class":272}," name, code ",[206,839,476],{"class":268},[206,841,842],{"class":310}," zip",[206,844,845],{"class":272},"(df[",[206,847,823],{"class":215},[206,849,850],{"class":272},"], df[",[206,852,339],{"class":215},[206,854,855],{"class":272},"]):\n",[206,857,858,861,864],{"class":104,"line":322},[206,859,860],{"class":272},"    ws.append([name, ",[206,862,863],{"class":310},"int",[206,865,866],{"class":272},"(code)])\n",[206,868,869,871,874,876,879,882,884,886,888,891,893,895,897,900,902,904],{"class":104,"line":333},[206,870,470],{"class":268},[206,872,873],{"class":272}," row ",[206,875,476],{"class":268},[206,877,878],{"class":272}," ws.iter_rows(",[206,880,881],{"class":405},"min_row",[206,883,295],{"class":268},[206,885,459],{"class":310},[206,887,402],{"class":272},[206,889,890],{"class":405},"min_col",[206,892,295],{"class":268},[206,894,459],{"class":310},[206,896,402],{"class":272},[206,898,899],{"class":405},"max_col",[206,901,295],{"class":268},[206,903,459],{"class":310},[206,905,906],{"class":272},"):\n",[206,908,909,912,914,917,919],{"class":104,"line":366},[206,910,911],{"class":272},"    row[",[206,913,72],{"class":310},[206,915,916],{"class":272},"].number_format ",[206,918,295],{"class":268},[206,920,921],{"class":215}," \"[\u003C=99999]00000;00000-0000\"\n",[206,923,924,927,930],{"class":104,"line":393},[206,925,926],{"class":272},"wb.save(",[206,928,929],{"class":215},"\"zip_plus4.xlsx\"",[206,931,304],{"class":272},[206,933,934,936,939,941,944,946,948,950,952,954,956,958,961,964,966,969,971,973,975,977,979,981,983,985],{"class":104,"line":416},[206,935,311],{"class":310},[206,937,938],{"class":272},"([ws.cell(r, ",[206,940,459],{"class":310},[206,942,943],{"class":272},").number_format ",[206,945,470],{"class":268},[206,947,473],{"class":272},[206,949,476],{"class":268},[206,951,479],{"class":310},[206,953,482],{"class":272},[206,955,459],{"class":310},[206,957,402],{"class":272},[206,959,960],{"class":310},"3",[206,962,963],{"class":272},")], [ws.cell(r, ",[206,965,459],{"class":310},[206,967,968],{"class":272},").value ",[206,970,470],{"class":268},[206,972,473],{"class":272},[206,974,476],{"class":268},[206,976,479],{"class":310},[206,978,482],{"class":272},[206,980,459],{"class":310},[206,982,402],{"class":272},[206,984,388],{"class":310},[206,986,491],{"class":272},[10,988,989,990,402,992,402,994,237,996,998,999,1002],{},"Opened in Excel, the column shows ",[14,991,20],{},[14,993,499],{},[14,995,240],{},[14,997,767],{},". A text alternative is to build the string in pandas: pad to 5 or 9 digits and insert the hyphen for the long ones, ",[14,1000,1001],{},"s.str.zfill(9).str.replace(r\"^(\\d{5})(\\d{4})$\", r\"\\1-\\2\", regex=True)"," applied only to values longer than five digits.",[50,1004,59,1010,59,1013,59,1016,59,1021,59,1026,59,1034,59,1038,59,1044,59,1048,59,1052,59,1056,59,1060,59,1064,59,1068,59,1070,59,1074,59,1076,59,1079,59,1081,59,1084,59,1087,59,1090,59,1092,59,1096,59,1099,59,1102,59,1104,59,1106,59,1109,59,1112,59,1114,59,1117,59,1119,59,1121,59,1123,59,1125,59,1128,59,1130,59,1132,59,1135,59,1137,59,1139,59,1141,59,1143,59,1146,59,1149,59,1151,59,1154,59,1156,59,1158,59,1160],{"viewBox":1005,"role":53,"ariaLabelledBy":1006,"xmlns":57,"style":1009},"198 0 363 228",[1007,1008],"lz-zip-col-t","lz-zip-col-d","width:100%;max-width:363px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[61,1011,1012],{"id":1007},"The ZIP column with the mixed-length format",[65,1014,1015],{"id":1008},"The zip_plus4.xlsx sheet as Excel displays it. Acme shows 02134, Birch 10001, Corex 07030 and Dunmore 02134-0042, although the cells store the numbers 2134, 10001, 7030 and 21340042.",[69,1017],{"x":1018,"y":72,"width":1019,"height":1020,"fill":75},"198","363","228",[29,1022,1025],{"x":1023,"y":1024,"style":158},"380.0","31.0","zip_plus4.xlsx — displayed values",[69,1027],{"x":1028,"y":1029,"width":1030,"height":1031,"rx":72,"fill":1032,"stroke":1033,"style":109},"214.7","48.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)",[69,1035],{"x":1036,"y":1029,"width":1037,"height":1031,"rx":72,"fill":1032,"stroke":1033,"style":109},"246.7","82.8",[29,1039,1043],{"x":1040,"y":1041,"style":1042},"288.1","65.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[69,1045],{"x":1046,"y":1029,"width":1047,"height":1031,"rx":72,"fill":1032,"stroke":1033,"style":109},"329.5","115.2",[29,1049,1051],{"x":1050,"y":1041,"style":1042},"387.1","B",[69,1053],{"x":1054,"y":1029,"width":1055,"height":1031,"rx":72,"fill":1032,"stroke":1033,"style":109},"444.7","100.6",[29,1057,1059],{"x":1058,"y":1041,"style":1042},"495.0","C",[69,1061],{"x":1028,"y":1062,"width":1030,"height":1063,"rx":72,"fill":1032,"stroke":1033,"style":109},"72.0","28.0",[29,1065,1067],{"x":1066,"y":107,"style":1042},"230.7","1",[69,1069],{"x":1036,"y":1062,"width":1037,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1071,1073],{"x":1040,"y":107,"style":1072},"font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","customer",[69,1075],{"x":1046,"y":1062,"width":1047,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1077,1078],{"x":1050,"y":107,"style":1072},"zip (displayed)",[69,1080],{"x":1054,"y":1062,"width":1055,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1082,1083],{"x":1058,"y":107,"style":1072},"stored value",[69,1085],{"x":1028,"y":1086,"width":1030,"height":1063,"rx":72,"fill":1032,"stroke":1033,"style":109},"100.0",[29,1088,459],{"x":1066,"y":1089,"style":1042},"119.0",[69,1091],{"x":1036,"y":1086,"width":1037,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1093,1095],{"x":1040,"y":1089,"style":1094},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","Acme",[69,1097],{"x":1046,"y":1086,"width":1047,"height":1063,"rx":72,"fill":83,"stroke":84,"style":1098},"stroke-width:1.5px",[29,1100,20],{"x":1050,"y":1089,"style":1101},"font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle",[69,1103],{"x":1054,"y":1086,"width":1055,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1105,24],{"x":1058,"y":1089,"style":1094},[69,1107],{"x":1028,"y":1108,"width":1030,"height":1063,"rx":72,"fill":1032,"stroke":1033,"style":109},"128.0",[29,1110,960],{"x":1066,"y":1111,"style":1042},"147.0",[69,1113],{"x":1036,"y":1108,"width":1037,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1115,1116],{"x":1040,"y":1111,"style":1094},"Birch",[69,1118],{"x":1046,"y":1108,"width":1047,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1120,499],{"x":1050,"y":1111,"style":1094},[69,1122],{"x":1054,"y":1108,"width":1055,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1124,499],{"x":1058,"y":1111,"style":1094},[69,1126],{"x":1028,"y":1127,"width":1030,"height":1063,"rx":72,"fill":1032,"stroke":1033,"style":109},"156.0",[29,1129,71],{"x":1066,"y":81,"style":1042},[69,1131],{"x":1036,"y":1127,"width":1037,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1133,1134],{"x":1040,"y":81,"style":1094},"Corex",[69,1136],{"x":1046,"y":1127,"width":1047,"height":1063,"rx":72,"fill":83,"stroke":84,"style":1098},[29,1138,240],{"x":1050,"y":81,"style":1101},[69,1140],{"x":1054,"y":1127,"width":1055,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1142,244],{"x":1058,"y":81,"style":1094},[69,1144],{"x":1028,"y":1145,"width":1030,"height":1063,"rx":72,"fill":1032,"stroke":1033,"style":109},"184.0",[29,1147,361],{"x":1066,"y":1148,"style":1042},"203.0",[69,1150],{"x":1036,"y":1145,"width":1037,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1152,1153],{"x":1040,"y":1148,"style":1094},"Dunmore",[69,1155],{"x":1046,"y":1145,"width":1047,"height":1063,"rx":72,"fill":83,"stroke":84,"style":1098},[29,1157,767],{"x":1050,"y":1148,"style":1101},[69,1159],{"x":1054,"y":1145,"width":1055,"height":1063,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1161,518],{"x":1058,"y":1148,"style":1094},[10,1163,1164],{},"The stored values never change; only the display does. That is exactly what makes this approach safe for columns other systems read as numbers, and exactly what makes it unsuitable when someone will copy the displayed code into another application, which receives the stored number.",[50,1166,59,1171,59,1174,59,1177,59,1180,59,1184,59,1189,59,1195,59,1198,59,1202,59,1206,59,1209,59,1211,59,1215,59,1217,59,1219,59,1222,59,1225,59,1227,59,1229,59,1231,59,1233,59,1236,59,1240,59,1242,59,1246,59,1248,59,1251,59,1254,59,1258,59,1260,59,1264,59,1266,59,1269,59,1272,59,1276,59,1278,59,1282,59,1284],{"viewBox":1167,"role":53,"ariaLabelledBy":1168,"xmlns":57,"style":58},"4 0 752 242",[1169,1170],"lz-formats-t","lz-formats-d",[61,1172,1173],{"id":1169},"Padding formats and what they display",[65,1175,1176],{"id":1170},"A table of number formats. 00000 shows 2134 as 02134. 00000-0000 shows 21340042 as 02134-0042. The conditional format [\u003C=99999]00000;00000-0000 shows 2134 as 02134 and 21340042 as 02134-0042 in the same column. \"EMP-\"000000 shows 42 as EMP-000042. [\u003C=9999999]###-####;(###) ###-#### shows 4155550123 as (415) 555-0123.",[69,1178],{"x":71,"y":72,"width":73,"height":1179,"fill":75},"242",[69,1181],{"x":78,"y":79,"width":1182,"height":1183,"rx":72,"fill":75,"stroke":1033,"style":109},"232.8","40.0",[69,1185],{"x":1186,"y":79,"width":1187,"height":1183,"rx":72,"fill":146,"stroke":147,"style":1188},"252.8","243.6","stroke-width:1.2px",[29,1190,1194],{"x":1191,"y":1192,"style":1193},"374.6","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Stored value",[69,1196],{"x":1197,"y":79,"width":1187,"height":1183,"rx":72,"fill":146,"stroke":147,"style":1188},"496.4",[29,1199,1201],{"x":1200,"y":1192,"style":1193},"618.2","Displays",[69,1203],{"x":78,"y":1204,"width":1182,"height":1205,"rx":72,"fill":1032,"stroke":1033,"style":109},"56.0","34.0",[29,1207,541],{"x":1030,"y":100,"style":1208},"font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start",[69,1210],{"x":1186,"y":1204,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1212,24],{"x":1191,"y":1213,"style":1214},"77.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle",[69,1216],{"x":1197,"y":1204,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1218,20],{"x":1200,"y":1213,"style":1214},[69,1220],{"x":78,"y":1221,"width":1182,"height":1205,"rx":72,"fill":1032,"stroke":1033,"style":109},"90.0",[29,1223,771],{"x":1030,"y":1224,"style":1208},"112.0",[69,1226],{"x":1186,"y":1221,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1228,518],{"x":1191,"y":113,"style":1214},[69,1230],{"x":1197,"y":1221,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1232,767],{"x":1200,"y":113,"style":1214},[69,1234],{"x":78,"y":1235,"width":1182,"height":1205,"rx":72,"fill":1032,"stroke":1033,"style":109},"124.0",[29,1237,1239],{"x":1030,"y":1238,"style":1208},"146.0","[\u003C=99999]00000;00000-0000",[69,1241],{"x":1186,"y":1235,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1243,1245],{"x":1191,"y":1244,"style":1214},"145.0","2134 \u002F 21340042",[69,1247],{"x":1197,"y":1235,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1249,1250],{"x":1200,"y":1244,"style":1214},"02134 \u002F 02134-0042",[69,1252],{"x":78,"y":1253,"width":1182,"height":1205,"rx":72,"fill":1032,"stroke":1033,"style":109},"158.0",[29,1255,1257],{"x":1030,"y":1256,"style":1208},"180.0","\"EMP-\"000000",[69,1259],{"x":1186,"y":1253,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1261,1263],{"x":1191,"y":1262,"style":1214},"179.0","42",[69,1265],{"x":1197,"y":1253,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1267,1268],{"x":1200,"y":1262,"style":1214},"EMP-000042",[69,1270],{"x":78,"y":1271,"width":1182,"height":1205,"rx":72,"fill":1032,"stroke":1033,"style":109},"192.0",[29,1273,1275],{"x":1030,"y":1274,"style":1208},"214.0","phone pattern",[69,1277],{"x":1186,"y":1271,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1279,1281],{"x":1191,"y":1280,"style":1214},"213.0","4155550123",[69,1283],{"x":1197,"y":1271,"width":1187,"height":1205,"rx":72,"fill":75,"stroke":1033,"style":109},[29,1285,1286],{"x":1200,"y":1280,"style":1214},"(415) 555-0123",[192,1288,1290],{"id":1289},"step-4-add-prefixes-and-patterns-without-changing-the-value","Step 4 — Add prefixes and patterns without changing the value",[10,1292,1293,1294,1296,1297,1299],{},"Number formats can add literal text, so a stored ",[14,1295,1263],{}," can display as ",[14,1298,1268],{}," while staying a sortable number, and a 10-digit number can display as a phone number. Text in double quotes is shown as it is:",[197,1301,1303],{"className":259,"code":1302,"language":261,"meta":202,"style":202},"wb = Workbook(); ws = wb.active\nws.append([\"employee\", \"phone\"])\nws.append([42, 4155550123])\nws.append([30551, 2125550199])\nfor r in (2, 3):\n    ws.cell(r, 1).number_format = '\"EMP-\"000000'\n    ws.cell(r, 2).number_format = \"[\u003C=9999999]###-####;(###) ###-####\"\nwb.save(\"patterns.xlsx\")\nprint([(ws.cell(r, 1).value, ws.cell(r, 1).number_format) for r in (2, 3)])\n",[14,1304,1305,1317,1330,1342,1356,1375,1389,1402,1411],{"__ignoreMap":202},[206,1306,1307,1309,1311,1313,1315],{"class":104,"line":208},[206,1308,805],{"class":272},[206,1310,295],{"class":268},[206,1312,810],{"class":272},[206,1314,295],{"class":268},[206,1316,815],{"class":272},[206,1318,1319,1321,1323,1325,1328],{"class":104,"line":282},[206,1320,820],{"class":272},[206,1322,371],{"class":215},[206,1324,402],{"class":272},[206,1326,1327],{"class":215},"\"phone\"",[206,1329,830],{"class":272},[206,1331,1332,1334,1336,1338,1340],{"class":104,"line":289},[206,1333,820],{"class":272},[206,1335,1263],{"class":310},[206,1337,402],{"class":272},[206,1339,1281],{"class":310},[206,1341,830],{"class":272},[206,1343,1344,1346,1349,1351,1354],{"class":104,"line":307},[206,1345,820],{"class":272},[206,1347,1348],{"class":310},"30551",[206,1350,402],{"class":272},[206,1352,1353],{"class":310},"2125550199",[206,1355,830],{"class":272},[206,1357,1358,1360,1362,1364,1367,1369,1371,1373],{"class":104,"line":317},[206,1359,470],{"class":268},[206,1361,473],{"class":272},[206,1363,476],{"class":268},[206,1365,1366],{"class":272}," (",[206,1368,459],{"class":310},[206,1370,402],{"class":272},[206,1372,960],{"class":310},[206,1374,906],{"class":272},[206,1376,1377,1380,1382,1384,1386],{"class":104,"line":322},[206,1378,1379],{"class":272},"    ws.cell(r, ",[206,1381,1067],{"class":310},[206,1383,943],{"class":272},[206,1385,295],{"class":268},[206,1387,1388],{"class":215}," '\"EMP-\"000000'\n",[206,1390,1391,1393,1395,1397,1399],{"class":104,"line":333},[206,1392,1379],{"class":272},[206,1394,459],{"class":310},[206,1396,943],{"class":272},[206,1398,295],{"class":268},[206,1400,1401],{"class":215}," \"[\u003C=9999999]###-####;(###) ###-####\"\n",[206,1403,1404,1406,1409],{"class":104,"line":366},[206,1405,926],{"class":272},[206,1407,1408],{"class":215},"\"patterns.xlsx\"",[206,1410,304],{"class":272},[206,1412,1413,1415,1417,1419,1421,1423,1425,1427,1429,1431,1433,1435,1437,1439],{"class":104,"line":393},[206,1414,311],{"class":310},[206,1416,456],{"class":272},[206,1418,1067],{"class":310},[206,1420,462],{"class":272},[206,1422,1067],{"class":310},[206,1424,718],{"class":272},[206,1426,470],{"class":268},[206,1428,473],{"class":272},[206,1430,476],{"class":268},[206,1432,1366],{"class":272},[206,1434,459],{"class":310},[206,1436,402],{"class":272},[206,1438,960],{"class":310},[206,1440,491],{"class":272},[10,1442,1443,1444,237,1446,1449,1450,237,1452,1455],{},"The first column shows ",[14,1445,1268],{},[14,1447,1448],{},"EMP-030551","; the second ",[14,1451,1286],{},[14,1453,1454],{},"(212) 555-0199",". The prefix is display only: filtering the column for \"EMP-000042\" in Excel finds nothing, because the cell contains 42. When people will search or copy the code as written, store the full text instead.",[192,1457,1459],{"id":1458},"step-5-keep-lookups-consistent","Step 5 — Keep lookups consistent",[10,1461,1462,1463,1466,1467,1469,1470,1472],{},"The choice matters most where sheets meet. A lookup — VLOOKUP, XLOOKUP, a pandas merge — compares stored values, not displayed ones. The text ",[14,1464,1465],{},"\"02134\""," and the number ",[14,1468,24],{}," formatted as ",[14,1471,541],{}," look identical but never match:",[197,1474,1476],{"className":259,"code":1475,"language":261,"meta":202,"style":202},"orders = pd.DataFrame({\"zip\": [\"02134\", \"07030\"], \"orders\": [12, 5]})\nas_numbers = df[[\"customer\", \"zip\"]]\nas_text = df[[\"customer\"]].assign(zip=df[\"zip\"].astype(str).str.zfill(5))\n\ntry:\n    as_numbers.merge(orders, on=\"zip\")\nexcept ValueError as exc:\n    print(\"number vs text:\", str(exc)[:80])\nprint(\"text vs text:  \", as_text.merge(orders, on=\"zip\").to_dict(\"records\"))\n",[14,1477,1478,1517,1536,1571,1575,1583,1597,1611,1633],{"__ignoreMap":202},[206,1479,1480,1483,1485,1488,1490,1493,1495,1497,1500,1503,1506,1508,1510,1512,1514],{"class":104,"line":208},[206,1481,1482],{"class":272},"orders ",[206,1484,295],{"class":268},[206,1486,1487],{"class":272}," pd.DataFrame({",[206,1489,339],{"class":215},[206,1491,1492],{"class":272},": [",[206,1494,1465],{"class":215},[206,1496,402],{"class":272},[206,1498,1499],{"class":215},"\"07030\"",[206,1501,1502],{"class":272},"], ",[206,1504,1505],{"class":215},"\"orders\"",[206,1507,1492],{"class":272},[206,1509,667],{"class":310},[206,1511,402],{"class":272},[206,1513,361],{"class":310},[206,1515,1516],{"class":272},"]})\n",[206,1518,1519,1522,1524,1527,1529,1531,1533],{"class":104,"line":282},[206,1520,1521],{"class":272},"as_numbers ",[206,1523,295],{"class":268},[206,1525,1526],{"class":272}," df[[",[206,1528,823],{"class":215},[206,1530,402],{"class":272},[206,1532,339],{"class":215},[206,1534,1535],{"class":272},"]]\n",[206,1537,1538,1541,1543,1545,1547,1550,1553,1555,1558,1560,1562,1564,1566,1568],{"class":104,"line":289},[206,1539,1540],{"class":272},"as_text ",[206,1542,295],{"class":268},[206,1544,1526],{"class":272},[206,1546,823],{"class":215},[206,1548,1549],{"class":272},"]].assign(",[206,1551,1552],{"class":405},"zip",[206,1554,295],{"class":268},[206,1556,1557],{"class":272},"df[",[206,1559,339],{"class":215},[206,1561,352],{"class":272},[206,1563,355],{"class":310},[206,1565,358],{"class":272},[206,1567,361],{"class":310},[206,1569,1570],{"class":272},"))\n",[206,1572,1573],{"class":104,"line":307},[206,1574,286],{"emptyLinePlaceholder":285},[206,1576,1577,1580],{"class":104,"line":317},[206,1578,1579],{"class":268},"try",[206,1581,1582],{"class":272},":\n",[206,1584,1585,1588,1591,1593,1595],{"class":104,"line":322},[206,1586,1587],{"class":272},"    as_numbers.merge(orders, ",[206,1589,1590],{"class":405},"on",[206,1592,295],{"class":268},[206,1594,339],{"class":215},[206,1596,304],{"class":272},[206,1598,1599,1602,1605,1608],{"class":104,"line":333},[206,1600,1601],{"class":268},"except",[206,1603,1604],{"class":310}," ValueError",[206,1606,1607],{"class":268}," as",[206,1609,1610],{"class":272}," exc:\n",[206,1612,1613,1616,1618,1621,1623,1625,1628,1631],{"class":104,"line":366},[206,1614,1615],{"class":310},"    print",[206,1617,482],{"class":272},[206,1619,1620],{"class":215},"\"number vs text:\"",[206,1622,402],{"class":272},[206,1624,355],{"class":310},[206,1626,1627],{"class":272},"(exc)[:",[206,1629,1630],{"class":310},"80",[206,1632,830],{"class":272},[206,1634,1635,1637,1639,1642,1645,1647,1649,1651,1654,1657],{"class":104,"line":393},[206,1636,311],{"class":310},[206,1638,482],{"class":272},[206,1640,1641],{"class":215},"\"text vs text:  \"",[206,1643,1644],{"class":272},", as_text.merge(orders, ",[206,1646,1590],{"class":405},[206,1648,295],{"class":268},[206,1650,339],{"class":215},[206,1652,1653],{"class":272},").to_dict(",[206,1655,1656],{"class":215},"\"records\"",[206,1658,1570],{"class":272},[10,1660,1661,1662,1665,1666,48],{},"pandas refuses to merge an integer column with a text one, and Excel's lookup simply returns ",[14,1663,1664],{},"#N\u002FA",". Pick one representation for each kind of code across the whole workbook — text is the usual choice for identifiers — and convert at the point data enters the report. Codes longer than 15 digits must be text in any case, because Excel keeps only 15 significant digits of a number; see ",[36,1667,1669],{"href":1668},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-long-id-numbers-losing-digits-in-excel\u002F","Fix Long ID Numbers Losing Digits in Excel",[192,1671,1673],{"id":1672},"common-pitfalls","Common pitfalls",[1675,1676,1677,1684,1692,1701,1707,1713],"ul",{},[1678,1679,1680,1683],"li",{},[27,1681,1682],{},"Formatting when the value is already text."," Number formats do nothing to text cells; pad the string instead.",[1678,1685,1686,1691],{},[27,1687,1688,1690],{},[14,1689,509],{}," on ZIP+4 codes."," It pads to a minimum width only; build the hyphenated form explicitly.",[1678,1693,1694,1697,1698,1700],{},[27,1695,1696],{},"Expecting the format to change the value."," A ",[14,1699,541],{}," format still stores 2134; exports and lookups see 2134.",[1678,1702,1703,1706],{},[27,1704,1705],{},"Mixing text and numbers across sheets."," Lookups fail silently; use one representation.",[1678,1708,1709,1712],{},[27,1710,1711],{},"Saving to CSV."," CSV has no formats; the padded display is lost, and Excel strips zeros again on opening.",[1678,1714,1715,1718],{},[27,1716,1717],{},"Long IDs as numbers."," Beyond 15 digits they are rounded; store them as text.",[192,1720,1722],{"id":1721},"performance-notes","Performance notes",[10,1724,1725,1728,1729,1732,1733,1736],{},[14,1726,1727],{},"astype(str).str.zfill()"," is vectorised and fast for any sheet size. Applying a format per column with xlsxwriter's ",[14,1730,1731],{},"set_column"," costs nothing per row; in openpyxl, setting ",[14,1734,1735],{},"number_format"," cell by cell is fine for tens of thousands of rows.",[192,1738,1740],{"id":1739},"conclusion","Conclusion",[10,1742,1743,1744,1746,1747,1749,1750,1752,1753,1755],{},"For identifiers, store codes as text padded with ",[14,1745,255],{},", and suppress the number-as-text warning if it bothers readers. When the column must stay numeric, write numbers and apply ",[14,1748,541],{},"-style formats — ",[14,1751,771],{}," for ZIP+4, ",[14,1754,1239],{}," for mixed lengths, and quoted literals for prefixes. Use the same representation in every sheet that is looked up against, and keep codes longer than 15 digits as text.",[192,1757,1759],{"id":1758},"frequently-asked-questions","Frequently asked questions",[10,1761,1762,1765],{},[27,1763,1764],{},"How do I keep leading zeros when writing to Excel with Python?","\nEither write the value as text — \"02134\" as a string, for example with str.zfill(5) — or write the number 2134 and give the cell the number format 00000. Both display 02134; text is safer for identifiers, the format for values that must stay numeric.",[10,1767,1768,1771,1772,1775],{},[27,1769,1770],{},"What number format shows a 9-digit ZIP code as ZIP+4?","\nUse 00000-0000, which shows 21340042 as 02134-0042. For a column that mixes 5- and 9-digit codes, the conditional format ",[206,1773,1774],{},"\u003C=99999","00000;00000-0000 picks the right pattern for each value.",[10,1777,1778,1781],{},[27,1779,1780],{},"Should IDs be stored as text or numbers in Excel?","\nAs text, if nobody does arithmetic on them. Text keeps every digit, never switches to scientific notation and is unaffected by number formats. Store them as numbers only when a downstream system requires numeric IDs, and then apply a padding format.",[10,1783,1784,1787],{},[27,1785,1786],{},"Why does VLOOKUP fail on IDs with leading zeros?","\nBecause the two sides have different types: \"02134\" as text in one table and 2134 as a number with a 00000 format in the other look identical but do not match. Use the same storage choice in every sheet that is looked up against.",[192,1789,1791],{"id":1790},"related","Related",[1675,1793,1794,1800,1807,1812],{},[1678,1795,1796,1797,1799],{},"Up one level: ",[36,1798,39],{"href":38}," — every kind of number format.",[1678,1801,1802,1806],{},[36,1803,1805],{"href":1804},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fwrite-custom-number-format-codes-in-excel-with-python\u002F","Write Custom Number Format Codes in Excel with Python"," — the format code syntax.",[1678,1808,1809,1811],{},[36,1810,47],{"href":46}," — the reading side.",[1678,1813,1814,1818],{},[36,1815,1817],{"href":1816},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmerging-and-joining-excel-dataframes\u002Fmerge-excel-data-on-multiple-key-columns\u002F","Merge Excel Data on Multiple Key Columns with pandas"," — keys that do not match.",[1820,1821,1822],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}",{"title":202,"searchDepth":282,"depth":282,"links":1824},[1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835],{"id":194,"depth":282,"text":195},{"id":248,"depth":282,"text":249},{"id":531,"depth":282,"text":532},{"id":760,"depth":282,"text":761},{"id":1289,"depth":282,"text":1290},{"id":1458,"depth":282,"text":1459},{"id":1672,"depth":282,"text":1673},{"id":1721,"depth":282,"text":1722},{"id":1739,"depth":282,"text":1740},{"id":1758,"depth":282,"text":1759},{"id":1790,"depth":282,"text":1791},"2026-09-25","Write ZIP codes, employee numbers and account codes to Excel so 02134 stays 02134. Choose between storing them as text and storing numbers with a zero-padding format, write both ways with pandas, openpyxl and xlsxwriter, handle 5- and 9-digit ZIPs in one column, add prefixes and phone-style patterns, and avoid the lookup mismatches each choice can cause.","md",[1840,1842,1844,1846],{"q":1764,"a":1841},"Either write the value as text — \"02134\" as a string, for example with str.zfill(5) — or write the number 2134 and give the cell the number format 00000. Both display 02134; text is safer for identifiers, the format for values that must stay numeric.",{"q":1770,"a":1843},"Use 00000-0000, which shows 21340042 as 02134-0042. For a column that mixes 5- and 9-digit codes, the conditional format [\u003C=99999]00000;00000-0000 picks the right pattern for each value.",{"q":1780,"a":1845},"As text, if nobody does arithmetic on them. Text keeps every digit, never switches to scientific notation and is unaffected by number formats. Store them as numbers only when a downstream system requires numeric IDs, and then apply a padding format.",{"q":1786,"a":1847},"Because the two sides have different types: \"02134\" as text in one table and 2134 as a number with a 00000 format in the other look identical but do not match. Use the same storage choice in every sheet that is looked up against.","format zip codes and ids with leading zeros",null,{"breadcrumb":1851},[1852,1855,1858],{"name":1853,"item":1854},"Home","\u002F",{"name":1856,"item":1857},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":39,"item":38},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros",{"title":1861,"description":1862},"Keep Leading Zeros in Excel Output (ZIP Codes, IDs) with Python","Write codes with leading zeros to Excel from Python: text versus number format 00000, zfill, ZIP+4 00000-0000, a conditional format for mixed 5 and 9 digit ZIPs, \"EMP-\"000000 prefixes, phone patterns, number-stored-as-text warnings and lookup type mismatches.","format-zip-codes-and-ids-with-leading-zeros","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-zip-codes-and-ids-with-leading-zeros\u002Findex",[1866,1867],"number-formats","writing-excel","how-to","iHlonaz1IPqUIaqySbUaVW6RnyjSVQ3u0Qay1uLQ04M",[1871,1875],{"title":1872,"path":1873,"stem":1874,"children":-1},"Format Numbers in Thousands and Millions in Excel with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-numbers-in-thousands-and-millions-in-excel\u002Findex",{"title":1876,"path":1877,"stem":1878,"children":-1},"Localise an Excel Report for Other Languages and Locales","\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Flocalise-an-excel-report-for-other-languages-and-locales","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Flocalise-an-excel-report-for-other-languages-and-locales\u002Findex",[1880,1882],{"path":1881,"title":39},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel",{"path":1883,"title":1856},"\u002Fformatting-and-charting-excel-reports-with-python",[],[1886,1889,1892,1895,1898,1901],{"path":1887,"title":1888,"kind":1868},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fconvert-currency-strings-to-numbers-with-pandas","Convert Currency Strings Like \"$1,234.56\" and \"(500)\" to Numbers with pandas",{"path":1890,"title":1891,"kind":1868},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fconvert-percentage-strings-to-numbers-with-pandas","Convert Percentage Strings Like \"12.5%\" to Numbers with pandas",{"path":1893,"title":1894,"kind":1868},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fexcel-text-function-equivalent-in-pandas","Excel TEXT Function Equivalent in pandas",{"path":1896,"title":1897,"kind":1868},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fmatch-excel-rounding-in-pandas","Match Excel Rounding in pandas",{"path":1899,"title":1900,"kind":1868},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fconvert-excel-time-values-and-durations","Convert Excel Time Values and Durations in Python",{"path":1902,"title":1903,"kind":1868},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-variance-arrows-and-trend-indicators-to-a-dashboard","Add Variance Arrows and Trend Indicators to a Dashboard",1790972107130]