☰
用 SpreadJS 数据验证实现省市区三级联动
2026/10/15 3:18:27 网站建设 项目流程

地址、商品分类、组织架构、费用科目都有一个共同特点:下一级选项取决于上一级选择。用户选了省份,城市列表就不应该再出现其他省的城市;选了城市,区域也应该随之收窄。三级联动这个 demo 用 SpreadJS 的数据验证、自定义名称和INDIRECT函数组合,在普通单元格里实现省份、城市、区域三级下拉。

为什么这个细节重要

级联下拉解决的是数据质量问题。让用户自由输入省市区,后续清洗会很痛苦;让用户从完整城市列表里找,也不够友好。产品经理需要的是更低的填错概率,开发者需要的是一套能维护的数据源结构,业务用户需要的是“我选完上一级,下一级自然变对”。

这个 demo 的优势是它没有写复杂的弹窗控件,而是沿用电子表格里的数据验证能力。用户仍然在单元格里选择,表格仍然可以复制、粘贴、保存,联动规则则由公式引用完成。

这也让它更适合嵌入已有模板。很多企业表单已经围绕行列设计好了权限、导入和导出流程,级联下拉如果仍然发生在单元格内部,就不会破坏原来的工作方式。

SpreadJS 的实现思路

代码创建了一个名为“级联数据源”的工作表,把树形地址数据展开到不同列。第一列存所有省份;每个省份对应一列城市;每个“省份+城市”再对应一列区域。关键是用sheet.addCustomName给这些区域命名,并用GC.Spread.Sheets.CalcEngine.rangesToFormula生成绝对引用。

sourceSheet.name("级联数据源"); ​ let prRange = new GC.Spread.Sheets.Range(1, 0, source.length, 1); sourceSheet.addCustomName( "省份", "级联数据源!" + GC.Spread.Sheets.CalcEngine.rangesToFormula( [prRange], 0, 0, GC.Spread.Sheets.CalcEngine.RangeReferenceRelative.allAbsolute, false ) );

主表三列分别是省份、城市、区域。省份列直接引用名称“省份”;城市列使用INDIRECT拼出“级联数据源! + 当前行 A 列值”;区域列再拼接 A 列和 B 列,找到对应区域列表。

let provinceList = GC.Spread.Sheets.DataValidation.createFormulaListValidator("级联数据源!省份"); sheet.setDataValidator(1, 0, 10, 1, provinceList); ​ let cityList = GC.Spread.Sheets.DataValidation.createFormulaListValidator( 'INDIRECT("级联数据源!"&$A2)' ); sheet.setDataValidator(1, 1, 10, 1, cityList);

可以扩展到哪些场景

省市区只是最容易理解的例子。同样方法可以用于商品大类、中类、小类,部门、岗位、人员,费用一级科目、二级科目、明细科目,设备类型、型号、点位。只要层级清晰、选项数量适中,这种基于数据源表和名称的方案就比较好维护。

需要注意,自定义名称要避免冲突。demo 用“省份+城市”作为区域名称,如果业务里存在重名城市,就要引入编码或更稳定的 key。数据量特别大时,也可以考虑自定义 CellType 或服务端查询式下拉。

实际交付时,还建议监听上级单元格变化并清空下级旧值。否则用户先选了“广东省-广州市”,再把省份改成“浙江省”,城市列可能还保留旧城市,形成看似合法但业务不一致的组合。如果要支持批量粘贴,也要在粘贴后重新校验三列组合,避免绕过下拉选择产生脏数据。

给开发者的关键词

SpreadJS、DataValidation、createFormulaListValidator、addCustomName、INDIRECT、GC.Spread.Sheets.Range、rangesToFormula、三级联动、省市区下拉、JavaScript 电子表格控件。

小结

三级联动展示了 SpreadJS 里很“电子表格原生”的交互方式:用数据验证限制输入,用自定义名称管理候选集,用公式把上下级选项连起来。它让表格录入更稳,也让层级数据维护留在工作簿结构里。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询