@amaster.ai/pi-lark 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/package.json +2 -2
  2. package/skills/lark-approval/SKILL.md +2 -2
  3. package/skills/lark-approval/references/lark-approval-instances-initiated.md +5 -0
  4. package/skills/lark-approval/references/lark-approval-tasks-add-sign.md +68 -20
  5. package/skills/lark-approval/references/lark-approval-tasks-query.md +5 -0
  6. package/skills/lark-base/SKILL.md +108 -5
  7. package/skills/lark-base/references/lark-base-data-query.md +2 -6
  8. package/skills/lark-base/references/lark-base-field-extension.md +170 -0
  9. package/skills/lark-base/references/lark-base-field-lookup.md +1 -1
  10. package/skills/lark-base/references/lark-base-filter-condition.md +32 -5
  11. package/skills/lark-base/references/lark-base-form-detail.md +1 -1
  12. package/skills/lark-base/references/lark-base-form-submit.md +2 -2
  13. package/skills/lark-base/references/lark-base-record-history-list.md +1 -1
  14. package/skills/lark-base/references/lark-base-record-query-and-analysis-sop.md +95 -205
  15. package/skills/lark-base/references/lark-base-template-center.md +5 -1
  16. package/skills/lark-calendar/SKILL.md +6 -0
  17. package/skills/lark-calendar/references/lark-calendar-join-event.md +43 -0
  18. package/skills/lark-drive/references/lark-drive-member-remove.md +2 -1
  19. package/skills/lark-im/SKILL.md +15 -1
  20. package/skills/lark-im/references/lark-im-messages-edit.md +89 -0
  21. package/skills/lark-im/references/lark-im-messages-mget.md +8 -0
  22. package/skills/lark-im/references/lark-im-messages-reply.md +2 -0
  23. package/skills/lark-im/references/lark-im-messages-send.md +6 -2
  24. package/skills/lark-markdown/SKILL.md +1 -1
  25. package/skills/lark-meeting/SKILL.md +6 -2
  26. package/skills/lark-meeting/references/lark-minutes-summary.md +1 -0
  27. package/skills/lark-meeting/references/lark-minutes-todo.md +39 -1
  28. package/skills/lark-meeting/references/lark-minutes-upload.md +6 -0
  29. package/skills/lark-meeting/references/lark-vc-agent-meeting-end.md +26 -0
  30. package/skills/lark-meeting/references/lark-vc-agent-meeting-invite.md +32 -0
  31. package/skills/lark-meeting/references/lark-vc-agent-meeting-join.md +8 -2
  32. package/skills/lark-meeting/references/lark-vc-meeting-countdown.md +103 -0
  33. package/skills/lark-meeting/references/lark-vc-meeting-events.md +1 -0
  34. package/skills/lark-meeting/references/lark-vc-meeting-screenshot.md +34 -0
  35. package/skills/lark-meeting/scenes/create-and-edit-minutes.md +25 -3
  36. package/skills/lark-meeting/scenes/live-meeting-attend.md +63 -6
  37. package/skills/lark-meeting/scenes/live-meeting-interact.md +32 -3
  38. package/skills/lark-sheets/SKILL.md +76 -60
  39. package/skills/lark-sheets/references/lark-sheets-batch-update.md +83 -14
  40. package/skills/lark-sheets/references/lark-sheets-chart.md +296 -159
  41. package/skills/lark-sheets/references/lark-sheets-conditional-format.md +46 -9
  42. package/skills/lark-sheets/references/lark-sheets-filter.md +1 -1
  43. package/skills/lark-sheets/references/lark-sheets-formula-translation.md +78 -65
  44. package/skills/lark-sheets/references/lark-sheets-formula-verify.md +21 -17
  45. package/skills/lark-sheets/references/lark-sheets-pivot-table.md +2 -1
  46. package/skills/lark-sheets/references/lark-sheets-range-operations.md +1 -1
  47. package/skills/lark-sheets/references/lark-sheets-read-data.md +8 -5
  48. package/skills/lark-sheets/references/lark-sheets-search-replace.md +4 -4
  49. package/skills/lark-sheets/references/lark-sheets-sheet-structure.md +2 -2
  50. package/skills/lark-sheets/references/lark-sheets-sparkline.md +1 -0
  51. package/skills/lark-sheets/references/lark-sheets-styles-put.md +3 -3
  52. package/skills/lark-sheets/references/lark-sheets-visual-standards.md +6 -4
  53. package/skills/lark-sheets/references/lark-sheets-workbook.md +3 -1
  54. package/skills/lark-sheets/references/lark-sheets-write-cells.md +50 -48
  55. package/skills/lark-sheets/scripts/lark_chart_layout_check.py +472 -0
  56. package/skills/lark-slides/references/cli/lark-slides-add-slide.md +6 -6
  57. package/skills/lark-slides/references/cli/lark-slides-delete-slide.md +3 -3
  58. package/skills/lark-slides/references/cli/lark-slides-replace-slide.md +11 -11
  59. package/skills/lark-slides/references/cli/lark-slides-xml-presentation-slide-get.md +1 -1
  60. package/skills/lark-slides/references/cli/lark-slides-xml-presentation-slide-replace.md +2 -2
  61. package/skills/lark-slides/references/workflow/slides-editing.md +11 -11
  62. package/skills/lark-slides/references/xml/slides_xml_schema_definition.xml +2 -0
  63. package/skills/lark-base/references/lark-base-cell-value.md +0 -165
  64. package/skills/lark-base/references/lark-base-data-analysis-pandas.md +0 -93
  65. package/skills/lark-base/references/lark-base-data-analysis-python-stdlib.md +0 -120
  66. package/skills/lark-base/references/lark-base-record-batch-create.md +0 -63
  67. package/skills/lark-base/references/lark-base-record-batch-update.md +0 -57
  68. package/skills/lark-base/references/lark-base-record-query-and-analysis-cloud-sop.md +0 -145
@@ -1,11 +1,11 @@
1
1
  # Lark Sheet Search & Replace
2
2
 
3
- ## 替换前 dry-run + 范围明确(替换前必做)
3
+ ## 替换前 dry-run + 范围明确(替换前建议)
4
4
 
5
5
  `+cells-replace` 的副作用是不可逆的(除非另写代码回滚)。执行前必须:
6
6
 
7
- 1. **明确替换范围**:必须显式说明"只替换 X 列 / X 区域,还是全表替换"。**禁止**默认全表替换——容易误改无关列。范围应由用户指令决定,模糊时主动询问。
8
- 2. **dry-run 命中数量**:先用 `+cells-search` 在同一范围、同一关键词、同一匹配选项(大小写 / 精确 / 正则)下统计命中数量。把数量和**期望命中数**(用户明示的或基于业务理解推断的)对照——一致才进入 `+cells-replace`,不一致先排查(关键词太宽?范围太大?)。
7
+ 1. **明确替换范围**:建议显式说明"只替换 X 列 / X 区域,还是全表替换"。避免默认全表替换——容易误改无关列。范围应由用户指令决定,模糊时主动询问。
8
+ 2. **dry-run 命中数量**:先用 `+cells-search` 在同一范围、同一关键词、同一匹配选项(大小写 / 精确 / 正则)下统计命中数量。把数量和**期望命中数**(用户明示的或基于业务理解推断的)对照;不一致先排查(关键词太宽?范围太大?)。
9
9
  3. **替换后回读校验**:执行后再次 `+cells-search` 旧关键词,预期为 0;并对替换后的若干代表性单元格回读确认值符合预期。
10
10
 
11
11
  ## 使用场景
@@ -17,7 +17,7 @@
17
17
  | 搜索/定位文本 | `+cells-search` | 返回匹配的单元格位置,支持正则、精确匹配等 |
18
18
  | 查找并替换文本 | `+cells-replace` | 批量替换文本;`--regex` 模式下 `--replacement` 可用 `$1`、`$2` 引用 `--find` 的捕获组 |
19
19
 
20
- **常见配置错误(必须注意)**:
20
+ **常见配置错误(注意)**:
21
21
  - **不要把操作动词当搜索词**:用户说"汇总金额"是一个操作动作(求和),不是要搜索"汇总金额"这个文本。只有当确实需要定位某个文本值的位置时才用 `+cells-search`
22
22
  - **不要用搜索来了解表格结构**:要了解表头和数据结构时,应使用 `+csv-get` 读取前几行,而不是用 `+cells-search` 逐个猜测字段名
23
23
  - **注意正则特殊字符**:使用正则匹配时,`.`、`*`、`(`、`)` 等特殊字符需要转义
@@ -87,7 +87,7 @@ _公共四件套 · 系统:`--yes`、`--dry-run`_
87
87
  | Flag | Type | 必填 | 说明 |
88
88
  | --- | --- | --- | --- |
89
89
  | `--range` | string | xor | 要删除的行/列闭区间;行用 1-based 数字如 `3:7` 或单行 `5`,列用字母如 `C:F` 或单列 `C`。与 `--ranges` 二选一 |
90
- | `--ranges` | string + File + Stdin(简单 JSON) | xor | 要删除的多个行/列区间 JSON 数组(最多 100 个,如 `["5:5","8:8","11:13"]` 或 `["C:C","F:G"]`),全行或全列不可混用,区间不可重叠;与 `--range` 二选一。CLI 按位置**从大到小逆序**合成一次批量删除(fail-fast、不回滚)——正序删除会因前面的行/列被删导致后续索引前移错位,逆序由 CLI 代劳,无需自行排序 |
90
+ | `--ranges` | string + File + Stdin(简单 JSON) | xor | 要删除的多个行/列区间 JSON 数组(最多 100 个,如 `["5:5","8:8","11:13"]` 或 `["C:C","F:G"]`),全行或全列不可混用,区间不可重叠;与 `--range` 二选一。CLI 按位置**从大到小逆序**合成一次批量删除(fail-fast,失败后先回读再补发)——正序删除会因前面的行/列被删导致后续索引前移错位,逆序由 CLI 代劳,无需自行排序 |
91
91
 
92
92
  ### `+dim-hide`
93
93
 
@@ -170,7 +170,7 @@ lark-cli sheets +dim-delete --url "..." --sheet-id "$SID" --range "5:7" --yes
170
170
  # 删除 D-F 列
171
171
  lark-cli sheets +dim-delete --url "..." --sheet-id "$SID" --range "D:F" --yes
172
172
 
173
- # 删除多个散布区间(如按查重结果删行):--ranges 一次批量交付(fail-fast、不回滚,CLI 逆序保索引)。
173
+ # 删除多个散布区间(如按查重结果删行):--ranges 一次批量交付(fail-fast,失败后先回读再补发;CLI 逆序保索引)。
174
174
  # CLI 自动按位置从大到小逆序执行——正序会因前面的行被删导致后续索引前移错位;
175
175
  # 无需自行排序,也不要为此拼 +batch-update 的子操作数组
176
176
  lark-cli sheets +dim-delete --url "..." --sheet-id "$SID" --ranges '["5:5","8:8","11:13"]' --yes
@@ -18,6 +18,7 @@
18
18
  **常见配置错误(必须注意)**:
19
19
  - **数据源范围要精确**:迷你图的数据源范围必须与实际数据行列精确对应,范围偏移会导致图形展示错误
20
20
  - **不要与 SPARKLINE() 公式混淆**:飞书表格的 `SPARKLINE()` 公式函数已被禁用,迷你图只能通过 `+sparkline-{create|update|delete}` 的对象方式创建
21
+ - **胜负 / count 迷你图原生支持**:`config.type="win_loss"`——别因速查表没列就判"不支持"绕路
21
22
  - **创建后必须验证**:调用 `+sparkline-list` 确认迷你图配置正确
22
23
 
23
24
  ## Shortcuts
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## 使用场景
8
8
 
9
- 写入。对存量表格的多个子表批量应用视觉规格:新表美化、加汇总行后统一版式、按分组合并同类单元格、调列宽行高、冻结表头。整份规格展开为一次批量提交按序执行,与 `+batch-update` 同为 **fail-fast 且不回滚**——失败时已执行的子操作保留生效。
9
+ 写入。对存量表格的多个子表批量应用视觉规格:新表美化、加汇总行后统一版式、按分组合并同类单元格、调列宽行高、冻结表头。整份规格展开为一次批量提交按序执行,与 `+batch-update` 同为 **fail-fast**——失败后哪些子操作已生效不做统一假设,先回读确认再补发(语义同 `lark-sheets-batch-update`「执行语义」)。
10
10
 
11
11
  ⚠️ **失败后不要照抄报错里的 `operations[N]` 去续发**:那个数组是 CLI 从 `--styles` 展开出来的(相邻同样式的 `cell_styles` 还会被合并成更大的矩形),下标与你写的 spec 项没有对应关系,也不是你能直接重发的东西。正确做法:回读受影响区域(`+cells-get --include style` / `+sheet-info`)确认哪些已生效,再重发没落上的部分。样式 / 行高列宽 / 冻结是幂等盖章(整份重发无副作用,这通常就是最省事的解法),只有 `cell_merges` 需要挑出未生效的部分单独发。
12
12
 
@@ -36,7 +36,7 @@ _公共:URL/token(无 sheet 定位) · 系统:`--dry-run`_
36
36
 
37
37
  | Flag | Type | 必填 | 说明 |
38
38
  | --- | --- | --- | --- |
39
- | `--styles` | string + File + Stdin(复合 JSON) | required | 对**已有**表格应用的视觉规格 JSON:顶层 `{styles:[...]}`,每项对应一个目标子表(`name` 用真实子表名),并至少给 `cell_styles` / `cell_merges` / `row_sizes` / `col_sizes` / `freeze` 之一。字段词汇与 `+workbook-create` / `+table-put` 的 `--styles` 完全同构(cell_styles 用 A1 range + 扁平样式字段,边框用 `border` 简写 {style,weight,color} 四边同款、分侧才用 border_styles;row/col sizes 用行/列范围 + size(px 即像素,standard/auto 才需 type);merges 用单元格 range;freeze 用 `{rows:N, cols:N}` 冻结前 N 行/列)。整份规格展开为一次批量提交(fail-fast、不回滚:失败时已生效的子操作保留);range 不受「本次写入区域」限制,可指向表内任意区域 |
39
+ | `--styles` | string + File + Stdin(复合 JSON) | required | 对**已有**表格应用的视觉规格 JSON:顶层 `{styles:[...]}`,每项对应一个目标子表(`name` 用真实子表名),并至少给 `cell_styles` / `cell_merges` / `row_sizes` / `col_sizes` / `freeze` 之一。字段词汇与 `+workbook-create` / `+table-put` 的 `--styles` 完全同构(cell_styles 用 A1 range + 扁平样式字段,边框用 `border` 简写 {style,weight,color} 四边同款、分侧才用 border_styles;row/col sizes 用行/列范围 + size(px 即像素,standard/auto 才需 type);merges 用单元格 range;freeze 用 `{rows:N, cols:N}` 冻结前 N 行/列)。整份规格展开为一次批量提交(fail-fast:失败后哪些已生效不做统一假设,先回读确认再补发);range 不受「本次写入区域」限制,可指向表内任意区域 |
40
40
 
41
41
  ## Schemas
42
42
 
@@ -90,4 +90,4 @@ JSON
90
90
 
91
91
  - `Validate`:`--styles` 必须是合法 JSON、`styles` 非空数组;每项 `name` 必填、至少给 `cell_merges` / `cell_styles` / `row_sizes` / `col_sizes` / `freeze` 之一;`cell_styles` 每项至少一个样式字段;展开后受子操作数(100)与总格数预算约束,超限报错给拆分建议。
92
92
  - `DryRun`:输出展开后每个子操作的请求模板,不发起调用。
93
- - `Execute`:整份规格合成一次批量请求按序执行;fail-fast 且不回滚。报错会列出失败的子操作及原因,但其中的 `operations[N]` 是 CLI 展开后的内部下标(含 `cell_styles` 合并),不对应 `--styles` 里的项,也不能直接按下标续发——报错会明说这一点并让你先回读再补发。
93
+ - `Execute`:整份规格合成一次批量请求按序执行;fail-fast。报错会列出失败的子操作及原因,但其中的 `operations[N]` 是 CLI 展开后的内部下标(含 `cell_styles` 合并),不对应 `--styles` 里的项,也不能直接按下标续发——报错会明说这一点并让你先回读再补发。
@@ -9,12 +9,14 @@
9
9
  - **继承原表风格**:编辑前先采样原文件视觉特征(色系、边框、对齐、数字格式),新增内容必须与之对齐。严禁对已有风格的文件强行施加通用标准化格式。
10
10
  - **扩展而非覆盖**:新增行列或追加数据时,目标是"扩展原模板"——继承邻近区域的表头风格、条纹节奏、边框层级、对齐方式、数字格式和列宽/行高策略。
11
11
  - **美化只动样式属性,不动数据**:对**已有区域**做美化时,**只能**修改 `font` / `fill` / `border` / `alignment` / `number_format` 这 5 类样式属性。**禁止**改动原始单元格的 `value` / `formula`、合并区域、行列结构、Sheet 名称。如果美化需求需要改变数据布局(例如"汇总行加进表里"),必须把"加汇总行"和"美化"拆成两步,前者属于编辑动作、需另行得到用户授权。
12
- - **不可见视觉属性也属保护对象**:原表的**合并范围、对齐方式(H-Align/V-Align)、行高列宽、数字格式**是用户能感知但不一定会明示的视觉属性。即使用户没说"保留这些",**禁止**因写入新内容而修改它们;写公式 / 写值 / 写新列时只传 `value` / `formula`,不要重置 `alignment` / `number_format` 等字段为默认值(重置等同于改动)。**例外**:用户明示要修改这些属性时(如"调整对齐 / 合并 / 列宽")才能动。
12
+ - **不可见视觉属性也属保护对象**:原表的**合并范围、对齐方式(H-Align/V-Align)、行高列宽、数字格式**是用户能感知但不一定会明示的视觉属性。即使用户没说"保留这些",**禁止**因写入新内容而修改它们;写公式 / 写值 / 写新列时只传 `value` / `formula`,不要重置 `alignment` / `number_format` 等字段为默认值(重置等同于改动)。**例外**:用户明示要修改这些属性时(如"调整对齐 / 合并 / 列宽")才能动;用户**点名美化**("美化 / 让表清晰 / 适合打印")视同授权下节 checklist 的全部 5 个维度(含列宽行高)。
13
+ - **标红 / 高亮默认用背景色**:用户说"标红 / 标出来 / 高亮"时,默认改**背景色**(可叠加字体色)——背景色在人工核对与导出后都更醒目;仅当用户明确说"字体标红"才只改字体色。
14
+ - **打印 / 下载类任务的完成标准是导出后也无遮挡**:涉及"适合打印 / 下载 / 导出"时,在线表格调整完行高列宽后,导出 xlsx 再检查一次无截断、无 `####`、无溢出;长文本列给足列宽并设明确行高兜底值,不要只依赖 auto。
13
15
  - **美化范围必须覆盖所有用户语义目标**:用户说"给表格加边框 / 美化整个表"时,范围 = 实际数据区域**含所有数据行**(含汇总行、总计行、表尾备注行),不能停在"看起来主体内容结束"的地方。落地前先用 `current_region` + 末尾 5~10 行核对真实末行(同 `lark-sheets-read-data` 的「确定数据范围的正确流程」),再设置美化范围。范围漏掉用户提到的目标行 / 列**直接判失败**。
14
16
 
15
- ## 美化任务 5 维度 checklist(用户说"美化 / 整理 / 让表更清晰 / 适合打印"时必做)
17
+ ## 美化任务 5 维度 checklist(用户**点名美化**——"美化 / 让表更清晰 / 适合打印"时必做;"整理"默认指数据整理,不触发本节)
16
18
 
17
- 当用户用"美化 / 整理表格 / 让表清晰 / 适合打印 / 调整样式"等口语表达**主动美化需求**时,**必须**遍历以下 5 个维度逐一落地,**只动一处就交付**(如只加边框)属于违规:
19
+ 当用户**点名美化**("美化 / 让表清晰 / 适合打印 / 调整样式"——"整理"不算,那是数据整理)时,**必须**遍历以下 5 个维度逐一落地,**只动一处就交付**(如只加边框)属于违规。**已有表点名美化时,5 个维度的取值先沿用原表色系 / 对齐(继承原则优先),checklist 只补原表缺失的维度**:
18
20
 
19
21
  1. **表头格式区分**:表头行加粗 + 背景色填充(与数据行有色差)+ 居中对齐;多行表头时全部行同步处理
20
22
  2. **对齐方式**:文本列左对齐、数值 / 货币 / 百分比列右对齐、日期 / 分类列居中;垂直方向统一居中
@@ -79,7 +81,7 @@
79
81
  ### 6. 图表展示
80
82
 
81
83
  - 遵循用户指令选择图表类型,或匹配用户意图(饼图/环形图 → 占比,折线图 → 趋势)。
82
- - 包含必要元素:标题、图例、数据标签、坐标轴标题。
84
+ - 包含必要元素:标题、坐标轴标题、多系列图例;数据标签按需(关键点 / 末值标注即可,不必每个数据点都加)。
83
85
  - 调整至合适大小,避免数据和标签过多堆叠。
84
86
  - **图表放置防重叠**:新增图表前须计算放置区域,避免与已有图表重叠。具体步骤:
85
87
  1. 调用 `+chart-list` 获取当前工作表所有已有图表的 `position`(锚点单元格:`col` 是列字母如 "A"/"B"、`row` 是 1-based 行号;以 `+chart-list` 实际返回字段为准)、`offset`(锚点内偏移:`row_offset`、`col_offset`,单位像素)以及 `size`(`width`、`height`,单位像素)。
@@ -245,7 +245,7 @@ lark-cli sheets +workbook-create --title "交易" --sheets '{
245
245
 
246
246
  `--sheets` 协议与 `+table-put` 完全同构(字段含义见 lark-sheets-write-cells 的 `+table-put`,大 payload 走 stdin / `@file`)。关键差异:**新建工作簿的默认子表会被复用为第一个子表**(重命名后承载数据),不会残留空 `Sheet1`;其余子表按需新建。它把 `+table-put` 单独做不到的"建表 + typed 写入"合到一条命令,是「pandas 算完直接落地一张带真日期的新表」的首选。回读校验用 `+table-get`(与 `--sheets` 同构、可 round-trip)。
247
247
 
248
- > 💡 pandas DataFrame 走 `--sheets` 时直接 `from sheets_df import df_to_sheet`([`scripts/sheets_df.py`](../scripts/sheets_df.py),与 `+table-put` 共用同一份 helper),多子表场景 helper 优势更明显:
248
+ > 💡 pandas DataFrame 走 `--sheets` 时用 `from sheets_df import df_to_sheet`([`scripts/sheets_df.py`](../scripts/sheets_df.py),与 `+table-put` 共用同一份 helper;import 前先把 skill 的 `scripts/` 目录加入 `sys.path`),多子表场景 helper 优势更明显:
249
249
  > ```python
250
250
  > payload = {"sheets": [df_to_sheet(income, "Income Statement"),
251
251
  > df_to_sheet(balance, "Balance Sheet"),
@@ -331,6 +331,8 @@ lark-cli sheets +workbook-import --file ./report.csv --folder-token <FOLDER_TOKE
331
331
  ```
332
332
 
333
333
  - **不接受任何 spreadsheet / sheet 定位 flag**(它是新建,不操作已有表):只有 `--file`(必填)/ `--folder-token` / `--name`。
334
+ - **`--file` 只接受当前工作目录内的相对路径**:先 `cd` 到文件所在目录(或 workspace),再传 `./file.xlsx` / `data/file.xlsx`;传 `/home/.../file.xlsx`、`C:\...\file.xlsx` 这类绝对路径会被判定 `unsafe file path` 拒绝。
335
+ - 导入成功后把新表链接交付给用户。
334
336
  - 本地表格文件 → 飞书电子表格一律用本命令,**不要**用 `drive +import` 导电子表格——它是 sheets 之外的通用导入、还需额外指定 `--type`,绕路且更易错。只有要把本地表格导入成**多维表格**(bitable)时,才改用 `lark-cli drive +import --type bitable`。
335
337
  - 返回 `token` / `url`(导入完成的新表格)/ `ticket` / `ready` / `job_status`;未在内置轮询窗口内完成时返回 `timed_out=true` 与续查命令 `next_command`。
336
338
 
@@ -1,37 +1,37 @@
1
1
  # Lark Sheet Write Cells
2
2
 
3
- ## 写入边界 + 回读校验(编辑类任务必做)
3
+ ## 写入边界 + 回读诊断(编辑类任务建议)
4
4
 
5
- 1. **明确写入边界**:写入前必须能回答"目标 range 的起止行列号是多少?是否落在用户授权范围内?"。除用户明示要修改的区域外,禁止扩张到原数据列以外或新建 Sheet。
6
- 2. **完整性断言**:批量写入前先把"预期写入条数"硬编码到代码里(如要填 106 条翻译 → `expected = 106`),写完后回读断言 `actual == expected`。少于预期就继续写,禁止交付半成品。
5
+ 1. **明确写入边界**:写入前建议能回答"目标 range 的起止行列号是多少?是否落在用户授权范围内?"。除用户明示要修改的区域外,避免扩张到原数据列以外或新建 Sheet。
6
+ 2. **完整性断言**:批量写入前建议把"预期写入条数"硬编码到代码里(如要填 106 条翻译 → `expected = 106`),写完后回读比较 `actual == expected`。少于预期时优先补齐,补不齐则在交付说明里列出缺口。
7
7
  3. **回读抽样校验**:写完关键值 / 公式后,用 `+csv-get` 或 `+cells-get` 重新读取写入区域,至少抽样 3-5 个代表性单元格(首 / 中 / 末),核对值与预期一致(与本地脚本计算的预期值对照)。公式特定的"先验证模板再 --copy-to-range / 修完再读回"细则见下方相关章节。
8
- 4. **护原表 · 派生产物落点(写排名 / 标记 / 汇总 / 改写列时易丢数据)**:派生结果一律写到**真实末列 +1 的全新空列**或新建子表,**禁止复用任何已有原数据列**——哪怕该列看起来"空",也要先 `+csv-get` 回读确认整列无原始数据再写。三条准则:① 不把新公式 / 新值写进原数据列(典型反例:把新算的排名公式写进了原本存放另一份原始数据的列,整列原始数据被覆盖丢失);② 不改写、不合并原表头字段名(典型反例:把几个独立表头字段合并成一列,原字段名丢失);③ 慎用 `--allow-overwrite`:它一旦让写入区盖到相邻原始列 / 行就是不可逆数据丢失,加它之前必须用 `+sheet-info` / `+csv-get` 核清目标 range 不含任何原始数据。
8
+ 4. **护原表 · 派生产物落点(写排名 / 标记 / 汇总 / 改写列时易丢数据)**:派生结果优先写到**真实末列 +1 的全新空列**或新建子表,避免复用任何已有原数据列——哪怕该列看起来"空",也要先 `+csv-get` 回读确认整列无原始数据再写。三条准则:① 尽量不把新公式 / 新值写进原数据列(典型反例:把新算的排名公式写进了原本存放另一份原始数据的列,整列原始数据被覆盖丢失);② 尽量不改写、不合并原表头字段名(典型反例:把几个独立表头字段合并成一列,原字段名丢失);③ 慎用 `--allow-overwrite`:它一旦让写入区盖到相邻原始列 / 行就是不可逆数据丢失,加它之前建议用 `+sheet-info` / `+csv-get` 核清目标 range 不含任何原始数据。
9
9
 
10
10
  ## 新增列 / 新增行的样式继承(防止视觉风格不一致)
11
11
 
12
- 新增列 / 新增行**必须**先用 `+cells-get` 读相邻原列 / 原行的完整样式作为模板,**禁止**只传 `value` 期望默认样式与原表一致——飞书新单元格默认对齐通常是 `H:right, V:bottom`,与多数原表的 `H:center, V:middle` 不一致。
12
+ 新增列 / 新增行建议先用 `+cells-get` 读相邻原列 / 原行的完整样式作为模板,避免只传 `value` 期望默认样式与原表一致——飞书新单元格默认对齐通常是 `H:right, V:bottom`,与多数原表的 `H:center, V:middle` 不一致。
13
13
 
14
- **完整继承清单**(写新列 / 新行时 cells 数组必须同时携带):
14
+ **完整继承清单**(写新列 / 新行时建议同时携带):
15
15
 
16
16
  1. `cell_styles.font_family` / `cell_styles.font_size` / `cell_styles.font_weight` / `cell_styles.font_color` / `cell_styles.font_style`(字体名称 / 字号 / 粗细 / 颜色 / 斜体等)
17
17
  2. `cell_styles.horizontal_alignment` / `cell_styles.vertical_alignment`(H-Align / V-Align)—— 漏继承会导致新列对齐与原列不一致(常见)
18
18
  3. `cell_styles.number_format`(小数位 / 千分位 / 百分比 / 日期格式)—— 漏继承会导致同列数值格式混乱
19
19
  4. `cell_styles.background_color`(背景色)
20
20
  5. `border_styles`(四边框)
21
- 6. **`merged_cells`(合并范围)**——续写场景必查:用 `+sheet-info --include merges` 读原数据区域的合并信息。**原行有跨列合并**(如标题行 `A1:G1` 合并)时,新行**必须**用 `+cells-{merge|unmerge}` 工具复制相同合并模式到新行(如续写第 3 个周报块的标题行 `A23:G23` 必须合并)。仅传 cells 数组的 5 类样式不够——合并范围要单独靠 `+cells-{merge|unmerge}` 工具落地(典型反例:续写多周记录表时,新增周次的标题行未合并,视觉上与原前几周风格不一致)
21
+ 6. **`merged_cells`(合并范围)**——续写场景必查:用 `+sheet-info --include merges` 读原数据区域的合并信息。**原行有跨列合并**(如标题行 `A1:G1` 合并)时,新行建议用 `+cells-{merge|unmerge}` 工具复制相同合并模式到新行(如续写第 3 个周报块的标题行 `A23:G23` 建议合并)。仅传 cells 数组的 5 类样式不够——合并范围要单独靠 `+cells-{merge|unmerge}` 工具落地(典型反例:续写多周记录表时,新增周次的标题行未合并,视觉上与原前几周风格不一致)
22
22
 
23
23
  **采样模板的正确做法**:
24
24
  - 表头新列 → 读相邻表头单元格(如新加 D1 → 读 A1/B1/C1 任一)
25
25
  - 数据新列 → 读相邻数据行单元格(如新加 M5:M100 → 读 L5 / L6 / L7)
26
26
  - 续写新行 → 读最近一行已有数据(如续写第 20 行 → 读 19 行所有列)
27
27
 
28
- **反模式**(违规):
28
+ **反模式**(风险):
29
29
  - 只传 `{"value": "四级菜单"}` 给 D1,不传 `cell_styles` → D1 默认非加粗、非居中,与 A1/B1/C1 风格断裂
30
30
  - 新列 M5 写入 `=SUM(F5:L5)` 时只传 `formula`,不传 `cell_styles.horizontal_alignment / vertical_alignment / number_format` → M 列对齐变 `H:right`,数字格式变默认
31
31
 
32
32
  ## 长数字防科学计数法(数值列写入必查)
33
33
 
34
- 写入或计算结果可能产生长数字(≥ 12 位整数 / 高精度小数)的列,**必须**在 `cell_styles.number_format` 显式设置非通用格式,否则飞书会自动用科学计数法显示,用户看到的就是"内容被截断 / 看不清原值"。
34
+ 写入或计算结果可能产生长数字(≥ 12 位整数 / 高精度小数)的列,建议在 `cell_styles.number_format` 显式设置非通用格式,否则飞书会自动用科学计数法显示,用户看到的就是"内容被截断 / 看不清原值"。
35
35
 
36
36
  | 场景 | 必加的 `number_format` |
37
37
  |---|---|
@@ -43,7 +43,7 @@
43
43
 
44
44
  **典型反例**:长数字列(如审批单号、流水号)未设 `number_format`,飞书显示为 `1.23E+15`,用户复制出来已经丢失精度。
45
45
 
46
- > **数字还是文本,按"数据本质是量值还是标识符"二选一 —— 不看当下要不要计算**:金额 / 百分比 / 比率 / 计数 / 度量这类**本质是量值**的数据,一律以**数字类型**写入(百分比存小数 `0.54` 配 `number_format:"0%"`),**不要**设 `@` 文本格式。**这与"用户当下是否要排序 / 求和"无关**——数据类型由数据本质决定、不由当下用途决定:表格数据几乎总会被后续排序 / 图表 / 二次计算复用,`"54%"` 文本与数值列混排本就破坏一致性,且数字 + `number_format` 显示效果与文本**完全相同**,没有任何理由选文本。**最常见的误判就是"这只是 leaderboard / 报表 / 看板展示,又不用算,写成 `54%` 字符串就行"——这是错的,展示用途不改变"百分比是数值"的事实。**(`+table-put` 用 `dtypes` 声明 `int64` / `float64`;版式 `+table-put` 装不下时用 `+cells-set` 传数字 + `number_format`;都别在本地拼成带 `$` / `%` 的字符串走 `+csv-put`。)反过来,编号 `001`、规格 `3-1`、身份证 / 电话 / 单据号等**本质是标识符 / 标签**、要原样保留不被飞书自动解释的内容(否则 `001`→`1`、`3-1`→日期、点分日期 `12.10`→`12.1`(尾零丢失)、长号→科学计数),才以**字符串类型**写入(`dtypes` 设 `object`)并把 `number_format` 设为 `"@"`(文本格式),字面保真。
46
+ > **数字还是文本,按"数据本质是量值还是标识符"二选一 —— 不看当下要不要计算**:金额 / 百分比 / 比率 / 计数 / 度量这类**本质是量值**的数据,优先以**数字类型**写入(百分比存小数 `0.54` 配 `number_format:"0%"`),避免设 `@` 文本格式。**这与"用户当下是否要排序 / 求和"无关**——数据类型由数据本质决定、不由当下用途决定:表格数据几乎总会被后续排序 / 图表 / 二次计算复用,`"54%"` 文本与数值列混排本就破坏一致性,且数字 + `number_format` 显示效果与文本**完全相同**,没有任何理由选文本。**最常见的误判就是"这只是 leaderboard / 报表 / 看板展示,又不用算,写成 `54%` 字符串就行"——这是错的,展示用途不改变"百分比是数值"的事实。**(`+table-put` 用 `dtypes` 声明 `int64` / `float64`;版式 `+table-put` 装不下时用 `+cells-set` 传数字 + `number_format`;都别在本地拼成带 `$` / `%` 的字符串走 `+csv-put`。)反过来,编号 `001`、规格 `3-1`、身份证 / 电话 / 单据号等**本质是标识符 / 标签**、要原样保留不被飞书自动解释的内容(否则 `001`→`1`、`3-1`→日期、点分日期 `12.10`→`12.1`(尾零丢失)、长号→科学计数),才以**字符串类型**写入(`dtypes` 设 `object`)并把 `number_format` 设为 `"@"`(文本格式),字面保真。
47
47
 
48
48
  ## 使用场景
49
49
 
@@ -61,11 +61,11 @@
61
61
 
62
62
  **选命令按内容形态分流(不设"默认首选")**:① 列有数值语义(金额 / 百分比 / 日期 / 计数)→ `+table-put`(`dtypes` 声明类型 + `formats` 设展示格式),版式装不下时 → `+cells-set` 传数字 + `number_format`;② 要样式 / 批注 / 图片 / 富文本 → `+cells-set`;③ **仅**全文本、无数值语义的内容平铺 → `+csv-put`(入参最短)。判据详见上方「数字还是文本」。
63
63
 
64
- ⚠️ `+csv-put` 可写值或公式:以 `=` 开头的单元格会被当作公式计算(读回时 `formula` 字段保留、`value` 为计算结果)。**公式内部含逗号 / 引号 / 换行时必须按 RFC 4180 转义**——含逗号的字段整格用双引号包裹、字段内部的引号再翻倍:如 `=COUNTIF(D5:D22,"及格")` 必须写成 `"=COUNTIF(D5:D22,""及格"")"`(外层双引号包裹整格,内部 `"及格"` 的引号翻倍成 `""及格""`)。漏转义会被 CSV 解析器按逗号拆列、整块写入区域错位(如本该 `G4:H6` 错成 `G4:K4`),详见下方 `+csv-put` 示例。**因此含逗号 / 引号 / 换行的公式优先改用 `+cells-set`(JSON 二维数组)写入——`cells[r][c].formula` 字段直接放公式串,零 CSV 转义负担,从根上避免拆列错位**(`+table-put` 的 typed 协议只接受 `columns / data / dtypes / formats` 四件套、没有 `formula` 字段,公式写入只能走 `+cells-set` / `+csv-put`)。此外 `+csv-put` **不会**携带样式/批注/图片,也无法把 `=` 开头的内容当字面量文本写入;需要样式/批注/图片用 `+cells-set`(或"写值 + 补样式"两步法)。
64
+ ⚠️ `+csv-put` 可写值或公式:以 `=` 开头的单元格会被当作公式计算(读回时 `formula` 字段保留、`value` 为计算结果)。**公式内部含逗号 / 引号 / 换行时建议按 RFC 4180 转义**——含逗号的字段整格用双引号包裹、字段内部的引号再翻倍:如 `=COUNTIF(D5:D22,"及格")` 建议写成 `"=COUNTIF(D5:D22,""及格"")"`(外层双引号包裹整格,内部 `"及格"` 的引号翻倍成 `""及格""`)。漏转义会被 CSV 解析器按逗号拆列、整块写入区域错位(如本该 `G4:H6` 错成 `G4:K4`),详见下方 `+csv-put` 示例。**因此含逗号 / 引号 / 换行的公式优先改用 `+cells-set`(JSON 二维数组)写入——`cells[r][c].formula` 字段直接放公式串,零 CSV 转义负担,从根上避免拆列错位**(`+table-put` 的 typed 协议只接受 `columns / data / dtypes / formats` 四件套、没有 `formula` 字段,公式写入只能走 `+cells-set` / `+csv-put`)。此外 `+csv-put` **不会**携带样式/批注/图片,也无法把 `=` 开头的内容当字面量文本写入;需要样式/批注/图片用 `+cells-set`(或"写值 + 补样式"两步法)。
65
65
 
66
66
  ⚠️ **`+csv-put` 会把数值落成文本**:把金额 / 百分比 / 计数等在本地拼成带 `$` / `%` / 千分位的字符串(如 `"$1,234.50"` / `"+30.5%"`)再 `+csv-put` 灌进去,单元格就是**文本**——丢失排序 / 求和 / 图表能力,且与数值列混排无法参与计算。数值该怎么写、何时 `+table-put`、版式装不下时何时退 `+cells-set` 传数字 + `number_format`,判据与分流见上方「数字还是文本」;核心一句:**准备把数字 format 成字符串再写时就是走错了路,数值一律以数字写入 + `number_format` 控制显示。**
67
67
 
68
- ⚠️ **`+csv-put` 也会把「看着像数字」的字段静默数值化**(与上一条相反的另一半坑):CSV 里语义是**日期标签 / 编号 / 标识符**、内容却全是数字字符的列,会被按数值解析——`12.10`→`12.1`(点分日期尾零丢失)、`3.0`→`3`、`001`→`1`、长号→科学计数。**这类列即使已攒好 CSV 文本也不能裸走 `+csv-put`**:优先 `+table-put` 把该列 `dtypes` 声明为 `object`(无年份的点分标签如 `12.10` / `3-1` 字面保真)或 `datetime64[ns]`(完整真日期),版式装不下再退 `+cells-set` + `number_format:"@"`。此类失真在「抽样首 / 中 / 末」回读时易被掩盖(`12.10` / `12.20` 等尾零行常不落在抽样窗口),日期 / 编号列回读要专挑带尾零 / 前导零的代表值核对。
68
+ ⚠️ **`+csv-put` 也会把「看着像数字」的字段静默数值化**(与上一条相反的另一半坑):CSV 里语义是**日期标签 / 编号 / 标识符**、内容却全是数字字符的列,会被按数值解析——`12.10`→`12.1`(点分日期尾零丢失)、`3.0`→`3`、`001`→`1`、长号→科学计数。**这类列即使已攒好 CSV 文本也不建议裸走 `+csv-put`**:优先 `+table-put` 把该列 `dtypes` 声明为 `object`(无年份的点分标签如 `12.10` / `3-1` 字面保真)或 `datetime64[ns]`(完整真日期),版式装不下再退 `+cells-set` + `number_format:"@"`。此类失真在「抽样首 / 中 / 末」回读时易被掩盖(`12.10` / `12.20` 等尾零行常不落在抽样窗口),日期 / 编号列回读要专挑带尾零 / 前导零的代表值核对。
69
69
 
70
70
  ⚠️ 大数据回写走"`+csv-get` 按 `--range` 行窗口分批读到本地 + 本地脚本处理 + `+csv-put` 分批回写"。
71
71
 
@@ -77,19 +77,20 @@
77
77
 
78
78
  > **单元格图片 vs 浮动图片(最易选错)**:图若**属于某条记录、要随那行排序 / 筛选 / 增删**(凭证 / 证件照 / 每行配图,话里带「对应 / 每行 / 这列」等绑定词)→ **单元格图片**(本工具):用 `+cells-set-image`(最短)或 `+cells-set` 的 `rich_text` + `type: "embed-image"`。只是自由摆放的装饰(logo / 水印 / 封面)→ 浮动图片,见 lark-sheets-float-image。别因「浮动图更好控制 / 更熟」默认选浮动图——它承载"对应某记录"的图会随增删行 / 排序错位。
79
79
 
80
- 常用模式(**必须遵守,禁止逐行写入替代**):
80
+ 常用模式(推荐,避免逐行写入替代):
81
81
 
82
- - 整列公式:先在 `H2` 写一个公式,再用 `--copy-to-range "H2:H100"` 或 `--copy-to-range "H:H"` 向下填充。**禁止对每一行单独调用 `+cells-set` 写入相同结构的公式**
83
- - 整列格式:先在 `J1` 写一个带样式的模板单元格,再用 `--copy-to-range "J:J"`
84
- - 首行样式:先在 `A1` 写一个模板单元格,再用 `--copy-to-range "1:1"`
85
- - 用户说”这列 / 整列 / 这行 / 首行 / 向下复制”时,**必须**使用模板单元格 + `--copy-to-range`
86
- - 多区域写入相同格式/公式结构时,优先写一个模板,再用 `--copy-to-range` 复制到所有目标区域
82
+ - 整列公式:先在 `H2` 写一个公式,再用 `--copy-to-range "H2:H100"` 或 `--copy-to-range "H:H"` 向下填充。避免对每一行单独调用 `+cells-set` 写入相同结构的公式
83
+ - **新写入**的整列格式:写模板格(值 + 样式)后 `--copy-to-range` 铺开;**已有值**的列 / 行统一格式改用 `+cells-set-style` / `+styles-put`(copy 会连值一起覆盖,见下方 ⚠️)——给已有表头行刷样式同理
84
+ - 用户说”这列 / 整列 / 这行 / 首行 / 向下复制”且目标区**本就要写同构值 / 公式**时,优先使用模板单元格 + `--copy-to-range`
85
+ - 多区域写入相同公式 / 值结构时,优先写一个模板,再用 `--copy-to-range` 复制到所有目标区域
86
+
87
+ ⚠️ **`--copy-to-range` 复制的是模板格的全部内容(值 + 公式 + 样式),不是只复制样式**:目标区域**已有值**时不要用它"刷样式"——会把整个区域的值覆盖成模板格的值(65 个格子全变成同一个数的事故就是这么来的)。只改样式、值 / 公式不动,用 `+cells-set-style` / `+cells-batch-set-style`;`--copy-to-range` 只用于目标区为空或本就要写同构公式 / 值的场景。
87
88
 
88
89
  ⚠️ **模板 `--range` 从数据行起算、别把表头圈进去**:`--copy-to-range` 会把 `--range` 模板按目标区尺寸周期性平铺,模板里若含了表头行,表头会每隔几行重复铺进数据区。整列填充时模板只取一格数据样式(如 `H2`),不要取成 `H1:H2`。
89
90
 
90
91
  ⚠️ **逐行写入公式是常见低效写法**:对每一行单独调用 `+cells-set` 写公式(如 26 次)既慢又易错,且不会自动平移公式引用。正确做法是 1 次模板写入 + 1 次 `--copy-to-range`(公式引用自动平移)。
91
92
 
92
- 💡 **多个不连续区域写入(批量修公式的正解)**:散布多处(可跨 sheet)的值 / 公式写入,用 `--writes` 一次批量交付(fail-fast、不回滚)——每项 `{sheet_name, range, cells}`(sheet 定位必须写在每项里),不要为此拼 `+batch-update` 的 `--operations`,也不要逐区域多次调用(多次往返、中途失败难恢复):
93
+ 💡 **多个不连续区域写入(批量修公式的正解)**:散布多处(可跨 sheet)的值 / 公式写入,用 `--writes` 一次批量交付(fail-fast,失败后先回读再补发)——每项 `{sheet_name, range, cells}`(sheet 定位必须写在每项里),不要为此拼 `+batch-update` 的 `--operations`,也不要逐区域多次调用(多次往返、中途失败难恢复):
93
94
 
94
95
  ```bash
95
96
  lark-cli sheets +cells-set --url "..." --writes - <<'JSON'
@@ -105,19 +106,19 @@ JSON
105
106
  💡 **写入公式前先按迁移规则改写**:如果公式来自 Excel 或包含数组场景,先读取并遵循 `lark-sheets-formula-translation` 的规则完成改写,再把最终公式写入 `formula` 字段。
106
107
 
107
108
  💡 **内容与样式分离写入(推荐)**:当需要同时写入内容和样式时,`cells` 中每个单元格都带上 `cell_styles` / `border_styles` 会导致入参非常冗长。由于同一区域的样式通常高度重复(如整列统一背景色、统一边框),推荐拆成两步:
108
- 1. **先写内容**:`+cells-set` 只传 `value` / `formula`,不带样式,`cells` 入参精简。⚠️ 这里"不带样式"指暂不带 `cell_styles`,**不是**降级用 `+csv-put` 铺文本——数值列(百分比 / 金额 / 计数)仍必须以数字写入(百分比传 `0.44`):样式能后补,数据类型不能后补(见上方「数字还是文本」)。
109
- 2. **再批量刷样式**:对区域中的一个单元格写入目标样式作为模板,再用 `--copy-to-range` 将样式扩展到整列 / 整行 / 整个区域(`--copy-to-range` 会复制值、公式和样式,所以模板单元格应已包含正确的值)
109
+ 1. **先写内容**:`+cells-set` 只传 `value` / `formula`,不带样式,`cells` 入参精简。⚠️ 这里"不带样式"指暂不带 `cell_styles`,**不是**降级用 `+csv-put` 铺文本——数值列(百分比 / 金额 / 计数)仍建议以数字写入(百分比传 `0.44`):样式能后补,数据类型不能后补(见上方「数字还是文本」)。
110
+ 2. **再批量刷样式**:用 `+styles-put` 对整个区域声明统一样式(可与合并 / 行高列宽 / 冻结同一份规格交付,见 `lark-sheets-styles-put`)。**不要**在这一步用模板格 `--copy-to-range` 刷样式——第 1 步已写入的各行值会被模板格的值整片覆盖(见上方 ⚠️);`--copy-to-range` 只适用于目标区本就要写同构值 / 公式的场景
110
111
 
111
112
  示例:要对 A2:A100 写入数据并统一设置蓝色背景 + 边框:
112
113
  ```
113
114
  Step 1: `+cells-set` — range="A2:A100", cells 只含 value(无样式,入参短)
114
- Step 2: `+cells-set` — range="A2", cells 含 value + cell_styles + border_styles(单个模板), --copy-to-range="A2:A100"
115
+ Step 2: `+styles-put` — 对 A2:A100 声明统一的 fill + border 样式
115
116
  ```
116
117
  这比在 99 个单元格中都重复写样式 JSON 高效得多。
117
118
 
118
119
  💡 **样式更新是「部分合并」,不是整体覆盖**:`+cells-set-style` / `+styles-put`(以及 `+cells-set` 的 `cell_styles` / `border_styles`)只改你**显式传入**的样式属性,未传的属性保留原值。两个实用推论:
119
120
  - **可分层叠加**:对同一区域先刷字体色、再单独刷背景色、再单独刷边框,后一步不会清掉前一步——美化已有区域时无需一次带齐所有字段,可拆成多次窄调用。
120
- - **`border_styles` 按边合并**:只传 `{"top":{...}}` 只更新上边框,`bottom` / `left` / `right` 保留原状;不必为了「只改一条边」而把四边全部重传。(例外见上方「新增行的边框/样式禁止用 `{}` 跳过」:**全新行**底子里没有边框,仍需把要显示的边都显式传出。)
121
+ - **`border_styles` 按边合并**:只传 `{"top":{...}}` 只更新上边框,`bottom` / `left` / `right` 保留原状;不必为了「只改一条边」而把四边全部重传。(例外见上方「新增行的边框/样式避免用 `{}` 跳过」:**全新行**底子里没有边框,仍需把要显示的边都显式传出。)
121
122
 
122
123
  💡 **大批量数据分批写入(推荐)**:当需要写入大量行(如几十行以上)时,不要试图在一次调用中生成全部 `cells` 数据——`cells` 数组过大会让单次生成的内容过长,容易出错或被截断。应将数据拆分为多批,每批 20-50 行,分多次调用 `+cells-set` 逐批生成并写入(如先写 `A2:D21`,再写 `A22:D41`,依此类推)。每次只生成当前批次的数据,控制单次生成量。
123
124
 
@@ -126,38 +127,38 @@ Step 2: `+cells-set` — range="A2", cells 含 value + cell_styles + border_styl
126
127
  - 不要把 `cells` 写成字符串化 JSON
127
128
  - `+cells-set` 默认即覆盖非空 cell(`--allow-overwrite` 默认 true);若要**保护**非空 cell 不被覆盖,显式传 `--allow-overwrite=false`(遇非空 cell 报错)
128
129
  - 若目标区域涉及合并单元格,不要向合并区域中的非左上角单元格写入数据;如需写入,应改写合并区域左上角单元格,或先调整/取消合并区域
129
- - **构造 `range` 时行号必须基于逻辑行号**:如果之前通过 `+csv-get` 读取了数据,CSV 中被双引号包裹的多行字段(如 `"2026年3月2日\n星期一"`)是**一个单元格**,不是两行。写入时的行号必须按逻辑记录计算,不能按物理换行符计数,否则 `range` 会整体偏移导致写入到错误位置
130
+ - **构造 `range` 时行号建议基于逻辑行号**:如果之前通过 `+csv-get` 读取了数据,CSV 中被双引号包裹的多行字段(如 `"2026年3月2日\n星期一"`)是**一个单元格**,不是两行。写入时的行号建议按逻辑记录计算,不能按物理换行符计数,否则 `range` 会整体偏移导致写入到错误位置
130
131
 
131
- > 用户说"样式和原表一致 / 保持原表格式 / 边框继承"时同理:`cell_styles` 只覆盖字体和对齐、**不含边框**,边框必须用独立 `border_styles` 字段传——完整继承清单见上方「新增列 / 新增行的样式继承」。
132
+ > 用户说"样式和原表一致 / 保持原表格式 / 边框继承"时同理:`cell_styles` 只覆盖字体和对齐、**不含边框**,边框建议用独立 `border_styles` 字段传——完整继承清单见上方「新增列 / 新增行的样式继承」。
132
133
 
133
- ⚠️ **公式写入必须自己校验结果(后端不会报语法错)**:`+cells-set` 写公式时,即便公式有括号不配对(如 `=IFERROR(VALUE(REGEXEXTRACT(D5, "\d+"))), 0)` 比 IFERROR 多一个 `)`)或用了飞书不支持的函数(如 `GOOGLETRANSLATE` / `CUBEVALUE`),**后端工具也会返回 `updated_cells_count=N, rc=0` 的"成功"**——错误会静默写进单元格显示为 `#VALUE!` / `#NAME?` / `#REF!`。因此:
134
- 1. **写完立即读回**:`+cells-set` 后紧跟 `+csv-get`(或 `+cells-get`)读目标范围前几行,检查是否出现 `#VALUE!` / `#NAME?` / `#REF!` / `#N/A` / `#DIV/0!` / `#NUM!`
135
- 2. **看到 `#` 开头的错误值**立即修公式:`#NAME?` 多半是函数名拼错或用了飞书不支持的函数(如 `GOOGLETRANSLATE` / CUBE 系列;注意 `UNIQUE` / `FILTER` / `SPLIT` 飞书是支持的);`#VALUE!` 多半是类型不匹配或括号错位;`#REF!` 是引用错误;`~CIRCULAR~REF~` 是循环引用(公式引用了自身或会闭环)
136
- 3. **`--copy-to-range` 扩展前先验证模板**:模板单元格公式自己都算错,`--copy-to-range` 复制到 100 行就是 100 个错误
137
- 4. **去重 / 筛选函数**:飞书**支持** `UNIQUE` / `FILTER` / `SPLIT`(原生数组函数,详见 `lark-sheets-formula-translation`),可直接用;`DISTINCT` 不是飞书函数,去重用 `UNIQUE`。大数据量去重 / 分组也可用透视表(`+pivot-{create|update|delete}`,值字段聚合方式选 count)
138
- 5. **循环引用预检**:写聚合公式(SUM / AVERAGE / COUNT 等)前必须明确**引用范围不包含目标单元格自身或其传递依赖**。典型反例:在 C3 写 `=SUMIF(B:B,LEFT(B3,9)&"*",C:C)`,B 列匹配 B3 前 9 位时 C3 自己也命中,导致 C3 自引用 → `~CIRCULAR~REF~`。修法:用辅助列 / 显式排除自身(`SUMIFS(C:C, B:B, ..., A:A, "<>"&A3)`)/ 缩小范围避开自己
139
- 6. **REGEX 模式覆盖率验证**:公式里的 `REGEXEXTRACT` / `REGEXMATCH` / `REGEXREPLACE` 等正则模式落地前必须用本地脚本在源列上跑一遍命中率统计(`df[col].str.contains(pattern).mean()`);命中率 < 100% 时必须扩展 pattern 或加多分支(IFS / 多个 IFERROR 串联)兜底,**禁止**只覆盖样本前 N 行就交付(典型反例:用 `REGEXEXTRACT(D5,"长(\d+)")` 只匹配带"长"前缀的尺寸文本,对"宽×高"、"×"、"*"等其它分隔符直接漏匹配)
140
- 7. **公式范围与用户指令字面对齐**:用户说"对 F 至 L 列求和"就必须写 `SUM(F2:L2)` 或 `F2+G2+H2+I2+J2+K2+L2`,**不能漏列、多列、错列**。写完用 `+cells-get` 拿回 `formula` 字符串,与用户原话逐字对照(参与求和的列名一致 / 起止列号一致 / 运算符一致),不一致就是违规
141
- 8. **量纲 / 单位换算 / 数量乘项预检(公式不报错但结果整体偏倍数)**:从文本提取数字做计算前,先核对**单位是否统一、是否漏乘数量、口径是否一致**——这类错误公式能跑通、无 `#` 报错,回读也看不出(值"像对的")。必须用本地脚本对 3–5 个代表行**离线手算一遍预期值**,与公式结果逐格比对量级:① 单位不一致先统一再算(典型反例:尺寸 `320CM*337CM` 直接取数相乘除以 1e6 得 0.11,正确是 CM→MM 换算后得 10.78,**差 100 倍**);② 按"单件×数量"的量必须乘数量列(典型反例:侧面板面积漏乘 F 列数量,F=2 的行只算了一半);③ 标准值口径对齐(典型反例:营养成分 mg/kg 与 g/100g 口径混用,整列放大 100 倍)。**口径 / 单位 / 数量任一项错,整列计算结果就是错的;这类错误公式不报错、回读也不易看出,必须靠离线手算对照。**
134
+ ⚠️ **公式写入建议自己校验结果(后端不会报语法错)**:`+cells-set` 写公式时,即便公式有括号不配对(如 `=IFERROR(VALUE(MID(D5,3,4))), 0)` 比 IFERROR 多一个 `)`)或用了飞书不支持的函数(如 `GOOGLETRANSLATE` / `CUBEVALUE`),**后端工具也会返回 `updated_cells_count=N, rc=0` 的"成功"**——错误会静默写进单元格显示为 `#VALUE!` / `#NAME?` / `#REF!`。因此:
135
+ 1. **写完建议读回**:`+cells-set` 后紧跟 `+csv-get`(或 `+cells-get`)读目标范围前几行,检查是否出现 `#VALUE!` / `#NAME?` / `#REF!` / `#N/A` / `#DIV/0!` / `#NUM!`
136
+ 2. **看到 `#` 开头的错误值**立即修公式:`#NAME?` 多半是函数名拼错或用了飞书不支持的函数(如 `GOOGLETRANSLATE` / CUBE 系列;注意 `UNIQUE` / `FILTER` 飞书是支持的);`#VALUE!` 多半是类型不匹配或括号错位;`#REF!` 是引用错误;`~CIRCULAR~REF~` 是循环引用(公式引用了自身或会闭环)
137
+ 3. **`--copy-to-range` 扩展前建议先验证模板**:模板单元格公式自己都算错,`--copy-to-range` 复制到 100 行就是 100 个错误
138
+ 4. **去重 / 筛选函数**:飞书**支持** `UNIQUE` / `FILTER`(原生数组函数,详见 `lark-sheets-formula-translation`),可直接用;`DISTINCT` 不是飞书函数,去重用 `UNIQUE`。大数据量去重 / 分组也可用透视表(`+pivot-{create|update|delete}`,值字段聚合方式选 count)
139
+ 5. **循环引用预检**:写聚合公式(SUM / AVERAGE / COUNT 等)前建议明确**引用范围不包含目标单元格自身或其传递依赖**。典型反例:在 C3 写 `=SUMIF(B:B,LEFT(B3,9)&"*",C:C)`,B 列匹配 B3 前 9 位时 C3 自己也命中,导致 C3 自引用 → `~CIRCULAR~REF~`。修法:用辅助列 / 显式排除自身(`SUMIFS(C:C, B:B, ..., A:A, "<>"&A3)`)/ 缩小范围避开自己
140
+ 6. **文本提取公式的覆盖率验证**:用 `LEFT` / `MID` / `FIND` / `SUBSTITUTE` / `TEXTSPLIT` 等从文本里抠数据前,建议用本地脚本在**整列源数据**上跑一遍命中率统计(`df[col].str.contains(pattern).mean()`);命中率 < 100% 时优先补分支(IFS / 多个 IFERROR 串联)兜底,或改用本地脚本算好写静态值,**避免**只覆盖样本前 N 行就交付(典型反例:按"长123"这种带前缀的尺寸文本取数,对"宽×高"、"×"、"*"等其它写法直接漏匹配)
141
+ 7. **公式范围与用户指令字面对齐**:用户说"对 F 至 L 列求和"优先写 `SUM(F2:L2)` 或 `F2+G2+H2+I2+J2+K2+L2`,**不能漏列、多列、错列**。写完用 `+cells-get` 拿回 `formula` 字符串,与用户原话逐字对照(参与求和的列名一致 / 起止列号一致 / 运算符一致),不一致就是风险
142
+ 8. **量纲 / 单位换算 / 数量乘项预检(公式不报错但结果整体偏倍数)**:从文本提取数字做计算前,先核对**单位是否统一、是否漏乘数量、口径是否一致**——这类错误公式能跑通、无 `#` 报错,回读也看不出(值"像对的")。建议用本地脚本对 3–5 个代表行**离线手算一遍预期值**,与公式结果逐格比对量级:① 单位不一致先统一再算(典型反例:尺寸 `320CM*337CM` 直接取数相乘除以 1e6 得 0.11,正确是 CM→MM 换算后得 10.78,**差 100 倍**);② 按"单件×数量"的量建议乘数量列(典型反例:侧面板面积漏乘 F 列数量,F=2 的行只算了一半);③ 标准值口径对齐(典型反例:营养成分 mg/kg 与 g/100g 口径混用,整列放大 100 倍)。**口径 / 单位 / 数量任一项错,整列计算结果就是错的;这类错误公式不报错、回读也不易看出,建议靠离线手算对照。**
142
143
 
143
- ⚠️ **公式写入的默认收尾不是停在回读,而是继续跑 `+formula-verify`**:`+csv-get` / `+cells-get` 的抽样回读只能帮你快速发现明显错误,但它覆盖不到整列中段、隐藏行、被条件格式遮蔽的错误,也看不到 `partial` 截断。**只要这次 `+cells-set` / `--copy-to-range` / `+csv-put` 实际写入了公式,收尾默认就是转到 `lark-sheets-formula-verify` 跑 `+formula-verify`,直到 `status='success'`。** 不要等用户补一句“再验证下公式”才做。
144
+ 💡 **公式写入后的补充诊断可用 `+formula-verify`**:`+csv-get` / `+cells-get` 的抽样回读只能帮你快速发现明显错误,但它覆盖不到整列中段、隐藏行、被条件格式遮蔽的错误,也看不到 `partial` 截断。如果这次 `+cells-set` / `--copy-to-range` / `+csv-put` 实际写入了公式,可转到 `lark-sheets-formula-verify` 跑 `+formula-verify` 做诊断。不要等用户补一句“再验证下公式”才想到这个工具。
144
145
 
145
- ⚠️ **收到 `formula_errors` 反馈后不要只打补丁**:`+cells-set` 返回值里若出现 `formula_errors: [{cell, formula, error_type, detail}]`,说明某些 cell 公式编译失败(`error_type=compile_failed` 通常是函数语法错如 `SPLIT(x)[1]` 的下标取值飞书不支持(SPLIT 本身支持,取第 N 项用 `INDEX(SPLIT(...),N)`);`non_formula` 是 `=` 开头但解析不通过)。此时**禁止只聚焦修报错点的局部语法**(如仅把 `[1]` 换成 `INDEX(..,1)`),必须:
146
+ ⚠️ **收到 `formula_errors` 反馈后不建议只打补丁**:`+cells-set` 返回值里若出现 `formula_errors: [{cell, formula, error_type, detail}]`,说明某些 cell 公式编译失败(`error_type=compile_failed` 通常是函数语法错,如对数组结果直接写 `[1]` 下标取值——飞书不支持这种写法,取第 N 项要用 `INDEX(<数组表达式>, N)`;`non_formula` 是 `=` 开头但解析不通过)。此时**避免只聚焦修报错点的局部语法**(如仅把 `[1]` 换成 `INDEX(..,1)`),建议:
146
147
 
147
148
  1. **重新审视整条公式的完整性**:被 formula_errors 标出的那一行,公式除了下标语法错,还可能有其他先天缺陷(字符清洗不全、IFERROR 兜底漏条件、引用列写错),修完语法错后立即整体复核
148
- 2. **同步对称修复所有相似列**:如果同一任务涉及多列相似处理(如"算 H 列面积"用 D 列尺寸、"算 I 列面积"用 E 列尺寸),**修完一列必须把同样的清洗/兜底逻辑同步到所有相似列**,禁止出现 H 列用 `SUBSTITUTE(长)+SUBSTITUTE(高)+SUBSTITUTE(×)` 而 I 列只用 `SUBSTITUTE(×)` 这种不对称处理——会导致一列编译通过有值、另一列编译通过但 IFERROR 全返回空,用户看到的是"数据为空"而非"公式错"
149
- 3. **修完再读回验证**:不只看 `formula_errors` 为空(这只证明编译通过,不证明运行时有值),必须 `+csv-get` 读目标列前 3-5 行,确认**非空源数据对应的目标列有非空计算结果**
149
+ 2. **同步对称修复所有相似列**:如果同一任务涉及多列相似处理(如"算 H 列面积"用 D 列尺寸、"算 I 列面积"用 E 列尺寸),**修完一列建议把同样的清洗/兜底逻辑同步到所有相似列**,避免出现 H 列用 `SUBSTITUTE(长)+SUBSTITUTE(高)+SUBSTITUTE(×)` 而 I 列只用 `SUBSTITUTE(×)` 这种不对称处理——会导致一列编译通过有值、另一列编译通过但 IFERROR 全返回空,用户看到的是"数据为空"而非"公式错"
150
+ 3. **修完再读回验证**:不只看 `formula_errors` 为空(这只证明编译通过,不证明运行时有值),建议 `+csv-get` 读目标列前 3-5 行,确认**非空源数据对应的目标列有非空计算结果**
150
151
  4. **核心心智**:`formula_errors` 是"帮你暴露编译错"的工具,不是"修掉它就收工"的通行证。编译通过 + 运行时 IFERROR 兜底空 = 用户视角的"没算出来"
151
152
 
152
- ⚠️ **新增行的边框/样式禁止用 `{}` 跳过**:`cells` 数组里 `{}` 的语义是"**此单元格不做任何修改、保留原状态**"。这在写入**已有行**时是安全的(原有边框/样式保持不变),但在写入**新行**(比如表尾追加汇总行、扩展行)时是灾难:新行底子里本来就没边框,`{}` 不修改 = 保留无边框状态,导致该 cell 视觉断裂。
153
+ ⚠️ **新增行的边框/样式避免用 `{}` 跳过**:`cells` 数组里 `{}` 的语义是"**此单元格不做任何修改、保留原状态**"。这在写入**已有行**时是安全的(原有边框/样式保持不变),但在写入**新行**(比如表尾追加汇总行、扩展行)时是灾难:新行底子里本来就没边框,`{}` 不修改 = 保留无边框状态,导致该 cell 视觉断裂。
153
154
 
154
- ⚠️ **"汇总行"识别 → 读 `lark-sheets-visual-standards` 拿完整样式规范**:下述双重条件**同时满足**才是汇总行,禁止仅凭"有 AVERAGE"就判定:
155
+ ⚠️ **"汇总行"识别 → 读 `lark-sheets-visual-standards` 拿完整样式规范**:下述双重条件**同时满足**才是汇总行,避免仅凭"有 AVERAGE"就判定:
155
156
  - **语义信号**(二选一):用户 prompt 含"合计/汇总/总计/统计/各科平均分/最下面加一行算…/底部总计"等意图词;或上下文明确是"表尾追加一行做聚合"
156
157
  - **结构信号**:新行全行都在做聚合(含 `=SUM/AVERAGE/COUNT/MAX/MIN/SUBTOTAL(...)`,支持 IFERROR 包裹),**不是**单个 cell 算个参考值或每行都算的派生列
157
158
 
158
159
  满足上述时,**不要在本文里猜样式**,直接去读 `lark-sheets-visual-standards` 的「场景一 → 1A. 添加汇总行 / 表头行」章节,按那里的样式要点配齐 `font.bold / horizontal_alignment / background_color / border_styles`。
159
160
 
160
- 反例(**不是**汇总行,禁止自动加粗):
161
+ 反例(**不是**汇总行,避免自动加粗):
161
162
  - 用户说"在 H5 帮我算个 AVERAGE 参考"→ 单 cell 计算
162
163
  - 每行都有 `=AVERAGE(本行区间)` 的派生列 → 属数据列
163
164
  - 用户明确说"不要加粗/样式和数据行保持一致"→ 遵循用户意图
@@ -167,11 +168,11 @@ Step 2: `+cells-set` — range="A2", cells 含 value + cell_styles + border_styl
167
168
  - **做法 A(推荐)**:按上方「内容与样式分离写入」两步法——先用模板单元格 + `--copy-to-range` 铺**完整样式**(`cell_styles` + `border_styles` 都要,不能只铺 border,否则新行字体 / 对齐 / 背景色全裸奔),再单独 `+cells-set` 写 value / formula。汇总行的 `cell_styles` 要点(bold / 背景色 / 上边框)见 `lark-sheets-visual-standards` 的「场景一 → 1A. 添加汇总行 / 表头行」。
168
169
  - **做法 B**:一次写入,但每个 cell(含空白格)都显式带 `cell_styles` + `border_styles`,**不能用 `{}`**。
169
170
 
170
- **判断是不是"新行"**:写入 range 超出 `+csv-get` 返回的 `current_region` 右 / 下边界(如 `current_region=A1:H10`、写 `A11:H11`)即新行,必须按上述做法补边框。
171
+ **判断是不是"新行"**:写入 range 超出 `+csv-get` 返回的 `current_region` 右 / 下边界(如 `current_region=A1:H10`、写 `A11:H11`)即新行,建议按上述做法补边框。
171
172
 
172
173
  ## 富文本单元格:超链接 / @人 / @文档(`rich_text`)
173
174
 
174
- 带显示文本的超链接、@人、@文档这类富内容**必须**走 `+cells-set` 的 `rich_text` 字段(`cells[].rich_text` 数组,每段一个对象、带 `type`),**不能**直接传普通字符串——纯字符串只会被当作纯文本存进单元格。完整字段跑 `lark-cli sheets +cells-set --print-schema --flag-name cells`,常用段类型:
175
+ 带显示文本的超链接、@人、@文档这类富内容**建议**走 `+cells-set` 的 `rich_text` 字段(`cells[].rich_text` 数组,每段一个对象、带 `type`),**不能**直接传普通字符串——纯字符串只会被当作纯文本存进单元格。完整字段跑 `lark-cli sheets +cells-set --print-schema --flag-name cells`,常用段类型:
175
176
 
176
177
  - **超链接(带显示文本)**:`{"type":"link","text":"飞书","link":"https://www.feishu.cn"}`。纯 URL 不需要 `rich_text`,直接写普通字符串即可。
177
178
  - **@人**:`{"type":"mention","mention_token":"<userId>","notify":false}`。**仅支持同租户用户,单次写入最多 50 人。** `notify` **默认 `true`**(会给被 @ 的人发通知),不想发务必显式传 `false`。
@@ -274,7 +275,7 @@ _公共四件套 · 系统:`--dry-run`_
274
275
  | --- | --- | --- | --- |
275
276
  | `--range` | string | xor | 写入区域(A1 格式)。与 `--writes` 二选一(单区域用 --range+--cells,多区域用 --writes) |
276
277
  | `--cells` | string + File + Stdin(复合 JSON) | xor | JSON:2D 数组 `[[{cell},...],...]`,维度与 `--range` 完全一致;每个 cell 可含 `value` / `formula` / `cell_styles` / `note` / `rich_text`(含 `type="embed-image"` 单元格嵌图)等,完整字段跑 `--print-schema` |
277
- | `--writes` | string + File + Stdin(复合 JSON) | xor | 多区域写入 JSON 数组(最多 100 项),每项 `{sheet_name\|sheet_id, range, cells}`——**sheet 定位必须写在每项里**(与 +batch-update 子操作、+styles-put 项同惯例,不认顶层 --sheet-name),cells 结构同 `--cells`(二维数组,可逐格带 cell_styles/border_styles)。整批展开为**单次批量提交**(fail-fast、不回滚),支持跨 sheet;典型场景:批量修复散布多处的公式、跨表同构写入——不要为此拼 +batch-update 的 --operations。与 `--range`+`--cells` 二选一;范围级统一样式不在此做,写完接 +styles-put |
278
+ | `--writes` | string + File + Stdin(复合 JSON) | xor | 多区域写入 JSON 数组(最多 100 项),每项 `{sheet_name\|sheet_id, range, cells}`——**sheet 定位必须写在每项里**(与 +batch-update 子操作、+styles-put 项同惯例,不认顶层 --sheet-name),cells 结构同 `--cells`(二维数组,可逐格带 cell_styles/border_styles)。整批展开为**单次批量提交**(fail-fast,失败后先回读再补发),支持跨 sheet;典型场景:批量修复散布多处的公式、跨表同构写入——不要为此拼 +batch-update 的 --operations。与 `--range`+`--cells` 二选一;范围级统一样式不在此做,写完接 +styles-put |
278
279
  | `--allow-overwrite` | bool | optional | 允许覆盖非空 cell(默认 true);设为 false 时遇非空 cell 报错 |
279
280
  | `--max-cells` | int | optional | 防爆,默认 50000(隐藏 flag:不在 `--help` 列出,但可正常传入) |
280
281
  | `--copy-to-range` | string | optional | 复制范围(A1 表示法):把 --range 中 --cells 写入的内容(值/公式/样式,取决于实际传入字段)复制到该区域,公式引用自动平移(如 C2=B2 → C3=B3)。适合先写一行/一块模板再扩展填充整列/整区域(如 --range A1:G1 写模板、--copy-to-range A1:G100 填充 100 行)。支持整行 3:6、整列 C:E、到列尾 D3:D、到行尾 D3:3;支持英文逗号分隔多个目标区域,如 C1:D2,E5:F6 |
@@ -320,7 +321,7 @@ _公共四件套 · 系统:`--dry-run`_
320
321
  | `--colors` | string + File + Stdin(简单 JSON) | optional | 下拉胶囊背景色,RGB hex 数组(如 `["#1FB6C1","#F006C2"]`)。长度可短不可长——超长 Validate 拦截(`--colors length (N) must not exceed dropdown source size (M)`),未指定项按内置 10 色色板循环补色。**单独传即生效**;`--highlight=false` 时被忽略。 |
321
322
  | `--multiple` | bool | optional | 启用多选;默认 `false` |
322
323
  | `--highlight` | bool | optional | 下拉胶囊背景色高亮开关。**不传 = 开**(按内置 10 色色板循环上色);`--highlight=false` 关闭得到纯白下拉。配色用 `--colors` 覆盖。 |
323
- | `--source-range` | string | xor | listFromRange 模式的下拉源 range,A1 表示法 + sheet 前缀(如 `'Sheet1'!T1:T3`)。映射到 server `data_validation.range`,搭配 server `data_validation.type='listFromRange'` 自动生效。跟 `--options` 二选一:传 `--options` 走 inline 列表(type=list),传本 flag 走 range 引用(type=listFromRange)。`--colors` 长度规则不变(≤ 源 range 单元格数),`--highlight` / `--multiple` 行为相同。当 `--highlight` 开启且 source 覆盖单元格数超过 2000 时,服务端会将该下拉判为 option-error(这是不支持的组合);CLI 会向 stderr 输出 warning。如需取消,传 `--highlight=false`。 |
324
+ | `--source-range` | string | xor | listFromRange 模式的下拉源 range,A1 表示法 + sheet 前缀(如 `'Sheet1'!T1:T3`)。映射到 server `data_validation.range`,搭配 server `data_validation.type='listFromRange'` 自动生效。跟 `--options` 二选一:传 `--options` 走 inline 列表(type=list),传本 flag 走 range 引用(type=listFromRange)。`--colors` 长度规则不变(≤ 源 range 单元格数),`--highlight` / `--multiple` 行为相同。当 `--highlight` 开启且 source 覆盖单元格数超过 2000 时,服务端会将该下拉判为 option-error(这是不支持的组合);CLI 会在返回结果的 `data.warnings` 中给出 warning。如需取消,传 `--highlight=false`。 |
324
325
 
325
326
  ### `+csv-put`
326
327
 
@@ -362,7 +363,7 @@ _【维度】行列数必须与 range 完全一致:'A1:C2'→[[_,_,_],[_,_,_]]
362
363
 
363
364
  ### `+cells-set` `--writes`
364
365
 
365
- _多区域写入项数组(最多 100 项),整批单次批量提交(fail-fast、不回滚);支持跨 sheet_
366
+ _多区域写入项数组(最多 100 项),整批单次批量提交(fail-fast,失败后先回读再补发);支持跨 sheet_
366
367
 
367
368
  **数组项**(类型 object):
368
369
  - `sheet_id` (string?) — 目标子表 reference_id;与 sheet_name 二选一,必须写在每一项里(不认顶层 sheet 定位)
@@ -500,10 +501,10 @@ lark-cli sheets +csv-put --spreadsheet-token shtXXX --sheet-id "$SID" \
500
501
  > # 反过来:无法用 +csv-put 写「= 开头的字面量文本」(会被当公式);样式/批注/图片仍用 +cells-set。
501
502
  > ```
502
503
  >
503
- > ⚠️ **公式内部含逗号 / 引号必须 RFC 4180 转义**:CSV 用逗号分隔字段,公式里的逗号(如 `COUNTIF(D5:D22,"及格")` 的参数分隔逗号)会被解析器当成字段分隔符,把一格拆成多格、整块二维结构压扁错位。规则:**含逗号的字段整格用双引号包裹,字段内部的引号再翻倍**:
504
+ > ⚠️ **公式内部含逗号 / 引号建议 RFC 4180 转义**:CSV 用逗号分隔字段,公式里的逗号(如 `COUNTIF(D5:D22,"及格")` 的参数分隔逗号)会被解析器当成字段分隔符,把一格拆成多格、整块二维结构压扁错位。规则:**含逗号的字段整格用双引号包裹,字段内部的引号再翻倍**:
504
505
  >
505
506
  > ```bash
506
- > # 从 G4 写一个 2 列 3 行的统计块;=COUNTIF 含逗号 + 内部引号,必须转义
507
+ > # 从 G4 写一个 2 列 3 行的统计块;=COUNTIF 含逗号 + 内部引号,建议转义
507
508
  > lark-cli sheets +csv-put --url "..." --sheet-name "Sheet1" \
508
509
  > --start-cell "G4" \
509
510
  > --csv $'统计项,结果\n成绩总和,=SUM(C5:C22)\n及格人数,"=COUNTIF(D5:D22,""及格"")"'
@@ -547,6 +548,7 @@ lark-cli sheets +table-put --url "<表URL>" --sheets - --styles @styles.json < s
547
548
  pandas 的 `df.to_json(orient="split", date_format="iso")` 一步完成所有清洗(NaN→null、Timestamp→ISO 字符串、numpy 标量→原生数字),把 dtypes 拼上即可。本 skill 把这段 5 行 helper 打包成可 import 的 [`scripts/sheets_df.py`](../scripts/sheets_df.py)(含 `df_to_sheet` 和 `sheet_to_df`,写入 / 读回成对):
548
549
 
549
550
  ```python
551
+ import sys; sys.path.insert(0, "scripts") # helper 在 skill 根的 scripts/ 下;cwd 不在 skill 根时填该目录的实际路径
550
552
  from sheets_df import df_to_sheet
551
553
 
552
554
  # 单 sheet(显式 format 覆盖默认显示)