docs: Filter/Sorter対応・API仕様訂正をspecに反映

PleasanterのGet API仕様(PageSizeはクライアント指定不可、Response.Dataが直接配列、ClassHash等のネスト構造)を公式マニュアルで確認し訂正。
併せてFilter/Sorter条件をシート上の表で指定できる機能をExport/Get共通で追加する設計に更新。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Kenichiro NOGI 2026-09-11 11:14:24 +09:00
parent 6f33339d43
commit ee1448504c

View File

@ -16,6 +16,33 @@
| D6 | 経過秒数(`(D5 - D4) * 86400` の数値) | | D6 | 経過秒数(`(D5 - D4) * 86400` の数値) |
| D7 | 取得方式(`"Export"` または `"Get"`。未入力・それ以外の値は `"Export"` 扱い) | | D7 | 取得方式(`"Export"` または `"Get"`。未入力・それ以外の値は `"Export"` 扱い) |
## Filter・Sorter条件基本情報シート、Export/Get共通
Pleasanter APIの `ColumnFilterHash` / `ColumnSorterHash` に渡す条件を、基本情報シート上の表で指定できるようにする。Export方式・Get方式の両方で同じ条件を使う。
### セル配置
| 表 | 見出し | データ行 |
|---|---|---|
| Filter表 | F2:G2列名 / 値) | F3以降列名が空白の行で終了 |
| Sorter表 | H2:I2列名 / 昇降順) | H3以降`asc`または`desc`。列名が空白の行で終了) |
- Filter表・Sorter表とも、データ行が1件も無ければ該当するHashはAPIリクエストに含めない
- 両方とも0件の場合は `View` パラメータ自体をリクエストボディに含めない
### `SetupFilterSorterTables()`新規・セットアップ用Sub
基本情報シートのF2:G2、H2:I2を見出しとするExcelテーブルListObjectを新規作成する。`新版着工要因閲覧シートv0.1.xlsm` 上で手動実行することを想定したセットアップ専用処理(`run()` からは呼ばない)。既にテーブルが存在する場合は何もしない。
### `BuildViewFromSheet() As Object`(新規・共通関数)
基本情報シートのFilter表・Sorter表を読み取り、APIリクエストの `View` に渡す Dictionary を組み立てて返す。Filter表・Sorter表がともに0件の場合は `Nothing` を返す。
- Filter表の各行から `colFilter.Add 列名, 値``ColumnFilterHash` 用Dictionaryを作る1件以上ある場合のみ
- Sorter表の各行から `colSorter.Add 列名, 昇降順``ColumnSorterHash` 用Dictionaryを作る1件以上ある場合のみ
- どちらか一方でもあれば `View` Dictionaryに `ColumnFilterHash` / `ColumnSorterHash` をそれぞれ追加(無い方は追加しない)
- `exportCSVData``getRecordsData` の両方から呼び出し、`viewObj` が `Nothing` でなければ `apiBody.Add "View", viewObj` する
## 全体フロー(`Sub run()` ## 全体フロー(`Sub run()`
``` ```
@ -46,9 +73,21 @@ End Sub
- `runExportFlow` は既存の `exportCSVData``exportCSVDataToSheet` 呼び出しをそのまま移設したもの(ロジック無変更)。 - `runExportFlow` は既存の `exportCSVData``exportCSVDataToSheet` 呼び出しをそのまま移設したもの(ロジック無変更)。
- `runGetFlow` は新規追加の `getRecordsData``getRecordsDataToSheet` を呼ぶ。 - `runGetFlow` は新規追加の `getRecordsData``getRecordsDataToSheet` を呼ぶ。
## Export方式既存・無改造 ## Export方式Filter/Sorter対応のため一部変更
`exportCSVData` / `exportCSVDataToSheet` / `ParseCsv` / `CollectionToArray` は一切変更しない。 `exportCSVDataToSheet` / `ParseCsv` / `CollectionToArray` は変更しない。
`exportCSVData` のみ、既存のコメントアウトされた `colFilter` / `view` 部分を `BuildViewFromSheet()` 呼び出しに置き換える。
```
Dim viewObj As Object
Set viewObj = BuildViewFromSheet()
If Not viewObj Is Nothing Then
apiBody.Add "View", viewObj
End If
```
(旧来の `yearFilter` を使ったコメントアウトコードは削除する)
## Get方式新規追加 ## Get方式新規追加
@ -57,25 +96,39 @@ End Sub
Pleasanterの `api-record-get-multi` を呼び出し、レコード配列Collection of Dictionaryを返す。 Pleasanterの `api-record-get-multi` を呼び出し、レコード配列Collection of Dictionaryを返す。
- エンドポイント: `POST {baseURL}/pleasanter/api/items/{tableId}/get` - エンドポイント: `POST {baseURL}/pleasanter/api/items/{tableId}/get`
- リクエストボディ: `ApiVersion`, `ApiKey`, `View: { PageSize: 200 }`200件以下想定のため1回のリクエストで取得しきる - リクエストボディ: `ApiVersion`, `ApiKey`
- レスポンス: `res("Response")("Data")("Results")` を返す各要素はレコードのDictionary - 取得件数は指定しない。1回のリクエストでの取得上限はサーバー側既定値`Api.json` の `PageSize`、既定200件であり、クライアント側から `PageSize` を指定するパラメータは存在しない。200件以下想定のため既定動作のまま1回のリクエストで取得しきる`Offset` も指定不要)
- レスポンス: `res("Response")("Data")` を返すレコードDictionaryの配列。`Results` という入れ子は存在しない)
- 既存の `callRestApi` をそのまま利用する - 既存の `callRestApi` をそのまま利用する
- Filter/Sorter条件は `BuildViewFromSheet()` を呼び出し、`viewObj` が `Nothing` でなければ `apiBody.Add "View", viewObj` するExport方式と同じ共通関数を利用
### レコードのフラット化(`FlattenRecord(record As Dictionary) As Dictionary`
Pleasanterのget APIレスポンスは、`ClassA`〜`ClassZ` などの項目が `ClassHash`(同様に `NumHash`, `DateHash`, `DescriptionHash`, `CheckHash` など)という**入れ子のDictionary**の中に格納されている。トップレベルキーをそのままヘッダにすると、これらHash系フィールドが展開されずネストしたDictionaryのまま1セルに入ってしまう。
そのため `getRecordsDataToSheet` に渡す前に、各レコードをフラット化する処理を挟む。
- レコードDictionaryの各キー・値を走査する
- 値が `Dictionary` である場合(`ClassHash` など `*Hash` 系フィールド)は、そのキー自体は使わず、**中身のキー・値をそのままフラット化後のDictionaryにマージ**する(例: `ClassHash("ClassA")` → フラット化後の `ClassA` キー)
- 値が `Dictionary` でない単純値(`Title`, `Body`, `Status`, `ResultId` など)はそのままキー・値を引き継ぐ
- 全レコードに対して同じ処理を行う
### `getRecordsDataToSheet(records As Collection, targetSheet As String)` ### `getRecordsDataToSheet(records As Collection, targetSheet As String)`
`exportCSVDataToSheet` とは完全に独立した新規関数として実装する(既存ロジックへの影響を避けるため共通化しない)。 `exportCSVDataToSheet` とは完全に独立した新規関数として実装する(既存ロジックへの影響を避けるため共通化しない)。
- `records.count = 0` の場合はメッセージ表示して終了 - `records.count = 0` の場合はメッセージ表示して終了
- ヘッダは **1件目のレコードのキー一覧をそのまま使用**`Title`, `Body`, `ClassA`, `DateA` などPleasanterの内部キー名。日本語ラベルへの変換は行わない - 各レコードを `FlattenRecord` でフラット化する
- 各レコードの値をヘッダ順に2次元配列へ格納 - ヘッダは **フラット化後の1件目レコードのキー一覧をそのまま使用**`Title`, `Body`, `ClassA`, `DateA` などPleasanterの内部キー名。日本語ラベルへの変換は行わない
- 各レコードフラット化後の値をヘッダ順に2次元配列へ格納
- シート・テーブルListObjectの取得新規作成、ヘッダ設定、`DataBodyRange` のクリアと書き込みは `exportCSVDataToSheet` と同様の手順を独自に実装する - シート・テーブルListObjectの取得新規作成、ヘッダ設定、`DataBodyRange` のクリアと書き込みは `exportCSVDataToSheet` と同様の手順を独自に実装する
- テーブル名・出力先シートは `targetSheet``tableId`を共用し、Export方式実行時に作られた既存テーブルを上書きする方式を切り替えるたびにヘッダ列構成が変わる点は許容する - テーブル名・出力先シートは `targetSheet``tableId`を共用し、Export方式実行時に作られた既存テーブルを上書きする方式を切り替えるたびにヘッダ列構成が変わる点は許容する
## 変更対象・追加対象まとめ ## 変更対象・追加対象まとめ
- 変更: `init()``fetchMethod` 読み込み追加), `Sub run()`(分岐フローに書き換え) - 変更: `init()``fetchMethod` 読み込み追加), `Sub run()`(分岐フローに書き換え), `exportCSVData``View` 組み立てを `BuildViewFromSheet()` 呼び出しに置き換え)
- 追加: `runExportFlow`, `runGetFlow`, `getRecordsData`, `getRecordsDataToSheet` - 追加: `runExportFlow`, `runGetFlow`, `getRecordsData`, `getRecordsDataToSheet`, `FlattenRecord`, `BuildViewFromSheet`, `SetupFilterSorterTables`
- 無改造: `exportCSVData`, `exportCSVDataToSheet`, `ParseCsv`, `CollectionToArray`, `callRestApi` - 無改造: `exportCSVDataToSheet`, `ParseCsv`, `CollectionToArray`, `callRestApi`
## 非対象・考慮しないこと ## 非対象・考慮しないこと