从表单保护到按单元格控制顶部菜单
在报价单、预算表和填报系统中,权限控制很少是简单地把整张表设为只读。更常见的做法是:锁定表头和公式,只开放输入区域;保护状态下仍允许筛选、分组或调整格式;当用户选中不同区域时,顶部菜单也随之变化。
SpreadJS 将这些能力拆分为工作表保护、单元格锁定和交互选项三个层次。理解这三个层次后,大多数权限场景都可以用很少的代码组合出来。

图 1 SpreadJS 权限控制的三个层次
先确定哪些区域可以编辑
在 Excel 的保护模型中,单元格默认按 locked=true 处理。因此,对于“默认只读、少量区域可填”的表单,通常只需要把输入区域设置为 locked=false,再开启工作表保护:
const sheet = workbook.getActiveSheet()
// B2:B5 是用户输入区域,其他单元格保持锁定
sheet.getRange(1, 1, 4, 1).locked(false)
sheet.options.isProtected = true
如果业务是“默认可编辑、少量区域只读”,则反过来先解锁整张表,再锁定指定区域:
sheet.getRange(0, 0, rowCount, colCount).locked(false)
sheet.getRange(1, 1, 4, 1).locked(true)
sheet.options.isProtected = true
需要区分的是:locked 决定单元格能否编辑,isProtected 决定保护是否生效。两者缺一不可。
保护状态下的操作权限
protectionOptions 用来补充保护状态下的操作权限。例如,表格不能修改内容,但仍希望用户可以筛选、排序、展开行分组或调整行高,可以按需配置:
sheet.options.protectionOptions = {
allowSort: true,
allowFilter: true,
allowOutlineRows: true,
formatRows: true
}
常用选项还包括 allowSelectLockedCells、allowSelectUnlockedCells、allowResizeColumns、allowInsertRows、allowDeleteRows、allowOutlineColumns,以及 Designer 场景下的 formatCells、formatRows 和 formatColumns。它们控制的是保护状态下的操作,不会把锁定单元格自动变成可编辑。
让顶部菜单跟着选区变化
如果只设置 formatCells,Designer 会在保护状态下保留格式相关命令,但它并不知道当前选区是否可编辑。要实现“选中可编辑区域时菜单可用,选中锁定区域时菜单置灰”,可以给命令的 enableContext 增加一个自定义开关。
const CONTROL_KEY = 'controlByMyself'
sheet.options.protectionOptions = { formatCells: true }
sheet.options.isProtected = true
function selectionEditable() {
const range = workbook.getActiveSheet().getSelections()[0]
if (!range) return false
for (let r = range.row; r < range.row + range.rowCount; r++) {
for (let c = range.col; c < range.col + range.colCount; c++) {
if (sheet.getCell(r, c).locked()) return false
}
}
return true
}
workbook.bind(GC.Spread.Sheets.Events.SelectionChanged, () => {
designer.setData(CONTROL_KEY, !selectionEditable())
designer.refresh()
})
在 Designer 命令配置中,将需要控制的命令改为“原有条件并且不是 controlByMyself”。当选区中包含一个 locked 单元格时,自定义开关为 true,相关命令就会置灰。混合选区采用这种规则也更安全。


图 2 可编辑选区与锁定选区的菜单状态示意
实践中的三个建议
- 优先采用“默认只读、按需开放”的设计,公式、汇总结果和说明列保持 locked=true。
- 提前约定混合选区规则。只要选区包含锁定单元格就禁用菜单,通常比部分执行更容易理解,也更不容易误修改。
- 前端保护主要解决交互和误操作问题,不能替代后端授权。提交数据时仍应校验用户身份、字段权限、数据范围和公式结果。
小结:用 isProtected 开启保护,用 locked 划分可编辑区域,用 protectionOptions 放开必要操作,再用 enableContext 让 Designer 菜单随当前选区联动。这样既能保持表格的可用性,也能让用户清楚地知道当前区域可以做什么。