CSV で出力する
一覧や帳票の内容を CSV で落とす。受け側が Shift_JIS 固定でも合わせられる。
CSV は actions に type: export のボタンを1つ置くだけ。出す内容はその画面の列(table.columns)と行から組むので、列を並べ直す指定は要らない。
actions:
- { id: csv, type: export, label: CSV出力, config: { filename: 受注一覧, bom: true } }一覧(search / crud)でも帳票(report)でも書き方は同じ。画面が持っている列がそのまま見出し行になり、行がそのままデータ行になる。
ロールで見えない列は CSV にも出ない。 画面に出ていない原価列が CSV から漏れる、という事故が起きない代わりに、「画面では隠すが CSV には入れたい」はできない(それは別の画面か plugin の仕事)。
出るのは検索結果の全部
一覧の export は表示中のページではなく検索結果全体を出す。20 件表示のページで押しても、条件に合う 3,000 件が出る。そのために Repository を config.limit(既定 10000)まで読み直す。
だから件数が多い画面では limit を確認しておく。上限で切られても CSV は普通に出てくるので、足りていないことに気づきにくい。
帳票は事情が違って、既に読んだ行をそのまま出す(帳票は report.limit の分を一度に読んでいるので読み直さない)。同じ limit という言葉が2箇所にあって、帳票側で効くのは report.limit。
小計行や改ページは紙のための指定なので CSV には現れない。明細だけが出る。
ファイルを書くのは Framework の外
Framework がやるのは文字列を作るところまで。ダウンロード、保存ダイアログ、共有、サーバへのアップロード、どれもアプリ側が登録した出力先(exportSink)の担当。
登録していなければ失敗する(onSuccess も動かない)。Framework がファイルシステムもブラウザも知らないのはわざとで、Web と Desktop とモバイルで「保存」の意味が違うものを Framework に持ち込みたくない。
文字コードは「欲しいコード」を宣言するだけ
受け側が Shift_JIS 固定、という連携はまだ普通にある。config.charset(既定 utf-8)はそれを宣言する場所。ここでも変換するのは出力先で、定義に書いた名前がそのまま渡る。
- { id: csvSjis, type: export, label: CSV出力(Shift_JIS), config: { filename: 受注一覧, charset: cp932 } }名前で悩むのはだいたいここ。
| 名前 | どういうとき |
|---|---|
cp932 | 実務の「Shift_JIS で下さい」はほぼこれ。 Windows / Excel の Shift_JIS で、① ㈱ 髙 ~ が通る |
shift_jis | JIS X 0208 の厳密な Shift_JIS。汎用機など、拡張文字を弾きたいときに選ぶ |
euc_jp | EUC-JP が欲しいと言われたとき |
cp932 と shift_jis を同じものだと思って shift_jis を選ぶと、顧客名に 髙 が1人いた日に落ちる。逆に受け側が JIS X 0208 しか受けないなら、cp932 で出しても向こうで化けるだけなので、shift_jis にして手前で弾くのが正しい。どちらが正しいかは相手の仕様次第なので選べるようにしてある。
迷いどころ
bom は UTF-8 のときだけ効く。 BOM は UTF-8 のものなので、Shift_JIS に付けても先頭のセルに 3 バイトのゴミが入るだけ。なので charset が UTF-8 でなければ、bom: true と書いてあっても付けない。「Excel で開くから BOM」と「Shift_JIS で渡す」は同時に要らない、と考えると分かりやすい。
raw: true は format を通さない。 画面で currency で ¥1,234 と見せている列は、既定では CSV にも ¥1,234 と出る。Excel で足し算させたいなら raw: true にして生の値(1234)を書く。人が読む資料なら既定のまま、機械に食わせるなら raw。
変換の実装は opt-in
cp932 / Shift_JIS / EUC-JP の変換そのものは hatake_encoding という別パッケージにある。使わない人が 9,000 文字ぶんの変換表を抱えないため。出力先で名前からバイト列にするときに使う。
変換できない文字は既定で例外にしてある。黙って ? に化けさせない。顧客名が ? になったまま相手に渡って誰も気づかない、が一番困るので、置き換えるなら「置き換える」と自分で書く。
書けるキー
| キー | 書く場所 | 型 | 必須 | 既定値 | 有効なページ種別 | 説明 |
|---|---|---|---|---|---|---|
type | action | string (create / edit / delete / navigate / plugin / export / print ほか) | 必須 | — | crud dashboard detail form master report search wizard | Action type (open string). Built-ins: create, edit, delete, navigate, plugin, export, print. |
type | column | string (text / number / badge / boolean / date / dateTime ほか) | 任意 | "text" | crud dashboard detail form master report search wizard | Render type (open string). Built-ins: text, number, badge, boolean, date, dateTime. |
type | crudPage | string (crud) | 必須 | — | crud | Page kind. |
type | dashboardItem | string (metric / table / chart ほか) | 任意 | "metric" | dashboard | Card kind. Open string; built-ins below. |
type | dashboardPage | string (dashboard) | 必須 | — | dashboard | Page kind. |
type | detailPage | string (detail) | 必須 | — | detail | Page kind. |
type | field | string (text / textarea / number / select / multiSelect / checkbox / radio / date / dateTime / time / subTable ほか) | 任意 | "text" | crud dashboard detail form master report search wizard | Field type (open string). Built-ins: text, textarea, number, select, multiSelect, checkbox, radio, date, dateTime, time, subTable. A subTable holds child rows — see columns / fields / source. |
type | filter | string (text / textarea / number / select / multiSelect / checkbox / radio / date / dateTime / time ほか) | 任意 | "text" | crud dashboard master report search | Input type (open string). Built-ins: text, textarea, number, select, multiSelect, checkbox, radio, date, dateTime, time. |
type | formPage | string (form) | 必須 | — | form | Page kind. |
type | masterPage | string (master) | 必須 | — | master | Page kind. |
type | reportPage | string (report) | 必須 | — | report | Page kind. |
type | searchPage | string (search) | 必須 | — | search | Page kind. |
type | validator | string (required / maxLength / minLength / pattern / min / max / email / postalCode / compare ほか) | 必須 | — | crud dashboard detail form master report search wizard | Validator type (open string). Built-ins: required, maxLength, minLength, pattern, min, max, email, postalCode, compare. compare is the cross-field one: it reads another field of the same record (see the node description for its parameters). |
type | wizardPage | string (wizard) | 必須 | — | wizard | Page kind. |
config | action | object → config | 任意 | — | crud dashboard detail form master report search wizard | Plugin / renderer specific extra settings. |
config | column | object → config | 任意 | — | crud dashboard detail form master report search wizard | Plugin / renderer specific extra settings. |
config | dashboardItem | object → dashboardItem.config | 任意 | — | dashboard | Extra settings (formatter options, height, ...). |
config | field | object → config | 任意 | — | crud dashboard detail form master report search wizard | Plugin / renderer specific extra settings. |
config | filter | object → config | 任意 | — | crud dashboard master report search | Plugin / renderer specific extra settings. |
config | theme | object → config | 任意 | — | すべて | Plugin / renderer specific extra settings. |
limit | dashboardItem | integer | 任意 | 100 | dashboard | Rows to fetch (the query's pageSize). |
limit | optionsSource | integer | 任意 | 200 | crud dashboard detail form master report search wizard | Rows to fetch (a select is not a list screen). |
limit | report | integer | 任意 | 1000 | report | Rows read for one run (a report is printed, not paged). |
この表は spec/reference.json から生成している(JSON Schema が正)。手元では npx hatake reference <キー名> で同じものが引ける。
近い例
例は丸ごと写して直すのが一番速い。以下は CI で検証済み(そのまま動く形)。
| ファイル | 種別 | 画面 | どういうときに使うか |
|---|---|---|---|
sales_dashboard.yaml | dashboard | 売上ダッシュボード | 件数・金額・グラフのカードを並べて、まず数字を見せたい |
sales_report.yaml | report | 売上明細表 | 一覧の印刷版が欲しい。顧客ごとに小計を出して、CSV も落としたい、紙にも刷りたい |
実物を見る
デモアプリの「売上明細表」がこれを使っている。 デモを開く