做培训评估的那阵子,我每周都要造一批模拟数据:随机日期、随机评分等级、随机抽人做演练。一开始我老老实实用在线随机数网站,生成一批、复制、粘贴,重复到吐。后来被同事点醒——Excel 里就有现成的整数随机生成器 RANDBETWEEN,两个参数,闭区间返回整数,配合 DATE、CHOOSE、INDEX 这些函数,能直接把日期、评级、编号、时间点、分组结果一次性铺满整张表。RANDBETWEEN 这个东西看起来简单到不值一提,但它有几个特别容易被忽略的脾性:它是易失性函数,整张表随便动一下它就全跳;它只吃整数,日期和时间得先换算成序列号;它没法设种子,同一批随机数你复现不了。这篇文章我把这几年在数据模拟、抽奖、排班、抽样核对里攒下来的用法和坑一次性摊开,从最基础的区间取数讲到加权随机、偏态分布、不重复抽取,适合刚接触 Excel 函数的新手,也适合天天和数据打交道的老人对照着查漏。
1. 先把 RANDBETWEEN 的脾气摸清楚
1.1 两个参数、一个闭区间,返回值到底怎么算
RANDBETWEEN 的语法只有两个参数:=RANDBETWEEN(bottom, top),bottom 是区间下限,top 是区间上限,返回的是这两个数之间(含两端)的一个整数。注意“含两端”这三个字,很多人默认它像编程语言里的 random 一样是左闭右开,结果做概率统计的时候算错。举个具体的:=RANDBETWEEN(1,6)返回 1、2、3、4、5、6 六个数,每个数出现的概率是 1/6,这个可以直接当骰子用;如果你要模拟 0 到 99 的两位编号,就得写=RANDBETWEEN(0,99),写=RANDBETWEEN(0,100)就多出一个 100。
参数顺序不能反。=RANDBETWEEN(10,1)不会自动帮你换过来,Excel 直接甩一个#NUM!错误给你。这一点和某些函数不一样,比如 RAND 没有参数,你写成什么样它都不管;RANDBETWEEN 对参数是较真的。实际填表的时候我一般会把上下限写到两个单元格里,公式引用单元格,这样改范围不用去动公式本身,也方便后面做批量填充。
还有一个细节:官方文档写的是“如果 bottom 或 top 不是整数,则会被截断”。也就是说=RANDBETWEEN(1.9, 5.9)实际等价于=RANDBETWEEN(1, 5)。我自己不太依赖这个行为,因为不同版本、不同场景下的截断处理容易让人误判,尤其是参数来自其他公式计算结果时,你很难一眼看出它到底是 1.9 还是 2.0。稳妥的做法是显式套一层 INT 或者 ROUND,把意图写明白:=RANDBETWEEN(INT(A1), INT(B1))。这样别人接手你的表,扫一眼就知道你在干什么。
参数可以是负数,=RANDBETWEEN(-10,10)返回 -10 到 10 之间的整数,做温度波动模拟、涨跌幅模拟都很顺手。参数的绝对值大小倒没什么限制,=RANDBETWEEN(1,1000000000)也能跑,只是这种大范围的值拿去当编号还行,当业务数据基本没法用。
1.2 易失性函数:为什么你填完一格整张表都在跳
这是 RANDBETWEEN 最招人烦也最容易被误解的地方。它和 RAND、NOW、TODAY 一样属于易失性函数(volatile function),含义是:只要工作簿发生任何一次重算,它就会重新取一个值。而“重算”这件事在 Excel 里发生得比你想的频繁得多——你改任何一个单元格、插入一行、删一列、切换工作表、甚至只是双击某个单元格再按回车,都可能触发整张表重算。
所以经常出现这种场面:你在 A 列铺了 500 行随机日期,准备按日期排序,结果鼠标刚点排序按钮,A 列的数字全变了,排出来的顺序和你刚才看到的不一样。这不是 bug,是它的设计行为。理解这一点之后,处理思路就很清楚了:先算完,再固化,最后再做排序、筛选、透视这类会触发重算的操作。固化方法我在第 3 章详细讲。
还有一个连带影响是性能。假设你有一张两万行的表,每行三个 RANDBETWEEN,加起来六万个易失性单元格,那你每敲一次回车,Excel 就要重算六万次。机械硬盘时代的机器能卡到你以为软件崩了,SSD 上也明显有延迟感。我吃过一次亏:给某公司做一份模拟考勤数据,整列铺了随机打卡时间,边填边卡,最后是把计算模式切成手动才把活干完的。路径在“公式”选项卡 →“计算选项”→“手动”,干完活再切回自动,别忘了切回来。
1.3 RAND、RANDBETWEEN、RANDARRAY 该怎么分工
三个函数经常被混着用,其实各自的位置很清楚,选错了会让后面的处理变得别扭。
| 函数 | 返回类型 | 区间控制 | 典型用途 |
|---|---|---|---|
| RAND | 0 到 1 之间的小数(不含 1) | 只能靠乘加缩放 | 需要连续均匀分布、做排序键打乱顺序 |
| RANDBETWEEN | 指定区间内的整数 | 直接指定上下限 | 评级、编号、日期、时间、骰子类场景 |
| RANDARRAY | 数组形式的小数或整数 | 行列数、上下限、是否取整都可指定 | 一次性铺开一片随机区域,Office 365 才有 |
RAND 的最大特点是连续,它不会像 RANDBETWEEN 那样把值卡在整数上。所以凡是“我要打乱顺序”的需求,我基本都用 RAND 而不� RANDBETWEEN——因为 RAND 出现重复值的概率极低,而 RANDBETWEEN(1,100) 在一百多行里必然撞车。给员工名单加一列=RAND(),然后按这列排序,名单就彻底打乱了,这是最经典的做法。
RANDARRAY 是后来的东西,只有在支持动态数组的版本里才能用。它的好处是一次就能生成一片,比如=RANDARRAY(10,3,1,100,TRUE)直接给你 10 行 3 列、1 到 100 的整数,不用往下拖公式。坏处是它同样易失,而且一旦你的文件要给用旧版本的人打开,整个公式会挂掉。所以对外交付的文件,我一般还是老老实实写 RANDBETWEEN,兼容性优先。
2. 从日期到评级:四个高频场景的落地写法
2.1 随机日期:把日期当成序列号来算
新手最容易卡住的地方就是想“随机生成一个 3 月”这种思路,结果写出=RANDBETWEEN(1,31)当日期用,遇到 2 月直接爆炸,遇到 4 月也会冒出 31 号。正确的思路是:Excel 里的日期本质就是一个整数序列号,1900 年 1 月 1 日对应 1,往后每过一天加 1。2024 年 1 月 1 日对应 45292,2025 年 1 月 1 日对应 45658。既然日期就是整数,那 RANDBETWEEN 天生就能干这活,你只需要把上下限用 DATE 函数包起来:
=RANDBETWEEN(DATE(2024,1,1), DATE(2024,12,31))公式本身没问题,但直接回车你会发现单元格显示的是一串四五位的数字,比如 45567。这不是算错了,是单元格格式还停在“常规”。选中这一列,右键设置单元格格式,选“日期”,挑一个yyyy-mm-dd的样式,瞬间就正常了。这一步我见过太多人以为是公式写错,反复删了重写,其实是格式问题。
如果你不想改格式,也可以用 TEXT 函数把结果直接转成文本型的日期:
=TEXT(RANDBETWEEN(DATE(2024,1,1),DATE(2024,12,31)),"yyyy-mm-dd")代价是它变成文本了,没法再参与日期计算,也没法用日期筛选器。所以我的习惯是:要参与后续运算的用第一种,纯展示的用第二种。
跨年、跨月、跨季度的随机日期,思路完全一样,只是把 DATE 的边界换掉。比如要生成 2024 年第一季度的随机日期,下限DATE(2024,1,1),上限DATE(2024,3,31)。要生成近三年的随机日期,用DATE(YEAR(TODAY())-3,MONTH(TODAY()),DAY(TODAY()))当起点,TODAY()当终点。这样每次打开文件,范围都自动跟着当天走,做滚动期的模拟数据特别省事。
如果只要工作日,不要周末,就得多绕一步。RANDBETWEEN 本身不认识“工作日”这个概念,它只会在序列号上均匀取整。我的做法是先算出这段时间一共有多少个工作日,然后在这个数量范围内取随机序号,再用 WORKDAY 偏移过去:
=WORKDAY(DATE(2024,1,1)-1, RANDBETWEEN(1, NETWORKDAYS(DATE(2024,1,1),DATE(2024,12,31))))注意DATE(2024,1,1)-1这个减一,它的意思是“从起始日的前一天开始偏移”。WORKDAY 的第二个参数是偏移的工作日天数,如果你从 1 月 1 日当天开始偏移 1 天,结果会是 1 月 2 日,1 月 1 日就永远抽不到。这种差一天的细节,做排班表的时候是致命的,我第一次写就漏了,导致新年第一天的班次永远是空的,排查了半小时才反应过来。
2.2 随机评级:CHOOSE、INDEX 与权重的取舍
评级类的需求在考核、调研、评分模拟里太常见了:给一批模拟数据随机打上 A/B/C/D 四档,或者随机生成“优秀/良好/合格/待改进”。最直接的写法是用 CHOOSE 做映射:
=CHOOSE(RANDBETWEEN(1,4),"A","B","C","D")RANDBETWEEN 先摇出一个 1 到 4 的序号,CHOOSE 按序号去取对应的文本。这个组合的好处是一眼看懂,改档位只要改 CHOOSE 后面的参数,不用动结构。缺点是档位多了以后公式会很长,十几个等级写进去,编辑栏里根本看不清楚,改起来容易漏。
档位多的时候我改用 INDEX 配合区域引用。把档位清单放在一列里,比如 F2:F9 是八个等级,公式写成:
=INDEX($F$2:$F$9, RANDBETWEEN(1,8))这样档位清单可以随时增删改,公式不用动。要注意区域锁定(美元符号),否则往下填充的时候引用范围会跟着往下跑,越填越偏,最后一行引用到空白区,返回#REF!。这个坑我在给别人改表的时候见过无数次,本质是相对引用和绝对引用没分清。
还有一个更灵活的写法,适合档位本身还带权重的情况,比如“优秀”只占 10%、“良好”占 30%、“合格”占 50%、“待改进”占 10%。这时候不能直接 RANDBETWEEN(1,4),因为那样四档概率相同。正确的做法是造一个累积权重区间,这个我在第 4 章展开讲。
顺便提一个容易忽略的细节:CHOOSE 和 INDEX 返回的都是文本,如果后面要做排序或者筛选,中文的排序规则是按拼音还是按笔画,取决于你的排序设置,有时候“优秀”排在“合格”前面,有时候反过来,看着很迷惑。真要做等级排序,我一般会额外加一列数字权重(A=4、B=3……),按数字排,比跟中文较劲省心。
2.3 随机抽人与不重复抽取的三条路
“从 50 个人里随机抽 5 个”,这需求看着简单,做起来有好几条路,各有各的适用条件。
第一条路是辅助列排序法。在名单旁边加一列=RAND(),然后选中整个区域按这列升序排,取前 5 行。优点是不用动脑子,缺点是抽完这 5 个人之后,如果还想抽第二批,得重新排一遍,而且前后两批可能重复。适合一次性抽奖、一次性抽样这种”抽完就完“的场景。
第二条路是硬摇加校验。用=RANDBETWEEN(1,50)摇号码,摇完用条件格式或者 COUNTIF 检查有没有重复,重复了就按 F9 重摇,直到凑齐 5 个不重复的。这个方法在小样本、大范围的时候挺快,比如从 1 到 100 里抽 10 个不同的,重复一两次就能凑齐。但从 1 到 10 里抽 9 个不同的,你会发现抽到天荒地老也凑不齐——这属于生日问题的直观体感,范围越接近样本量,撞车概率越恐怖。
第三条路是用动态数组一次性搞定,适合 Office 365:
=TAKE(SORTBY(SEQUENCE(50), RANDARRAY(50)), 5)SEQUENCE 生成 1 到 50 的序号,SORTBY 用随机数组把这 50 个序号打乱,TAKE 取前 5 个。整个过程一次成型,按 F9 换一批,而且天然不重复。如果你还要把号码映射回人名,外面套一层 INDEX 就行:=INDEX($A$2:$A$51, TAKE(...))。
三条路怎么选,我的判断标准是:一次性、无重复要求,用第一条;样本小、范围大、想手动控制节奏,用第二条;要批量、要多批、环境支持新函数,用第三条。给别人做模板的话,第一条最保险,因为它不依赖版本。
2.4 随机时间、随机分组与随机排班
随机时间是日期的近亲,原理也一样:Excel 里一天是 1,一小时是 1/24,一分钟是 1/1440。所以随机生成 9:00 到 18:00 之间的打卡时间,可以这么写:
=RANDBETWEEN(9*60, 18*60)/1440960 是 540 分钟,1860 是 1080 分钟,摇出分钟数再除以 1440 换算成天的小数部分,单元格格式设成hh:mm就完事。精确到秒就把 60 换成 3600,除以 86400。这样生成的时间点分布是均匀的,做模拟打卡记录完全够用。但要注意一个业务陷阱:真实的打卡时间不是均匀分布,早晚高峰会有聚集。如果你要做看起来“像真的”数据,纯均匀分布反而假,得用第 4 章讲的偏态做法。
随机分组也很常用。给一列名单每人摇一个 1 到 4 的组号,=RANDBETWEEN(1,4),然后按组号排序,一张表就分成四组了。问题是这样分出来的组人数不均匀,可能一组 15 人一组 8 人。要人数均等,思路是先打乱顺序再按位置切:
=ROUNDUP(ROW(A1)/3, 0)这行的意思是每 3 个人一组,第 1 到 3 行是 1 组,第 4 到 6 行是 2 组,依次往下。配合前面用 RAND 打乱的顺序,就得到了人数基本相等的随机分组。这个写法比直接摇组号稳定得多,做团建分组、实验对照分组我都用这套。
随机排班稍微复杂一点,因为要避开周末和已排的班次。我的做法是先用 WORKDAY 生成一个可选日期池(一列放所有工作日),再用 INDEX 加 RANDBETWEEN 从池子里取:
=INDEX($D$2:$D$262, RANDBETWEEN(1, COUNTA($D$2:$D$262)))这样取出来的日期一定落在工作日里,不会出现周六排班的笑话。至于“同一个人不能连排两天”这类约束,单靠公式很难保证,我的经验是公式负责生成初稿,人工或者条件格式标红负责兜底,别指望一个公式把所有业务规则都吃掉。
3. 让随机数“定”下来:固化与快照的几种手法
3.1 选择性粘贴为值:最笨但最稳
所有固化手段里,选择性粘贴为值是唯一一个 100% 可靠、且不挑版本的办法。操作就三步:选中整片随机数区域,Ctrl+C,然后右键 →“选择性粘贴”→ 选“值”,或者用快捷键Ctrl+Alt+V再按 V 回车。粘完之后,易失性公式全部变成了静态数字,再怎么重算、排序、筛选,它都不会动了。
这个动作看起来土,但它是所有正式交付文件的必经步骤。我给别的部门做过一份模拟销售数据,当时偷懒没转值,结果对方拿去开会演示,领导随手点了个排序,整片数据全变,会上尴尬得不行。从那以后我养成了习惯:只要这批随机数据要给别人看,先转值再说,哪怕自己后面还要改,也可以留一列原始公式在旁边备用。
转值之前有两个提醒。第一,如果不是整列转,而是要保留部分公式,务必确认选区没有选偏,粘错位置的话原始公式就没了,撤销不一定救得回来(尤其是文件保存过之后)。第二,转值会让数据失去可追溯性,别人问“这个数字怎么来的”,你只能说“随机生成的”,所以正式场合我会在表头加一句说明,写清楚这是模拟数据、生成日期、取值范围,避免后续被误当成真实数据引用。
3.2 F9 系列重算键的正确用法
F9 是 Excel 里的重算触发键,但它的三个变体差别很大,很多人只用了最粗的那个。
F9单独按,重算整个工作簿里所有需要重算的内容,包括所有工作表的易失性函数。这是最常用的“换一批随机数”。
Shift+F9只重算当前工作表,其他表不动。这个在你有多个 sheet 各自有随机数据的时候特别有用,可以只换当前这一页,不影响别的页已经定好的结果。
Ctrl+Alt+F9是强制全量重算,连那些 Excel 认为“不需要重算”的缓存也会一起清掉。什么时候用?当你发现公式明明引用的单元格改了,但结果死活不更新的时候,按一下这个,多半能救回来。这种情况通常发生在大型工作簿、跨表引用、或者用了大量易失性函数之后,Excel 为了性能偷了懒。
还有一个技巧是在编辑栏里预览:选中一个含 RANDBETWEEN 的单元格,点进编辑栏,选中整个公式,按 F9,公式会临时变成一个具体数值。这一步只是预览,按 Esc 就恢复公式;如果想让这个数值彻底定下来,按回车确认,公式会被结果替换掉——但这个操作我一般不用,因为一旦替换,你就再也拿不回公式了,而且多单元格区域操作起来容易出错。相比之下,选择性粘贴为值可控得多。
3.3 用辅助列做可复现的随机快照
有些场景需要“同一批随机数,今天看和明天看必须一样”,比如给学员发的练习题、给测试同事的固定样本。RANDBETWEEN 本身做不到这一点,因为它没有种子参数,你没法告诉 Excel“用 42 这个种子生成”。这时候只能绕开它,用行号造一个确定性的伪随机序列。
最简单的做法是用乘法加取模:
=MOD(ROW(A1)*97+13, 50)+1ROW(A1) 是 1,ROW(A2) 是 2,往下每一行都会得到一个不同的值,而且这个值只跟行号有关,跟计算次数无关,所以你什么时候打开文件,看到的都是同一串数字。97 和 13 这两个数可以随便换,换掉之后整串序列就变了,相当于换了个“种子”。这样生成的序列在 1 到 50 之间循环,分布谈不上均匀,但做练习题、做固定样本完全够用。
如果对分布均匀性有要求,可以叠一层更复杂的线性同余,或者直接用MOD(ROW(A1)*1103515245+12345, 2147483647)这种经典参数。要注意 Excel 只有 15 位有效数字,乘法结果太大时会丢精度,导致序列退化,所以参数别选得太夸张。我在实际使用中就用 97 和 13 这种朴素参数,够稳定,谁都能看懂。
这种确定性序列的另一个好处是可审计。别人拿到文件,可以按行号复算出同一个值,不需要你再附一份原始数据。做内部培训材料、做演示模板,我都倾向于用这一套,而不是直接铺 RANDBETWEEN。
4. 参数设计的进阶:加权、偏态与边界防御
4.1 加权随机:用累积权重把概率掰弯
前面说过,=RANDBETWEEN(1,4)生成四个等级,每档概率都是 25%。但真实的业务分布从来不是均匀的:优秀的人少,合格的人多,如果模拟数据里四档各占四分之一,一眼就假。要做出真实感,就得给每档配上权重。
标准做法是三步。第一步,把选项和权重列成一张小表,A 列是等级,B 列是权重(用整数,比如优秀 10、良好 30、合格 50、待改进 10)。第二步,C 列算累积权重:C2 是=B2,C3 是=C2+B3,一路往下,最后一行累积值等于总权重 100。第三步,用 RANDBETWEEN 摇一个 1 到总权重的整数,再用 MATCH 的近似匹配去找它落在哪个区间:
=INDEX($A$2:$A$5, MATCH(RANDBETWEEN(1,$C$5), $C$2:$C$5, 1))MATCH(..., 1)返回的是“小于等于查找值的最后一个位置”,这正是累积区间需要的逻辑。摇到 1 到 10 落在第一档(优秀),11 到 40 落在第二档(良好,累积 40),41 到 90 落在第三档(合格),91 到 100 落在第四档(待改进)。概率分布就是 10%、30%、50%、10%,和设定完全一致。
这里有个容易被忽略的坑:RANDBETWEEN 只能出整数,权重也必须是整数。如果你的权重写成 0.1、0.3、0.5、0.1 这种小数,累积之后变成 0.1、0.4、0.9、1.0,RANDBETWEEN(1, 1) 永远只能返回 1,然后 MATCH 永远匹配到第一档,结果全变成优秀,而且你还看不出来是哪里错了。解决办法是把权重整体放大 100 倍变成整数,或者干脆改用 RAND:
=INDEX($A$2:$A$5, MATCH(RAND()*$C$5, $C$2:$C$5, 1))RAND 返回连续小数,乘以总权重之后是连续的,能精确对应任何精度的权重,不受整数限制。代价是 RAND 同样易失,同样要转值。这两种写法我都在用:权重能凑成整数用 RANDBETWEEN,图个直观;权重必须精确到小数用 RAND,图个准确。
4.2 造出“像真的”的偏态分布
均匀分布的数据有个明显的破绽:数值在整个区间里铺得太平了。真实的业务数据几乎都是中间多、两头少,比如考试成绩集中在 70 到 85 分,90 分以上和 60 分以下都稀稀拉拉。要模拟出这种钟形感,不需要什么复杂函数,用最朴素的办法就行——几个均匀分布加起来。
=(RANDBETWEEN(1,100)+RANDBETWEEN(1,100)+RANDBETWEEN(1,100))/3三个 1 到 100 的均匀随机数取平均,结果的分布会向 50 附近聚集,最大值和最小值的出现频率大幅降低。虽然和真正的正态分布不完全一样,但用来做模拟数据已经绰绰有余,肉眼根本分辨不出来。加的次数越多,分布越尖,三个是常用的平衡点。
如果还要再省事一点,可以配合 ROUND 控制小数位,做成绩的话保留一位小数就够了:
=ROUND((RANDBETWEEN(1,100)+RANDBETWEEN(1,100)+RANDBETWEEN(1,100))/3, 1)这个技巧的应用范围比想象中广。做模拟销量、模拟响应时长、模拟年龄分布,只要是需要“自然感”的场合都能用。反过来,如果你要模拟的是完全随机的东西,比如抽奖号码、验证码数字,那就必须用单次 RANDBETWEEN,叠了平均反而失去随机性。
还有一种偏态是“截断”,比如成绩只可能落在 60 到 100 之间,不能低于 60。这时别指望 RANDBETWEEN 自己约束,直接改上下限就行:=RANDBETWEEN(60,100)。如果数据是别处算出来的,用 MAX 和 MIN 夹一下:=MAX(60, MIN(100, 原公式)),把越界的值强行拉回区间内。
4.3 边界、取整与非法输入的防御写法
RANDBETWEEN 的报错不多,但每种都挺常见。上下限反过来是#NUM!;参数引用了空单元格,Excel 会把空单元格当 0 处理,于是=RANDBETWEEN(A1, B1)变成=RANDBETWEEN(0, 0),结果永远是 0,不报错但结果全错,这种“静默错误”比报错更难查;参数是文本,会返回#VALUE!。
做模板的时候我会在公式外面包一层防御:
=IF(OR(A1="", B1="", A1>B1), "参数待检查", RANDBETWEEN(A1,B1))这样哪一格没填、哪一格填反了,一眼就能看出来,不会被一堆 0 或者错误码淹没。给别人用的模板,我强烈建议加这一层,事后省下的沟通成本远超写公式的时间。
另外,不要把 RANDBETWEEN 和“数据验证”混为一谈。数据验证是用来限制用户输入的,它管不了公式生成的值。我见过有人想用数据验证来约束随机数的范围,结果发现随机数该越界还是越界,因为数据验证只在你手动输入时生效,公式结果它不管。要约束随机数,只能在公式的上下限上做文章。
5. 常见问题与排查实录
5.1 现象速查表
下面这张表是我这两年攒下来的高频故障,遇到问题可以先扫一眼,很多时候能省掉半小时排查。
| 现象 | 最可能的原因 | 处理办法 |
|---|---|---|
| 返回一串四、五位的数字而不是日期 | 单元格格式还是常规 | 右键设置单元格格式,选日期类型 |
公式返回#NUM! | 上下限写反,或其中一个是负数区间 | 检查 bottom 是否小于等于 top |
| 结果永远是 0 | 参数引用了空单元格 | 用 IF 判断参数是否为空 |
| 整片数据在排序时全变 | 易失性函数被重算触发 | 先转值,再做排序筛选 |
| 抽出来的号码大量重复 | 范围接近样本量,生日问题 | 改用 RAND 辅助列排序法 |
| 文件打开后计算结果全部刷新 | 易失性函数的默认行为 | 计算选项设为手动,或提前转值 |
| 公式明明改了结果不更新 | 计算链路缓存 | 按Ctrl+Alt+F9强制全量重算 |
| 加权随机结果全落第一档 | 权重用了小数,RANDBETWEEN 只能取整数 | 权重放大成整数,或改用 RAND |
这张表里最值得单独说的是第四行和最后一行,因为它们都是“看起来没报错,但结果完全错”的类型,比报错更危险。
5.2 重复值、卡顿与重算异常
重复值是最常见的心病。很多人第一次用=RANDBETWEEN(1,10)生成十个号,发现必然有重复,第一反应是函数坏了。其实这跟函数没关系,这就是概率:10 个槽位放 10 个球,至少有一个重复的概率接近 100%,你只是在体验数学。要真正生成不重复的序列,必须走前面讲的三条路之一,靠反复按 F9 硬碰,在范围小的时候是行不通的。
卡顿的问题我在第 1 章提过,这里补充一个更彻底的解法:如果整张表有大量随机数是你最终要转值的,那就干脆别让它自动算。打开“公式”→“计算选项”→“手动”,铺完公式,按一次 F9 看结果满意,立刻全选转值。这一套流程走下来,两万行的表也就几秒钟的事。反过来,如果你忘了切回自动计算,第二天发现所有依赖这些数值的公式都不更新了,会非常抓狂,所以我在文件里会留一个显眼的备注提醒自己。
重算异常还有一种隐蔽的表现:公式引用了其他工作表的随机数,结果每次切换 sheet 都在变。这同样是易失性导致的,跨表引用会触发更频繁的重算。解决办法要么是转值,要么是用Ctrl+Shift+Alt+F9之外的常规刷新控制,别频繁切换。说白了还是那句话,随机的部分越早固化越好。
5.3 我踩过的几个坑
第一个坑是拿 RANDBETWEEN 生成手机号后八位。写起来很简单,=RANDBETWEEN(10000000,99999999),但我当时忘了前三位也得有,结果拼出来的号码长度不对,而且有些以 0 开头的号码会被 Excel 当成数字自动去掉前导零。后来改成全部用 TEXT 补零,=TEXT(RANDBETWEEN(0,99999999),"00000000"),才算稳。这个教训是:涉及编号、工号、卡号这类有格式要求的字段,永远用 TEXT 定长,别指望数字格式能保住前导零。
第二个坑是日期跨月的随机。早期我为了图省事,写成=DATE(2024,1,RANDBETWEEN(1,31))生成 1 月的日期,跑通之后直接复制到 2 月那份,忘了改天数,结果 2 月冒出一堆 2 月 30 日、2 月 31 日,Excel 很老实地把它们顺延到了 3 月 2 日、3 月 3 日,表里就混进了一批“2 月的表里出现 3 月日期”。这个 bug 特别隐蔽,因为不报错、不标红,只有做月度汇总的时候才会发现总数对不上。正确做法始终是对序列号取随机,别去碰“第几天”这个参数。
第三个坑跟排序有关。有一次我把随机数转值之后排序,排完发现序号列乱了。查了半天才想明白:我只转值了随机数那一列,旁边还有人名列是公式引用的,排序时公式的相对引用跟着行号一起变,人名和随机数就对不上了。正确做法是转值之后,把要排序的整个区域一起选中排,或者排序前把所有人名列也转成值。这个坑的本质不是 RANDBETWEEN 的问题,是 Excel 排序和公式引用的经典冲突,但只要你在用随机数配名单,就一定会撞上。
第四个坑是给旧版本用户发文件。我用=RANDARRAY和=SORTBY做的抽奖小工具,在自己机器上跑得好好的,发过去对方打开一片#NAME?。动态数组函数在旧版本里根本不认识,连降级处理都没有。从那以后我给自己定了条规矩:凡是可能外发的文件,只用 RANDBETWEEN、INDEX、CHOOSE 这些老函数,花哨的新函数留给自己的内部分析用。
现在我做任何跟随机相关的表,流程基本固定下来了:先想清楚这是“一次性抽”还是“要复现”,一次性就用 RANDBETWEEN 铺完立刻转值,要复现就用行号造确定性序列;涉及多档位就查权重表,涉及多字段就统一用 TEXT 定长;交付前一定切到手动计算、全选转值、检查一遍有没有残留的易失性公式。这套流程不复杂,但每一条都是被坑过之后才长记性的,尤其是“交付前转值”这一条,它能帮你躲掉绝大部分现场翻车的可能。