当业务表格开始同时记录课程、教师、学员、家庭和缴费状态,困难通常不是“还缺一列”,而是同一条信息已经在很多地方重复出现。Grist 官方的课后活动教程用一个儿童课程机构作例子,展示如何先规划关系,再把关联的表组织成方便日常使用的页面。
本文据 Grist Help Center 的 How to manage business data 全文翻译整理。可以从空白文档手工建立所有表;原文提供的 CSV 和 模板只是节省录入时间的可选路线。下面沿用英文表名与字段名,方便对照公式和界面。
先想清楚两种日常工作
这个机构开设多门课程,每门课由一位教师负责,并容纳多名学员。一个孩子可以报名多门课,也可能下一年继续回来。工作人员一方面需要选中课程,看到已报名的学员和剩余名额;另一方面需要在家长来电时,快速添加、调整或取消孩子的报名。
不必一开始就预见所有功能。先把当前实体和操作场景理顺,后续可以逐步增加家庭资料、付款信息和其他层次。这个过程同时是在设计数据库和搭建应用,不过实际操作仍然围绕表格、公式和视图展开。

建立 Classes 和 Staff:把教师资料从课程中分离
同一位教师可以教授多门课程,因此教师与课程应放在不同的表里。每门课程只需保存指向教师记录的引用,避免在每门课程中反复录入教师姓名和联络资料。
- 创建一个空白 Grist 文档,把最初的
Table1改名为Classes,添加课程需要的列,并录入几门虚构课程。也可以使用原文的 Classes.csv。 - 点击 Add New → Add Empty Table,把新表改名为
Staff,添加教师字段并录入虚构记录。可选样例为 Staff.csv。 - 准备让
Classes中的Instructor列指向Staff。先为教师记录增加一个便于识别的姓名显示列。
用公式生成 Full Name
进入 Staff 页面,通过列菜单或 Alt + = 快捷键添加列,将其命名为 Full Name。在新列任意单元格以等号开始输入公式,公式内容为:
$Last_Name + ", " + $First_Name
也可以使用类似 Excel 的函数写法:
CONCAT($Last_Name, ", ", $First_Name)
Grist 的公式列对整个表中每一行生效,因此不需要逐行拖拽填充。它既支持 Python 表达式,也支持许多使用大写名称的 Excel 风格函数。计算后,每位教师都会显示为“姓, 名”。界面显示名 Full Name 与公式中的标识符可能带下划线,编写公式时应使用 Grist 显示的实际列 ID。
编者说明:原文把完整姓名作为方便识别每条记录的列,但现实中的同名教师或同名学员并不少见。Full Name 是显示标签,不应被当成永不重复的业务主键;引用实际指向 Grist 的记录身份。需要对外对账或去重时,可另设稳定的教师、学员或家庭编号。
把 Instructor 转成 Reference 引用列
- 返回 Classes 页面,打开 Instructor 列的 Column Options。
- 在右侧面板把 Column Type 设置为 Reference,被引用表选择
Staff。 - 在 SHOW COLUMN 中选择刚才的
Full Name。 - 点击 Apply 完成类型转换。若原列为空,可能不需要额外确认。
引用列类似数据库中的外键。现在点击 Instructor 单元格,可以按 Enter 从已有教师中选择,也可以输入部分文字自动补全。这样改动教师资料时,不必逐门课程去维护副本。已有文字转为引用后,应逐条确认匹配结果,尤其注意同名或拼写差异。
建立 Students,并用 Enrollments 保存多对多关系
再创建 Students 表,记录学员姓名、年级等信息;也可以导入 Students.csv。像 Staff 一样添加 Full Name 公式列,方便后续显示和选择。
学员与课程不能简单地放进单一引用列:一个孩子会参加多门课程,一门课程也有很多孩子,还需要保留过去的课程和报名历史。合适的做法是新增 Enrollments 表。它的一条记录表示“某位学员报名某门课程”,这条关联本身还可以保存报名状态、是否缴费等属性。
原文使用三个报名状态:Confirmed(已确认)、Waitlisted(候补)和 Cancelled(已取消)。这张连接表把多对多关系拆为两个一对多关系:一个学员对应多条报名,一门课程也对应多条报名。
- 创建
Enrollments表,或导入可选的 Enrollments.csv。 - 把
Student列设为 Reference,引用Students,SHOW COLUMN 选择Full Name。 - 把
Class列设为 Reference,引用Classes,SHOW COLUMN 选择Class Code。 - 添加状态、付款等需要的列。可以直接在连接表中新增一行,再通过自动补全选择学员和课程。
取消报名时修改状态,可以保留曾经发生的关联与付款历史。直接删除关联行会失去这些信息。至于同一学员是否可重复报同一课程、每期课程怎样区分,应按实际业务另行定义;连接表的存在本身不会自动完成所有去重规则。
建立 Class View:选课程看报名
第一个工作页面围绕课程展开。
- 点击 Add New → Add Page,在组件选择器中选择显示
Classes的 Table,再点击 Add Page;将页面改名为Class View。 - 再点 Add New → Add Widget to Page,选择
Enrollments的 Table;把 SELECT BY 设为 CLASSES,然后 Add to Page。 - 页面现在有两个关联表格。选中一门课程,报名组件只显示这门课对应的报名记录,并包含学员引用及报名状态等信息。
- 继续 Add Widget to Page,为
Classes添加 Card,SELECT BY 仍选择 CLASSES,让选中课程的详细信息更集中。 - 为
Staff添加 Card,SELECT BY 选择 CLASSES • Instructor,即可展示所选课程的教师资料。
卡片右上角三点菜单中的 Widget options 可以打开设置;在右侧 Theme 下选择 Compact,会得到紧凑样式。之后隐藏重复或无关字段,调整组件位置,让课程列表、课程详情、教师卡片和报名表各自负责清晰的任务。
建立 Enrollment View:选学员办理报名
第二个页面从学员出发。点击 Add New → Add Page,选择 Students 表格并把页面命名为 Enrollment View。然后 Add Widget to Page,添加 Enrollments 表格,将 SELECT BY 设置为 STUDENTS。
点击左侧某位学员,右侧就会显示其全部报名。在这个已关联的报名组件底部空白行中输入课程代码,便能新增报名;Student 会按当前关联选择自动带入,Class 引用列继续提供自动补全。因此 Student 列可以在此组件隐藏,避免重复显示当前已经选中的姓名。
如果希望在报名表里同时看到上课时间,打开 Class 列的 Column Options,点击侧边栏的 + Add Column,选择课程中的字段。原文以 Times 为例,生成的实际上是引用取值公式:
$Class.Times
课程资料因此仍保留在 Classes 中;报名组件只是按关联读取相应值,没有手动复制一份需要单独维护的时间信息。
增加 Families:让来电操作从家庭开始
给儿童办理课程报名时,工作人员通常与家长沟通。可以把家长联络资料直接加到 Students,但若一个家庭有多个孩子,这些资料又会重复。原文因此增加 Families 表,记录家长姓名与联络方式,并让每个孩子引用一个家庭记录。
- 添加 Families 表,可选使用 Families.csv。同样添加 Full Name 公式列。
- 在 Students 表增加
Family列,设为 Reference,引用 Families。 - 若原列已有家庭姓名,转换引用时会尝试按文字匹配;新资料则可以像其他引用列一样自动补全。真实数据需要核对同名、重复记录和空值。
- 回到 Enrollment View,新增 Families 表格组件,调整布局,使家庭位于左侧,Students 和 Enrollments 位于右侧。
- 打开 STUDENTS 组件右上角三点菜单,选择 Data Selection,在侧边栏把 SELECT BY 改为 FAMILIES。原有 Enrollments 继续跟随 Students。
- 按需要补充所选家庭和所选学员的 Card,重新排列字段与组件。
此时操作顺序变成:选家长或家庭,看到其孩子;再选孩子,看到其报名。工作人员可以增加课程报名、把某条状态改为 Cancelled、添加同一家庭的另一个孩子,或者建立新的家庭记录。
计算已确认人数与剩余名额
官方示例文档在上述流程之外,为 Classes 增加了 Count 与 Spots Left 两个字段。Count 的公式是:
len(Enrollments.lookupRecords(Class=$id, Status="Confirmed"))
$id 是当前课程记录的 ID;lookupRecords 在 Enrollments 中找出 Class 引用该课程、且状态恰好为 Confirmed 的记录,len 再计算数量。候补和已取消记录不计入这个值,重复的已确认报名则会各算一条。因此列 ID、状态拼写与重复数据都影响结果。
Spots Left 用最大人数减去已确认人数,最低显示为零;当结果为零时显示 Full:
max($Max_Students - $Count, 0) or "Full"

编者核查:这是便于工作人员观察的显示公式,不是并发报名锁或数据库约束。两人同时办理报名时,不能指望这个单元格自动阻止超额;还需要业务规则与合适的写入校验。另外,这个公式会把零名额和超额都显示为 Full,不能用它识别超额幅度。若要单独追踪超额,可另设数值列 $Max_Students - $Count,并保留负数;这是编者建议,未在原教程中提供或测试。
使用边界与来源
练习时仅使用虚构家庭与儿童资料。若要投入实际业务,应先确定哪些工作人员能查看或修改各张表,并合理限制家庭联络方式、儿童资料和导出文件的访问。隐藏列或隐藏组件只是界面整理,不能替代访问规则。
本文完整覆盖原文的规划、数据建模、公式、引用、多对多关系、课程视图、报名视图、家庭层次与人数计算。来源:How to manage business data — Grist Help Center;原页未单列个人作者和明确发表日期,本稿不推定。原图:spots-left.png,归属 Grist。本文经授权翻译整理,不用产品代码许可证推定帮助文档转载权。
本次只读原文并静态核对公式、关联方向与操作说明;未创建 Grist 文档、导入 CSV、执行公式或操作真实报名。编者补充的唯一性、权限和并发边界已单独标出。
文档许可与改编说明
原始 Grist Help Center 文档及相关原图:Copyright 2022 Grist Labs Inc.。官方 grist-help 文档仓库依据 Creative Commons Attribution-ShareAlike 4.0 International(CC BY-SA 4.0) 提供内容。本文保留各处原文链接及图片归属;中文翻译、结构整理、明确标示的技术补充和原创示意图同样依 CC BY-SA 4.0 提供。修改与原文结论已在相应段落区分,不暗示原作者为本译稿背书。












暂无评论内容