[{"data":1,"prerenderedAt":2409},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsequence-and-randarray-equivalents-in-python":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsequence-and-randarray-equivalents-in-python":2375,"ancestors:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsequence-and-randarray-equivalents-in-python":2384,"children:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsequence-and-randarray-equivalents-in-python":2389,"related:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsequence-and-randarray-equivalents-in-python":2390},{"id":4,"title":5,"body":6,"dateModified":2342,"datePublished":2342,"description":2343,"extension":2344,"faq":2345,"keyword":2354,"kind":2355,"meta":2356,"navigation":133,"path":2365,"seo":2366,"slug":2369,"stem":2370,"topics":2371,"type":2373,"__hash__":2374},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsequence-and-randarray-equivalents-in-python\u002Findex.md","SEQUENCE and RANDARRAY Equivalents in Python",{"type":7,"value":8,"toc":2329},"minimark",[9,40,45,76,87,91,105,246,278,282,285,684,711,953,1105,1109,1126,1334,1369,1373,1387,1628,1655,1730,1734,1744,2130,2154,2158,2176,2180,2230,2234,2264,2268,2274,2280,2286,2292,2296,2325],[10,11,12,13,17,18,21,22,25,26,29,30,33,34,39],"p",{},"Excel's dynamic-array functions made a few small jobs one-formula affairs: ",[14,15,16],"code",{},"=SEQUENCE(12)"," for the numbers 1 to 12, ",[14,19,20],{},"=SEQUENCE(4,3,10,5)"," for a grid counting in fives, ",[14,23,24],{},"=SEQUENCE(12,1,DATE(2026,1,1),...)"," for a column of dates, ",[14,27,28],{},"=RANDARRAY(5,2,1,100,TRUE)"," for random whole numbers and ",[14,31,32],{},"=SORTBY(list,RANDARRAY(ROWS(list)))"," for a shuffled list. In Python these jobs are usually part of something larger — building a calendar table, creating test data, drawing a random sample for an audit — and NumPy and pandas do each of them in a line. The one real difference is randomness: Excel's random functions recalculate every time anything changes, so their results can never be reproduced, while NumPy's can be seeded. This page translates each pattern, checks the deterministic ones against a spreadsheet's results, and writes the outputs to Excel as values. It belongs to ",[35,36,38],"a",{"href":37},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002F","Excel Formula Equivalents in pandas",".",[41,42,44],"h2",{"id":43},"prerequisites","Prerequisites",[46,47,52],"pre",{"className":48,"code":49,"language":50,"meta":51,"style":51},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install numpy pandas openpyxl\n","bash","",[14,53,54],{"__ignoreMap":51},[55,56,59,63,67,70,73],"span",{"class":57,"line":58},"line",1,[55,60,62],{"class":61},"sMTad","pip",[55,64,66],{"class":65},"srMev"," install",[55,68,69],{"class":65}," numpy",[55,71,72],{"class":65}," pandas",[55,74,75],{"class":65}," openpyxl\n",[10,77,78,79,82,83,86],{},"The deterministic examples are compared with the same formulas recalculated by LibreOffice (",[14,80,81],{},"soffice","), which supports ",[14,84,85],{},"SEQUENCE","; Excel 365 gives the same results. The random examples cannot be compared value for value — that is the point of them — so their properties are checked instead.",[41,88,90],{"id":89},"step-1-sequence-counting-in-rows-and-columns","Step 1 — SEQUENCE: counting in rows and columns",[10,92,93,96,97,100,101,104],{},[14,94,95],{},"SEQUENCE(rows, [columns], [start], [step])"," fills a grid row by row. NumPy's ",[14,98,99],{},"arange"," produces the numbers and ",[14,102,103],{},"reshape"," lays them out:",[46,106,110],{"className":107,"code":108,"language":109,"meta":51,"style":51},"language-python shiki shiki-themes github-light github-dark-high-contrast","import numpy as np\n\ndef sequence(rows, cols=1, start=1, step=1):\n    return start + step * np.arange(rows * cols).reshape(rows, cols)\n\nprint(sequence(5).ravel())\nprint(sequence(4, 3, 10, 5))\n","python",[14,111,112,128,135,172,198,203,218],{"__ignoreMap":51},[55,113,114,118,122,125],{"class":57,"line":58},[55,115,117],{"class":116},"s-kum","import",[55,119,121],{"class":120},"skGVy"," numpy ",[55,123,124],{"class":116},"as",[55,126,127],{"class":120}," np\n",[55,129,131],{"class":57,"line":130},2,[55,132,134],{"emptyLinePlaceholder":133},true,"\n",[55,136,138,141,145,148,151,155,158,160,162,165,167,169],{"class":57,"line":137},3,[55,139,140],{"class":116},"def",[55,142,144],{"class":143},"s_Opv"," sequence",[55,146,147],{"class":120},"(rows, cols",[55,149,150],{"class":116},"=",[55,152,154],{"class":153},"sP0c6","1",[55,156,157],{"class":120},", start",[55,159,150],{"class":116},[55,161,154],{"class":153},[55,163,164],{"class":120},", step",[55,166,150],{"class":116},[55,168,154],{"class":153},[55,170,171],{"class":120},"):\n",[55,173,175,178,181,184,187,190,193,195],{"class":57,"line":174},4,[55,176,177],{"class":116},"    return",[55,179,180],{"class":120}," start ",[55,182,183],{"class":116},"+",[55,185,186],{"class":120}," step ",[55,188,189],{"class":116},"*",[55,191,192],{"class":120}," np.arange(rows ",[55,194,189],{"class":116},[55,196,197],{"class":120}," cols).reshape(rows, cols)\n",[55,199,201],{"class":57,"line":200},5,[55,202,134],{"emptyLinePlaceholder":133},[55,204,206,209,212,215],{"class":57,"line":205},6,[55,207,208],{"class":153},"print",[55,210,211],{"class":120},"(sequence(",[55,213,214],{"class":153},"5",[55,216,217],{"class":120},").ravel())\n",[55,219,221,223,225,228,231,234,236,239,241,243],{"class":57,"line":220},7,[55,222,208],{"class":153},[55,224,211],{"class":120},[55,226,227],{"class":153},"4",[55,229,230],{"class":120},", ",[55,232,233],{"class":153},"3",[55,235,230],{"class":120},[55,237,238],{"class":153},"10",[55,240,230],{"class":120},[55,242,214],{"class":153},[55,244,245],{"class":120},"))\n",[10,247,248,251,252,255,256,258,259,262,263,266,267,269,270,273,274,277],{},[14,249,250],{},"SEQUENCE(5)"," is the column 1 to 5; ",[14,253,254],{},"SEQUENCE(4,3,10,5)"," is a four-by-three grid starting at 10 and counting in fives, filled across each row before moving down — exactly NumPy's default (row-major) ",[14,257,103],{}," order. Building the values as ",[14,260,261],{},"start + step * index"," rather than ",[14,264,265],{},"arange(start, stop, step)"," avoids the floating-point surprises ",[14,268,99],{}," can produce with fractional steps, where the last value may or may not be included. For row numbers in a DataFrame, ",[14,271,272],{},"range(1, len(df) + 1)"," or ",[14,275,276],{},"np.arange(1, len(df) + 1)"," is the everyday version.",[41,279,281],{"id":280},"step-2-check-against-the-spreadsheet","Step 2 — Check against the spreadsheet",[10,283,284],{},"Write the same formulas into a workbook, recalculate, and compare:",[46,286,288],{"className":107,"code":287,"language":109,"meta":51,"style":51},"import subprocess\nfrom openpyxl import Workbook, load_workbook\nfrom openpyxl.worksheet.formula import ArrayFormula\n\nwb = Workbook()\nws = wb.active\nws[\"A1\"] = ArrayFormula(\"A1:C4\", \"=_xlfn.SEQUENCE(4,3,10,5)\")\nws[\"E1\"] = ArrayFormula(\"E1:E6\", \"=_xlfn.SEQUENCE(6,1,0.1,0.1)\")\nws[\"G1\"] = \"=SEQUENCE(4,3,10,5)\"                        # no prefix: what goes wrong\nwb.save(\"seq.xlsx\")\nsubprocess.run([\"soffice\", \"--headless\", \"--convert-to\", \"xlsx\", \"--outdir\", \"calc\", \"seq.xlsx\"], check=True, capture_output=True)\ncalc = load_workbook(\"calc\u002Fseq.xlsx\", data_only=True).active\ngrid = np.array([[calc.cell(r, c).value for c in range(1, 4)] for r in range(1, 5)])\ntenths = np.array([calc.cell(r, 5).value for r in range(1, 7)])\nprint(\"grid matches:\", np.array_equal(grid, sequence(4, 3, 10, 5)))\nprint(\"tenths match:\", np.allclose(tenths, sequence(6, 1, 0.1, 0.1).ravel()), tenths)\nprint(\"without the _xlfn prefix:\", calc[\"G1\"].value)\n",[14,289,290,297,310,322,326,336,346,373,397,416,427,488,514,569,604,634,666],{"__ignoreMap":51},[55,291,292,294],{"class":57,"line":58},[55,293,117],{"class":116},[55,295,296],{"class":120}," subprocess\n",[55,298,299,302,305,307],{"class":57,"line":130},[55,300,301],{"class":116},"from",[55,303,304],{"class":120}," openpyxl ",[55,306,117],{"class":116},[55,308,309],{"class":120}," Workbook, load_workbook\n",[55,311,312,314,317,319],{"class":57,"line":137},[55,313,301],{"class":116},[55,315,316],{"class":120}," openpyxl.worksheet.formula ",[55,318,117],{"class":116},[55,320,321],{"class":120}," ArrayFormula\n",[55,323,324],{"class":57,"line":174},[55,325,134],{"emptyLinePlaceholder":133},[55,327,328,331,333],{"class":57,"line":200},[55,329,330],{"class":120},"wb ",[55,332,150],{"class":116},[55,334,335],{"class":120}," Workbook()\n",[55,337,338,341,343],{"class":57,"line":205},[55,339,340],{"class":120},"ws ",[55,342,150],{"class":116},[55,344,345],{"class":120}," wb.active\n",[55,347,348,351,354,357,359,362,365,367,370],{"class":57,"line":220},[55,349,350],{"class":120},"ws[",[55,352,353],{"class":65},"\"A1\"",[55,355,356],{"class":120},"] ",[55,358,150],{"class":116},[55,360,361],{"class":120}," ArrayFormula(",[55,363,364],{"class":65},"\"A1:C4\"",[55,366,230],{"class":120},[55,368,369],{"class":65},"\"=_xlfn.SEQUENCE(4,3,10,5)\"",[55,371,372],{"class":120},")\n",[55,374,376,378,381,383,385,387,390,392,395],{"class":57,"line":375},8,[55,377,350],{"class":120},[55,379,380],{"class":65},"\"E1\"",[55,382,356],{"class":120},[55,384,150],{"class":116},[55,386,361],{"class":120},[55,388,389],{"class":65},"\"E1:E6\"",[55,391,230],{"class":120},[55,393,394],{"class":65},"\"=_xlfn.SEQUENCE(6,1,0.1,0.1)\"",[55,396,372],{"class":120},[55,398,400,402,405,407,409,412],{"class":57,"line":399},9,[55,401,350],{"class":120},[55,403,404],{"class":65},"\"G1\"",[55,406,356],{"class":120},[55,408,150],{"class":116},[55,410,411],{"class":65}," \"=SEQUENCE(4,3,10,5)\"",[55,413,415],{"class":414},"s-wDw","                        # no prefix: what goes wrong\n",[55,417,419,422,425],{"class":57,"line":418},10,[55,420,421],{"class":120},"wb.save(",[55,423,424],{"class":65},"\"seq.xlsx\"",[55,426,372],{"class":120},[55,428,430,433,436,438,441,443,446,448,451,453,456,458,461,463,465,468,472,474,477,479,482,484,486],{"class":57,"line":429},11,[55,431,432],{"class":120},"subprocess.run([",[55,434,435],{"class":65},"\"soffice\"",[55,437,230],{"class":120},[55,439,440],{"class":65},"\"--headless\"",[55,442,230],{"class":120},[55,444,445],{"class":65},"\"--convert-to\"",[55,447,230],{"class":120},[55,449,450],{"class":65},"\"xlsx\"",[55,452,230],{"class":120},[55,454,455],{"class":65},"\"--outdir\"",[55,457,230],{"class":120},[55,459,460],{"class":65},"\"calc\"",[55,462,230],{"class":120},[55,464,424],{"class":65},[55,466,467],{"class":120},"], ",[55,469,471],{"class":470},"sa561","check",[55,473,150],{"class":116},[55,475,476],{"class":153},"True",[55,478,230],{"class":120},[55,480,481],{"class":470},"capture_output",[55,483,150],{"class":116},[55,485,476],{"class":153},[55,487,372],{"class":120},[55,489,491,494,496,499,502,504,507,509,511],{"class":57,"line":490},12,[55,492,493],{"class":120},"calc ",[55,495,150],{"class":116},[55,497,498],{"class":120}," load_workbook(",[55,500,501],{"class":65},"\"calc\u002Fseq.xlsx\"",[55,503,230],{"class":120},[55,505,506],{"class":470},"data_only",[55,508,150],{"class":116},[55,510,476],{"class":153},[55,512,513],{"class":120},").active\n",[55,515,517,520,522,525,528,531,534,537,540,542,544,546,549,551,554,556,558,560,562,564,566],{"class":57,"line":516},13,[55,518,519],{"class":120},"grid ",[55,521,150],{"class":116},[55,523,524],{"class":120}," np.array([[calc.cell(r, c).value ",[55,526,527],{"class":116},"for",[55,529,530],{"class":120}," c ",[55,532,533],{"class":116},"in",[55,535,536],{"class":153}," range",[55,538,539],{"class":120},"(",[55,541,154],{"class":153},[55,543,230],{"class":120},[55,545,227],{"class":153},[55,547,548],{"class":120},")] ",[55,550,527],{"class":116},[55,552,553],{"class":120}," r ",[55,555,533],{"class":116},[55,557,536],{"class":153},[55,559,539],{"class":120},[55,561,154],{"class":153},[55,563,230],{"class":120},[55,565,214],{"class":153},[55,567,568],{"class":120},")])\n",[55,570,572,575,577,580,582,585,587,589,591,593,595,597,599,602],{"class":57,"line":571},14,[55,573,574],{"class":120},"tenths ",[55,576,150],{"class":116},[55,578,579],{"class":120}," np.array([calc.cell(r, ",[55,581,214],{"class":153},[55,583,584],{"class":120},").value ",[55,586,527],{"class":116},[55,588,553],{"class":120},[55,590,533],{"class":116},[55,592,536],{"class":153},[55,594,539],{"class":120},[55,596,154],{"class":153},[55,598,230],{"class":120},[55,600,601],{"class":153},"7",[55,603,568],{"class":120},[55,605,607,609,611,614,617,619,621,623,625,627,629,631],{"class":57,"line":606},15,[55,608,208],{"class":153},[55,610,539],{"class":120},[55,612,613],{"class":65},"\"grid matches:\"",[55,615,616],{"class":120},", np.array_equal(grid, sequence(",[55,618,227],{"class":153},[55,620,230],{"class":120},[55,622,233],{"class":153},[55,624,230],{"class":120},[55,626,238],{"class":153},[55,628,230],{"class":120},[55,630,214],{"class":153},[55,632,633],{"class":120},")))\n",[55,635,637,639,641,644,647,650,652,654,656,659,661,663],{"class":57,"line":636},16,[55,638,208],{"class":153},[55,640,539],{"class":120},[55,642,643],{"class":65},"\"tenths match:\"",[55,645,646],{"class":120},", np.allclose(tenths, sequence(",[55,648,649],{"class":153},"6",[55,651,230],{"class":120},[55,653,154],{"class":153},[55,655,230],{"class":120},[55,657,658],{"class":153},"0.1",[55,660,230],{"class":120},[55,662,658],{"class":153},[55,664,665],{"class":120},").ravel()), tenths)\n",[55,667,669,671,673,676,679,681],{"class":57,"line":668},17,[55,670,208],{"class":153},[55,672,539],{"class":120},[55,674,675],{"class":65},"\"without the _xlfn prefix:\"",[55,677,678],{"class":120},", calc[",[55,680,404],{"class":65},[55,682,683],{"class":120},"].value)\n",[10,685,686,687,690,691,694,695,698,699,702,703,706,707,39],{},"Both results match NumPy's — the decimals within floating-point precision, which is why ",[14,688,689],{},"allclose"," rather than exact equality is the right comparison for fractional steps. Two details made the formulas work at all. In the file format, functions added to Excel after 2010 are stored with an ",[14,692,693],{},"_xlfn."," prefix; written without it, as in G1, the spreadsheet does not recognise the name and shows ",[14,696,697],{},"#NAME?",". And because openpyxl does not write the metadata that marks a formula as a spilling dynamic array, the formula is written as an ",[14,700,701],{},"ArrayFormula"," over the exact range it should fill — ",[14,704,705],{},"A1:C4"," for a four-by-three result. Without that, a plain formula fills only its first cell. Writing dynamic-array formulas properly is covered in ",[35,708,710],{"href":709},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-dynamic-array-formulas-with-python\u002F","Write Dynamic Array Formulas with Python",[712,713,721,722,721,726,721,730,721,737,721,746,721,750,721,757,721,760,721,764,721,767,721,771,721,775,721,779,721,781,721,784,721,786,721,789,721,791,721,794,721,797,721,801,721,803,721,807,721,809,721,812,721,814,721,817,721,820,721,823,721,825,721,828,721,830,721,833,721,835,721,838,721,841,721,844,721,846,721,849,721,851,721,854,721,856,721,859,721,862,721,866,721,869,721,872,721,875,721,878,721,881,721,884,721,886,721,888,721,890,721,892,721,895,721,898,721,900,721,902,721,904,721,906,721,909,721,912,721,914,721,916,721,918,721,920,721,925,721,928,721,934,721,939,721,947],"svg",{"viewBox":714,"role":715,"ariaLabelledBy":716,"xmlns":719,"style":720},"6 0 748 192","img",[717,718],"seq-grid-t","seq-grid-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:748px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[723,724,725],"title",{"id":717},"SEQUENCE fills row by row, like NumPy's reshape",[727,728,729],"desc",{"id":718},"SEQUENCE(4,3,10,5) produces 10, 15, 20 across the first row, 25, 30, 35 across the second, and so on. numpy arange of 12 values reshaped to 4 rows and 3 columns, multiplied by the step and added to the start, gives the same grid.",[731,732],"rect",{"x":649,"y":733,"width":734,"height":735,"fill":736},"0","748","192","#ffffff",[731,738],{"x":739,"y":740,"width":741,"height":742,"rx":733,"fill":743,"stroke":744,"style":745},"22.3","40.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)","stroke-width:1px",[731,747],{"x":748,"y":740,"width":749,"height":742,"rx":733,"fill":743,"stroke":744,"style":745},"54.3","44.0",[751,752,756],"text",{"x":753,"y":754,"style":755},"76.3","57.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[731,758],{"x":759,"y":740,"width":749,"height":742,"rx":733,"fill":743,"stroke":744,"style":745},"98.3",[751,761,763],{"x":762,"y":754,"style":755},"120.3","B",[731,765],{"x":766,"y":740,"width":749,"height":742,"rx":733,"fill":743,"stroke":744,"style":745},"142.3",[751,768,770],{"x":769,"y":754,"style":755},"164.3","C",[731,772],{"x":739,"y":773,"width":741,"height":774,"rx":733,"fill":743,"stroke":744,"style":745},"64.0","28.0",[751,776,154],{"x":777,"y":778,"style":755},"38.3","83.0",[731,780],{"x":748,"y":773,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,782,238],{"x":753,"y":778,"style":783},"font-size:10.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle",[731,785],{"x":759,"y":773,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,787,788],{"x":762,"y":778,"style":783},"15",[731,790],{"x":766,"y":773,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,792,793],{"x":769,"y":778,"style":783},"20",[731,795],{"x":739,"y":796,"width":741,"height":774,"rx":733,"fill":743,"stroke":744,"style":745},"92.0",[751,798,800],{"x":777,"y":799,"style":755},"111.0","2",[731,802],{"x":748,"y":796,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,804,806],{"x":753,"y":799,"style":805},"font-size:10.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","25",[731,808],{"x":759,"y":796,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,810,811],{"x":762,"y":799,"style":805},"30",[731,813],{"x":766,"y":796,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,815,816],{"x":769,"y":799,"style":805},"35",[731,818],{"x":739,"y":819,"width":741,"height":774,"rx":733,"fill":743,"stroke":744,"style":745},"120.0",[751,821,233],{"x":777,"y":822,"style":755},"139.0",[731,824],{"x":748,"y":819,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,826,827],{"x":753,"y":822,"style":805},"40",[731,829],{"x":759,"y":819,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,831,832],{"x":762,"y":822,"style":805},"45",[731,834],{"x":766,"y":819,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,836,837],{"x":769,"y":822,"style":805},"50",[731,839],{"x":739,"y":840,"width":741,"height":774,"rx":733,"fill":743,"stroke":744,"style":745},"148.0",[751,842,227],{"x":777,"y":843,"style":755},"167.0",[731,845],{"x":748,"y":840,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,847,848],{"x":753,"y":843,"style":805},"55",[731,850],{"x":759,"y":840,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,852,853],{"x":762,"y":843,"style":805},"60",[731,855],{"x":766,"y":840,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,857,858],{"x":769,"y":843,"style":805},"65",[731,860],{"x":861,"y":740,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},"605.7",[751,863,238],{"x":864,"y":865,"style":783},"627.7","59.0",[731,867],{"x":868,"y":740,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},"649.7",[751,870,788],{"x":871,"y":865,"style":783},"671.7",[731,873],{"x":874,"y":740,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},"693.7",[751,876,793],{"x":877,"y":865,"style":783},"715.7",[731,879],{"x":861,"y":880,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},"68.0",[751,882,806],{"x":864,"y":883,"style":805},"87.0",[731,885],{"x":868,"y":880,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,887,811],{"x":871,"y":883,"style":805},[731,889],{"x":874,"y":880,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,891,816],{"x":877,"y":883,"style":805},[731,893],{"x":861,"y":894,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},"96.0",[751,896,827],{"x":864,"y":897,"style":805},"115.0",[731,899],{"x":868,"y":894,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,901,832],{"x":871,"y":897,"style":805},[731,903],{"x":874,"y":894,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,905,837],{"x":877,"y":897,"style":805},[731,907],{"x":861,"y":908,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},"124.0",[751,910,848],{"x":864,"y":911,"style":805},"143.0",[731,913],{"x":868,"y":908,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,915,853],{"x":871,"y":911,"style":805},[731,917],{"x":874,"y":908,"width":749,"height":774,"rx":733,"fill":736,"stroke":744,"style":745},[751,919,858],{"x":877,"y":911,"style":805},[751,921,20],{"x":922,"y":923,"style":924},"104.3","29.0","font-size:12.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle",[751,926,927],{"x":871,"y":923,"style":924},"NumPy",[57,929],{"x1":930,"y1":894,"x2":931,"y2":894,"stroke":932,"style":933},"196.3","591.7","var(--brand,#5b5cf0)","stroke-width:2px",[935,936],"polygon",{"points":937,"fill":938},"595.7,96.0 586.7,101.0 586.7,91.0","#5b5cf0",[731,940],{"x":941,"y":942,"width":943,"height":944,"rx":945,"fill":736,"stroke":744,"style":946},"244.3","63.0","303.5","22.0","11","stroke-width:1.2px",[751,948,952],{"x":949,"y":950,"style":951},"396.0","78.0","font-size:11.5px;font-weight:400;fill:var(--brand-strong,#4338ca);text-anchor:middle;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace","start + step * arange(12).reshape(4, 3)",[712,954,721,960,721,963,721,966,721,970,721,978,721,989,721,994,721,998,721,1002,721,1005,721,1008,721,1014,721,1019,721,1027,721,1034,721,1038,721,1043,721,1045,721,1048,721,1052,721,1055,721,1060,721,1067,721,1071,721,1074,721,1076,721,1079,721,1083,721,1086,721,1091,721,1098,721,1102],{"viewBox":955,"role":715,"ariaLabelledBy":956,"xmlns":719,"style":959},"4 0 752 272",[957,958],"seq-write-t","seq-write-d","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[723,961,962],{"id":957},"Writing SEQUENCE into a workbook from Python",[727,964,965],{"id":958},"A formula written as =SEQUENCE without the _xlfn prefix shows a NAME error. With the prefix but as a plain formula, only the first cell is filled. With the prefix and as an ArrayFormula over the full result range, every cell of the grid is filled.",[731,967],{"x":227,"y":733,"width":968,"height":969,"fill":736},"752","272",[731,971],{"x":972,"y":973,"width":974,"height":975,"rx":976,"fill":977,"stroke":932,"style":933},"240.0","16.0","280.0","75.5","12","#f0f4ff",[979,980,982],"g",{"transform":981},"translate(368.0,29.0) scale(1.000)",[983,984],"path",{"d":985,"fill":986,"stroke":987,"style":988},"M9 8l-4 4 4 4 M15 8l4 4-4 4","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[751,990,993],{"x":991,"y":975,"style":992},"380.0","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","How is the formula written?",[57,995],{"x1":991,"y1":996,"x2":991,"y2":997,"stroke":932,"style":933},"91.5","111.5",[57,999],{"x1":1000,"y1":997,"x2":1001,"y2":997,"stroke":932,"style":933},"134.7","625.3",[57,1003],{"x1":1000,"y1":997,"x2":1000,"y2":1004,"stroke":932,"style":933},"157.5",[935,1006],{"points":1007,"fill":938},"134.7,161.5 129.7,152.5 139.7,152.5",[731,1009],{"x":1010,"y":1011,"width":1012,"height":1013,"rx":238,"fill":736,"stroke":744,"style":946},"77.8","121.5","113.7","21.0",[751,1015,1018],{"x":1000,"y":1016,"style":1017},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","=SEQUENCE(…)",[731,1020],{"x":1021,"y":1022,"width":1023,"height":1024,"rx":976,"fill":1025,"stroke":1026,"style":933},"20.0","163.5","229.3","93.0","#fce9e9","var(--danger,#dc2626)",[979,1028,1030],{"transform":1029},"translate(122.7,176.5) scale(1.000)",[983,1031],{"d":1032,"fill":986,"stroke":1033,"style":988},"M6 6l12 12 M18 6L6 18","var(--accent-ink,#be185d)",[751,1035,697],{"x":1000,"y":1036,"style":1037},"223.0","font-size:13.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle",[751,1039,1042],{"x":1000,"y":1040,"style":1041},"242.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","name not recognised",[57,1044],{"x1":991,"y1":997,"x2":991,"y2":1004,"stroke":932,"style":933},[935,1046],{"points":1047,"fill":938},"380.0,161.5 375.0,152.5 385.0,152.5",[731,1049],{"x":1050,"y":1011,"width":1051,"height":1013,"rx":238,"fill":736,"stroke":744,"style":946},"291.2","177.6",[751,1053,1054],{"x":991,"y":1016,"style":1017},"=_xlfn.SEQUENCE(…) plain",[731,1056],{"x":1057,"y":1022,"width":1023,"height":1024,"rx":976,"fill":1058,"stroke":1059,"style":933},"265.3","#fdefd8","var(--gold,#b4740a)",[979,1061,1063],{"transform":1062},"translate(368.0,176.5) scale(1.000)",[983,1064],{"d":1065,"fill":986,"stroke":1066,"style":988},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","var(--gold-ink,#7a4e06)",[751,1068,1070],{"x":991,"y":1036,"style":1069},"font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","first cell only",[751,1072,1073],{"x":991,"y":1040,"style":1041},"no spill metadata",[57,1075],{"x1":1001,"y1":997,"x2":1001,"y2":1004,"stroke":932,"style":933},[935,1077],{"points":1078,"fill":938},"625.3,161.5 620.3,152.5 630.3,152.5",[731,1080],{"x":1081,"y":1011,"width":1082,"height":1013,"rx":238,"fill":736,"stroke":744,"style":946},"530.3","190.1",[751,1084,1085],{"x":1001,"y":1016,"style":1017},"ArrayFormula(range, _xlfn…)",[731,1087],{"x":1088,"y":1022,"width":1023,"height":1024,"rx":976,"fill":1089,"stroke":1090,"style":933},"510.7","#d9f4f1","var(--teal,#0f9488)",[979,1092,1094],{"transform":1093},"translate(613.3,176.5) scale(1.000)",[983,1095],{"d":1096,"fill":986,"stroke":1097,"style":988},"M5 12.5l4.5 4.5L19 7","var(--teal-ink,#0b6157)",[751,1099,1101],{"x":1001,"y":1036,"style":1100},"font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","whole grid filled",[751,1103,1104],{"x":1001,"y":1040,"style":1041},"matches NumPy",[41,1106,1108],{"id":1107},"step-3-date-sequences","Step 3 — Date sequences",[10,1110,1111,1112,1114,1115,273,1118,1121,1122,1125],{},"A column of dates — every month start, every day, every working day — is what ",[14,1113,85],{}," is most often used for in reports, often combined with ",[14,1116,1117],{},"EDATE",[14,1119,1120],{},"WORKDAY",". pandas generates them directly with ",[14,1123,1124],{},"date_range",":",[46,1127,1129],{"className":107,"code":1128,"language":109,"meta":51,"style":51},"import pandas as pd\n\nmonth_starts = pd.date_range(\"2026-01-01\", periods=12, freq=\"MS\")\nmonth_ends = pd.date_range(\"2026-01-31\", periods=12, freq=\"ME\")\nworkdays = pd.bdate_range(\"2026-09-21\", periods=10)\nweekly_mondays = pd.date_range(\"2026-09-07\", periods=6, freq=\"W-MON\")\nprint(month_starts[:3].date, month_ends[:3].date)\nprint(\"10 business days from 21 Sep:\", workdays.strftime(\"%a %d\").tolist())\nprint(\"Mondays:\", weekly_mondays.strftime(\"%d %b\").tolist())\n",[14,1130,1131,1143,1147,1181,1212,1235,1266,1283,1310],{"__ignoreMap":51},[55,1132,1133,1135,1138,1140],{"class":57,"line":58},[55,1134,117],{"class":116},[55,1136,1137],{"class":120}," pandas ",[55,1139,124],{"class":116},[55,1141,1142],{"class":120}," pd\n",[55,1144,1145],{"class":57,"line":130},[55,1146,134],{"emptyLinePlaceholder":133},[55,1148,1149,1152,1154,1157,1160,1162,1165,1167,1169,1171,1174,1176,1179],{"class":57,"line":137},[55,1150,1151],{"class":120},"month_starts ",[55,1153,150],{"class":116},[55,1155,1156],{"class":120}," pd.date_range(",[55,1158,1159],{"class":65},"\"2026-01-01\"",[55,1161,230],{"class":120},[55,1163,1164],{"class":470},"periods",[55,1166,150],{"class":116},[55,1168,976],{"class":153},[55,1170,230],{"class":120},[55,1172,1173],{"class":470},"freq",[55,1175,150],{"class":116},[55,1177,1178],{"class":65},"\"MS\"",[55,1180,372],{"class":120},[55,1182,1183,1186,1188,1190,1193,1195,1197,1199,1201,1203,1205,1207,1210],{"class":57,"line":174},[55,1184,1185],{"class":120},"month_ends ",[55,1187,150],{"class":116},[55,1189,1156],{"class":120},[55,1191,1192],{"class":65},"\"2026-01-31\"",[55,1194,230],{"class":120},[55,1196,1164],{"class":470},[55,1198,150],{"class":116},[55,1200,976],{"class":153},[55,1202,230],{"class":120},[55,1204,1173],{"class":470},[55,1206,150],{"class":116},[55,1208,1209],{"class":65},"\"ME\"",[55,1211,372],{"class":120},[55,1213,1214,1217,1219,1222,1225,1227,1229,1231,1233],{"class":57,"line":200},[55,1215,1216],{"class":120},"workdays ",[55,1218,150],{"class":116},[55,1220,1221],{"class":120}," pd.bdate_range(",[55,1223,1224],{"class":65},"\"2026-09-21\"",[55,1226,230],{"class":120},[55,1228,1164],{"class":470},[55,1230,150],{"class":116},[55,1232,238],{"class":153},[55,1234,372],{"class":120},[55,1236,1237,1240,1242,1244,1247,1249,1251,1253,1255,1257,1259,1261,1264],{"class":57,"line":205},[55,1238,1239],{"class":120},"weekly_mondays ",[55,1241,150],{"class":116},[55,1243,1156],{"class":120},[55,1245,1246],{"class":65},"\"2026-09-07\"",[55,1248,230],{"class":120},[55,1250,1164],{"class":470},[55,1252,150],{"class":116},[55,1254,649],{"class":153},[55,1256,230],{"class":120},[55,1258,1173],{"class":470},[55,1260,150],{"class":116},[55,1262,1263],{"class":65},"\"W-MON\"",[55,1265,372],{"class":120},[55,1267,1268,1270,1273,1275,1278,1280],{"class":57,"line":220},[55,1269,208],{"class":153},[55,1271,1272],{"class":120},"(month_starts[:",[55,1274,233],{"class":153},[55,1276,1277],{"class":120},"].date, month_ends[:",[55,1279,233],{"class":153},[55,1281,1282],{"class":120},"].date)\n",[55,1284,1285,1287,1289,1292,1295,1298,1302,1305,1307],{"class":57,"line":375},[55,1286,208],{"class":153},[55,1288,539],{"class":120},[55,1290,1291],{"class":65},"\"10 business days from 21 Sep:\"",[55,1293,1294],{"class":120},", workdays.strftime(",[55,1296,1297],{"class":65},"\"",[55,1299,1301],{"class":1300},"sSjpA","%a",[55,1303,1304],{"class":1300}," %d",[55,1306,1297],{"class":65},[55,1308,1309],{"class":120},").tolist())\n",[55,1311,1312,1314,1316,1319,1322,1324,1327,1330,1332],{"class":57,"line":399},[55,1313,208],{"class":153},[55,1315,539],{"class":120},[55,1317,1318],{"class":65},"\"Mondays:\"",[55,1320,1321],{"class":120},", weekly_mondays.strftime(",[55,1323,1297],{"class":65},[55,1325,1326],{"class":1300},"%d",[55,1328,1329],{"class":1300}," %b",[55,1331,1297],{"class":65},[55,1333,1309],{"class":120},[10,1335,1336,1339,1340,1342,1343,1346,1347,1350,1351,1353,1354,1357,1358,1361,1362,1364,1365,39],{},[14,1337,1338],{},"freq=\"MS\""," gives month starts and ",[14,1341,1209],{}," month ends — the latter replacing the ",[14,1344,1345],{},"EOMONTH(SEQUENCE(...))"," construction, with February's end and leap years handled automatically. ",[14,1348,1349],{},"bdate_range"," skips weekends like ",[14,1352,1120],{},"; pass ",[14,1355,1356],{},"freq=\"C\""," with a ",[14,1359,1360],{},"holidays="," list to skip public holidays as well. ",[14,1363,1263],{}," anchors weekly dates to Mondays. These series are the backbone of a date table — see ",[35,1366,1368],{"href":1367},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fbuild-a-date-table-for-excel-reports-with-pandas\u002F","Build a Date Table for Excel Reports with pandas",[41,1370,1372],{"id":1371},"step-4-randarray-and-randbetween-reproducibly","Step 4 — RANDARRAY and RANDBETWEEN, reproducibly",[10,1374,1375,1378,1379,1382,1383,1386],{},[14,1376,1377],{},"RANDARRAY(rows, cols, min, max, whole_number)"," and ",[14,1380,1381],{},"RANDBETWEEN(low, high)"," produce random numbers. NumPy's ",[14,1384,1385],{},"Generator"," does the same, with one decisive advantage — a seed:",[46,1388,1390],{"className":107,"code":1389,"language":109,"meta":51,"style":51},"rng = np.random.default_rng(seed=2026)\n\ndecimals = rng.uniform(0, 1, size=(3, 2))              # =RANDARRAY(3,2)\nwhole = rng.integers(1, 100, size=(5, 2), endpoint=True) # =RANDARRAY(5,2,1,100,TRUE)\none = rng.integers(1, 6, endpoint=True)                 # =RANDBETWEEN(1,6)\nprint(decimals.round(3))\nprint(whole)\nagain = np.random.default_rng(seed=2026).uniform(0, 1, size=(3, 2))\nprint(\"same seed, same numbers:\", np.array_equal(decimals, again))\nprint(\"in range:\", whole.min() >= 1, whole.max() \u003C= 100)\n",[14,1391,1392,1412,1416,1453,1500,1529,1540,1547,1587,1599],{"__ignoreMap":51},[55,1393,1394,1397,1399,1402,1405,1407,1410],{"class":57,"line":58},[55,1395,1396],{"class":120},"rng ",[55,1398,150],{"class":116},[55,1400,1401],{"class":120}," np.random.default_rng(",[55,1403,1404],{"class":470},"seed",[55,1406,150],{"class":116},[55,1408,1409],{"class":153},"2026",[55,1411,372],{"class":120},[55,1413,1414],{"class":57,"line":130},[55,1415,134],{"emptyLinePlaceholder":133},[55,1417,1418,1421,1423,1426,1428,1430,1432,1434,1437,1439,1441,1443,1445,1447,1450],{"class":57,"line":137},[55,1419,1420],{"class":120},"decimals ",[55,1422,150],{"class":116},[55,1424,1425],{"class":120}," rng.uniform(",[55,1427,733],{"class":153},[55,1429,230],{"class":120},[55,1431,154],{"class":153},[55,1433,230],{"class":120},[55,1435,1436],{"class":470},"size",[55,1438,150],{"class":116},[55,1440,539],{"class":120},[55,1442,233],{"class":153},[55,1444,230],{"class":120},[55,1446,800],{"class":153},[55,1448,1449],{"class":120},"))              ",[55,1451,1452],{"class":414},"# =RANDARRAY(3,2)\n",[55,1454,1455,1458,1460,1463,1465,1467,1470,1472,1474,1476,1478,1480,1482,1484,1487,1490,1492,1494,1497],{"class":57,"line":174},[55,1456,1457],{"class":120},"whole ",[55,1459,150],{"class":116},[55,1461,1462],{"class":120}," rng.integers(",[55,1464,154],{"class":153},[55,1466,230],{"class":120},[55,1468,1469],{"class":153},"100",[55,1471,230],{"class":120},[55,1473,1436],{"class":470},[55,1475,150],{"class":116},[55,1477,539],{"class":120},[55,1479,214],{"class":153},[55,1481,230],{"class":120},[55,1483,800],{"class":153},[55,1485,1486],{"class":120},"), ",[55,1488,1489],{"class":470},"endpoint",[55,1491,150],{"class":116},[55,1493,476],{"class":153},[55,1495,1496],{"class":120},") ",[55,1498,1499],{"class":414},"# =RANDARRAY(5,2,1,100,TRUE)\n",[55,1501,1502,1505,1507,1509,1511,1513,1515,1517,1519,1521,1523,1526],{"class":57,"line":200},[55,1503,1504],{"class":120},"one ",[55,1506,150],{"class":116},[55,1508,1462],{"class":120},[55,1510,154],{"class":153},[55,1512,230],{"class":120},[55,1514,649],{"class":153},[55,1516,230],{"class":120},[55,1518,1489],{"class":470},[55,1520,150],{"class":116},[55,1522,476],{"class":153},[55,1524,1525],{"class":120},")                 ",[55,1527,1528],{"class":414},"# =RANDBETWEEN(1,6)\n",[55,1530,1531,1533,1536,1538],{"class":57,"line":205},[55,1532,208],{"class":153},[55,1534,1535],{"class":120},"(decimals.round(",[55,1537,233],{"class":153},[55,1539,245],{"class":120},[55,1541,1542,1544],{"class":57,"line":220},[55,1543,208],{"class":153},[55,1545,1546],{"class":120},"(whole)\n",[55,1548,1549,1552,1554,1556,1558,1560,1562,1565,1567,1569,1571,1573,1575,1577,1579,1581,1583,1585],{"class":57,"line":375},[55,1550,1551],{"class":120},"again ",[55,1553,150],{"class":116},[55,1555,1401],{"class":120},[55,1557,1404],{"class":470},[55,1559,150],{"class":116},[55,1561,1409],{"class":153},[55,1563,1564],{"class":120},").uniform(",[55,1566,733],{"class":153},[55,1568,230],{"class":120},[55,1570,154],{"class":153},[55,1572,230],{"class":120},[55,1574,1436],{"class":470},[55,1576,150],{"class":116},[55,1578,539],{"class":120},[55,1580,233],{"class":153},[55,1582,230],{"class":120},[55,1584,800],{"class":153},[55,1586,245],{"class":120},[55,1588,1589,1591,1593,1596],{"class":57,"line":399},[55,1590,208],{"class":153},[55,1592,539],{"class":120},[55,1594,1595],{"class":65},"\"same seed, same numbers:\"",[55,1597,1598],{"class":120},", np.array_equal(decimals, again))\n",[55,1600,1601,1603,1605,1608,1611,1614,1617,1620,1623,1626],{"class":57,"line":418},[55,1602,208],{"class":153},[55,1604,539],{"class":120},[55,1606,1607],{"class":65},"\"in range:\"",[55,1609,1610],{"class":120},", whole.min() ",[55,1612,1613],{"class":116},">=",[55,1615,1616],{"class":153}," 1",[55,1618,1619],{"class":120},", whole.max() ",[55,1621,1622],{"class":116},"\u003C=",[55,1624,1625],{"class":153}," 100",[55,1627,372],{"class":120},[10,1629,1630,1633,1634,1637,1638,1641,1642,1646,1647,1650,1651,1654],{},[14,1631,1632],{},"uniform(0, 1)"," matches ",[14,1635,1636],{},"RANDARRAY","'s default of decimals between 0 and 1; ",[14,1639,1640],{},"integers(1, 100, endpoint=True)"," matches whole numbers from 1 to 100 ",[1643,1644,1645],"em",{},"inclusive"," — without ",[14,1648,1649],{},"endpoint=True",", NumPy's upper bound is exclusive, a classic off-by-one when translating ",[14,1652,1653],{},"RANDBETWEEN",". Creating a generator with the same seed reproduces the same numbers exactly, so test data, simulations and audit samples can be regenerated and checked. In Excel the same formulas produce new numbers every time the sheet recalculates — pressing Delete on an empty cell is enough — so anyone who uses them for a sample must copy and paste them as values immediately, and can never show how the sample was drawn.",[712,1656,721,1661,721,1664,721,1667,721,1670,721,1675,721,1682,721,1687,721,1692,721,1696,721,1700,721,1704,721,1707,721,1712,721,1717,721,1721,721,1724,721,1727],{"viewBox":1657,"role":715,"ariaLabelledBy":1658,"xmlns":719,"style":959},"4 0 752 207",[1659,1660],"seq-rand-t","seq-rand-d",[723,1662,1663],{"id":1659},"Random numbers in Excel and in NumPy",[727,1665,1666],{"id":1660},"Excel's RANDARRAY and RANDBETWEEN are volatile, recalculate on every change and cannot be seeded, so results must be pasted as values and cannot be reproduced. NumPy's Generator with a seed gives the same numbers every run, so samples and test data can be regenerated and audited.",[731,1668],{"x":227,"y":733,"width":968,"height":1669,"fill":736},"207",[731,1671],{"x":1021,"y":973,"width":1672,"height":1673,"rx":1674,"fill":1058,"stroke":1059,"style":933},"351.0","175.0","14",[979,1676,1678],{"transform":1677},"translate(182.5,29.0) scale(1.083)",[983,1679],{"d":1680,"fill":986,"stroke":1066,"style":1681},"M20 11a8 8 0 1 0-2.3 5.7 M20 4v7h-7","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[751,1683,1686],{"x":1684,"y":950,"style":1685},"195.5","font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Excel RANDARRAY \u002F RANDBETWEEN",[57,1688],{"x1":1689,"y1":1690,"x2":1691,"y2":1690,"stroke":1059,"style":745},"36.0","91.0","355.0",[751,1693,1695],{"x":1684,"y":799,"style":1694},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","recalculates on every edit",[751,1697,1699],{"x":1684,"y":1698,"style":1694},"137.0","no seed, not reproducible",[751,1701,1703],{"x":1684,"y":1702,"style":1694},"163.0","paste as values to keep",[731,1705],{"x":1706,"y":973,"width":1672,"height":1673,"rx":1674,"fill":1089,"stroke":1090,"style":933},"389.0",[979,1708,1710],{"transform":1709},"translate(551.5,29.0) scale(1.083)",[983,1711],{"d":1096,"fill":986,"stroke":1097,"style":1681},[751,1713,1716],{"x":1714,"y":950,"style":1715},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","NumPy default_rng(seed)",[57,1718],{"x1":1719,"y1":1690,"x2":1720,"y2":1690,"stroke":1090,"style":745},"405.0","724.0",[751,1722,1723],{"x":1714,"y":799,"style":1694},"same seed, same numbers",[751,1725,1726],{"x":1714,"y":1698,"style":1694},"integers(..., endpoint=True)",[751,1728,1729],{"x":1714,"y":1702,"style":1694},"regenerate and audit anytime",[41,1731,1733],{"id":1732},"step-5-shuffle-and-sample-without-repeats","Step 5 — Shuffle and sample without repeats",[10,1735,1736,1739,1740,1743],{},[14,1737,1738],{},"=SORTBY(list, RANDARRAY(ROWS(list)))"," shuffles a list; ",[14,1741,1742],{},"=TAKE(SORTBY(...), 5)"," picks five items without repeats. NumPy and pandas have both built in:",[46,1745,1747],{"className":107,"code":1746,"language":109,"meta":51,"style":51},"invoices = pd.DataFrame({\"Invoice\": [f\"INV-{1000 + i}\" for i in range(40)],\n                         \"Amount\": np.random.default_rng(1).gamma(3, 400, 40).round(2)})\nshuffled = invoices.sample(frac=1, random_state=7).reset_index(drop=True)\naudit = invoices.sample(n=5, random_state=7)\nprint(audit[\"Invoice\"].tolist())\nprint(\"no repeats:\", audit[\"Invoice\"].is_unique, \"| reproducible:\",\n      audit[\"Invoice\"].tolist() == invoices.sample(n=5, random_state=7)[\"Invoice\"].tolist())\n\nwith pd.ExcelWriter(\"sequences.xlsx\") as xw:\n    pd.DataFrame(sequence(4, 3, 10, 5), columns=[\"A\", \"B\", \"C\"]).to_excel(xw, sheet_name=\"Grid\", index=False)\n    pd.DataFrame({\"Month start\": month_starts.date}).to_excel(xw, sheet_name=\"Months\", index=False)\n    audit.assign(Seed=7).to_excel(xw, sheet_name=\"Audit sample\", index=False)\nprint(\"written as values: Grid, Months, Audit sample\")\n",[14,1748,1749,1805,1837,1875,1901,1913,1936,1972,1976,1994,2059,2087,2119],{"__ignoreMap":51},[55,1750,1751,1754,1756,1759,1762,1765,1768,1771,1774,1777,1780,1783,1786,1788,1791,1794,1796,1798,1800,1802],{"class":57,"line":58},[55,1752,1753],{"class":120},"invoices ",[55,1755,150],{"class":116},[55,1757,1758],{"class":120}," pd.DataFrame({",[55,1760,1761],{"class":65},"\"Invoice\"",[55,1763,1764],{"class":120},": [",[55,1766,1767],{"class":116},"f",[55,1769,1770],{"class":65},"\"INV-",[55,1772,1773],{"class":1300},"{",[55,1775,1776],{"class":153},"1000",[55,1778,1779],{"class":116}," +",[55,1781,1782],{"class":120}," i",[55,1784,1785],{"class":1300},"}",[55,1787,1297],{"class":65},[55,1789,1790],{"class":116}," for",[55,1792,1793],{"class":120}," i ",[55,1795,533],{"class":116},[55,1797,536],{"class":153},[55,1799,539],{"class":120},[55,1801,827],{"class":153},[55,1803,1804],{"class":120},")],\n",[55,1806,1807,1810,1813,1815,1818,1820,1822,1825,1827,1829,1832,1834],{"class":57,"line":130},[55,1808,1809],{"class":65},"                         \"Amount\"",[55,1811,1812],{"class":120},": np.random.default_rng(",[55,1814,154],{"class":153},[55,1816,1817],{"class":120},").gamma(",[55,1819,233],{"class":153},[55,1821,230],{"class":120},[55,1823,1824],{"class":153},"400",[55,1826,230],{"class":120},[55,1828,827],{"class":153},[55,1830,1831],{"class":120},").round(",[55,1833,800],{"class":153},[55,1835,1836],{"class":120},")})\n",[55,1838,1839,1842,1844,1847,1850,1852,1854,1856,1859,1861,1863,1866,1869,1871,1873],{"class":57,"line":137},[55,1840,1841],{"class":120},"shuffled ",[55,1843,150],{"class":116},[55,1845,1846],{"class":120}," invoices.sample(",[55,1848,1849],{"class":470},"frac",[55,1851,150],{"class":116},[55,1853,154],{"class":153},[55,1855,230],{"class":120},[55,1857,1858],{"class":470},"random_state",[55,1860,150],{"class":116},[55,1862,601],{"class":153},[55,1864,1865],{"class":120},").reset_index(",[55,1867,1868],{"class":470},"drop",[55,1870,150],{"class":116},[55,1872,476],{"class":153},[55,1874,372],{"class":120},[55,1876,1877,1880,1882,1884,1887,1889,1891,1893,1895,1897,1899],{"class":57,"line":174},[55,1878,1879],{"class":120},"audit ",[55,1881,150],{"class":116},[55,1883,1846],{"class":120},[55,1885,1886],{"class":470},"n",[55,1888,150],{"class":116},[55,1890,214],{"class":153},[55,1892,230],{"class":120},[55,1894,1858],{"class":470},[55,1896,150],{"class":116},[55,1898,601],{"class":153},[55,1900,372],{"class":120},[55,1902,1903,1905,1908,1910],{"class":57,"line":200},[55,1904,208],{"class":153},[55,1906,1907],{"class":120},"(audit[",[55,1909,1761],{"class":65},[55,1911,1912],{"class":120},"].tolist())\n",[55,1914,1915,1917,1919,1922,1925,1927,1930,1933],{"class":57,"line":205},[55,1916,208],{"class":153},[55,1918,539],{"class":120},[55,1920,1921],{"class":65},"\"no repeats:\"",[55,1923,1924],{"class":120},", audit[",[55,1926,1761],{"class":65},[55,1928,1929],{"class":120},"].is_unique, ",[55,1931,1932],{"class":65},"\"| reproducible:\"",[55,1934,1935],{"class":120},",\n",[55,1937,1938,1941,1943,1946,1949,1951,1953,1955,1957,1959,1961,1963,1965,1968,1970],{"class":57,"line":220},[55,1939,1940],{"class":120},"      audit[",[55,1942,1761],{"class":65},[55,1944,1945],{"class":120},"].tolist() ",[55,1947,1948],{"class":116},"==",[55,1950,1846],{"class":120},[55,1952,1886],{"class":470},[55,1954,150],{"class":116},[55,1956,214],{"class":153},[55,1958,230],{"class":120},[55,1960,1858],{"class":470},[55,1962,150],{"class":116},[55,1964,601],{"class":153},[55,1966,1967],{"class":120},")[",[55,1969,1761],{"class":65},[55,1971,1912],{"class":120},[55,1973,1974],{"class":57,"line":375},[55,1975,134],{"emptyLinePlaceholder":133},[55,1977,1978,1981,1984,1987,1989,1991],{"class":57,"line":399},[55,1979,1980],{"class":116},"with",[55,1982,1983],{"class":120}," pd.ExcelWriter(",[55,1985,1986],{"class":65},"\"sequences.xlsx\"",[55,1988,1496],{"class":120},[55,1990,124],{"class":116},[55,1992,1993],{"class":120}," xw:\n",[55,1995,1996,1999,2001,2003,2005,2007,2009,2011,2013,2015,2018,2020,2023,2026,2028,2031,2033,2036,2039,2042,2044,2047,2049,2052,2054,2057],{"class":57,"line":418},[55,1997,1998],{"class":120},"    pd.DataFrame(sequence(",[55,2000,227],{"class":153},[55,2002,230],{"class":120},[55,2004,233],{"class":153},[55,2006,230],{"class":120},[55,2008,238],{"class":153},[55,2010,230],{"class":120},[55,2012,214],{"class":153},[55,2014,1486],{"class":120},[55,2016,2017],{"class":470},"columns",[55,2019,150],{"class":116},[55,2021,2022],{"class":120},"[",[55,2024,2025],{"class":65},"\"A\"",[55,2027,230],{"class":120},[55,2029,2030],{"class":65},"\"B\"",[55,2032,230],{"class":120},[55,2034,2035],{"class":65},"\"C\"",[55,2037,2038],{"class":120},"]).to_excel(xw, ",[55,2040,2041],{"class":470},"sheet_name",[55,2043,150],{"class":116},[55,2045,2046],{"class":65},"\"Grid\"",[55,2048,230],{"class":120},[55,2050,2051],{"class":470},"index",[55,2053,150],{"class":116},[55,2055,2056],{"class":153},"False",[55,2058,372],{"class":120},[55,2060,2061,2064,2067,2070,2072,2074,2077,2079,2081,2083,2085],{"class":57,"line":429},[55,2062,2063],{"class":120},"    pd.DataFrame({",[55,2065,2066],{"class":65},"\"Month start\"",[55,2068,2069],{"class":120},": month_starts.date}).to_excel(xw, ",[55,2071,2041],{"class":470},[55,2073,150],{"class":116},[55,2075,2076],{"class":65},"\"Months\"",[55,2078,230],{"class":120},[55,2080,2051],{"class":470},[55,2082,150],{"class":116},[55,2084,2056],{"class":153},[55,2086,372],{"class":120},[55,2088,2089,2092,2095,2097,2099,2102,2104,2106,2109,2111,2113,2115,2117],{"class":57,"line":490},[55,2090,2091],{"class":120},"    audit.assign(",[55,2093,2094],{"class":470},"Seed",[55,2096,150],{"class":116},[55,2098,601],{"class":153},[55,2100,2101],{"class":120},").to_excel(xw, ",[55,2103,2041],{"class":470},[55,2105,150],{"class":116},[55,2107,2108],{"class":65},"\"Audit sample\"",[55,2110,230],{"class":120},[55,2112,2051],{"class":470},[55,2114,150],{"class":116},[55,2116,2056],{"class":153},[55,2118,372],{"class":120},[55,2120,2121,2123,2125,2128],{"class":57,"line":516},[55,2122,208],{"class":153},[55,2124,539],{"class":120},[55,2126,2127],{"class":65},"\"written as values: Grid, Months, Audit sample\"",[55,2129,372],{"class":120},[10,2131,2132,2135,2136,2139,2140,2142,2143,2146,2147,2149,2150,39],{},[14,2133,2134],{},"sample(frac=1)"," shuffles all rows; ",[14,2137,2138],{},"sample(n=5)"," draws five without replacement, so no invoice is picked twice; ",[14,2141,1858],{}," makes both reproducible. For an audit, record the seed with the sample — as in the Audit sample sheet — so anyone can redraw it and confirm it was random rather than chosen. Writing the results with ",[14,2144,2145],{},"to_excel"," stores plain values, which is what a report or an audit file should contain; a sheet full of live ",[14,2148,1636],{}," formulas would show a different sample every time it was opened. Larger sampling questions are covered in ",[35,2151,2153],{"href":2152},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-large-excel-files-in-python\u002Ftake-a-random-sample-of-rows-from-a-large-excel-file\u002F","Take a Random Sample of Rows from a Large Excel File",[41,2155,2157],{"id":2156},"values-or-formulas","Values or formulas?",[10,2159,2160,2161,2164,2165,2167,2168,2170,2171,1378,2173,2175],{},"Most of the time a Python script should write the ",[1643,2162,2163],{},"values"," — the grid of numbers, the list of dates, the drawn sample — because the script already knows them and values work in every version of Excel and every other spreadsheet. Writing a ",[14,2166,85],{}," formula is worth it only when the workbook should keep recalculating after delivery: a template where the user types a start date and the column of month-ends updates itself, say. In that case use the ",[14,2169,693],{}," prefix and an array formula as in Step 2, and test the file in the spreadsheet versions your readers use. ",[14,2172,1636],{},[14,2174,1653],{}," formulas are almost never what a delivered file should contain; generate the numbers in Python with a seed and write them as values, so the workbook says the same thing every time it is opened.",[41,2177,2179],{"id":2178},"common-pitfalls","Common pitfalls",[2181,2182,2183,2195,2206,2218,2224],"ul",{},[2184,2185,2186,2192,2193,39],"li",{},[2187,2188,2189,2191],"strong",{},[14,2190,99],{}," with fractional steps."," The end point is unreliable; compute ",[14,2194,261],{},[2184,2196,2197,2200,2201,1378,2203,2205],{},[2187,2198,2199],{},"Column-major thinking."," ",[14,2202,85],{},[14,2204,103],{}," both fill row by row.",[2184,2207,2208,2211,2212,2214,2215,2217],{},[2187,2209,2210],{},"Exclusive upper bounds."," Use ",[14,2213,1649],{}," to match ",[14,2216,1653],{},"'s inclusive range.",[2184,2219,2220,2223],{},[2187,2221,2222],{},"Unseeded random numbers for samples."," Seed the generator and record the seed.",[2184,2225,2226,2229],{},[2187,2227,2228],{},"Live random formulas in delivered files."," Write values, not volatile formulas.",[41,2231,2233],{"id":2232},"conclusion","Conclusion",[10,2235,2236,2237,2240,2241,230,2243,1378,2246,2248,2249,1378,2252,2240,2255,1378,2257,2259,2260,2263],{},"Excel's sequence and random functions map onto short NumPy and pandas calls: ",[14,2238,2239],{},"start + step * np.arange(n).reshape(rows, cols)"," for ",[14,2242,85],{},[14,2244,2245],{},"pd.date_range",[14,2247,1349],{}," for date sequences, ",[14,2250,2251],{},"rng.uniform",[14,2253,2254],{},"rng.integers(..., endpoint=True)",[14,2256,1636],{},[14,2258,1653],{},", and ",[14,2261,2262],{},"DataFrame.sample"," for shuffles and samples without repeats. Check deterministic translations against a spreadsheet once, seed every random generator so results can be reproduced and audited, and write the outputs to Excel as values.",[41,2265,2267],{"id":2266},"frequently-asked-questions","Frequently asked questions",[10,2269,2270,2273],{},[2187,2271,2272],{},"What is the Python equivalent of Excel's SEQUENCE?","\nUse NumPy: start + step * np.arange(rows * cols).reshape(rows, cols). It fills the grid row by row, as SEQUENCE does.",[10,2275,2276,2279],{},[2187,2277,2278],{},"How do I create a sequence of dates like SEQUENCE with dates?","\nUse pandas date_range, for example date_range(\"2026-01-01\", periods=12, freq=\"MS\") for month starts or bdate_range for business days.",[10,2281,2282,2285],{},[2187,2283,2284],{},"What replaces RANDBETWEEN in Python?","\nnumpy's default_rng().integers(low, high, endpoint=True), which includes both ends of the range like RANDBETWEEN.",[10,2287,2288,2291],{},[2187,2289,2290],{},"How do I take a random sample without repeats like SORTBY with RANDARRAY?","\nUse DataFrame.sample(n=5, random_state=seed), which draws rows without replacement and is reproducible with the same seed.",[41,2293,2295],{"id":2294},"related","Related",[2181,2297,2298,2304,2311,2318],{},[2184,2299,2300,2301,2303],{},"Up one level: ",[35,2302,38],{"href":37}," — spreadsheet functions in Python.",[2184,2305,2306,2310],{},[35,2307,2309],{"href":2308},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Funique-sort-and-filter-equivalents-in-pandas\u002F","UNIQUE, SORT and FILTER Equivalents in pandas"," — other dynamic-array functions.",[2184,2312,2313,2317],{},[35,2314,2316],{"href":2315},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fvstack-hstack-take-and-choosecols-equivalents-in-pandas\u002F","VSTACK, HSTACK, TAKE and CHOOSECOLS Equivalents in pandas"," — reshaping arrays.",[2184,2319,2320,2324],{},[35,2321,2323],{"href":2322},"\u002Fautomating-reporting-workflows\u002Ftesting-and-packaging-excel-automation-scripts\u002Fgenerate-realistic-test-data-for-excel-reports-with-faker\u002F","Generate Realistic Test Data for Excel Reports with Faker"," — seeded random data at scale.",[2326,2327,2328],"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 .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":51,"searchDepth":130,"depth":130,"links":2330},[2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341],{"id":43,"depth":130,"text":44},{"id":89,"depth":130,"text":90},{"id":280,"depth":130,"text":281},{"id":1107,"depth":130,"text":1108},{"id":1371,"depth":130,"text":1372},{"id":1732,"depth":130,"text":1733},{"id":2156,"depth":130,"text":2157},{"id":2178,"depth":130,"text":2179},{"id":2232,"depth":130,"text":2233},{"id":2266,"depth":130,"text":2267},{"id":2294,"depth":130,"text":2295},"2026-10-02","Generate the number grids, date series, random numbers and shuffled lists that Excel's SEQUENCE, RANDARRAY, RANDBETWEEN and SORTBY formulas produce, with NumPy and pandas: row-major sequences with start and step, monthly and business-day date series, seeded random arrays that are reproducible unlike Excel's, random samples without repeats, and writing the results to a sheet as values.","md",[2346,2348,2350,2352],{"q":2272,"a":2347},"Use NumPy: start + step * np.arange(rows * cols).reshape(rows, cols). It fills the grid row by row, as SEQUENCE does.",{"q":2278,"a":2349},"Use pandas date_range, for example date_range(\"2026-01-01\", periods=12, freq=\"MS\") for month starts or bdate_range for business days.",{"q":2284,"a":2351},"numpy's default_rng().integers(low, high, endpoint=True), which includes both ends of the range like RANDBETWEEN.",{"q":2290,"a":2353},"Use DataFrame.sample(n=5, random_state=seed), which draws rows without replacement and is reproducible with the same seed.","sequence and randarray equivalents in python",null,{"breadcrumb":2357},[2358,2361,2364],{"name":2359,"item":2360},"Home","\u002F",{"name":2362,"item":2363},"Advanced Data Transformation and Cleaning for Excel Automation","\u002Fadvanced-data-transformation-and-cleaning\u002F",{"name":38,"item":37},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsequence-and-randarray-equivalents-in-python",{"title":2367,"description":2368},"SEQUENCE and RANDARRAY Equivalents in Python (NumPy, pandas)","Replace Excel SEQUENCE, RANDARRAY, RANDBETWEEN and SORTBY(…RANDARRAY) with numpy arange\u002Freshape, pandas date_range and seeded numpy Generators, including samples without repeats, verified against spreadsheet results.","sequence-and-randarray-equivalents-in-python","advanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsequence-and-randarray-equivalents-in-python\u002Findex",[2372],"formula-equivalents","how-to","7bGwR_VXXst5uVey5f0CkPJ3wBf3MpC6zQdUvL3j-i0",[2376,2380],{"title":2377,"path":2378,"stem":2379,"children":-1},"SCAN, REDUCE, MAP and BYROW Equivalents in pandas","\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fscan-reduce-and-map-equivalents-in-pandas","advanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fscan-reduce-and-map-equivalents-in-pandas\u002Findex",{"title":2381,"path":2382,"stem":2383,"children":-1},"SLN, DB and DDB Depreciation Functions in Python","\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsln-db-and-ddb-depreciation-functions-in-python","advanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsln-db-and-ddb-depreciation-functions-in-python\u002Findex",[2385,2387],{"path":2386,"title":38},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas",{"path":2388,"title":2362},"\u002Fadvanced-data-transformation-and-cleaning",[],[2391,2394,2397,2400,2403,2406],{"path":2392,"title":2393,"kind":2373},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmerging-and-joining-excel-dataframes\u002Fvlookup-equivalent-in-pandas-for-excel-files","The VLOOKUP Equivalent in pandas for Excel Files",{"path":2395,"title":2396,"kind":2373},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fextract-numbers-and-codes-from-text-with-pandas","Extract Numbers and Codes from Text with pandas",{"path":2398,"title":2399,"kind":2373},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fsplit-full-names-into-first-and-last-names-with-pandas","Split Full Names into First and Last Names with pandas",{"path":2401,"title":2402,"kind":2373},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fbin-values-into-ranges-with-pandas-cut","Bin Values into Ranges Like Excel FREQUENCY with pd.cut",{"path":2404,"title":2405,"kind":2373},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fcalculate-percent-of-total-per-group-in-pandas","Calculate Percent of Total per Group in pandas",{"path":2407,"title":2408,"kind":2373},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fcount-distinct-values-per-group-in-pandas","Count Distinct Values per Group in pandas",1790972088581]