ai_member_xiaoyan/skills/feishu-embedded-sheet/SKILL.md

7.5 KiB
Raw Blame History

name version description metadata
feishu-embedded-sheet 1.0.0 飞书云文档中内嵌电子表格Sheet的读取与写入技能。 当飞书 docx 文档中包含 `<sheet token="xxx"/>` 内嵌表格时,使用本技能进行精准的行列级读写操作。 **触发场景:** - 需要读取飞书文档中内嵌的 Excel/Sheet 表格数据 - 需要向飞书文档中内嵌的 Sheet 写入/更新数据 - 用户提到"文档里的表格"、"内嵌表格"、"剧本表格"等 - 从文档 markdown 中看到 `<sheet token="xxx_yyy"/>` 标签
requires identity
permissions
sheets:spreadsheet:readonly
sheets:spreadsheet
bot

飞书文档内嵌 Sheet 读写技能

核心概念

飞书 docx 文档可以内嵌电子表格Sheet。通过 lark-cli docs +fetch 获取文档 markdown 时,内嵌表格会渲染为:

<sheet token="WreDs73X1hrgdFtxdpJcItj2n5c_RuQopk"/>

Token 结构解析:

  • 完整 tokenWreDs73X1hrgdFtxdpJcItj2n5c_RuQopk
  • _ 前面部分 = spreadsheet_tokenWreDs73X1hrgdFtxdpJcItj2n5c
  • _ 后面部分 = sheet_idRuQopk

同一个文档内嵌的多个 Sheet 共享同一个 spreadsheet_token,通过不同的 sheet_id 区分。

前置步骤:获取 Bot Token

所有操作均使用 Bot 身份执行,禁止触发用户授权。

APP_ID="cli_a931175d41799cc7"
APP_SECRET=$(jq -r '.apps[0].appSecret' /root/.openclaw/credentials/xiaoyan/config.json)

TOKEN=$(curl -s -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \
  -H "Content-Type: application/json" \
  -d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" \
  | jq -r '.tenant_access_token')

Token 有效期 2 小时,过期需重新获取。

完整执行链路

第一步:从文档中提取 Sheet Token

  1. 先通过 lark_wiki_operate_as_bot 技能获取文档内容
  2. 在返回的 markdown 中查找 <sheet token="xxx"/> 标签
  3. 解析出 spreadsheet_tokensheet_id
# 获取文档内容(以 wiki 文档为例)
LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/xiaoyan \
  lark-cli wiki spaces get_node --params '{"token":"<wiki_token>"}' --as bot

LARKSUITE_CLI_CONFIG_DIR=/root/.openclaw/credentials/xiaoyan \
  lark-cli docs +fetch --doc <obj_token> --as bot

第二步:获取 Sheet 元数据(了解表结构)

curl -s -X GET \
  "https://open.feishu.cn/open-apis/sheets/v3/spreadsheets/${SPREADSHEET_TOKEN}/sheets/query" \
  -H "Authorization: Bearer $TOKEN" | jq '.'

返回信息包括:

  • sheet_id:每个子表的 ID
  • title:子表名称
  • grid_properties.row_count:总行数
  • grid_properties.column_count:总列数
  • grid_properties.frozen_row_count:冻结行数(通常表头行)
  • merges:合并单元格信息

第三步:读取数据

读取指定范围

# 格式:{sheet_id}!{起始单元格}:{结束单元格}
curl -s -X GET \
  "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/${SPREADSHEET_TOKEN}/values/${SHEET_ID}!A1:J196?valueRenderOption=ToString" \
  -H "Authorization: Bearer $TOKEN" | jq '.data.valueRange.values'

参数说明:

  • valueRenderOption=ToString:所有值转为字符串返回(推荐,避免类型混乱)
  • Range 格式:{sheet_id}!{列字母}{行号}:{列字母}{行号}
  • 行号从 1 开始列用字母表示A=1, B=2, ..., Z=26, AA=27...

读取全表

先从元数据获取 row_countcolumn_count,然后构造完整 range

# 例10列196行
curl -s -X GET \
  "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/${SPREADSHEET_TOKEN}/values/${SHEET_ID}!A1:J196?valueRenderOption=ToString" \
  -H "Authorization: Bearer $TOKEN"

读取结果处理

返回的 values 是二维数组,每个元素是一行:

{
  "data": {
    "valueRange": {
      "values": [
        ["类型", "组件配置", "ID", ...],   // 第1行表头
        ["TL\nxxx", "S1前置xxx", null, ...], // 第2行
        ...
      ]
    }
  }
}
  • null 表示空单元格
  • 换行符在值中以 \n 表示
  • 合并单元格:只有左上角单元格有值,其余为 null

第四步:写入数据

写入/更新指定行

curl -s -X PUT \
  "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/${SPREADSHEET_TOKEN}/values" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "valueRange": {
      "range": "'${SHEET_ID}'!A197:J197",
      "values": [
        ["对话测试", "S99主线\n自动\n对话测试", "9999901", "剧情描述", "User", "台词", "User", "润色台词", null, "知识点"]
      ]
    }
  }'

批量写入多行

curl -s -X PUT \
  "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/${SPREADSHEET_TOKEN}/values" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "valueRange": {
      "range": "'${SHEET_ID}'!A197:J199",
      "values": [
        ["行1列A", "行1列B", ...],
        ["行2列A", "行2列B", ...],
        ["行3列A", "行3列B", ...]
      ]
    }
  }'

更新指定单元格

# 只更新单个单元格
curl -s -X PUT \
  "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/${SPREADSHEET_TOKEN}/values" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "valueRange": {
      "range": "'${SHEET_ID}'!H50:H50",
      "values": [["更新后的台词润色内容"]]
    }
  }'

清空单元格

写入空字符串 "" 即可清空单元格内容。

第五步:写入后验证

必须回读验证,确保写入内容与预期一致:

curl -s -X GET \
  "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/${SPREADSHEET_TOKEN}/values/${SHEET_ID}!A197:J197?valueRenderOption=ToString" \
  -H "Authorization: Bearer $TOKEN" | jq '.data.valueRange.values'

注意事项

  1. 身份限制:所有操作使用 Bot 身份,需要 Bot 应用对目标文档有编辑权限
  2. 权限要求Bot 需在飞书开发者后台开通 sheets:spreadsheet 权限;目标文档/知识空间需将 Bot 添加为成员并授予编辑权限
  3. 合并单元格:写入合并单元格区域时,只写入左上角单元格即可,其余位置保持 null
  4. 行数限制:单次读取/写入建议不超过 500 行,超大表格请分批操作
  5. 并发写入:避免同时多次写入同一个 Sheet可能导致数据覆盖
  6. 数据类型:写入时,数字直接用 number 类型,文本用 string空值用 null
  7. 换行符:需要在单元格内换行时,在字符串中使用 \n

异常处理

错误码 含义 处理方式
1310251 spreadsheet_token 格式错误 检查是否正确从 sheet token 中拆分出 spreadsheet_token
1310201 无权限 Bot 未被添加为文档/知识空间成员,需用户授权
1310212 Range 格式错误 检查 sheet_id 和单元格范围格式
1310214 超出表格范围 检查行列号是否超出实际表格大小

与其他技能的配合

  • 读取文档内容:先用 lark_wiki_operate_as_bot 技能获取文档 markdown从中提取 <sheet> 标签
  • 多维表格操作如果目标是独立的多维表格Bitable应使用 lark_bitable_operate_as_bot 技能,而非本技能
  • 文档写入:如果需要修改文档中 Sheet 以外的内容(文本、表格等),使用 feishu-update-doc 技能