Docurain Labo

Docurainサービス開発日記

Docurainで手軽にガントチャートを出力してみる

「帳票開発は面倒くさい」というのは古来、万葉集にも書かれている事実でありますが、その中でも特に面倒な類の帳票の一つがガントチャートだと思われます。

意外と面倒くさいガントチャート

私のこれまでの帳票開発経験を振り返ってみても、ガントチャートを出力したいというケースは結構多いんですよね。なにか長い期間をかけて行うプロジェクトは必ず工程管理が必要です。そして工程管理でよく使われる図の一つがガントチャートです。

しかしながら、意外と業務でガントチャートを扱うのは面倒くさいのです。

ガントチャートを扱うための選択肢として、ぱっと思いつくものは下記のとおりです。

  • Microsoft Project
  • Open Project
  • Redmine
  • Excel(+ VBA)
  • JavaScriptライブラリ

MS ProjectやOpen Projectははガントチャートのみならず、一般的にプロジェクト管理で必要になるようなリソース管理(平準化)、コスト管理、EVM(Earned value management)などなどの多数の機能が盛り込まれており、使用する場合も例えばPMBOKに記載されているようなプロジェクト管理の基礎知識が要求されます。したがって、ただ「ガントチャートを出力したい」という用途では重厚すぎる場合がほとんどでしょう。

Redmineに関してはプロジェクト管理ツールとして紹介されることも多いですが、基本的にはプロジェクト管理というよりはチケット管理のためのツールであるので、用途にフィットしないケースも多いと思われます。

「とりあえずガントチャートを描きたい」という用途ではExcelでそれを行うことが多いのではないでしょうか。ITエンジニアの皆さんであれば、一度はExcel VBA等々を応用して作成されたガントチャート作成ツールを用いてガントチャートを書いたご経験があると思います。

Excelは誰もが扱え、比較的簡単にデザインすることができます。ただ、Excelでの管理はプロジェクト管理上の重要なパラメータがExcelのファイル内に入ってしまっているという関係上、

  • Excelデータは編集を繰り返すと壊れることもあり、データストアとしてお粗末
  • データの再利用性があまりに低い(基幹システムと連携しにくい)
  • ビューとデータが一緒くたになって保守しにくい

というあたりが問題になるでしょう。

一方、世の中には手軽にガントチャートを描画できるJavaScriptライブラリがいくつか存在します。これらを使用してブラウザ上でガントチャートを表示するのは、これまで挙げた選択肢の中ではおそらく最も手軽で、かつ、システムの中でビューの責務だけをシンプルに実装できる方法なのであるべき姿に近いと考えられます。

ただし、それはJavaScriptライブラリが提供する表示フォーマットで合意が得られれば、の話です。実際には運用を重ねていく過程で使用しているJavaScriptライブラリでは容易に対応できない要求仕様が盛り込まれ、それなりに作り込みが必要になってくるはずです。印刷やPDF出力が要求されたときに困るという点も挙げられるでしょう。方法としてはブラウザの印刷機能に依存することになりますが、そもそもほとんどのライブラリは印刷までは想定していないはずで、印刷時にレイアウトが崩れるという可能性は十分に考えられます。

ではどうすればいいのか…。

Docurainでガントチャートを出力する

Docurainを使えば上記で述べたような課題は概ね解決でき、「とりあえずガントチャートを出力したい」という要求にフィットするはずです。

Docurainは帳票テンプレートをExcelでデザインできるので、今もしExcelでガントチャートを運用しているという場合にはそれを流用して最小限の実装量で基幹システムと連携できます。Docurainでの帳票出力はREST APIでテンプレートと挿入するデータを送信し、出力結果のバイナリ(PDFやExcel、画像など)を受け取るというだけの仕組みなので、ビューの責務を完全に分離できます。

というわけで、作ってみました。以下が今回つくったテンプレートです。

f:id:withpop:20190528173653p:plain

流し込むデータは下記のようなJSONとしてみました。 tasks という配列に、それぞれタスクの名前と担当者、開始日、終了日が入っているだけのシンプルな構造です。

{
    "projectName": "株式会社 FooBar様 取材記事公開スケジュール",
    "startDate": "2019/04/01T00:00",
    "tasks": [
        {
            "name": "取材",
            "lead": "高崎",
            "start": "2019/04/01T00:00",
            "end": "2019/04/08T00:00"
        },
        {
            "name": "記事本文作成",
            "lead": "高崎",
            "start": "2019/04/09T00:00",
            "end": "2019/04/15T00:00"
        },
        {
            "name": "記事レビュー",
            "lead": "岡田",
            "start": "2019/04/15T00:00",
            "end": "2019/04/20T00:00"
        },
        {
            "name": "撮影写真レタッチ",
            "lead": "山下",
            "start": "2019/04/09T00:00",
            "end": "2019/04/20T00:00"
        },
        {
            "name": "記事公開準備",
            "lead": "篠田",
            "start": "2019/04/21T00:00",
            "end": "2019/04/22T00:00"
        },
        {
            "name": "記事公開",
            "lead": "篠田",
            "start": "2019/04/23T00:00",
            "end": "2019/04/23T00:00"
        }
    ]
}

これでDocurainのAPIに対してリクエストを投げると以下のような出力結果が返ってきます。

f:id:withpop:20190528173452p:plain

解説

ではどんな仕組みになっているのか説明していきます。

f:id:withpop:20190528174338p:plain

#set($e=$ENTITY) は私が半ば癖のように書いている文です。Docurainの帳票テンプレート中ではJSONのルートオブジェクトは $ENTITY という名前で参照できますが、この名前が長いので $e として参照したいためにこのように $e という変数に代入をしています。

${e.projectName} はルート直下のprojectNameというキーの値を参照するという意味です。

$e.startDate も同様ですが、こちらは日付として整形して表示できるようExcel側で書式設定をしています。

以下の黄色部分は日付欄です。

f:id:withpop:20190528174838p:plain

一番左に開始日を挿入し、その他のセルは左のセル+1の値を表示するようにして開始日以降の日付を入力しています。

続いて #foreach です。

f:id:withpop:20190528174151p:plain

この #foreach は直感的にも明らかと思いますが、 tasks 配列の要素のぶんだけ、 #end までの行を繰り返し表示します。 各行では、タスクの名前と担当者、開始・終了日時を表示しています。

Docurain側の処理は以上で、あとはExcel固有の機能で帳票を作り込んでいます。

ガントチャート上の開始日~終了日までのラインや、土日(非稼働日)の背景色はすべて条件付き書式で実現しています。まず非稼働日の背景色について説明します。これは以下のような条件付き書式を設定しています。

f:id:withpop:20190528175126p:plain

INDIRECT(ADDRESS(7,COLUMN())) は、その列の7行目の値を参照する動作になります。7行目にはその列での日付が格納されています。 WEEKDAY は引数で与えられた日付に対する曜日を数値で返却します。これで、「特定の曜日だった場合に書式を適用する」という処理が可能です。

次はガントチャートの作業期間を示す線を条件付き書式で実現します。これは、下記のような11行目が非表示になっています。

f:id:withpop:20190528175647p:plain

11行目は「この日は作業期間に含まれるか否か」をTRUE/FALSEで示しています。

=AND(INDIRECT(ADDRESS(ROW()-1,4))<=INDIRECT(ADDRESS(7,COLUMN())), INDIRECT(ADDRESS(ROW()-1,5))>=INDIRECT(ADDRESS(7,COLUMN())))

という式は長ったらしいですが、その列が示す日にちは開始日以上かつ終了日以下であるか、を評価しています。

その下の12行目(ガントチャートのバーを表示する行)には、以下のように「上のセルがTRUEならば書式を設定する」という条件付き書式が設定されています。

f:id:withpop:20190528180125p:plain

これでガントチャートのバーを表示させるしょりは完了です。

…と言いたいところですが、もう一つやらなければならないことがあります。12行目には下記のように、数式で空白文字を値として設定しています。

f:id:withpop:20190528180013p:plain

これは、Docurainでは「foreachによる繰り返しの中で値の入っていないセルには条件付き書式は設定されない」という仕様があるためです(直感的に必要な場所にだけ条件付き書式を設定している動作を意図したもの)。

と、以上のように説明が必要なややトリッキーな要素はあるものの、Excelの基本的な使い方を知っていて、かつ基本的なプログラミングの知識がある(foreachという制御構造を理解できる程度で良い)ならば誰でも簡単に実装ができることがわかると思います。

今回作成したテンプレートとデータはこちらからダウンロードできます。

また、以下のページの「お試しフォーム」から登録不要でいますぐにAPIをお試しすることが可能です(ただし透かしが入ります)。

docurain.jp

もしご興味があれば公式サイトよりアカウントを作成してみて下さい!支払い方法を登録しない限りは請求が発生することはありません。