hap-cli-data-query について
HAP ワークシートを hap コマンドラインで読み取り専用検索するためのスキルです。明細の絞り込みや集計を行う人向けに、filter JSON、フィールド識別子、レコード検索、ピボット集計を例と制限事項とともに説明します。
主な機能
- 01ワークシートレコードの検索、並べ替え、ページ分割
- 02ネストした filter JSON 条件の作成
- 03ピボット軸によるレコード集計
- 04関連、メンバー、日付フィールドの絞り込み
- 05関連レコードと変更ログの確認
- 06ワークシートのチャート設定の作成と管理
活用シーン
- 01複雑な条件に合うワークシートレコードの検索
- 02カテゴリ別の金額や件数の集計
- 03親レコードとの関連を使った子行の検索
- 04レコードの変更者と変更日時の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mingdaocom/ hap-skills --skill hap-cli-data-queryインストール後、Claude Code で/hap-cli-data-queryを入力して読み込まれたか確認します。
詳細
HAP 数据查询助手(筛选 · 透视 · 统计)
帮用户用 hap 命令行从 HAP 工作表里把想要的数据查出来。难点不在命令本身,而在参数 JSON 怎么写对——筛选条件的写法、各处支持哪些比较方式、透视的维度与聚合。本 skill 把这些易错点讲清楚,并给可直接套用的模板。
本 skill 只管"查/筛/统计"(只读)。定位到目标行后要写回数据(改备注、改状态等)用
hap worksheet record update——写记录不依赖默认应用,有WORKSHEET_ID就能定位,-a/--app-id可传可不传(传了只是限定字段查找范围),写入失败时别往「是不是没 select 对应用」上想。各字段类型该传什么值见hap guide record,写完读回确认。 增删改记录也直接用hap worksheet record相关命令。
覆盖的命令
| 命令 | 用途 | 筛选器格式 |
|---|---|---|
worksheet record list | 按条件查记录(筛选/排序/分页) | filter-json(统一筛选写法) |
worksheet record pivot | 透视聚合(分组维度 + 求和/计数等) | filter-json(同上) |
worksheet record bottom-stats | 视图底部那条汇总(单行统计) | filter-controls(主站 wire,不同) |
worksheet record relations | 顺着某条记录的关联字段列出被关联的记录 | 无(直接给 记录+字段) |
worksheet record logs | 某条记录的变更日志(谁在什么时候改了什么) | 无 |
worksheet chart | 图表命令组(create/get/update/delete/list) | spec-json(在 chart create 上) |
关键认知:
record list和record pivot共用同一套 filter-json;bottom-stats用的是另一套老格式,别混。绝大多数"查数据"诉求用前两个就够。
第 0 步永远是:拿到字段 ID
筛选条件里的 field 可以写字段 ID(controlId)、别名,或界面上显示的列标题原文(工作表上没有的名字会被点名拒绝);
但透视的维度 --rows-json / --columns-json 和值 --values-json 只认字段 ID 或别名,写列标题会被拒。先查出来:
hap worksheet fields WORKSHEET_ID # 列出每个字段的 controlId / 名称 / 类型
记下要筛选/分组/聚合的那几个字段的 controlId,后面 JSON 里直接用。
filter-json:筛选器怎么写(record list / pivot 通用)
写法
筛选条件就是一组条件,用 logic 组合,可嵌套以表达复杂的与/或:
{ "logic": "and", // and | or
"items": [
{ "field": "<字段 ID、别名或列标题>",
"op": "<比较方式>",
"value": <标量 或 数组> }, // empty / not_empty 不需要 value
{ "logic": "or", "items": [ ... ] } // 某一项本身也可以是一个组
] }
要表达「(A 且 B) 或 (C 且 D)」就在 items 里再嵌组。这一种写法 hap 各处都收——记录查询、视图、
业务规则、按钮、图表、工作流条件——权威说明见 hap guide record filter(3.1 写法、3.2 各处支持哪些
比较方式、3.3 透视的限制),它随 CLI 版本走,别照本 skill 的记忆写。
旧写法(
{"type":"group","children":[{"type":"condition",...}]}那棵树)和旧拼法(notin、isempty、ge、startswith…)仍然可用,以前写的筛选照样能跑;新写的一律用上面这种。
比较方式:记录查询能用哪些
record list / record pivot 能用这 21 个:
eq ne in not_in contains not_contains all_contains
starts_with not_starts_with ends_with not_ends_with
gt gte lt lte between not_between belongs not_belongs
empty not_empty
视图、业务规则、按钮、图表那几处还多一些专用的比较方式(date_is、self、rc_eq、array_eq…),
它们在 record list / record pivot 上不存在——写了 hap 会当场拒绝并列出这里能用的。
各处的完整对照见 hap guide record filter 的 3.2。
要点:
- 日期也用
between(配["2026-02-01","2026-03-31"])和gt/gte/lt/lte。 在视图/规则/按钮/图表上,hap会按列类型自动换成日期专用的比较方式,你照常写即可; 但date_between这类显式日期名只在那几处合法,记录查询会拒绝它。 empty/not_empty不带value。- 写错名字、写了这里没有的比较方式、写了不存在的列,
hap都会在发出去之前点名拒绝并告诉你可用取值。 node键和对象形态的value只属于工作流条件,写在记录查询里会被拒绝。
🚨 服务端对不认识的比较方式不报错——它把整个条件丢掉,返回全表,并且报成功。 用一个它不认的名字去查十二条逾期订单,拿回来的是全部订单,没有任何迹象说明筛选没生效。 你能看到报错,靠的是
hap在发出去之前的本地拦截。所以只要不是用hap发的筛选请求 (自己拼 HTTP、别的客户端),看结果要看条数,别只看success。
value 怎么填(按字段类型)
- 选项 / 单选 / 多选字段:value 用选项的 key 最稳(从
worksheet fields的字段 options 里查);写选项的显示文本hap也会替你换成 key。 - 关联表字段(Relation):value 用关联记录的 rowid 数组,配
in或eq。⚠️ 必须用 rowid,不能用关联显示的标题文本(如版本名)去匹配。怎么拿这个 rowid 见下方「关联字段筛选」。子表的反向关联字段同理:value 填父记录的 rowid,即可筛出该父记录的全部子行。 - 成员字段(Collaborator):value 用成员的 accountId 数组,配
in/eq。 - 部门字段:value 用部门 ID 数组,配
belongs/not_belongs(在record pivot上这两个只对地区字段可用,见下方 pivot 一节)。 - 文本字段:
contains/starts_with/eq等,value 直接给文本。 - 日期字段:
between给["2025-01-01","2025-01-31"],或gt/gte/lt/lte给单个日期/时间戳(不是date_between,记录查询不收它)。
关联字段筛选:先拿到关联记录的 rowid
关联字段(如「任务」表里的「版本」「项目」「客户」)在返回数据里长这样——一个数组,每项带 sid(关联记录的 rowid)和 name(显示标题):
"版本字段": [ { "sid": "ITERATION_ROW_ID", "name": "迭代A" } ]
筛选时 value 要用那个 sid。最直接的办法是让命令替你列:
hap --json worksheet record relations <本表WS_ID> <本条记录rowid> <关联字段ID>
它顺着这条记录的关联字段把被关联的记录列出来,并附带它们的来源工作表信息——省掉下面两步手工反查。
分页用 -p/-n(默认每页 20),要连系统字段一起拿加 --is-return-system-fields。
手工反查的两种办法(还没有具体某条记录、或要按名字找时用):
- 从关联表查:去被关联的那张表
record list --search "迭代A",拿到目标记录的rowid。注意关联显示的name来自该表的标题字段,可能和你以为的不一样(比如标题其实是 "2.3" 而非 "迭代A 2.3"),所以以实际查到的为准。 - 从已有数据反查:先
record list拉几条本表记录,看那个关联字段里已出现的{sid, name},挑出name匹配的sid。
拿到 sid 后这样筛(任务表里「版本」关联到「迭代A」):
hap worksheet record list TASK_WS_ID --filter-json '{
"logic":"and",
"items":[{"field":"<版本字段ID>","op":"in","value":["ITERATION_ROW_ID"]}]
}' -p 1 -n 100
サブテーブル(SubTable):「ある親レコードのすべての子行」を検索する
サブテーブルのデータは親レコード内にはなく、独立したワークシート(親の SubTable フィールドの dataSource)にあります。
子行は逆 Relation フィールド(親の SubTable フィールドの sourceField)を介して親行に紐付けられています。
そのため、ある親レコードの子行を検索するには、サブテーブルのワークシートでこの逆関連フィールドを使って絞り込みます。値は親レコードの rowid です。
hap worksheet record list <子表WS_ID> --use-field-id-as-key -p 1 -n 100 \
--filter-json '{"logic":"and","items":[
{"field":"<反向关联字段ID>","op":"in","value":["<父记录rowid>"]}]}' \
--sorts-json '[{"field":"<明细编号等排序字段ID>","isAsc":true}]'
<逆関連フィールドID>:親テーブルのworksheet fieldsで、SubTable フィールドのsourceFieldを確認します。- value は親レコードの rowid(親レコードのタイトルテキストではありません)です。
inを使います。 - サブテーブル行の「何行目か」は並べ替え順で決まり、通常は AutoNumber の明細番号の昇順で、フォームで表示される順序と一致します。
必ず
--sorts-jsonを指定してください。指定しない場合、デフォルトの順序は安定しないため、「N 行目」を数え間違える可能性があります。
完全な例
「姓が張で、1 月に入社」または「営業/マーケティング部、または華北地区に所属」:
hap worksheet record list WORKSHEET_ID --filter-json '{
"logic": "or",
"items": [
{ "logic": "and", "items": [
{ "field": "name", "op": "starts_with", "value": "张" },
{ "field": "onboard_date", "op": "between", "value": ["2025-01-01","2025-01-31"] }
]},
{ "logic": "or", "items": [
{ "field": "dept_option", "op": "in", "value": ["k_sales","k_mkt"] },
{ "field": "dept_id", "op": "belongs", "value": ["DEPT_HUABEI_ID"] }
]}
]
}'
単純な単一条件(ステータスが空のレコード)——empty には value を付けない点に注意してください:
hap worksheet record list WORKSHEET_ID --filter-json '{
"logic":"and",
"items":[{"field":"status","op":"empty"}]
}'
record list:レコードを検索する
hap worksheet record list WORKSHEET_ID \
--filter-json '<见上>' \
--sorts-json '[{"field":"onboard_date","isAsc":false}]' \
--fields '["name","status","amount"]' \ # 只返回这几个字段,省 token
--page-size 50 --page-index 1 \
--include-total-count # 想要总行数时加
--page-size/--page-indexはどちらも必須です。--searchはキーワードによるあいまい検索(複数フィールドを対象)です。filter と組み合わせられます。--view-idは、指定したビューに組み込まれたフィルター/並べ替えを適用します。--filter-jsonを指定しない場合、ページネーションに従ってすべてのレコードを検索します。- 返されるデータのキーには、デフォルトでフィールドの別名が使われます(例:
mingcheng、fuzeren、ssdd)。controlId ではありません。解析時は別名で値を取得するか、--use-field-id-as-keyを追加してキーを controlId にします。別名はworksheet fieldsで確認できます。 --fieldsにはフィールド ID または別名を指定できます。特定の列だけが必要な場合は、これを使うとトークンを節約できます。- メンバーフィールドはオブジェクト配列
[{accountId, fullname, avatar, status}]を返します。人名を表示するにはfullnameを取得します。
record pivot:ピボット集計(統計に最適)
「X でグループ化し、Y の合計/件数/平均を計算する」場合は、すべてこれを使います。必須なのは --values-json のみです。--view-id は任意です
(指定すると、そのビューのフィルター/並べ替えが適用されます。ビュー ID は hap worksheet view list WORKSHEET_ID で確認できます)。
-p/-n を指定しない場合はデフォルト値が使われます。-a も省略できます。コマンドがワークシートから所属するアプリを逆引きします。間違ったアプリを指定した場合は、
「このテーブルはそのアプリに属していません。本来の所属アプリを使用してください」と明確に通知されます。
hap worksheet record pivot WORKSHEET_ID \
--view-id VIEW_ID \ # 必填
--rows-json '[{"field":"status"}]' \ # 行维度(分组)
--columns-json '[{"field":"create_date","granularity":3}]' \ # 列维度,可选
--values-json '[{"field":"amount","aggregation":"SUM"}]' \ # 值(聚合),必填
--filter-json '<同 list 的筛选条件>' \ # 可选
--include-summary # 要总计行加
戻り値の構造は data.pivot(配列)で、各項目は次のような形式です。
{ "rows": { "<行维度字段ID>": "进行中" },
"columns": { },
"values": { "<值字段ID>": 190000.0 } }
解析時は rows/values からフィールド ID を使って値を取得します。ランキングを作る場合は、pivot 配列を特定の value で並べ替えてから上位 N 件を取得します(ピボット自体は値順を保証しません)。
🚨 pivot で使えるフィルターは list より少ない
同じ filter-json でも、record list では受け付けられても、pivot では受け付けられない場合があります——pivot で認識される比較条件は、フィールドに設定された型によって異なります:
| 比較方法 | pivot での対応 |
|---|---|
eq / ne、empty / not_empty | すべて対応 |
contains / not_contains | 一切対応しません。どのフィールド型でも拒否されます。hap はローカルで拒否し、starts_with / ends_with に変更するか、record list に切り替えるよう案内します |
in / not_in | 単一選択、地域でのみ対応します。テキスト/数値/日付では拒否されます |
gt / gte / lt / lte、between / not_between | 数値、日付でのみ対応します |
belongs / not_belongs | 地域でのみ対応します |
all_contains | テキストでのみ対応します |
starts_with / ends_with とその否定形 | テキストでのみ対応します |
contains 以外の型ごとの制限は、hap では拒否できません(フィールド型が分からないため)。サーバー側で拒否され、今回送信した条件がエラーメッセージに付加されます。たとえば「A pivot accepts fewer comparisons than record list does…」のような形式です。
pivot は value の形式にも制約があります(record list には制約がなく、どちらの形式も受け付けます):
| 比較方法 | pivot で必要な形式 |
|---|---|
gt / gte / lt / lte | 値をそのまま指定します。配列にすると拒否されます——"value": 0 は有効ですが、[0] と ["0"] はどちらも無効です |
between / not_between | 2 要素の配列が必要です。値をそのまま指定したり、要素を 1 つだけ指定したりすると拒否されます |
eq / ne / in / not_in | どちらの形式も受け付けます。気にする必要はありません |
同じ条件は record list ではどちらの形式でも実行できます。そのため、この種のエラーが発生するのは pivot に切り替えた場合だけです。
この 2 つの表は hap guide record filter の 3.3 に準拠しています。
絞り込めない場合は
record listに戻して明細を取得し、ローカルで集計してください。pivot の型や形式の制限と格闘するより早く済みます。
ディメンション(rows / columns)
各項目は {"field":"<controlId または別名>", "displayName":"任意", "granularity":<整数>, "includeEmpty":false} です。
granularityが意味を持つのは日付/地域フィールドのみです。- 日付:
1=日、2=週、3=月 - 地域:
1=省、2=省/市、3=省/市/県
- 日付:
includeEmpty:空の値も 1 グループとして含めるかどうかです。デフォルトは false です。
値(values)
各項目は {"field":"<controlId または別名>", "aggregation":"<集計方法>", "displayName":"任意"} です。
aggregation(大文字と小文字を区別しません):COUNTは件数、DISTINCTCOUNTは重複を除いた件数、SUMは合計、MINは最小値、MAXは最大値、AVGは平均です。- 行数だけを数える場合(特定のフィールドを対象にしない場合):
fieldに特殊値record_countを指定し、COUNTを組み合わせます。
例——月ごとに各ステータスの注文数と金額の合計を集計します。
hap worksheet record pivot WORKSHEET_ID \
--rows-json '[{"field":"create_date","granularity":3}]' \
--columns-json '[{"field":"status"}]' \
--values-json '[
{"field":"record_count","aggregation":"COUNT"},
{"field":"amount","aggregation":"SUM"}
]' --include-summary
bottom-stats と chart(補足)
record bottom-stats:ビュー下部にある集計行のみを返します(多次元ピボットではありません)。これは別の古い形式を使います:--column-rpts '[{"controlId":"amount","rptType":1}]'(rptType は整数です。対応関係は--helpで確認してください)。--filter-controlsには filter-json ではなく、メインサイトの wire 構造を使います。また、キーワードで絞り込む-k/--keywordsもあります。さらに--report-idを指定すると、通常のテーブルの集計ではなく、特定のグラフビューの集計を読み込みます(グラフ ID はhap worksheet chart listで取得します)。実際にグループ別の統計が必要な場合は、record pivotを優先してください。record logs:特定のレコードの変更ログで、「この値を誰がいつ変更したか」を確認できます。疑わしいレコードを特定した後に使うと、アプリ全体のhap app logsを調べるより正確です。worksheet chart:コマンドグループ(create/get/update/delete/list)であり、ワークシート上のグラフ設定を作成/変更します。リアルタイムにデータを取得するものではありません。グラフを作成するにはhap worksheet chart createを使います。--report-type(整数のグラフタイプ)と-j/--spec-json(xaxes/yaxisList/filter などを含む)はどちらもサブコマンドにあります。hap worksheet chart --helpにはサブコマンドのみが表示されます。グラフ仕様の書き方についてはhap guide chartを参照してください。 グラフの作成は多くの場合「アプリの変更」に当たるため、hap-cli-app-editor に任せられます。データの取得と分析だけならrecord pivotのほうが直接的です。
実行前に hap worksheet record bottom-stats --help / hap worksheet chart create --help を確認してください。
写对查询的要点
照这些规则写,绝大多数查询一次就成:
- 字段标识:筛选条件里的
field可用 controlId、别名或列标题;透视的维度 / 值里只认 controlId 或别名(用worksheet fields查)。 - 筛选条件:统一写法
{"logic","items":[{"field","op","value"}]},比较方式用gte/lte/empty/not_in这类统一名;视图/图表专用的(date_is、self…)记录查询不收。拿不准就看hap guide record filter。 - value 形态:选项字段用选项 key;关联字段用关联记录 rowid;成员字段用 accountId;
empty/not_empty不带 value。 - 必填项:只有
record pivot的--values-json是必填。分页-p/-n都有默认值 (record list每页 20、pivot每页 100,页码都从 1 起),--view-id两个命令都是可选的。 要一次取更多就显式给-n。 - 结果解析:返回默认用字段别名作 key,要用 controlId 作 key 就加
--use-field-id-as-key;成员/关联字段是对象数组,取其中的fullname/name。 - Shell 转义:用单引号包整个 JSON、内部用双引号;筛选复杂时写进文件再
--filter-json "$(cat f.json)"。 - 核对实际请求:
hap config log on后再跑命令,可在日志里看到真正发出的请求体。