Skip to content

CSV で出力する

一覧や帳票の内容を CSV で落とす。受け側が Shift_JIS 固定でも合わせられる。

CSV は actionstype: export のボタンを1つ置くだけ。出す内容はその画面の列(table.columns)と行から組むので、列を並べ直す指定は要らない。

yaml
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)はそれを宣言する場所。ここでも変換するのは出力先で、定義に書いた名前がそのまま渡る。

yaml
- { id: csvSjis, type: export, label: CSV出力(Shift_JIS), config: { filename: 受注一覧, charset: cp932 } }

名前で悩むのはだいたいここ。

名前どういうとき
cp932実務の「Shift_JIS で下さい」はほぼこれ。 Windows / Excel の Shift_JIS で、 が通る
shift_jisJIS X 0208 の厳密な Shift_JIS。汎用機など、拡張文字を弾きたいときに選ぶ
euc_jpEUC-JP が欲しいと言われたとき

cp932shift_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: trueformat を通さない。 画面で currency¥1,234 と見せている列は、既定では CSV にも ¥1,234 と出る。Excel で足し算させたいなら raw: true にして生の値(1234)を書く。人が読む資料なら既定のまま、機械に食わせるなら raw

変換の実装は opt-in

cp932 / Shift_JIS / EUC-JP の変換そのものは hatake_encoding という別パッケージにある。使わない人が 9,000 文字ぶんの変換表を抱えないため。出力先で名前からバイト列にするときに使う。

変換できない文字は既定で例外にしてある。黙って ? に化けさせない。顧客名が ? になったまま相手に渡って誰も気づかない、が一番困るので、置き換えるなら「置き換える」と自分で書く。

書けるキー

キー書く場所必須既定値有効なページ種別説明
typeactionstringcreate / edit / delete / navigate / plugin / export / print ほか)必須crud dashboard detail form master report search wizardAction type (open string). Built-ins: create, edit, delete, navigate, plugin, export, print.
typecolumnstringtext / number / badge / boolean / date / dateTime ほか)任意"text"crud dashboard detail form master report search wizardRender type (open string). Built-ins: text, number, badge, boolean, date, dateTime.
typecrudPagestringcrud必須crudPage kind.
typedashboardItemstringmetric / table / chart ほか)任意"metric"dashboardCard kind. Open string; built-ins below.
typedashboardPagestringdashboard必須dashboardPage kind.
typedetailPagestringdetail必須detailPage kind.
typefieldstringtext / textarea / number / select / multiSelect / checkbox / radio / date / dateTime / time / subTable ほか)任意"text"crud dashboard detail form master report search wizardField 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.
typefilterstringtext / textarea / number / select / multiSelect / checkbox / radio / date / dateTime / time ほか)任意"text"crud dashboard master report searchInput type (open string). Built-ins: text, textarea, number, select, multiSelect, checkbox, radio, date, dateTime, time.
typeformPagestringform必須formPage kind.
typemasterPagestringmaster必須masterPage kind.
typereportPagestringreport必須reportPage kind.
typesearchPagestringsearch必須searchPage kind.
typevalidatorstringrequired / maxLength / minLength / pattern / min / max / email / postalCode / compare ほか)必須crud dashboard detail form master report search wizardValidator 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).
typewizardPagestringwizard必須wizardPage kind.
configactionobjectconfig任意crud dashboard detail form master report search wizardPlugin / renderer specific extra settings.
configcolumnobjectconfig任意crud dashboard detail form master report search wizardPlugin / renderer specific extra settings.
configdashboardItemobjectdashboardItem.config任意dashboardExtra settings (formatter options, height, ...).
configfieldobjectconfig任意crud dashboard detail form master report search wizardPlugin / renderer specific extra settings.
configfilterobjectconfig任意crud dashboard master report searchPlugin / renderer specific extra settings.
configthemeobjectconfig任意すべてPlugin / renderer specific extra settings.
limitdashboardIteminteger任意100dashboardRows to fetch (the query's pageSize).
limitoptionsSourceinteger任意200crud dashboard detail form master report search wizardRows to fetch (a select is not a list screen).
limitreportinteger任意1000reportRows read for one run (a report is printed, not paged).

この表は spec/reference.json から生成している(JSON Schema が正)。手元では npx hatake reference <キー名> で同じものが引ける。

近い例

例は丸ごと写して直すのが一番速い。以下は CI で検証済み(そのまま動く形)。

ファイル種別画面どういうときに使うか
sales_dashboard.yamldashboard売上ダッシュボード件数・金額・グラフのカードを並べて、まず数字を見せたい
sales_report.yamlreport売上明細表一覧の印刷版が欲しい。顧客ごとに小計を出して、CSV も落としたい、紙にも刷りたい

実物を見る

デモアプリの「売上明細表」がこれを使っている。 デモを開く