Help us understand the problem. What is going on with this article?

Handsontableで本格的な帳票の入力フォームを作るとき必要だったことたち

More than 3 years have passed since last update.

はじめに

「帳票作る機能作って」

...といわれて、いったん今回の要望聞いたところ、
1. 「できる限り画面で編集したものがそのまま印刷される感じ(見た目的に)にしてちょ」
2. 「操作しやすくしてちょ(キーボードでセルを移動できたり...)」
とのこと。
うちの会社でまだweb上で帳票入力機能を作ったことがなかったので、依頼側も
「たり」の続きも出てきません(笑)
きっと料金の合計計算とかはマストで必要、
他にも、日付だったらDate picker的なものがあったらうれしいだろうなとか、
不適切な入力のバリデート機能はそこsこいるだろうとか、
まだイメージわかなくて上がってきてない要望が、
「操作しやすくしてちょ」という言葉には含まれています(笑)

Handsontable + Thinreportsでいこう

で、色々調べて、

  • 入力フォーム:Handsontable
  • PDF出力:Thinreports

でいこう、ということになりました。
PDFフォーム使う案とかもあったのですが、
Handsontableなら料金の計算やらバリデートやら、自由にjsで書けるし、ということで採用。
Thinreportsで別途テンプレートだけ作って表示することに。

もうちょっとだけ詳しく言うと、
Handsontableを本物の帳票と似せて作り(CSS)、
入力フォームとして使います。
それで、入力されたデータをThinreportsでPDFをつくる専用のAPIに投げて
PDFを出力させる、という流れです。
データはHandsontableの出力データをjsonでDB保存します。

本記事の位置づけ

基本的な導入の仕方等はたくさん記事がありますので、そちらをチェックしてください。
本記事では、「Handsontableって、Web上でエクセルみたいなセルを表示できて、
セルの結合とか、色々できるんだなー」という状態から、
実際問題、帳票を作るときに必要になったオプションや実装方法を書いていきます。

実際帳票を作る上で必要になったHandsontableの設定メモ

セルの色などスタイルを変える

項目名の部分は色を変えたり、文字サイズを変えたり・・・
スタイルを変えるには、セルにclassを割り振ってスタイルシートで設定しましょう。

cellProperties.className = 'td_white';

readonly

「お名前」「電話番号」など、項目名は編集できては困るのでreadonlyに。

cellProperties.readOnly = true;

メニューを表示しない

デフォルトで、右クリック時に「セルをマージする」などなどのメニューが出てきます。
帳票ではいらないので消します。

contextMenu: false, 

セルを結合する

エクセルのようにセルを結合することができます。
結合したいセルの中の、最も左上を起点として、そこから縦・横に、いくつを結合するかを記述します。

mergeCells:[
  {row: 0, col: 0, rowspan: 3, colspan: 1},
  {row: 1, col: 1, rowspan: 2, colspan: 1},
]

余分な行を出力させない

Handsontableは、デフォルトで、「最終行の入力をしたら新しい行が新規追加される」という機能があります。
帳票作成の場合、テンプレートの枠が勝手に増えていっては困るので、この設定をしておく必要があります。
また、こちらもデフォルトでは、「1行空行を余分に表示する」という仕様なので、明示的に「いらないよ」と言っておく必要があります。

maxRows: 4,
maxColumns: 6,
minSpareRows: 0

行の幅を動的に変えない

こちらも、自動で伸縮したら困るので数字で設定。

colWidths: [80,165,250,80,165,250],
rowHeights: [10,10,10,110]

セル入力後、次に選択されるセルを指定する

案外喜ばれた機能。
縦に入力することが予想される部分と、横の部分とで、
エンターを押したときに次に選ばれるセルを変えることができます。

enterMoves: { row: 1, col: 0 }

プルダウン

帳票という性質上、そこに書き込む文言が何パターンかのうちひとつであることはよくあります。
そこで、選択肢の中で選んで入力させてあげます。
選択肢を無視しての自由記述を認めるか否かも決められます。

cellProperties.type = 'dropdown';
cellProperties.source = ['ooo','xxx','△△△'];

Date picker

「契約日」など、日付を入力したい場合、jQueryのdatepicker的なものが使えます。

cellProperties.type = "date";
cellProperties.dateFormat = "YYYY/MM/DD";

バリデート,料金計算など

自分で好きなようにバリデータをつくるなら、afterChangeに。
料金の合計や、消費税計算などもここに書けます。

afterChange: function(change, source) {
  if (change != null) {
    if ($('.vali').height() > 110) {
      alert('行数はみ出てます');
    }
  }
}

確実に保存してもらうために

これはもはやHandsontableの使い方、とかではありませんが、
確実に保存してからPDF出力してもらう為に、
セルの内容に変更があったら、まずPDF出力ボタンを消し、
保存ボタン(点滅させてめちゃくちゃ目立つ)を表示するようにしました
この辺も、きちんとした書類ということで必要な機能です。

afterChange: function(change, source) {
  if (change != null) {
    $('.save_button').addClass('tenmetsu');
    $('.save_box').show();
    $('.pdf_button').hide();
  }
}

まとめ

Handsontableが「エクセルっぽいことがいろいろできる」だけに、
帳票として使うためには、むしろデフォルトの便利機能を明示的にオフにしていくような作業が必要でした。
一通りHandsontableのデフォルトの仕様が頭に入ってこれば
次回からは必要な機能を選びつつ、サクサク作れるかなといったところです。

是非、割ときちっとした用途にも、ご検討ください!

a-hikkoshi
当社は、親会社である株式会社エイチームの経営理念をそのままに、引越しの比較サービス開始以降、大切にしてきた「三方よし」の理念を基本として、世の中に求められるサービスの創造を目指します。 一緒に働けるエンジニアを募集しております。下記URLよりご応募ください。 https://bit.ly/3lwf7QJ
https://hikkoshi.a-tm.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away