docs(sheets): sync lark-sheets skill from sheet-skill-spec (add +recover)

Mirror generated/ from sheet-skill-spec: adds the +recover shortcut — skill
reference lark-sheets-recover.md + flag-defs/flag-schemas entry (方案B,
full-document rollback). Also brings this branch's lark-sheets skill in line
with the latest spec develop (workbook / write-cells reference + flag updates
larksuite-cli had not yet synced).
This commit is contained in:
zhengzhijie
2026-06-12 17:12:57 +08:00
parent c95ab1c28e
commit 0f238c25e0
6 changed files with 460 additions and 73 deletions

View File

@@ -1,37 +1,4 @@
{
"+recover": {
"risk": "write",
"flags": [
{
"name": "url",
"kind": "public",
"type": "string",
"required": "xor",
"desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)"
},
{
"name": "spreadsheet-token",
"kind": "public",
"type": "string",
"required": "xor",
"desc": "Spreadsheet token (XOR with `--url`)"
},
{
"name": "to-revision",
"kind": "own",
"type": "int",
"required": "required",
"desc": "Restore the whole spreadsheet to this revision (a revision number returned by a prior write)"
},
{
"name": "dry-run",
"kind": "system",
"type": "bool",
"required": "optional",
"desc": ""
}
]
},
"+workbook-info": {
"risk": "read",
"flags": [
@@ -87,7 +54,7 @@
"kind": "own",
"type": "int",
"required": "optional",
"desc": "Insert position; appended to the end when omitted",
"desc": "Insert position (0-based); appended to the end when omitted",
"default": "-1"
},
{
@@ -543,23 +510,12 @@
"required": "optional",
"desc": "Target folder token; placed at the drive root when omitted"
},
{
"name": "headers",
"kind": "own",
"type": "string",
"required": "optional",
"desc": "Header row as a JSON array: `[\"Col A\",\"Col B\"]`",
"input": [
"file",
"stdin"
]
},
{
"name": "values",
"kind": "own",
"type": "string",
"required": "optional",
"desc": "Initial data as a 2D JSON array: `[[\"alice\",95]]`",
"desc": "Untyped initial data as one 2D JSON array (`[[\"alice\",95]]`); values are written as-is with their type auto-detected, through the same batched set_cell_range path as --sheets — pair with --styles for number formats, colors, merges, and row/col sizes",
"input": [
"file",
"stdin"
@@ -570,19 +526,22 @@
"kind": "own",
"type": "string",
"required": "optional",
"desc": "Typed table payload as JSON (same shape as `+table-put`): a top-level `sheets` array, each item `{name, start_cell?, mode?, header?, allow_overwrite?, columns:[{name,type,format?}], rows:[[...]]}`; column `type` is one of string/number/date/bool. Mutually exclusive with --headers/--values. Creates the workbook, then writes typed type-faithful data (dates land as real dates, numbers keep precision).",
"desc": "Typed table payload as JSON (same shape as `+table-put`): a top-level `sheets` array, each item `{name, start_cell?, mode?, header?, allow_overwrite?, columns:[{name,type,format?}], rows:[[...]]}`; column `type` is one of string/number/date/bool. Mutually exclusive with --values. Creates the workbook, then writes typed type-faithful data (dates land as real dates, numbers keep precision).",
"input": [
"file",
"stdin"
]
},
{
"name": "header-style",
"name": "styles",
"kind": "own",
"type": "bool",
"type": "string",
"required": "optional",
"desc": "Bold the typed header row (only with --sheets; default true)",
"default": "true"
"desc": "Initial visual operations as JSON: top-level `{styles:[...]}`. Each item corresponds to one target sheet and must include `name`, plus at least one of `cell_styles` / `row_sizes` / `col_sizes` / `cell_merges`. `cell_styles` entries use +cells-set-style fields with a cell range; row/col sizes use dimension ranges plus type/size; merges use cell ranges plus optional merge_type. With --sheets, styles array length/order/name must match --sheets.sheets. With --values, pass exactly one styles item for the initial sheet (its name is ignored).",
"input": [
"file",
"stdin"
]
},
{
"name": "dry-run",
@@ -2053,7 +2012,7 @@
"kind": "own",
"type": "string",
"required": "required",
"desc": "RFC 4180 CSV text; plain values only (no formulas / styles / comments)",
"desc": "RFC 4180 CSV text; values or formulas (a leading = is evaluated as a formula); no styles / comments / images (use +cells-set for those).",
"input": [
"file",
"stdin"
@@ -2112,14 +2071,6 @@
"stdin"
]
},
{
"name": "header-style",
"kind": "own",
"type": "bool",
"required": "optional",
"desc": "Bold the header row written from column names (default true)",
"default": "true"
},
{
"name": "dry-run",
"kind": "system",
@@ -4787,5 +4738,38 @@
"desc": ""
}
]
},
"+recover": {
"risk": "write",
"flags": [
{
"name": "url",
"kind": "public",
"type": "string",
"required": "xor",
"desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)"
},
{
"name": "spreadsheet-token",
"kind": "public",
"type": "string",
"required": "xor",
"desc": "Spreadsheet token (XOR with `--url`)"
},
{
"name": "to-revision",
"kind": "own",
"type": "int",
"required": "required",
"desc": "Restore the whole spreadsheet to this revision (a revision number returned by a prior write)"
},
{
"name": "dry-run",
"kind": "system",
"type": "bool",
"required": "optional",
"desc": ""
}
]
}
}

View File

@@ -1730,11 +1730,12 @@
},
"aggregateType": {
"type": "string",
"description": "汇总方式,默认为'sum',仅在 aggregate 为 true 时生效",
"description": "汇总方式,默认为'sum',仅在 aggregate 为 true 时生效。count 只统计数值单元格counta 统计所有非空单元格(含文本),按文本/分类列统计出现次数(如各类别的数量、频次分布)时用 counta。",
"enum": [
"sum",
"average",
"count",
"counta",
"min",
"max",
"median"
@@ -2765,11 +2766,12 @@
},
"aggregateType": {
"type": "string",
"description": "汇总方式,默认为'sum',仅在 aggregate 为 true 时生效",
"description": "汇总方式,默认为'sum',仅在 aggregate 为 true 时生效。count 只统计数值单元格counta 统计所有非空单元格(含文本),按文本/分类列统计出现次数(如各类别的数量、频次分布)时用 counta。",
"enum": [
"sum",
"average",
"count",
"counta",
"min",
"max",
"median"
@@ -6424,6 +6426,293 @@
}
}
}
},
"styles": {
"items": {
"properties": {
"cell_merges": {
"description": "单元格合并操作数组range 使用 A1 单元格范围merge_type 默认 all。",
"items": {
"properties": {
"merge_type": {
"enum": [
"all",
"rows",
"columns"
],
"type": "string"
},
"range": {
"type": "string"
}
},
"required": [
"range"
],
"type": "object"
},
"type": "array"
},
"cell_styles": {
"description": "单元格样式操作数组;每项用 A1 单元格 range 指定范围,字段名与 +cells-set-style 对齐。",
"items": {
"properties": {
"background_color": {
"type": "string"
},
"border_styles": {
"type": "object",
"description": "边框配置,结构同 +cells-set-style --border-styles。",
"properties": {
"bottom": {
"properties": {
"color": {
"description": "边框颜色(十六进制,例如 \"#000000\"",
"type": "string"
},
"style": {
"description": "边框线型;传 \"none\" 表示清除该方向边框(无边框线)",
"enum": [
"solid",
"dashed",
"dotted",
"double",
"none"
],
"type": "string"
},
"weight": {
"description": "边框粗细/线宽",
"enum": [
"thin",
"medium",
"thick"
],
"type": "string"
}
},
"type": "object"
},
"left": {
"properties": {
"color": {
"description": "边框颜色(十六进制,例如 \"#000000\"",
"type": "string"
},
"style": {
"description": "边框线型;传 \"none\" 表示清除该方向边框(无边框线)",
"enum": [
"solid",
"dashed",
"dotted",
"double",
"none"
],
"type": "string"
},
"weight": {
"description": "边框粗细/线宽",
"enum": [
"thin",
"medium",
"thick"
],
"type": "string"
}
},
"type": "object"
},
"right": {
"properties": {
"color": {
"description": "边框颜色(十六进制,例如 \"#000000\"",
"type": "string"
},
"style": {
"description": "边框线型;传 \"none\" 表示清除该方向边框(无边框线)",
"enum": [
"solid",
"dashed",
"dotted",
"double",
"none"
],
"type": "string"
},
"weight": {
"description": "边框粗细/线宽",
"enum": [
"thin",
"medium",
"thick"
],
"type": "string"
}
},
"type": "object"
},
"top": {
"properties": {
"color": {
"description": "边框颜色(十六进制,例如 \"#000000\"",
"type": "string"
},
"style": {
"description": "边框线型;传 \"none\" 表示清除该方向边框(无边框线)",
"enum": [
"solid",
"dashed",
"dotted",
"double",
"none"
],
"type": "string"
},
"weight": {
"description": "边框粗细/线宽",
"enum": [
"thin",
"medium",
"thick"
],
"type": "string"
}
},
"type": "object"
}
}
},
"font_color": {
"type": "string"
},
"font_line": {
"enum": [
"none",
"underline",
"line-through"
],
"type": "string"
},
"font_size": {
"type": "number"
},
"font_style": {
"enum": [
"normal",
"italic"
],
"type": "string"
},
"font_weight": {
"enum": [
"normal",
"bold"
],
"type": "string"
},
"horizontal_alignment": {
"enum": [
"left",
"center",
"right"
],
"type": "string"
},
"number_format": {
"type": "string"
},
"range": {
"description": "A1 单元格范围,必须落在该子表本次写入区域内;例如 A1:B1、B2。",
"type": "string"
},
"vertical_alignment": {
"enum": [
"top",
"middle",
"bottom"
],
"type": "string"
},
"word_wrap": {
"enum": [
"overflow",
"auto-wrap",
"word-clip"
],
"type": "string"
}
},
"required": [
"range"
],
"type": "object"
},
"type": "array"
},
"col_sizes": {
"description": "列宽操作数组range 使用列范围如 A:Ctype 为 pixel/standardpixel 需要 size。",
"items": {
"properties": {
"range": {
"type": "string"
},
"size": {
"type": "number"
},
"type": {
"enum": [
"pixel",
"standard"
],
"type": "string"
}
},
"required": [
"range",
"type"
],
"type": "object"
},
"type": "array"
},
"name": {
"description": "子表名。--sheets 模式下必须与同位置 --sheets.sheets[].name 一致;--values 模式下建议写 Sheet1其 name 会被忽略)。",
"type": "string"
},
"row_sizes": {
"description": "行高操作数组range 使用行范围如 1:3type 为 pixel/standard/autopixel 需要 size。",
"items": {
"properties": {
"range": {
"type": "string"
},
"size": {
"type": "number"
},
"type": {
"enum": [
"pixel",
"standard",
"auto"
],
"type": "string"
}
},
"required": [
"range",
"type"
],
"type": "object"
},
"type": "array"
}
},
"required": [
"name"
],
"type": "object"
},
"type": "array"
}
}
}

View File

@@ -42,7 +42,7 @@ metadata:
| 读值 + 公式 / 样式 / 批注 | `+cells-get --include value,formula,style,comment,data_validation` | `--with-styles``--with-merges``--include-merged-cells` |
| 写纯文本值(整块 CSV 平铺,列里没有需保留的数值 / 日期语义) | `+csv-put`(定位用 `--start-cell`,单个左上角锚点格;也接受 `--range` 别名,区间自动取左上角) | — |
| 写带类型的数据到**已有**表(列里有数字 / 金额 / 百分比 / 日期 / 计数,要可排序 / 求和 / 入图表 / 透视) | `+table-put`(列显式声明 `type` + `format`,类型保真;来源不限 DataFrame——Counter / dict / list 同理,详见 write-cells | 在本地把数字拼成 `"$1,234"` / `"30.5%"` 字符串再 `+csv-put`(会落成文本、丢失计算能力) |
| **新建**电子表格并写带类型的数据(类型保真需求同上,但目标表还不存在) | `+workbook-create --sheets`(协议与 `+table-put` 同构、一步建表 + typed 写入,无需先建空表再 `+table-put`date / number 不丢,详见 workbook | 用 `--headers` / `--values` 灌日期 / 数字(会落成文本、丢类型) |
| **新建**电子表格并写带类型的数据(类型保真需求同上,但目标表还不存在) | `+workbook-create --sheets`(协议与 `+table-put` 同构、一步建表 + typed 写入,无需先建空表再 `+table-put`date / number 不丢,详见 workbook | 用 `--values` 灌日期 / 数字(会落成文本、丢类型) |
| 写值 / 公式 / 样式 | `+cells-set`(定位用 `--range` | — |
| 查找单元格 | `+cells-search`(关键字用 `--find` | `+cells-find``+find``--query` |
| 查找并替换 | `+cells-replace` | — |
@@ -90,6 +90,7 @@ metadata:
| [Lark Sheet Filter View](references/lark-sheets-filter-view.md) | 管理飞书表格中的筛选视图filter view。当用户需要"建一个 XX 视图"、"保存这个筛选状态"、"切换不同筛选"、维护一个 sheet 上多份独立筛选配置时使用。视图与筛选器filter相互独立可在同一 sheet 共存;视图的隐藏行仅在用户进入该视图时本地生效,不影响其他协作者。 |
| [Lark Sheet Sparkline](references/lark-sheets-sparkline.md) | 管理飞书表格中的迷你图(折线迷你图、柱形迷你图、胜负迷你图)。当用户需要在单元格内嵌入小型图表来展示数据趋势时使用。也适用于"趋势线"、"单元格内图表"、"迷你图"等场景。注意:不等同于被禁用的 SPARKLINE() 公式函数。 |
| [Lark Sheet Float Image](references/lark-sheets-float-image.md) | 管理飞书表格中的浮动图片。当用户需要在表格中插入浮动图片、调整图片位置和大小、查看已有浮动图片、删除图片时使用。也适用于"插入图片"、"添加 logo"、"放一张图"等场景。注意:如果用户需要将图片嵌入到某个单元格内部(单元格图片),请阅读 lark-sheets-write-cells。 |
| [Lark Sheet Recover](references/lark-sheets-recover.md) | 整表回退到历史版本(方案 B。当用户提到"恢复到之前的版本"、"撤销所有改动回到某个状态"、"整表回滚"、"recover"时使用。这是全文档回退(丢弃目标版本之后的所有编辑,含他人改动)——要精确逐笔撤销本链路最近编辑,用 +undo。 |
## 公共 flag 速查
@@ -107,7 +108,7 @@ metadata:
1. **spreadsheet 定位(必填)**`--url``--spreadsheet-token` 二选一,**必须给其中之一**。两个都不给 → 校验报错 `specify at least one of --url or --spreadsheet-token`;两个都给 → 互斥冲突。
- **`--url` 只解析 `/sheets/``/spreadsheets/` 两种链接**(从路径里抽出 token也可以直接把裸 token 传给 `--spreadsheet-token`)。其它形态的链接不会被解析成表格 token。
- ⚠️ **`/wiki/` 知识库链接不能直接当表格定位用**wiki 链接背后可能是电子表格,也可能是文档 / 多维表格等其它类型,`--url` **不会**自动把 wiki token 解析成 spreadsheet token直接传会失败。必须先把它解析成真实文档 token —— `lark-cli wiki +node-get --node-token "<wiki 链接或 token>"`,确认返回的 `obj_type``sheet` 后,取其 `obj_token` 作为 `--spreadsheet-token` 传入(解析细节见 [`../lark-wiki/SKILL.md`](../lark-wiki/SKILL.md))。
- **例外**`+workbook-create`(新建表 + 可选写入数据)与 `+workbook-import`(把本地文件导入为新表)都产出一张**还不存在**的表格,**不接受任何 spreadsheet / sheet 定位 flag**——`+workbook-create` 只有 `--title` / `--folder-token` / `--headers` / `--values` / `--sheets``+workbook-import` 只有 `--file`(必填)/ `--folder-token` / `--name`
- **例外**`+workbook-create`(新建表 + 可选写入数据)与 `+workbook-import`(把本地文件导入为新表)都产出一张**还不存在**的表格,**不接受任何 spreadsheet / sheet 定位 flag**——`+workbook-create` 只有 `--title` / `--folder-token` / `--values` / `--styles` / `--sheets``+workbook-import` 只有 `--file`(必填)/ `--folder-token` / `--name`
2. **sheet 定位(公共四件套 shortcut 必填)**`--sheet-id``--sheet-name` 二选一,**必须给其中之一**。两个都不给 → 校验报错 `specify at least one of --sheet-id or --sheet-name`
- ⚠️ **不确定 sheet 名时禁止直接猜 `Sheet1`**:除非用户对话明确说出 sheet 名 / id或上下文之前的工具调用 / URL 锚点 `?sheet=xxx`)已经出现过具体值,否则**第一步先调 `+workbook-info --url "..."`**(或 `--spreadsheet-token`)拿 `sheets[].sheet_id` / `sheets[].title` 列表再选。中文环境下子表常叫"数据" / "Sheet"(无数字)/ "工作表 1" / 业务名,猜 `Sheet1` 大概率撞 `sheet not found`,比先查多耗一次失败调用 + 重试。
- ⚠️ **`--range` 里的 `Sheet1!` 前缀不能替代 sheet 定位**:即使写了 `--range 'Sheet1!A1:B2'`,仍**必须**额外传 `--sheet-id``--sheet-name`,否则照样报上面的错。

View File

@@ -0,0 +1,41 @@
# Lark Sheet Recover
## 使用场景
写。整表回退到指定历史 revision方案 B。本 reference 覆盖 1 个 shortcut
| 操作需求 | 使用工具 | 说明 |
|---------|---------|------|
| 整表回退到历史版本 | `+recover` | 把整个 spreadsheet 回退到 `--to-revision` 指定的版本,丢弃其后所有编辑 |
⚠️ **全文档破坏性回退**`+recover` 丢弃 `--to-revision` 之后的**所有**编辑,包括其他协作者的改动。只在 agent 自己的草稿表、或确认要整表回滚时使用。要精确撤销本链路最近几笔编辑,请用 `+undo`(逐笔、可控、不波及他人)。
## Shortcuts
| Shortcut | Risk | 分组 |
| --- | --- | --- |
| `+recover` | write | 撤销恢复 |
## Flags
### `+recover`
_公共URL/token无 sheet 定位) · 系统:`--dry-run`_
| Flag | Type | 必填 | 说明 |
| --- | --- | --- | --- |
| `--to-revision` | int | required | 整表回退到该 revision来自此前写操作返回的 revision |
## Examples
### `+recover`
把整表回退到某个历史版本。`--to-revision` 取此前某次写操作响应里返回的 `revision`
```bash
lark-cli sheets +recover --spreadsheet-token <token> --to-revision 42
```
- 回退会产生一个**新** revision不是删历史而是追加一条回退记录响应里返回这个新 revision。
- 回退不可逆地丢弃 `--to-revision` 之后的内容,执行前先确认要丢弃的范围。
-`+undo` 的区别:`+undo` 精确撤销本 CLI 链路最近 N 笔编辑、不动他人改动;`+recover` 是全文档回到某版本、丢弃所有后续(含他人)。需要细粒度撤销时优先 `+undo`

View File

@@ -138,10 +138,9 @@ _系统`--dry-run`_
| --- | --- | --- | --- |
| `--title` | string | required | 新 spreadsheet 标题 |
| `--folder-token` | string | optional | 目标文件夹 token省略时放在云空间根目录 |
| `--headers` | string + File + Stdin简单 JSON | optional | 表头行 JSON 数组`["列A","列B"]` |
| `--values` | string + File + Stdin简单 JSON | optional | 初始数据 JSON 二维数组:`[["alice",95]]` |
| `--sheets` | string + File + Stdin复合 JSON | optional | 建表后写入的 typed 表格协议 JSON同 +table-put顶层 sheets 数组,每项 {name, start_cell?, mode?, header?, allow_overwrite?, columns:[{name,type,format?}], rows:[[...]]}type 为 string/number/date/bool。与 --headers/--values 互斥;新表默认子表复用为第一个子表,日期/数字类型保真。 |
| `--header-style` | bool | optional | 把 typed 表头行加粗(仅 --sheets 时生效,默认 true |
| `--values` | string + File + Stdin简单 JSON | optional | untyped 初始数据,一个 JSON 二维数组(表头并入第一行)`[["列A","列B"],["alice",95]]`;值原样写入、类型由飞书自动识别,走与 --sheets 相同的分批 `+cells-set`;配 --styles 控制格式/颜色/合并/行列尺寸 |
| `--sheets` | string + File + Stdin复合 JSON | optional | 建表后写入的 typed 表格协议 JSON同 +table-put顶层 sheets 数组,每项 {name, start_cell?, mode?, header?, allow_overwrite?, columns:[{name,type,format?}], rows:[[...]]}type 为 string/number/date/bool。与 --values 互斥;新表默认子表复用为第一个子表,日期/数字类型保真。 |
| `--styles` | string + File + Stdin复合 JSON | optional | 建表时同时写入的视觉处理操作 JSON顶层 `{styles:[...]}`,每项对应一个目标子表、含 `name`,并至少给 `cell_styles` / `row_sizes` / `col_sizes` / `cell_merges` 之一。`cell_styles` 用 A1 单元格 range + 扁平样式字段(字段同 +cells-set-style含 number_format / 颜色 / 对齐 / border_stylesrow/col sizes 用行/列范围 + type/sizemerges 用单元格 range + 可选 merge_type。与 --sheets 搭配时 styles 数组长度/顺序/name 必须与 --sheets.sheets 对应;与 --values 搭配时只给一个 styles 项(其 name 忽略)。 |
### `+workbook-export`
@@ -178,6 +177,16 @@ _一个或多个子表的 typed 数据,每个数组元素写入一张子表;
- `columns` (array<object>) — 列定义,顺序与 rows 中每行的取值一一对应 each: { name: string, type: enum, format?: string }
- `rows` (array<array<string|number|boolean|null>>) — 数据行;每行是一个数组,长度必须等于 columns 数
### `+workbook-create` `--styles`
**数组项**(类型 object
- `cell_merges` (array<object>?) — 单元格合并操作数组range 使用 A1 单元格范围merge_type 默认 all each: { merge_type?: enum, range: string }
- `cell_styles` (array<object>?) — 单元格样式操作数组;每项用 A1 单元格 range 指定范围,字段名与 +cells-set-style 对齐 each: { background_color?: string, border_styles?: object, font_color?: string, font_line?: enum, font_size?: number, …共 12 项 }
- `col_sizes` (array<object>?) — 列宽操作数组range 使用列范围如 A:Ctype 为 pixel/standardpixel 需要 size each: { range: string, size?: number, type: enum }
- `name` (string) — 子表名
- `row_sizes` (array<object>?) — 行高操作数组range 使用行范围如 1:3type 为 pixel/standard/autopixel 需要 size each: { range: string, size?: number, type: enum }
## Examples
公共四件套:所有 shortcut 顶部排列 `--url` / `--spreadsheet-token` / `--sheet-id` / `--sheet-name`XOR`+workbook-info` 只用前两者;`+sheet-*` 系列对单个工作表操作,需 `--sheet-id``--sheet-name`
@@ -188,12 +197,13 @@ _一个或多个子表的 typed 数据,每个数组元素写入一张子表;
### `+workbook-create`
新建电子表格,可选预填数据。两种数据入口**互斥**,按需二选一
新建电子表格,可选预填数据。两种数据入口untyped `--values` / typed `--sheets`**互斥**,按需二选一——两者都走同一条分批 `set_cell_range` 写入
```bash
# 1) untyped--headers + --values纯值类型由飞书自动识别,日期会落成文本)
# 1) untyped--values一个二维数组表头并入第一行值原样写、类型由飞书自动识别,
# 日期会落成文本,配 --styles 控制格式)
lark-cli sheets +workbook-create --title "销售" \
--headers '["门店","销售额"]' --values '[["北京",259874]]'
--values '[["门店","销售额"],["北京",259874]]'
# 2) typed--sheets一步建表 + 类型保真。date 列落成真日期(可排序/透视)、
# number 不丢精度、string 列保前导零(如订单号 00123多子表一次建。
@@ -209,6 +219,69 @@ lark-cli sheets +workbook-create --title "交易" --sheets '{
`--sheets` 协议与 `+table-put` 完全同构(字段含义见 lark-sheets-write-cells 的 `+table-put`,大 payload 走 stdin / `@file`)。关键差异:**新建工作簿的默认子表会被复用为第一个子表**(重命名后承载数据),不会残留空 `Sheet1`;其余子表按需新建。它把 `+table-put` 单独做不到的"建表 + typed 写入"合到一条命令是「pandas 算完直接落地一张带真日期的新表」的首选。回读校验用 `+table-get`(与 `--sheets` 同构、可 round-trip
`--styles` 可在建表写入时同时写视觉处理。它和 `--sheets` 一样只有一种外层写法:顶层对象里放 `styles` 数组;数组每项对应一个子表,含 `name`,并按能力拆成四类可选数组:
- `cell_styles`:像 `+cells-set-style`,用 A1 单元格 `range` 加扁平样式字段(`font_weight` / `background_color` / `number_format` 等)和可选 `border_styles`;这些样式会合并进同一次内容 `set_cell_range`
- `cell_merges`:用 A1 单元格 `range` 设置合并,`merge_type` 默认为 `all`,可选 `rows` / `columns`
- `row_sizes`:用行范围(如 `1:3`)设置行高,`type``pixel` / `standard` / `auto``pixel` 需要 `size`
- `col_sizes`:用列范围(如 `A:C`)设置列宽,`type``pixel` / `standard``pixel` 需要 `size`
同一单元格命中多个 `cell_styles` 项时,后面的操作继续合并覆盖已传字段。`cell_merges` / `row_sizes` / `col_sizes` 在内容写入后顺序执行。
```bash
# 3) untyped仍用 {"styles":[...]}只有一个子表样式项name 忽略range 覆盖 --values 初始区域
lark-cli sheets +workbook-create --title "销售" \
--values '[["门店","销售额"],["北京",259874],["上海",198320]]' \
--styles '{
"styles":[
{"name":"Sheet1","cell_styles":[
{"range":"A1:B1","font_weight":"bold","background_color":"#f5f5f5"},
{"range":"B2:B3","number_format":"#,##0"}
]}
]
}'
# 4) typed 单子表:--styles.styles[0].name 必须对应 --sheets.sheets[0].name
lark-cli sheets +workbook-create --title "交易" --sheets '{
"sheets":[
{"name":"明细","columns":[
{"name":"日期","type":"date"},
{"name":"金额","type":"number","format":"#,##0.00"}
],"rows":[["2024-01-15",1234.5]]}
]}' --styles '{
"styles":[
{"name":"明细",
"cell_styles":[
{"range":"A1:B1","font_weight":"bold","background_color":"#f5f5f5",
"border_styles":{"bottom":{"style":"solid","weight":"thin","color":"#000000"}}},
{"range":"A2:A2","number_format":"yyyy-mm-dd"},
{"range":"B2:B2","number_format":"#,##0.00","font_color":"#0f7b0f"}
],
"cell_merges":[{"range":"A1:B1"}],
"col_sizes":[{"range":"A:B","type":"pixel","size":120}],
"row_sizes":[{"range":"1:1","type":"pixel","size":28}]}
]
}'
# 5) typed 多子表styles 数组和 sheets 数组长度、顺序、name 都必须一致
lark-cli sheets +workbook-create --title "经营看板" --sheets '{
"sheets":[
{"name":"收入","columns":[{"name":"月份","type":"string"},{"name":"收入","type":"number","format":"#,##0"}],"rows":[["2026-05",1200000]]},
{"name":"成本","columns":[{"name":"月份","type":"string"},{"name":"成本","type":"number","format":"#,##0"}],"rows":[["2026-05",730000]]}
]}' --styles '{
"styles":[
{"name":"收入","cell_styles":[
{"range":"A1:B1","font_weight":"bold","background_color":"#f0f7ff"},
{"range":"B2:B2","font_color":"#0f7b0f"}
]},
{"name":"成本","cell_styles":[
{"range":"A1:B1","font_weight":"bold","background_color":"#fff7ed"},
{"range":"B2:B2","font_color":"#b42318"}
]}
]
}'
```
> ⚠️ **`+workbook-create` 是把内存里的数据写成新表;要把已有的本地 Excel/CSV 文件原样导入成新表,用 `+workbook-import`**(见下),不要先在本地读出文件再 `+workbook-create` 重灌。
### `+workbook-import`
@@ -283,6 +356,6 @@ lark-cli sheets +sheet-hide-gridline --url "..." --sheet-id "$SID"
### Validate / DryRun / Execute 约束
- `Validate`XOR 公共四件套;`+sheet-create` 校验 `--title` 非空、`--row-count` ≤ 50000、`--col-count` ≤ 200`+sheet-delete` 必须 `--yes``--dry-run``+workbook-create``--sheets``--headers`/`--values` **互斥**,给了 `--sheets` 则按 typed 协议校验 payload其余约束同 `+table-put`)。
- `Validate`XOR 公共四件套;`+sheet-create` 校验 `--title` 非空、`--row-count` ≤ 50000、`--col-count` ≤ 200`+sheet-delete` 必须 `--yes``--dry-run``+workbook-create``--sheets``--values` **互斥**,给了 `--sheets` 则按 typed 协议校验 payload其余约束同 `+table-put`)。
- `DryRun``+sheet-*` 写操作输出"将要 PATCH 的 sheet metadata"`--sheet-name` 在 dry-run 输出里生成为 `<resolve:Sheet1>` 占位符,不实际解析为 sheet-id。
- `Execute`:写操作不自动回读;如需确认目标 sheet 的新状态,自行调用 `+workbook-info`

View File

@@ -318,7 +318,6 @@ _公共URL/token无 sheet 定位) · 系统:`--dry-run`_
| Flag | Type | 必填 | 说明 |
| --- | --- | --- | --- |
| `--sheets` | string + File + Stdin复合 JSON | required | typed 表格协议 JSON顶层 sheets 数组,每项 {name, start_cell?, mode?, header?, allow_overwrite?, columns:[{name,type,format?}], rows:[[...]]}type 为 string/number/date/bool |
| `--header-style` | bool | optional | 把列名表头行加粗(默认 true |
## Schemas