対象読者
- Excel VBAで作成したマクロをWebアプリに移行したい方
- JavaScriptを使ってExcelライクな操作を実現したい方
- SpreadJSを使って業務アプリケーションのUIを改善したい方
SpreadJSとは
SpreadJSは、JavaScriptだけで動作する高機能なスプレッドシートコンポーネントライブラリです。Webブラウザ上でExcelに近い操作感と豊富な表計算機能を実現し、単なるテーブル表示を超えたインタラクティブなユーザー体験を提供します。
まさに「ExcelをそのままWebに持ち込める」ようなライブラリです。SpreadJSの主な特長は以下の通りです。
- Excel互換のUI/UX
- 豊富な関数とセルスタイル
- 大規模データでも高速レンダリング
- 豊富な拡張性とAPI
Excel互換をうたうばかりではなく、「多段ヘッダ」や「ツリー表示」「ガントチャート」など、Excelより高機能な部分もあり、かゆいところに手が届く仕様になっています。
今回紹介するExcel VBA資産のWebアプリ移行だけでなく、BIツールに組み込んだり、既存の帳票を活かした業務アプリケーションを構築したりと、さまざまなシーンで利用できます。また、SpreadJSの機能の基本的な使い方については、公式サイトで利用ガイドが公開されているのでそちらもご覧ください。
前提条件
今回は以下の環境を想定します。SpreadJSの機能だけでなにができるかをわかりやすくするため、フレームワークは使用しませんが、Angular、React、Vue.jsなどとの組み合わせでも利用可能です。
- 使用言語: JavaScript(Pure JS)
- SpreadJSのバージョン: 18.0.6
- 開発環境: Visual Studio Code(以下、「VS Code」)
移行するExcelの紹介と移行の流れ
本記事で移行対象とするExcelファイルは、店舗ごとの売上データを集計シートにまとめるマクロを搭載したサンプルファイルです。
サンプルファイルは以下のようなシートから構成されています。
-
祝日: 集計時に売上対象外とする日付リスト(集計シートの条件付き書式で使用) -
集計: 各店舗のデータを読み込み、全店舗の売り上げ合計や平均を計算するシート -
A店舗/B店舗/C店舗: 各店舗の日次売上データを表形式で記録するシート
なお、SpreadJSはマクロつきExcelファイル(demo.xlsm)に非対応のため、以下ではボタンを削除し、Excelファイル(.xlsx)として保存し直したファイル(demo.xlsx)を使用します。
では、サンプルプロジェクトの構成を確認した上で、SpreadJSの初期化とExcelファイルの読み込みから始めましょう。
サンプルプロジェクトの起動
以下3つのサンプルプロジェクトを用意しています。
-
samples/: サンプルプロジェクトのルートディレクトリ-
01-basic: SpreadJSの初期化とExcelファイルの読み込み -
02-with-buttons: HTMLのボタンからSpreadJSのデータを操作 -
03-with-ribbon: リボンをつけてExcelライクなインターフェースを実現
-
実際の動作確認は、VS CodeでLive Serverを起動して行います。VS Codeに拡張機能「Live Server」をインストールし、以下の手順でサンプルプロジェクトを起動します。
-
プロジェクトのルートディレクトリ(
samples)を開く - 任意のindex.htmlを右クリックし、「Open with Live Server」を選択する
-
ブラウザが起動し、
http://localhost:5500/01-basic/のようなURLが表示される
SpreadJSでサーバーに配置したExcelファイルを読み込む
まずは01-basicプロジェクトで、SpreadJSの初期化とExcelファイルの読み込みまでを見ていきましょう。
プロジェクトのファイル構成
今回のサンプルは、以下のようなディレクトリ構成になっています。
samples/ ├─ 01-basic/ │ ├─ index.html ← デモアプリのHTMLファイル │ ├─ css/ │ │ ├─ gc.spread.sheets.18.0.6.css ← SpreadJSメインスタイルシート │ │ ├─ ...その他のSpreadJS関連スタイルシート │ │ └─ style.css ← デモアプリ用スタイルシート │ ├─ scripts/ │ │ ├─ gc.spread.sheets.all.18.0.6.min.js ← SpreadJSメインファイル │ │ ├─ ...その他のSpreadJS関連ファイル │ │ └─ index.js ← デモアプリメインスクリプトファイル │ └─ data/ │ └─ demo.xlsx ← 移行元のExcel VBAサンプルファイル ├─ 02-with-buttons/ │ └── ... └─ 03-with-ribbon/ └── ...
なお、gc.spreadからはじまるファイルは、いずれもSpreadJSのパッケージファイルのSpreadJS_Release/SpreadJS-Libs/SpreadJSフォルダ以下に含まれるファイルをコピーします。ほかにもさまざまなファイルがあるので、必要な機能に応じてコピーして利用してください。
HTMLの準備
本記事では、Pure JSで実装するため、シンプルなindex.htmlを用意し、必要なCSSやJSファイルを読み込みます。今回はメインのスクリプトをscripts/index.jsに配置するので、そのファイルも読み込みます。
<link rel="stylesheet" href="css/gc.spread.sheets.18.0.6.css" /> <link rel="stylesheet" href="css/gc.spread.sheets.excel2013lightGray.18.0.6.css" /> <link rel="stylesheet" href="css/style.css" /> <script src="scripts/gc.spread.sheets.all.18.0.6.min.js"></script> <script src="scripts/gc.spread.sheets.io.18.0.6.min.js"></script> <script src="scripts/gc.spread.sheets.resources.ja.18.0.6.min.js"></script> <script src="scripts/index.js"></script>
css/gc.spread.sheets.excel2013lightGray.18.0.6.cssは、Excel 2013のライトグレーのテーマを適用するためのスタイルシートです。これを指定するとSpreadJSの見た目がよりExcelに近くなります。
scripts/gc.spread.sheets.io.18.0.6.min.jsは、SpreadJSのIO機能を提供するスクリプトで、Excelファイルの読み込みや保存に必要です。
また、HTMLのbodyには以下のようにid(今回はcontainer)を指定した要素を配置します。この要素にSpreadJSを展開します。
<body> <div id="container"></div> </body>
メインスクリプトの実装
既存のExcelファイルを読み込むため、以下の流れでSpreadJSを初期化します。
- ライセンスキーと言語の設定
-
new GC.Spread.Sheets.Workbook("container")のようにSpreadJSのWorkbookを初期化 -
サーバーからExcelファイルをダウンロード(
fetchを使用) -
workbook.import関数でExcelファイルをSpreadJSにインポート
実際の初期化部分のソースコードは以下のようになります。
// 1. ライセンスキーと言語の設定
// GC.Spread.Sheets.LicenseKey = "ここにSpreadJSのライセンスキーを設定します";
GC.Spread.Common.CultureManager.culture("ja-jp");
// 2. SpreadJS の Workbook を初期化
const workbook = new GC.Spread.Sheets.Workbook("container");
// 3. サーバーからExcelファイルをダウンロード
const response = await fetch("data/demo.xlsx");
if (!response.ok) {
throw new Error("Excelファイルの取得に失敗しました");
}
// 4. ExcelファイルをSpreadJSにインポート
workbook.import(
await response.blob(), // ダウンロードしたExcelファイルをBlobとして渡す
() => console.log("Excelファイルの読み込みに成功しました"),
(error) => console.error("Excelファイルの読み込みに失敗しました", error),
{
fileType: GC.Spread.Sheets.FileType.excel,
}
);
1の部分で、各自が入手したライセンスキーを記述してください。ライセンスキーを設定せずにトライアル版として利用する場合には、コメントアウトしてください。この場合、実行時にトライアル版であることを示すメッセージが表示されます。
実行してみる
VS CodeのLive Serverを起動し、http://localhost:5500/01-basic/をブラウザで開いてみましょう。Excelファイルが読み込まれ、SpreadJS上にシートが展開されていることが確認できると思います。
ここでおもしろいのは「集計」タブのB2やB3セルなど、Excelの計算式が入っているセルがそのまま動作している点です。SpreadJSはExcelの計算式をサポートしているため、計算処理をJavaScriptで独自に実装する必要がありません。
また、Excelの条件付き書式もそのまま使用できるので、集計シートの2024年10月14日のように、祝日シートに記載されている日付のセル色が動的に変更されていることが確認できます。
HTMLのボタンからSpreadJSのデータを操作する
次に、HTML上にボタンを配置し、VBAマクロを実行するのと同じように、SpreadJS上で集計やクリアといった処理を実行できるようにします。サンプルプロジェクト02-with-buttonsを参照してください。
HTMLへのボタン追加
index.htmlに2つのボタン要素を追加しています。これでもHTMLはとてもシンプルですね。
<body>
<div id="toolbar">
<button id="aggregateBtn">集計</button>
<button id="clearBtn">クリア</button>
</div>
<div id="container"></div>
</body>
http://localhost:5500/02-with-buttons/をブラウザで開くと、2つのボタンが表示されており、クリックすることで、実際に集計シートの内容が変更されることが確認できると思います。
「集計」ボタンの実装
実際の「集計」ボタンの処理を確認しましょう。
-
集計シートのB列に、各店舗シート(A店舗/B店舗/C店舗)の店舗名を記載 -
集計シートのC列~AG列に、各店舗シートの売上データを日付ごとにコピー(縦方向に並んだデータを横方向に転記するイメージ)
「集計」ボタンの実装は以下のようになっています。
function performAggregate() {
// 集計シートを取得
const aggregateSheet = workbook.getSheetFromName(aggregateSheetName);
const aggregateSheetIndex = workbook.getSheetIndex(aggregateSheetName);
// 店舗シートを取得(集計シートの後のシートを取得)
const storeSheets = workbook.sheets.slice(aggregateSheetIndex + 1, workbook.sheets.length);
workbook.suspendPaint(); // 描画を一時停止
let storeIndex = 0;
for (const storeSheet of storeSheets) {
const storeName = storeSheet.name();
// 店舗名を最初の列にセット
aggregateSheet.setValue(aggregateRange.row + storeIndex, aggregateRange.col, storeName);
// 各店舗のシートから日ごとの売り上げの値を集計シートにセット(縦に並んだ数値を横並びにセット)
for (let dateIndex = 0; dateIndex < 31; dateIndex++) {
const value = storeSheet.getValue(2 + dateIndex, 1);
aggregateSheet.setValue(aggregateRange.row + storeIndex, aggregateRange.col + dateIndex + 1, value);
}
storeIndex++;
}
workbook.resumePaint(); // 描画を再開
}
ここで使用したSpreadJSのAPIを紹介します。
-
Workbook.getSheetFromName(sheetName): 指定したシート名のシートを取得します。 -
Workbook.getSheetIndex(sheetName): 指定したシート名のシートのインデックスを取得します。 -
Workbook.suspendPaint()/Workbook.resumePaint(): 大量のデータを操作する際に、描画のパフォーマンスを向上させるために使用します。suspendPaintで描画を一時停止し、resumePaintで描画を再開します。 -
Worksheet.setValue(row, col, value): 指定した行・列のセルに値をセットします。 -
Worksheet.getValue(row, col): 指定した行・列のセルの値を取得します。 -
Worksheet.name(): シートの名前を取得します(プロパティではなく関数なので注意してください)
「クリア」ボタンの実装
「クリア」ボタンでは集計シートの各店舗の売り上げ部分を消去しています。実際の処理は以下のようにWorksheet.clear()関数で、指定した範囲のセルをクリアしているだけです。
aggregateSheet.clear( aggregateRange.row, // 開始行 aggregateRange.col, // 開始列 aggregateRange.rowCount, // 行数 aggregateRange.colCount, // 列数 GC.Spread.Sheets.SheetArea.viewport, // 対象エリア GC.Spread.Sheets.StorageType.data // ストレージタイプ );
GC.Spread.Sheets.SheetArea列挙体では、操作対象のエリアタイプを指定します。今回は 通常のセル範囲を対象とするためSheetArea.viewportを指定しています。
GC.Spread.Sheets.StorageType列挙体では、操作対象の属性タイプを指定します。今回はセルの値を消去するため、StorageType.dataを指定しています。
以上で、サーバーから読み込んだExcelデータに対し、HTML上のボタン操作で処理を行うことができました。
リボンをつけてExcelライクなインターフェースを実現する
SpreadJSでは、リボンをWebアプリに追加することもできます。リボンは、デスクトップ版のMicrosoft Officeでおなじみの、あのUIコンポーネントです。
さきほど配置したボタンの代わりにリボンを使用して、よりExcelに近い画面にしてみましょう。
リボン関連ファイルの追加
リボン関連のファイルは、SpreadJSのパッケージファイルのSpreadJS_Release/RibbonContainerフォルダ以下に含まれているので、必要なファイルをscriptsフォルダにコピーしてください。配置例は03-with-ribbonプロジェクトを参考にしてください。
なお、CSSとJSファイルはribbonという直感的な名前のファイルではなくdesignerという名前になっています。これは、SpreadJSのDesignerと呼ばれる機能を使用してリボンを実現するためです。
リボンつきでSpreadJSを初期化する
これまでの例ではnew GC.Spread.Sheets.Workbook("container")のようにWorkbookを初期化していましたが、リボンを使用する場合は先にDesignerを初期化します。Designerを初期化した後、getWorkbook()メソッドでWorkbookを取得します。
// Designer用デフォルト設定を取得
const config = GC.Spread.Sheets.Designer.DefaultConfig;
// 既存タブをすべてクリア
config.ribbon = [
// リボンのタブ・ボタン設定
];
config.commandMap = {
// リボンのコマンド設定
};
// Designerを生成(Designerはリボンを実現するためのコンポーネント)
const designer = new GC.Spread.Sheets.Designer.Designer(
document.getElementById("container"),
config
);
// Workbookを取得
const workbook = designer.getWorkbook();
なお、リボンを使う場合は、SpreadJSのライセンスキーのほかにGC.Spread.Sheets.Designer.LicenseKeyに「リボンコンテナ配布用」のライセンスキーを設定する必要があるので注意してください。
リボンのタブやボタンの設定は、config.ribbonにJSON形式で指定します。そのボタンに対する処理(コマンド)は、config.commandMapに定義します。実際の定義例はサンプルファイルをご確認ください。
たとえば集計ボタンのコマンドでは以下のように定義し、ボタンが押されたときには元のperformAggregate関数が呼び出されるようにしています。
cmdAggregateExec: {
title: "集計シートに店舗の売り上げを転記します",
text: "集計",
iconClass: "cmdAggregateExec",
bigButton: "true",
commandName: "cmdAggregateExec",
execute: () => performAggregate(),
},
実際にLive Serverを起動して、http://localhost:5500/03-with-ribbon/をブラウザで開いてみると、画面上部にリボンが表示され、ボタンを押すと、集計シートの内容が変更されることが確認できると思います。
まとめ
本記事では、SpreadJSを使用して既存のExcel資産をWebアプリに移行する方法を解説しました。Excelに慣れたユーザーにとっては、操作感を損なうことなく、直感的に利用できるWebアプリが構築できそうです。
開発者にとっても、Excelの数式や条件付き書式をそのまま使用できるため、複雑なロジックをJavaScriptで実装する必要がなく、開発工数を大きく削減できるでしょう。APIも豊富に用意されており、業務ロジックに合わせたカスタマイズも容易です。
有料のライブラリですが、ExcelライクなUI/UXを実現するための開発コストを考えれば、リーズナブルに感じます。要件や予算にもよりますが、Excel資産が多い場合や、ユーザーにとってExcelライクな操作が重要な場合は、SpreadJSを検討してみてはいかがでしょうか。

