- 移除 TodoItem 中的 priority、created_at 和 updated_at 字段 - 强制每个任务都必须有唯一 id,且由用户负责生成 - 修改合并模式逻辑,merge=true 下保留未提及的旧任务 - 支持已完成和已取消任务重新激活(状态改回 pending 或 in_progress) - 禁止 in_progress 状态退回到 pending,必须标记为 completed 或 cancelled - 优化状态转换校验,允许特定状态间合法切换 - 简化任务变更消息,移除详细的新增/更新/移除统计 - 更新文档和示例,明确 id 必须由用户生成和使用 - 修复和补充测试,增强状态转换和合并模式验证 - 调整任务时间戳生成逻辑,统一使用当前时间及索引 - 该变更提供更合理的任务状态机械及管理模式,提升稳定性和易用性
15 KiB
Lark Sheet Range Operations
结构性操作影响面预检(清除 / 合并 / 排序 / 移动前必做)
+cells-clear、+cells-{merge|unmerge}、+range-{move|copy|fill|sort}(移动 / 复制 / 排序 / 自动填充)都会让既有引用关系发生偏移或失效。操作前必须先确认以下两点;否则禁止执行:
- 打印当前合并单元格 + 公式引用 + 数据验证范围:用
+sheet-info --include merges++cells-get抽样目标区域和它周边的公式 / 透视表 / 图表 / 条件格式 / 筛选器的数据源;评估操作后这些引用是否仍指向正确数据。 +cells-clear不得侵入用户授权范围之外:清除范围只能是用户明示要清的区域;不要顺手清除"看起来没用"的相邻单元格。
排序场景的存储类型识别 + 辅助列抽数值的细则见下方「sort 操作前必读」章节。
使用场景
写入。对指定区域执行结构性操作。本 reference 覆盖 9 个 shortcut,按 4 类用途组织:
| 操作需求 | 使用工具 | 说明 |
|---|---|---|
| 清除内容/格式 | +cells-clear |
"清空"、"删除内容"、"去掉格式" |
| 合并/取消合并单元格 | `+cells-{merge | unmerge}` |
| 调整行高/列宽 | +rows-resize / +cols-resize |
"加宽列"、"调整行高"、"自适应列宽" |
| 移动/复制/填充/排序 | `+range-{move | copy |
注意:
- 用户说"这行 / 整行 / 首行"时,优先使用整行范围如
1:1;"这列 / 整列"时使用J:J。不要截断为局部矩形 - 合并后只保留左上角单元格的内容,其余清除。写入合并区域用
+cells-set对左上角单元格操作 - 调整行高列宽时,先读取相邻行列尺寸再决定像素值,不要随意猜测
--copy-to-range(+cells-set的参数)复制的是值/公式/样式,不含行高列宽。需要统一尺寸时另行调用+rows-resize / +cols-resize
写入后列宽自适应(防内容遮挡)
写入文本 / 数值后必须主动检查列宽是否适配,否则会出现"内容被截断 / 长数字显示为科学计数法 / 文本溢出被相邻列遮挡"等用户感知问题:
- 写入后回读最长内容字符数:用
+csv-get读目标列的实际写入内容,统计最长单元格的字符数(max(len(cell) for cell in col))。汉字按 2 字符宽度估算,半角字母数字按 1 字符。 - 判定阈值:当前列宽(用
+sheet-info --include row_heights,col_widths拿)≥ 最长字符数 × 字体宽度系数 + buffer 才算适配。默认列宽 11 通常只够 11 个半角字符或 5-6 个汉字,写长文本前必扩宽。 - 修复二选一:
- 扩列宽:用
+rows-resize / +cols-resize把目标列宽设为max(表头字符数, 内容采样最长字符数) × 8 + 16像素(经验值) - 自动换行:在
+cells-set时给单元格设置cell_styles.word_wrap="auto-wrap"(可选值:overflow/auto-wrap/word-clip),并用+rows-resize / +cols-resize调高对应行的行高
- 扩列宽:用
- 新增列默认列宽规则:新增列宽度 ≥
max(表头字符数, 内容采样最长字符数) × 8 + 16像素,禁止用默认 11 直接交付。
典型反例:默认列宽 11 但内容含 12+ 字符的中文 / 含单位的数值(如 109.10μmol/L)/ 长数字未设 number_format 显示为科学计数法 —— 用户在结果表里看不到完整原值。
⚠️ 合并单元格安全操作规则(+cells-{merge|unmerge} 必读):
- 先读后写:操作前必须用
+sheet-info --include merges或+cells-get识别已有合并区域(特征:多个连续单元格中只有左上角有值,其余为空)。 - 不要对已合并区域重复 merge:对已合并的区域再次调用 merge 会报错或产生不可预期结果。
- 修改合并区域的正确顺序:先
unmerge→ 修改内容/样式 → 再merge。 - 对合并区域设置样式:只对完整 range 设置一次
cell_styles(写在左上角单元格),其余位置用{}占位。 - 新增合并时数据保护:合并前确认目标区域只有左上角有数据,其余单元格为空,否则合并会导致非左上角的数据丢失。
- 批量取消合并一次调用即可:当一个范围(整列
A:A、整行3:3、矩形A1:D100)内存在多个合并区域,直接调一次+cells-unmerge传入这个大范围,会一次性取消该范围内所有合并区域;不要为每个合并区域单独调用 unmerge,也不要用+batch-update拆成多次 unmerge。
⚠️ 批量操作必须用 +batch-update:对多个不同区域执行 +cells-merge 或 +rows-resize / +cols-resize 时,禁止逐个调用,合并为单次原子 +batch-update(语义与 --operations 入参格式见 lark-sheets-batch-update)。
唯一例外:+cells-unmerge 原生支持传一个大 range 一次性取消其中所有合并区域,应直接单次调用,不要拆进 +batch-update。
⚠️ sort 操作前必读:确认目标列的数据类型
排序按单元格的存储类型比较:纯数字按数值排序;文本字符串按字典序("1000" 排在 "999" 之前,与数值相反);日期按时间戳排序。
以下形态看起来像数字但实际是字符串,直接 sort 会得到错误结果:
| 示例 | 说明 |
|---|---|
843688.69+20042.35=863731.04 |
表达式文本(无前导 = 不是公式,整串按字典序比较) |
¥1,234.56 / $1,234 |
带货币符号 |
1.2万 / 3.5亿 / 100kg |
带中文 / 英文单位 |
| 前后含空格或不可见字符的数字串 | 被当文本 |
| 同列混文本和数字 | 排序后分块 |
硬性流程:
- sort 前先用
+csv-get抽样目标列的前 3–5 行确认原始值形态,不要只看列名和用户问题就直接排。 - 若是纯数字或日期 → 直接 sort。
- 若是带符号 / 表达式 / 单位的文本 → 不要直接排:
- 简单场景(货币、千分位、单位前缀):新增辅助列,用公式提取数值(如
=VALUE(SUBSTITUTE(SUBSTITUTE(A2,"¥",""),",",""))),按辅助列排序,排完可按需清除辅助列。
- 简单场景(货币、千分位、单位前缀):新增辅助列,用公式提取数值(如
- 复杂场景(多段表达式、中文单位、混合格式):分批
+csv-get读到本地,按数值排序后用+csv-put/+cells-set分批回写。
Shortcuts
| Shortcut | Risk | 分组 |
|---|---|---|
+cells-clear |
high-risk-write | 单元格 |
+cells-merge |
write | 单元格 |
+cells-unmerge |
write | 单元格 |
+rows-resize |
write | 工作表 |
+cols-resize |
write | 工作表 |
+range-move |
write | 区域 |
+range-copy |
write | 区域 |
+range-fill |
write | 区域 |
+range-sort |
write | 区域 |
Flags
+cells-clear
公共四件套 · 系统:--yes、--dry-run
| Flag | Type | 必填 | 说明 |
|---|---|---|---|
--range |
string | required | 清除范围(A1 格式) |
--scope |
string | optional | 清除范围 enum:content(默认,仅清内容)/ formats(仅清格式)/ all(清内容 + 格式)(可选值:content / formats / all) |
+cells-merge
公共四件套 · 系统:--dry-run
| Flag | Type | 必填 | 说明 |
|---|---|---|---|
--range |
string | required | 待合并 / 取消合并的范围(A1 格式) |
--merge-type |
string | optional | 合并方向(仅 +cells-merge)(可选值:all / rows / columns)(默认 all) |
+cells-unmerge
公共四件套 · 系统:--dry-run
| Flag | Type | 必填 | 说明 |
|---|---|---|---|
--range |
string | required | 待合并 / 取消合并的范围(A1 格式) |
+rows-resize
公共四件套 · 系统:--dry-run
| Flag | Type | 必填 | 说明 |
|---|---|---|---|
--type |
string | required | 尺寸方式 enum:pixel(指定 px 像素值,需配 --size)/ standard(重置为默认标准行高)/ auto(自动适应内容)(可选值:pixel / standard / auto) |
--size |
int | optional | 行高(像素,例:30 / 40 / 60);--type pixel 时必填,其它 type 忽略 |
--range |
string | required | 要调整行高的行闭区间;1-based 行号如 2:10 或单行 5 |
+cols-resize
公共四件套 · 系统:--dry-run
| Flag | Type | 必填 | 说明 |
|---|---|---|---|
--type |
string | required | 尺寸方式 enum:pixel(指定 px 像素值,需配 --size)/ standard(重置为默认标准列宽)(可选值:pixel / standard) |
--size |
int | optional | 列宽(像素,例:80 / 120 / 200);--type pixel 时必填,其它 type 忽略 |
--range |
string | required | 要调整列宽的列闭区间;列字母如 A:E 或单列 C |
+range-move
公共四件套 · 系统:--dry-run
| Flag | Type | 必填 | 说明 |
|---|---|---|---|
--source-range |
string | required | 源 A1 范围 |
--target-sheet-id |
string | optional | 目标子表 id;省略时同源 sheet |
--target-range |
string | required | 目标 A1 范围(传起点 cell 即可,按源尺寸自动推断) |
+range-copy
公共四件套 · 系统:--dry-run
| Flag | Type | 必填 | 说明 |
|---|---|---|---|
--source-range |
string | required | 源 A1 范围 |
--target-sheet-id |
string | optional | 目标子表 id;省略时同源 sheet |
--target-range |
string | required | 目标 A1 范围(传起点 cell 即可,按源尺寸自动推断) |
--paste-type |
string | optional | 粘贴内容(仅 +range-copy)(可选值:values / formulas / formats / all)(默认 all) |
+range-fill
公共四件套 · 系统:--dry-run
| Flag | Type | 必填 | 说明 |
|---|---|---|---|
--source-range |
string | required | 填充模板范围(系列起始 cells) |
--target-range |
string | required | 目标填充范围(A1 格式) |
--series-type |
string | optional | 填充序列类型(可选值:auto / linear / growth / date / copy)(默认 auto) |
+range-sort
公共四件套 · 系统:--dry-run
| Flag | Type | 必填 | 说明 |
|---|---|---|---|
--range |
string | required | 排序范围(A1 格式;含或不含表头由 --has-header 决定) |
--sort-keys |
string + File + Stdin(复合 JSON) | required | JSON 数组:[{"column":"<列字母>","ascending":<bool>}, ...] |
--has-header |
bool | optional | 第一行是表头不参与排序,默认 false |
Schemas
复合 JSON flag 字段速查(只列顶层 + 一层嵌套)。深层结构看下方
## Examples,或用--print-schema读完整 JSON Schema(用法见 SKILL.md「公共 flag 速查」与「Agent 使用提示」)。
+range-sort --sort-keys
排序条件列表(仅 sort 操作)
数组项(类型 object):
column(string) — 排序依据的列字母(如 "C"、"D"),必须在 range 范围内ascending(boolean) — 是否升序排序
Examples
⚠️ 本 skill 派生的 shortcut 跨 3 个分组:
+rows-resize/+cols-resize→ 工作表,+cells-*→ 单元格,+range-*→ 区域。skill 视角统一在这里讲解。
公共四件套:所有 shortcut 顶部排列 --url / --spreadsheet-token / --sheet-id / --sheet-name(XOR)。
+cells-clear
删不掉嵌入对象:
+cells-clear(任何--scope,含all)只清单元格的值 / 格式,删不掉压在范围内的透视表 / 图表等嵌入对象——后端会报can not find embedded block。删透视表用+pivot-delete、删图表用+chart-delete(先用+pivot-list/+chart-list拿对象 id)。
需要一次清除多个不连续 range(如把内容搬走后批量去掉散落各处的边框/底色)时,改用
lark-sheets-batch-update的+cells-batch-clear,避免对+cells-clear逐个 range 调用。
# dry-run 先看
lark-cli sheets +cells-clear --url "..." --sheet-id "$SID" --range "A2:Z1000" --scope all --dry-run
# 执行
lark-cli sheets +cells-clear --url "..." --sheet-id "$SID" --range "A2:Z1000" --scope all --yes
+cells-merge / +cells-unmerge
# 合并 A1:C1(可选 --merge-type all/rows/columns)
lark-cli sheets +cells-merge --url "..." --sheet-id "$SID" --range "A1:C1"
# 取消合并:传大 range 一次性取消其中所有合并区域
lark-cli sheets +cells-unmerge --url "..." --sheet-id "$SID" --range "A1:C100"
+rows-resize / +cols-resize
行高列宽分两条 shortcut,避免行 / 列在底层 schema 的差异(行支持 auto,列不支持)混在一起。每条 --type 必填:
# 把第 2-10 行设为固定 30 px
lark-cli sheets +rows-resize --url "..." --sheet-id "$SID" --range "2:10" --type pixel --size 30
# 把 A-C 列设为固定 120 px
lark-cli sheets +cols-resize --url "..." --sheet-id "$SID" --range "A:C" --type pixel --size 120
# 第 1 行行高自动适应内容(列宽不支持 auto)
lark-cli sheets +rows-resize --url "..." --sheet-id "$SID" --range "1" --type auto
# 重置 A-E 列为默认列宽
lark-cli sheets +cols-resize --url "..." --sheet-id "$SID" --range "A:E" --type standard
同时出现在
lark-sheets-sheet-structure.md—— 行高 / 列宽调整也算行列结构层动作。
+range-move / +range-copy
+range-move会清空源区域(move = copy + clear_source);+range-copy不动源。
+range-fill
# 用 A1:A2 的序列规律向下填充到 A3:A100(target 区域不能与 source 重叠,否则后端报 source overlaps destination)
lark-cli sheets +range-fill --url "..." --sheet-id "$SID" --source-range "A1:A2" --target-range "A3:A100" --series-type auto
+range-sort
# 按 C 列降序排 A1:E100(首行为表头不参与)
lark-cli sheets +range-sort --url "..." --sheet-id "$SID" --range "A1:E100" --has-header --sort-keys '[{"column":"C","ascending":false}]'
Validate / DryRun / Execute 约束
Validate:XOR 公共四件套;+cells-clear强制--yes或--dry-run;+range-*校验源 / 目标 range 在同一 spreadsheet;+range-sort的--sort-keys必须合法 JSON 数组且 col 都在--range内;+rows-resize/+cols-resize的--type必填,--type pixel时--size必填、其它 type 时--size会被忽略(传了无害);+cols-resize.--type不接受auto(只行高支持自适应)。DryRun:所有写操作输出"将要 PATCH 的 range + 受影响 cell 数估算"。Execute:写后不自动回读;如需确认,自行调用+cells-get --range <影响范围>抽样比对。