SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

高機能JavaScriptスプレッドシート部品「SpreadJS」の活用(AD)

ガントチャートをWebアプリに組み込める「ガントシート」でプロジェクト管理機能を作成してみよう

  • X ポスト
  • このエントリーをはてなブックマークに追加

 メシウス株式会社の提供する「SpreadJS」は、サーバサイドの実装を必要とせずにWebブラウザのみでExcelライクなスプレッドシートを作成、表示することのできるJavaScriptライブラリです。本記事では、SpreadJS V17Jの新機能であるガントシート機能でガントチャートをWebアプリに組み込み、レベル階層フォーマットの使い方や先行タスク、達成度の表示、スタイルのカスタマイズなどの事例を紹介します。

  • X ポスト
  • このエントリーをはてなブックマークに追加

必要な環境

 本記事のサンプルコードは、以下の環境で動作を確認しています。

  • macOS Sonoma
    • SpreadJS(17.1.5)
    • Visual Studio Code 1.95.1(Live Server 5.7.9)
    • Google Chrome 130.0

対象読者

  • Webアプリにガントチャート機能を実装したい方
  • Webアプリでプロジェクトの工程管理を行いたい方
  • SpreadJSのスプレッドシート以外の機能を知りたい方

作成するガントチャート

 本記事では、図1のガントチャートを作成します。このガントシートは、架空のプロジェクトにおける進捗を表示します。ワークシートを2つ作成し、ガントシートのデータ形式であるレベル階層形式と子階層形式で、それぞれガントチャートを表示します。また、先行タスクと達成率の表示、ガントチャートのスタイルのカスタマイズも実施します。

図1 本記事で作成するガントチャート
図1 本記事で作成するガントチャート

開発環境と事前準備

 最初に、開発環境と必要なファイルを準備しておきます。

開発環境

 開発環境としては、VSCode(Visual Studio Code)をインストールしておきます。そのあと、VSCodeにHTTPサーバを提供する拡張機能Live Serverをインストールします。本記事のサンプルではHTTPサーバは必須ではありませんが、ホットリロードなどが利用できるので、インストールしておくと便利です。

SpreadJSモジュールの入手と配置

 アプリの拠点となる作業フォルダを作成しておきます。ここでは、spreadjs_ganttとしました。この作業フォルダに、JavaScriptファイルの置き場所であるscriptsフォルダと、CSSファイルの置き場所であるcssフォルダをさらに作成しておきます。

 SpreadJSのトライアル版、または製品版を入手して配置します。トライアル版は公式ページからダウンロードできます。Zipファイルを解凍してできるSpreadJS_Release/SpreadJS-Libs/SpreadJS以下にあるフォルダから、以下のファイルを作業フォルダにコピーします。scriptsフォルダ配下のファイルはscriptsフォルダへ、cssフォルダ配下のファイルはcssフォルダへ、それぞれコピーしてください。

 なお、cssフォルダにはCSSファイルが7種類収納されています。ライト系とダーク系などからお好みのデザインのものを選択してください。ここではオーソドックスなexcel2013white.17.1.5.cssとしました。

 scripts/gc.spread.sheets.all.17.1.5.min.js

 scripts/plugins/gc.spread.sheets.tablesheet.17.1.5.min.js

 scripts/plugins/gc.spread.sheets.ganttsheet.17.1.5.min.js

 scripts/resources/ja/gc.spread.sheets.resources.ja.17.1.5.min.js

 css/gc.spread.sheets.excel2013white.17.1.5.css

SpreadJSのバージョン

 執筆にはSpreadJS 17.1.5を使用しました。入手したバージョンが異なる場合には、index.htmlファイルの<link>タグと<script>タグにおいて、ファイル名中のバージョンの表記を実際のバージョンに合わせてください。

カスタムCSSファイルの準備

 カスタムCSSは、ガントシートをHTMLにどのように表示させるかを決めるためのものです。以下のリストの内容で作成し、cssフォルダに配置します。基本的にページ領域いっぱいを使用して表示します。

css/styles.css
body, html {			/* ガントシートをページいっぱいに表示 */
    padding: 0;
    margin: 0;
    width: 100%;
    height: 100%;
    position: relative;
    overflow: hidden;
}
.sample, .spreadsheets{		/* 親要素に対して100%の領域で表示 */
    width: 100%;
    height: 100%;
}

レベル階層形式ガントシートの組み込み

 SpreadJSモジュールとカスタムCSSの準備ができたら、HTMLファイルなどを作成してガントシートを組み込んでいきましょう。

HTMLファイルの準備

 アプリの起点であるindex.htmlファイルを、以下のリストの内容で作業フォルダに作成します。(1)のCSSファイルの読み込みパスは、実際に使うCSSファイルに合わせてください。(2)以降のJavaScriptファイルの読み込みも同様です。(3)がガントシートアプリとデータの読み込みで、(4)がスプレッドシートが展開される要素です。

index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" type="text/css" href="css/gc.spread.sheets.excel2013white.17.1.5.css">	(1)
    <script src="scripts/gc.spread.sheets.all.17.1.5.min.js"></script>	(2)
    <script src="scripts/gc.spread.sheets.tablesheet.17.1.5.min.js"></script>
    <script src="scripts/gc.spread.sheets.ganttsheet.17.1.5.min.js"></script>
    <script src="scripts/gc.spread.sheets.resources.ja.17.1.5.min.js"></script>
    <script src="scripts/app.js"></script>	(3)
    <script src="scripts/data.js"></script>
    <link rel="stylesheet" type="text/css" href="css/styles.css">
</head>
<body style="height: 100%; font-size: 14px;">
    <div class="sample">
        <div id="ss" class="spreadsheets"></div>	(4)
    </div>
</body>
</html>

JavaScriptファイルの準備

 ガントシートを表示するためのapp.jsファイルを、scriptsフォルダに作成します。まずは、ガントシート作成処理以前の部分を、以下のリストの内容で作成します。

scripts/app.js(ワークブックの初期化)
// (1)ライセンスキーと言語の設定
//GC.Spread.Sheets.LicenseKey = "ここにSpreadJSのライセンスキーを設定します";
GC.Spread.Common.CultureManager.culture("ja-jp");

// (2)ページ読み込み後にワークブックを初期化する
window.onload = () => {
  const spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), {
    sheetCount: 0
  });
  initSpread(spread);			// スプレッドシートの初期化
};

// (3)スプレッドシートの初期化関数
function initSpread(spread) {
  spread.suspendPaint();		// 描画の停止
  initGanttSheetLevel(spread);		// レベル階層形式ガントシートの初期化
  spread.resumePaint();			// 描画の再開
}

 (1)のライセンスキーの設定では、各自が入手したライセンスキーを記述してください。ライセンスキーを設定せずにトライアル版として利用する場合には、1行目をコメントアウトしてください。この場合、実行時にトライアル版であることを示すメッセージが表示されます。

 (2)は、ページ読み込み終了時のイベントハンドラ(onload)で、ワークブックを初期化しています。表示領域となるHTML要素(id="ss")を指定してWorkbookオブジェクトを生成します。sheetCountプロパティをゼロに設定しているのは、初期状態でシートを作成しないことを意味します。

 (3)は、ワークブックの生成後に呼び出されるinitSpread関数です。ここでは、ガントシート描画中の画面のちらつきを抑えるために、suspendPaintメソッドで描画を保留し、initGanttSheetLevel関数の呼び出し後に、resumePaintメソッドで描画を再開しています。

 続いて、レベル階層形式のガントシートの初期化関数です。

scripts/app.js(ガントシートの初期化)
// ガントシートの初期化関数(レベル階層)
function initGanttSheetLevel(spread) {
  // (1)データマネージャの取得とテーブルの作成
  const dataManager = spread.dataManager();
  const table = dataManager.addTable("linkTable", {
    data: getDataLevel(),			// バインドするデータの指定
    batch: true,				// 同期モードにバッチを指定
    schema: {					// スキーマの指定
      hierarchy: {
        type: "Level",				// レベル階層形式の指定
        column: "level"				// レベルはlevelプロパティで指定
      }
    }
  });
  // (2)ガントシートの追加と外見の設定
  const ganttSheet = spread.addSheetTab(0, "レベル階層プロジェクト",
    GC.Spread.Sheets.SheetType.ganttSheet);	// ガントシートのシートを追加
  //ganttSheet.project.startDate = new Date("2024/11/13 09:00");	// 開始日時(省略時は現在日時)
  ganttSheet.gridlines.bottomTierColumn.lineType = 	// 縦線をダッシュに
    GC.Spread.Sheets.GanttSheet.GanttGridlineType.dashed;
  ganttSheet.gridlines.ganttRows = {	// 横線は細線のグレー
    lineType: GC.Spread.Sheets.GanttSheet.GanttGridlineType.thin,
    lineColor: "lightgray",
  }
  // (3)ビューの作成
  const view = table.addView("linkView", [
    { value: "taskNumber", caption: "NO.", width: 70 },
    { value: "name", caption: "タスク名", width: 260 },
    { value: "pic", caption: "担当責任者", width: 120 },
    { value: "duration", caption: "予定工数", width: 90 }
  ]);
  // (4)データの読み込みとビューのバインド
  view.fetch().then(() => {
    ganttSheet.bindGanttView(view);
  }).then(() => {
    // (5)タイムスケールの設定
    const tierMode = 
      GC.Spread.Sheets.GanttSheet.TimescaleTierMode.topMiddleBottom;	// 上段、中段、下段の全てを指定
    ganttSheet.project.timescale.tierMode = tierMode;
    ganttSheet.project.timescale.topTier.unit = 
      GC.Spread.Sheets.GanttSheet.TimescaleUnit.months;	// 上部は月表示
    ganttSheet.project.timescale.topTier.formatter = "yyyy年mm月";	// 月表示のフォーマット
  });
}

 initGanttSheetLevel関数は、ガントシートを初期化します。

 (1)以降は、データ管理をつかさどるデータマネージャオブジェクトをdataManagerで取得し、addTableメソッドでテーブルを追加しています。テーブルは、名前("linkTable")とオプションで構成されます。以下は、それぞれのプロパティの意味です。

  • data:バインドするデータを表します。ここでは後述するgetDataLevel関数から返される配列を渡しています。
  • batch:リモートデータベースの更新方法をBatchモードに指定します。通信効率の向上のために、スプレッドシートの変更を保存し、一度に更新するようになります。サンプルには更新処理はありませんが、ガントシートでは、batchプロパティをtrueに設定する必要があります。
  • schema:データの構成を指定します。レベル階層形式では、hierarchy.typeプロパティに"Level"を、columnプロパティにはレベルを指定するデータソース上のプロパティ(この場合は"level")を指定します。

 (2)以降は、addSheetTabメソッドでシートタブを追加し、外見を設定しています。addSheetTabメソッドの引数は、前から「位置(ここでは0=先頭)」「名前(ここでは"レベル階層プロジェクト")」を意味します。gridlinesプロパティは、名前の通り、グリッド線の見た目を設定します。なお、サンプルではコメントアウトしていますが、project.startDateプロパティを設定すると、プロジェクトの開始日を指定できます。省略時は、現在日時となります。

 (3)以降では、テーブルに対応するビューを作成します。ここで、個々の列情報を指定できます。それぞれのプロパティの意味は、以下の通りです。

  • value:列名
  • caption:キャプション
  • width:表示幅
  • visible:列を表示するか

 表示したい列を追加する場合には、ここに列情報を追加していきます。

 あとは、(4)のfetchメソッドでデータを読み込み、bindGanttViewメソッドでガントシートにバインドするだけです。なお、必須ではありませんが、(5)のように、タイムスケールの表示をカスタマイズすることも可能です。なお、タイムスケールとはガントチャート部の列ヘッダーです。最大3段階の表示が可能で、月、週、日などの期間を表示できます。

データソースの準備

 レベル階層形式のデータソースとして、data.jsファイルをscriptsフォルダ配下に以下のリストの内容で作成します。全体は配布サンプルを参照してください。

scripts/data.js
function getDataLevel() {
  const Gantt_Data = [
    {
      "id": 1,
      "level": 0,			(1)
      "taskNumber": 1,
      "name": "要件定義",
      "duration": "6 days",
      "pic": "正門 恵子"
    },
    …略
  ]
  return Gantt_Data;
}

 データソースにおけるポイントは(1)のlevelプロパティで、レベル階層形式においてレベルを指定することです。スキーマ設定におけるhierarchy.columnプロパティに指定した名前である必要があります。値には、レベルを整数値で指定します。数値に応じた階層に項目が配置されます。

実行確認

 ここまで作成すると、実行確認できます。VSCodeのエクスプローラーからindex.htmlファイルを右クリックして、メニューから[Open with Live Server]をクリックしてサーバを起動します。図2のようにガントシートが表示されれば、ここまでの手順はうまくいっています。以降は、コードの修正で自動的にページが更新されます。

図2 レベル階層によるガントチャートの例
図2 レベル階層によるガントシートの例

ガントシートの活用例

 ここからは、先行タスクの設定やタスク達成度の表示、スタイルのカスタマイズなど、ガントシートの活用についてのトピックスをいくつか紹介します。

先行タスクの設定

 ここまでのサンプルでは、複数のタスクがあってもそれらは同時進行していました。しかし、現実的なプロジェクトでは、通常は先行タスクがあって、その終了を待って次のタスクが始まるのが一般的です。このように、別のタスクの終了に依存する形で次のタスクを開始させたい場合には、predecessorsプロパティをタスクデータに追加し、ビューにも項目を追加します。

 predecessorsプロパティの値は文字列で、通常は先行タスクのidを指定します(複数ある場合にはカンマ区切り)。先行タスクがない場合には、空文字列を指定します。ここには、先行タスクなしの場合とありの場合の例を示すので、全体は配布サンプルを参照してください。

scripts/data.js(getDataLevel関数)
function getDataLevel() {
  const Gantt_Data = [
    …略…
    {
      "id": 2,
      "level": 1,
      "taskNumber": 2,
      "name": "社内関係者ヒアリング",
      "duration": "1 day",
      "predecessors": "",			// 先行タスクなし
      "pic": "正門 恵子"
    },
    {
      "id": 3,
      "level": 1,
      "taskNumber": 3,
      "name": "要求事項の細分化",
      "duration": "3 days",
      "predecessors": "2",			// 先行タスクはid=2のタスク
      "pic": "青木 俊之"
    },
    …略…

 対応するビューは、以下のとおりです。項目は必要ですが、列として見える必要はないのでvisibleプロパティをfalseとしています。

scripts/app.js(initGanttSheetLevel関数)
const view = table.addView("linkView", [
  …略…
  { value: "duration", caption: "予定工数", width: 90 },
  { value: "predecessors", caption: "先行タスク", width: 120, visible: false },
]);	// 追加
図3 先行タスクを設定
図3 先行タスクを設定

タスク達成度の表示

 それぞれのタスクには、達成度をパーセント表示することができます。タスクにcompleteプロパティを追加し、達成度を0~1.0までの数値で指定します。なお、completeプロパティを追加できるのは子要素を持たない要素のみです(追加しても無視されます)。親要素には、子要素の達成度を合計したものが反映されます。

scripts/data.js(getDataLevel関数)
…略…
{
  "id": 8,
  "level": 2,
  "taskNumber": 8,
  "name": "帳票設計",
  "duration": "2 days",
  "predecessors": "",
  "pic": "成宮 真紀",
  "complete": 0.5,		// 達成度は50パーセント
}
…略…

 ビューは、以下のリストのようになります。

scripts/app.js(initGanttSheetLevel関数)
const view = table.addView("linkView", [
  …略…
  { value: "predecessors", caption: "先行タスク", width: 120, visible: false },
  { value: "complete", caption: "進捗率", width: 70 },	// 追加
]);
図4 タスク達成度の表示
図4 タスク達成度の表示

タスクの表示スタイルのカスタマイズ

 タスクの表示スタイル(シェイプや色など)は、タスクバーの各要素につき、スタイルルール(GC.Spread.Sheets.GanttSheet.TaskbarStyleRuleName)という形で決められています。各要素のスタイルルールは以下が組み込みで用意されています。

表 タスクの表示スタイル
スタイルルール 概要
durationOnly 期間
durationOnlyMilestone 期間(マイルストーン)
finishOnly タスク終了
finishOnlyMilestone タスク終了(マイルストーン)
manualMilestone マイルストーン、手動スケジュール
manualProgress 進捗、手動スケジュール
manualSummary サマリー、手動スケジュール
manualTask タスク、手動スケジュール
milestone マイルストーン
progress 進捗
projectSummary プロジェクトのサマリー
startOnly タスク開始
startOnlyMilestone タスク開始(マイルストーン)
summary サマリータスク
task タスク

 カスタマイズの基本は、上記いずれかのスタイルルールのオブジェクトを取得し、シェイプや色のプロパティを変更してオブジェクトを書き戻すという流れです。なお、以下の行に挙げるプロパティが指定できます。シェイプは矩形(rectangle)、円(circle)、矢印(arrow)などから選択できます。タイプは実線(solid)、破線(dashed)、枠線(framed)から選択できます。テキストに指定できるのは、プロパティ名と列の数式です。

表 表示スタイルのプロパティ
プロパティ 概要
startShape GC.Spread.Sheets.GanttSheet.TaskbarStartShape 開始部のシェイプ形状
startType GC.Spread.Sheets.GanttSheet.TaskbarStartType 開始部のタイプ
startColor string 開始部のカラー
middleShape GC.Spread.Sheets.GanttSheet.TaskbarMiddleShape 中間部のシェイプ
middlePattern GC.Spread.Sheets.GanttSheet.TaskbarFillPattern 中間部の埋めパターン
middleColor string 中間部のカラー
endShape GC.Spread.Sheets.GanttSheet.TaskbarEndShape 終了部のシェイプ
endType GC.Spread.Sheets.GanttSheet.TaskbarEndType 終了部のタイプ
endColor string 終了部のカラー
topText string 上部に表示するテキスト
rightText string 右に表示するテキスト
bottomText string 下部に表示するテキスト
leftText string 左に表示するテキスト
insideText string 内部に表示するテキスト

 以下のリストは、taskスタイルルールを取得し、startShapeとendShape(始点と終点のシェイプ)に"circle"(円)を設定し、さらにカラー(startColorとendColor)に中間部の色(middleColor)を設定しています。最後に、taskbarStyleオブジェクトに書き戻している点に注意してください。この設定により、タスク工程のバーの両端が丸くなります(図4)。

scripts/app.js(initGanttSheetLevel関数)
let taskRule = ganttSheet.project.taskStyleRules.getRule("task");
let taskStyle = taskRule.style.taskbarStyle;
taskStyle.startShape = "circle";
taskStyle.endShape = "circle";
taskStyle.startColor = taskStyle.middleColor;
taskStyle.endColor = taskStyle.middleColor;
taskRule.style.taskbarStyle = taskStyle;
図5 タスクの表示スタイルのカスタマイズ
図5 タスクの表示スタイルのカスタマイズ

子階層形式ガントシートの組み込み

 ここまではレベル階層形式(levelプロパティで階層を表す形式)を使った例を紹介しましたが、最後に子階層形式での指定方法についても紹介します。基本的なコードはレベル階層形式(initGanttSheetLevel関数)と同じなので、異なるポイントのみを紹介します。

 子階層形式のデータは、以下のリストのように表します。簡略化のためにnameプロパティとchildrenプロパティのみ掲載しているので、全容は配布サンプルを参照してください。見た目に階層構造が分かりやすいのが子階層形式の特徴です。

scrips/data.js(getDataChildren関数)
function getDataChildren() {
  const Gantt_Data = [
  …略…
    {
      "name": "設計",
      "children": [			// スキーマで指定する子階層のキー
        {
          "name": "基本設計",
          "children": [
            {
              "name": "画面設計",
            },
            …略…

 app.jsファイルでは、childrenプロパティが子階層のデータであることを示すために、スキーマの設定において、hierarchy.typeプロパティを"ChildrenPath"に、columnプロパティを"children"に設定します。

scripts/app.js(initGanttSheetChildren関数)
…略…
const table = dataManager.addTable("childTable", {
  data: getDataChildren(),		// 子階層形式のデータを指定
  batch: true,
  schema: {
    hierarchy: {
      type: "ChildrenPath",		// 子階層形式であることを示す
      column: "children"		// データ中のプロパティ名を指定する
    }
  }
});

 initGanttSheetChildren関数の呼び出しを、initSpread関数に追加します。すると子階層形式のシートが追加され、子階層形式のデータで表示されます(図6)。シートが複数になったので、どのシートを表示するかをシート左下の4本線のボタンで選択できます。

図6 子階層形式でのガントシート表示
図6 子階層形式でのガントシート表示

まとめ

 本記事では、SpreadJS V17Jの新機能であるガントシート機能でガントチャートをWebアプリに組み込み、複数の階層フォーマットの使い方や、先行タスク、達成度の表示、スタイルのカスタマイズなどの事例を紹介しました。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加

提供:メシウス株式会社

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/20541 2025/01/07 12:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング