mirror of
https://github.com/larksuite/cli.git
synced 2026-08-03 08:32:46 +08:00
Compare commits
1 Commits
feat/lark-
...
feat/get-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7d7cb03eb |
@@ -1316,7 +1316,14 @@
|
||||
"kind": "own",
|
||||
"type": "bool",
|
||||
"required": "optional",
|
||||
"desc": "Skip hidden rows and columns; default `false`"
|
||||
"desc": "Skip hidden or collapsed rows and columns. Default `false`; when `--skip-filter` is omitted, filtered-out rows follow this value for backward compatibility"
|
||||
},
|
||||
{
|
||||
"name": "skip-filter",
|
||||
"kind": "own",
|
||||
"type": "bool",
|
||||
"required": "optional",
|
||||
"desc": "Skip filtered-out rows. When omitted, inherits `--skip-hidden`; explicitly set to `false` to keep filtered-out rows while skipping hidden rows and columns"
|
||||
},
|
||||
{
|
||||
"name": "dry-run",
|
||||
|
||||
@@ -78,7 +78,8 @@ var flagDefs = map[string]commandDef{
|
||||
{Name: "include", Kind: "own", Type: "string_slice", Required: "optional", Desc: "Comma-separated info categories to include. `truncation` additionally estimates whether each cell's content is clipped (by row height / col width / font size / wrap) and returns `isRowTruncated` / `isColTruncated` (extra compute; enable only for layout checks or before adjusting row heights / column widths)", Enum: []string{"value", "formula", "style", "comment", "data_validation", "truncation"}},
|
||||
{Name: "max-chars", Kind: "own", Type: "int", Required: "optional", Desc: "Max output chars per call; default 500000 (safety cap). For a full untruncated read, use --output-path to dump to a file (auto-unlimited); only lower it (e.g. 25000) when you want results inline without a file, paging via has_more.", Default: "500000"},
|
||||
{Name: "output-path", Kind: "own", Type: "string", Required: "optional", Desc: "Write the full read result to a local path (e.g. `./out.json`); the file holds the data payload as JSON while stdout returns only a small confirmation (output_path, byte count). **When set, the char cap defaults to unlimited** (overriding the --max-chars default), so a large sheet can be dumped in full for later analysis without stdout being truncated by max_chars. Omit it to print to stdout as usual."},
|
||||
{Name: "skip-hidden", Kind: "own", Type: "bool", Required: "optional", Desc: "Skip hidden rows and columns; default `false`"},
|
||||
{Name: "skip-hidden", Kind: "own", Type: "bool", Required: "optional", Desc: "Skip hidden or collapsed rows and columns. Default `false`; when `--skip-filter` is omitted, filtered-out rows follow this value for backward compatibility"},
|
||||
{Name: "skip-filter", Kind: "own", Type: "bool", Required: "optional", Desc: "Skip filtered-out rows. When omitted, inherits `--skip-hidden`; explicitly set to `false` to keep filtered-out rows while skipping hidden rows and columns"},
|
||||
{Name: "dry-run", Kind: "system", Type: "bool", Required: "optional"},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -83,6 +83,11 @@ func cellsGetInput(runtime *common.RuntimeContext, token, sheetID, sheetName str
|
||||
if runtime.Bool("skip-hidden") {
|
||||
input["skip_hidden"] = true
|
||||
}
|
||||
// Preserve omission so the tool can keep the legacy fallback where
|
||||
// skip_filter inherits skip_hidden. An explicit false must still be sent.
|
||||
if runtime.Changed("skip-filter") {
|
||||
input["skip_filter"] = runtime.Bool("skip-filter")
|
||||
}
|
||||
// --cell-limit was removed from the CLI surface; --max-chars is the single
|
||||
// read cap. Pin cell_limit very high so the tool's own default never binds
|
||||
// before max_chars.
|
||||
|
||||
@@ -34,6 +34,25 @@ func TestReadDataShortcuts_DryRun(t *testing.T) {
|
||||
"cell_limit": float64(unboundedReadLimit), // pinned high; --max-chars is the only cap
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "+cells-get skip filtered rows only",
|
||||
sc: CellsGet,
|
||||
args: []string{"--url", testURL, "--sheet-id", testSheetID, "--range", "A1:B2", "--skip-filter"},
|
||||
toolName: "get_cell_ranges",
|
||||
wantInput: map[string]interface{}{
|
||||
"skip_filter": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "+cells-get skip hidden but keep filtered rows",
|
||||
sc: CellsGet,
|
||||
args: []string{"--url", testURL, "--sheet-id", testSheetID, "--range", "A1:B2", "--skip-hidden", "--skip-filter=false"},
|
||||
toolName: "get_cell_ranges",
|
||||
wantInput: map[string]interface{}{
|
||||
"skip_hidden": true,
|
||||
"skip_filter": false,
|
||||
},
|
||||
},
|
||||
{
|
||||
// --include truncation toggles include_truncation_info so the tool
|
||||
// estimates and returns per-cell isRowTruncated / isColTruncated.
|
||||
@@ -90,6 +109,17 @@ func TestReadDataShortcuts_DryRun(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCellsGet_OmitsSkipFilterWhenUnset(t *testing.T) {
|
||||
t.Parallel()
|
||||
body := parseDryRunBody(t, CellsGet, []string{
|
||||
"--url", testURL, "--sheet-id", testSheetID, "--range", "A1:B2",
|
||||
})
|
||||
got := decodeToolInput(t, body, "get_cell_ranges")
|
||||
if _, ok := got["skip_filter"]; ok {
|
||||
t.Fatalf("skip_filter must be omitted when --skip-filter is unset: %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestDropdownGet_RequiresSheetSelector locks the +cells-get-style
|
||||
// selector contract: at least one of --sheet-id / --sheet-name must be
|
||||
// supplied. Before BUG-019 fix this shortcut required a "Sheet!A1"
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
注意:
|
||||
|
||||
- `+csv-get` 和 `+cells-get` 支持分页/截断,注意检查 `has_more` / `truncated` 标志;两者在处理返回数据之前都必须先读 `warning_message`(上游 schema 要求先读它再用其它字段,内含定位与截断续读提示),`+cells-get` 还要用每个 range 的 `actual_range` / `row_indices` / `col_indices` 判断真实位置
|
||||
- 隐藏行列默认包含在返回结果中(`--skip-hidden=false`),如需只看可见数据设为 `true`。读取原语本身不标注哪些行列被隐藏:若要识别隐藏区间(以决定是否过滤、或如何解读混入的隐藏数据),用 `+sheet-info --include hidden_rows,hidden_cols` 取隐藏行列集合,再结合 `+csv-get` / `+cells-get` 返回的 `row_indices` / `col_indices` 判断每行 / 每列是否隐藏
|
||||
- `+cells-get` 可独立控制隐藏与筛选:`--skip-hidden` 只控制隐藏或分组折叠的行列,`--skip-filter` 只控制被筛选掉的行。两者都为 `false` 时返回完整数据;仅 `--skip-filter=true` 时保留隐藏行列但跳过筛选行;仅 `--skip-hidden=true --skip-filter=false` 时跳过隐藏行列但保留筛选行;两者都为 `true` 时只返回同时可见且未被筛选掉的数据。为兼容旧调用,未显式传 `--skip-filter` 时会继承 `--skip-hidden`。读取原语本身不标注哪些行列被隐藏:若要识别隐藏区间,用 `+sheet-info --include hidden_rows,hidden_cols` 取隐藏行列集合,再结合 `+cells-get` 返回的 `row_indices` / `col_indices` 判断真实位置
|
||||
- 要判断单元格内容是否被行高列宽挤到显示不全(排版检查、调整行高列宽前),给 `+cells-get` 加 `--include truncation`:会按字号 / 自动换行 / 行高列宽估算并返回被截断单元格的 `isRowTruncated` / `isColTruncated`(未返回视为未截断)。有额外计算开销,仅需要时才开
|
||||
|
||||
**常见配置错误(必须注意)**:
|
||||
@@ -54,7 +54,7 @@
|
||||
- 数据量大或会进入上下文上限时,分批读 + 本地处理 + 分批回写,不要一口气拉全表到上下文。
|
||||
- **`+cells-get` 滥用**:当只需要数据值时,使用 `+csv-get`(token 开销约为 `+cells-get` 的 1/5)。只有确实需要公式、样式或批注时才用 `+cells-get`
|
||||
- **忽略分页标志**:读取返回 `has_more=true` 时,说明还有更多数据。如果任务需要完整数据,必须继续分页读取,不能只处理第一页就开始写入
|
||||
- **直接按 `+cells-get` 返回二维数组下标推导真实位置**:`ranges[n].cells[i][j]` 里的 `i/j` 只是返回数组下标,不等于真实表格行列。定位真实行号必须用 `ranges[n].row_indices[i]`,定位真实列字母必须用 `ranges[n].col_indices[j]`;若 `--skip-hidden=true`、请求范围越界被裁剪,或最后一行是部分返回,错误地自己数下标会立刻错位
|
||||
- **直接按 `+cells-get` 返回二维数组下标推导真实位置**:`ranges[n].cells[i][j]` 里的 `i/j` 只是返回数组下标,不等于真实表格行列。定位真实行号必须用 `ranges[n].row_indices[i]`,定位真实列字母必须用 `ranges[n].col_indices[j]`;若 `--skip-hidden=true`、`--skip-filter=true`、请求范围越界被裁剪,或最后一行是部分返回,错误地自己数下标会立刻错位
|
||||
- **CSV 行号计数错误**:`+csv-get` 返回的 CSV 遵循 RFC 4180 标准,被双引号 `"..."` 包裹的字段中的换行符属于**字段内容的一部分**(即单元格内换行),不代表新的一行。计算行号时必须按**逻辑记录**计数,而非按物理换行符 `\n` 计数
|
||||
- **手动数列确定列号**:禁止通过在 CSV 表头中手动数逗号/字段来确定目标列的列字母。当列数超过 10 时,手动计数极易产生 off-by-one 偏移(例如把 W 列误判为 X 列)。**必须使用 `col_indices`**:先在 CSV 表头中找到目标字段名是第 j 个字段(0-based),再用 `col_indices[j]` 获取该列的实际列字母
|
||||
- **用数据列的值推导行号(常被巧合掩盖)**:CSV 中常见"序号 / ID / 编号 / No."等形似行号的列,其值与实际表格行号**没有任何绑定关系**——序号可能跳号(1,2,3,5,6...)、可能从非 1 开始、可能有重复或被中途重置。此规则适用于**所有需要行号的下游操作**:合并单元格、区间写入/清空/格式化、插入/删除行、条件格式范围、筛选器范围、图表数据源、透视表范围、搜索替换范围等等——**凡是要把行号填进任何工具参数的场景,行号一律从 `annotated_csv` 中目标行开头的 `[row=N]` 前缀直接读取**,禁止用"序号=行号"、"表头占 1 行所以数据从第 2 行开始"、"第 N 个序号就在第 N+1 行"等心算,也禁止先心算再"事后核对"。**危险特征**:前几十行中序号恰好等于表格行号(典型成因:表头 +1 与一次跳号 -1 的偏移互相抵消形成巧合),模型一旦把这个巧合当作规律,会在后续所有行沿用;而中间再出现跳号时,从该行起整块区域全部错位,且错位不自查很难发现。**正确工作流**:①在 `annotated_csv` 里定位目标逻辑行(按字段内容匹配);②直接读取该行开头的 `[row=N]` 前缀得到真实表格行号;③把这个行号填进下游工具参数。区间操作时,起始行用 start 行的 `[row=N]`、结束行用 end 行的 `[row=N]`。**自检**:动手前,在 `annotated_csv` 靠后位置再抽 1~2 行,核对 `[row=N]` 是否与首列"序号"一致——不一致(典型:`[row=57] 58,...`)即说明有跳号/隐藏行,更要严格从 `[row=N]` 取值,不要被序号列迷惑
|
||||
@@ -103,7 +103,8 @@ _公共四件套 · 系统:`--dry-run`_
|
||||
| `--include` | string_slice | optional | 要返回的信息类别,逗号分隔多个。`truncation` 会额外按行高列宽 / 字号 / 自动换行估算每个单元格是否被截断显示,返回 `isRowTruncated` / `isColTruncated`(有额外计算开销,仅排版检查 / 调整行高列宽前才开)(可选值:`value` / `formula` / `style` / `comment` / `data_validation` / `truncation`) |
|
||||
| `--max-chars` | int | optional | 单次返回字符上限,默认 500000(兜底防爆)。要整表无截断直接用 --output-path 落盘(自动放开为无限);仅当要让结果直接进上下文、又不落盘时才调小(如 25000),按 has_more 分页。 |
|
||||
| `--output-path` | string | optional | 把完整读取结果写入本地路径(如 `./out.json`),文件内容为 data 载荷的 JSON;stdout 只回一个含 output_path/字节数的确认信息。**一旦设置,字符上限默认放开为无限**(覆盖 --max-chars 默认),适合大表整表落盘再分析,避免 stdout 被 max_chars 截断。省略时按常规把结果打到 stdout。 |
|
||||
| `--skip-hidden` | bool | optional | 跳过隐藏行列,默认 `false` |
|
||||
| `--skip-hidden` | bool | optional | 跳过隐藏或分组折叠的行列。默认 `false`;未显式传 `--skip-filter` 时,筛选行也会随之跳过(兼容旧行为) |
|
||||
| `--skip-filter` | bool | optional | 跳过被筛选掉的行。未设置时继承 `--skip-hidden`;显式设为 `false` 可在跳过隐藏行列的同时保留筛选行 |
|
||||
|
||||
### `+dropdown-get`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user