更新于 2026-07 · 作者:汪斌(老汪),制造业财务实战 · Excel BI(Power Query / Power Pivot / CUBE)
系列:Excel BI 财务建模实战课讲义(第二阶段)· Power Query / M 语言 · List
SEO focus:List.Generate
SEO 关键词:List.Generate,Power Query,M语言,循环构建表,Table.ToRecords,List.Combine,List.Range,工资条,财务BP,Excel BI
直接答案(TL;DR)
List.Generate 用「初始值 → 条件 → 下一步 →(可选)取值」循环造列表。财务BP用它两件事:把「一行表头 + 多行人员」拆成一人一页工资条;把「每产品连着 N 行工序」按步长切片,再筛平均达标的产品。
学完 EP029 能独立完成哪三件事?
- 写倒序序列(如 10→1),并知道正序优先
{1..10},别硬 Generate。 - 用 Generate 第四参数把「下标」映射成「表头记录 + 当前人记录」,再 Combine 成工资条。
- 用 Generate 步长 3 +
List.Range切三工序块,再用List.Select+List.Average筛达标产品。
List.Generate 四个参数分别干什么?
| 参数 | 角色 | 例子(倒序 10→1) |
|---|---|---|
| 1 初始值 | 循环从哪开始 | () => 10 |
| 2 条件 | 什么时候继续 | each _ > 0 |
| 3 下一步 | 状态怎么变 | each _ - 1 |
| 4 取值(可选) | 这一步真正往列表里塞什么 | 省略则塞状态本身 |
空白查询可直接验证:
List.Generate(
() => 10,
each _ > 0,
each _ - 1
)
期望返回:{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}。
正序 1→10 也能 Generate,但更简单:
{1..10}
原则:能用字面量 / List.Numbers 解决的,不要上 Generate;Generate 留给「步长不规则、或每一步要组装复杂结构」的场景。
案例一:华凯精工 · 车间计件工资条怎么拆?
场景:人事把「表头一行 + 多人一行」宽表导出给财务BP。车间主任要的是一人一页确认条:每页先看字段名,再看该人数字。
教学源表(导入后先「使用第一行作为标题」的反操作——降级标题,让表头也变成数据行):
| Column1 | Column2 | Column3 | Column4 |
|---|---|---|---|
| 姓名 | 基本工资 | 计件工资 | 补贴 |
| 张工 | 4200 | 1800 | 300 |
| 李工 | 4000 | 2100 | 200 |
| 王工 | 3800 | 1500 | 250 |
步骤 0:导入,删「更改的类型」(可选)
方便公式锚定步骤名。
步骤 1:降标题 + 行转记录
行转记录 = Table.ToRecords(Table.DemoteHeaders(源))
此时 行转记录{0} = 表头那一行记录;行转记录{1} = 张工;{2} = 李工;{3} = 王工。共 4 条。
步骤 2:Generate 下标,跳过第 0 行
只要「人」的下标:1、2、3。
人员下标 = List.Generate(
() => 1,
each _ < List.Count(行转记录),
each _ + 1
)
期望:{1, 2, 3}。
步骤 3:第四参数——每一步拼「表头 + 当前人」
工资条块 = List.Generate(
() => 1,
each _ < List.Count(行转记录),
each _ + 1,
each { 行转记录{0}, 行转记录{_} }
)
每一步得到一个含两条记录的列表:{表头, 张工} / {表头, 李工} / {表头, 王工}。
若要页间空行,可写成:
each { 行转记录{0}, 行转记录{_}, null }
(预览可能报错显示,加载到工作表后多为空行,属预期。)
步骤 4:合并 → 记录转表 → 提升标题
合并 = List.Combine(工资条块),
成表 = Table.FromRecords(List.Select(合并, each _ <> null)),
结果 = Table.PromoteHeaders(成表)
得到:张工页(表头+数据)、李工页、王工页依次堆叠——这就是「工资条」结构。
案例二:产品 × 三道工序,如何筛平均产量达标?
场景:MES 导出一维长表,每个产品固定三行(下料 / 机加 / 装配)。经营会只要「三工序平均产量 ≥ 85」的产品清单。
| 产品编码 | 工序 | 产量 |
|---|---|---|
| P-A | 下料 | 98 |
| P-A | 机加 | 95 |
| P-A | 装配 | 90 |
| P-B | 下料 | 70 |
| P-B | 机加 | 72 |
| P-B | 装配 | 68 |
| P-C | 下料 | 88 |
| P-C | 机加 | 90 |
| P-C | 装配 | 86 |
| P-D | 下料 | 92 |
| P-D | 机加 | 80 |
| P-D | 装配 | 78 |
手算平均:P-A 94.33、P-B 70、P-C 88、P-D 83.33 → 达标应剩 P-A、P-C。
步骤 1:行转记录(本案例不降标题)
行转记录 = Table.ToRecords(源)
12 条记录;下标 0–2 = P-A,3–5 = P-B,6–8 = P-C,9–11 = P-D。
步骤 2:Generate 步长 3 + Range 切片
按产品切块 = List.Generate(
() => 0,
each _ < List.Count(行转记录),
each _ + 3,
each List.Range(行转记录, _, 3)
)
得到 4 个「各含 3 条记录」的子列表。
步骤 3:Select 平均产量 ≥ 85
达标块 = List.Select(
按产品切块,
each List.Average({ _{0}[产量], _{1}[产量], _{2}[产量] }) >= 85
)
步骤 4:Combine → FromRecords
合并 = List.Combine(达标块),
结果 = Table.FromRecords(合并)
期望:只剩 P-A、P-C 共 6 行。改源表产量后刷新,名单跟着变——这是 Generate 切片的价值。
实务提醒:若只是「先算平均再筛选」,透视表 / 分组更直观。本课重点是练 Generate + Range 步长思维;上会报表选更简单的路即可。
和 List.Numbers / {1..n} / List.Range 怎么选?
| 需求 | 更合适 |
|---|---|
| 连续正序整数 | {1..n} / List.Numbers |
| 从已有列表按起点+长度取一段 | List.Range(EP027) |
| 倒序、不规则步长、每步组装结构 | List.Generate(本课) |
| 按条件留下元素 | List.Select(EP028) |
操作自检:案例与公式能否一一对上?
自检结论(2026-07-23):PASS。
| 演示 | 输入 | 期望输出 |
|---|---|---|
| 倒序 Generate | 10,_ > 0,_ - 1 |
{10..1} |
| 人员下标 | Count=4,从 1 起 | {1,2,3} |
| P-A 平均产量 | 98,95,90 | 94.33 ≥85 → 保留 |
| P-B 平均产量 | 70,72,68 | 70 → 剔除 |
| P-C 平均产量 | 88,90,86 | 88 ≥85 → 保留 |
| P-D 平均产量 | 92,80,78 | 83.33 → 剔除 |
| 达标结果产品 | — | P-A、P-C |
上会前财务BP要自检哪三项?
- Generate 的「停止条件」是否用
< List.Count(...),避免越界或少取一行。 - 步长是否等于「每个对象固定行数」(三工序 → +3;若有四行成本要素 → +4)。
- 工资条场景是否永远钉住
行转记录{0}当表头,人员下标从 1 起。
读者常问 AI 的问题有哪些?(FAQ)
List.Generate 和 for 循环是一回事吗?
语义接近「带状态的循环」,但是函数式:你声明初始/条件/下一步,引擎生成列表,没有过程式 for 写法。
第四参数什么时候必须写?
当你循环的「状态」(如下标 1,2,3)本身不是最终要的值,而要映射成记录块、Range 切片时——本课两个案例都必须写。
为什么工资条一定要降标题?
因为表头也要变成「可被下标引用的记录」。不降标题时,字段名在列名里,拼不出「表头行 + 数据行」成对结构。
空行用 null 后预览报错正常吗?
常见。加载到工作表后多为空白行。正式上会前可在 FromRecords 前 List.Select(..., each _ <> null) 或接受空行展示。
和 EP027 List.Range、EP028 Select/Skip 什么关系?
Generate 负责「造下标 / 造块」;Range 负责「按起点取一段」;Select/Skip 负责筛和丢。本课把三者串成一条生产链。
本课公式速查表在哪里?
// 倒序
List.Generate(() => 10, each _ > 0, each _ - 1)
// 工资条:下标 + 表头配对
List.Generate(
() => 1,
each _ < List.Count(行转记录),
each _ + 1,
each { 行转记录{0}, 行转记录{_} }
)
// 三工序切块
List.Generate(
() => 0,
each _ < List.Count(行转记录),
each _ + 3,
each List.Range(行转记录, _, 3)
)
// 筛平均达标
List.Select(按产品切块, each List.Average({_{0}[产量], _{1}[产量], _{2}[产量]}) >= 85)
文末
我是汪斌(老汪),长期做制造业成本、业财与 Excel BI 建模。本篇是陪跑课讲义 EP029:把 List.Generate 落到工资条拆页与「固定行数切片筛选」。
继续学:打通数据全链路闭环

不只录播课,更是手把手带做实操。长按识别海报二维码咨询,或微信备注「Excel BI」。










暂无评论内容