SpreadJSのコンテキストメニューをカスタマイズする(1)

「Excelライク」なスプレッドシートをWeb上で実現するJavaScriptライブラリの「SpreadJS (スプレッドJS)」には、Excelでなじみのある機能を搭載したコンテキストメニューを標準装備しており、自由にカスタマイズも可能です。

一口にコンテキストメニューといっても、SpreadJSのコンテキストメニューはリボンコンテナを使用している場合とそうでない場合とで使用できるメニューが異なり、さらにカスタマイズする方法も異なってきます。

本連載ではリボンコンテナの使用有無や要件に応じていくつか方法が存在するコンテキストメニューのカスタマイズ方法を、複数回にわたりご紹介していきます。第1回はリボンコンテナを使用していない、通常のSpreadJSのコンテキストメニューをカスタマイズする方法です。

開発環境の準備とSpreadJSの参照

この記事では以下の開発環境を使用します。

作成するファイルは次の2つです。

index.htmlページ本体。ページの要素としてSpreadJSを配置します
app.jsSpreadJSを作成するコードを記載します

SpreadJSの機能を使うために必要となるSpreadJSのモジュールなどへの参照設定は「index.html」で行います。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>SpreadJSのコンテキストメニューのカスタマイズ</title>
    <link rel="stylesheet" type="text/css" href="css/gc.spread.sheets.excel2013white.16.1.4.css"/>
    <script src="scripts/gc.spread.sheets.all.16.1.4.min.js"></script>
    <script src="scripts/resources/gc.spread.sheets.resources.ja.16.1.4.min.js"></script>
    <script src="scripts/app.js"></script>
</head>
<body>
    <div id="ss" style="width: 640px; height: 500px; border: 1px solid gray"></div>
</body>
</html>

SpreadJSを作成する

「app.js」に次のようなコードを記述してSpreadJSを作成しましょう。ここでは、最初にCultureManagerクラスのcultureメソッドを使ってカルチャを指定してから、WorkbookクラスのコンストラクタでSpreadJSを生成します。
※ ライセンスキーを設定しない場合トライアル版を示すメッセージが表示されます。ライセンスキーの設定方法についてはこちらをご覧ください。

// ライセンスキーの設定
GC.Spread.Sheets.LicenseKey = 'ここにSpreadJSのライセンスキーを設定します';

// SpreadJSの設定
document.addEventListener("DOMContentLoaded", function () {
    GC.Spread.Common.CultureManager.culture('ja-jp');
    const spread = new GC.Spread.Sheets.Workbook('ss');
});

コンテキストメニューに独自のメニュー項目を追加する

ページを表示して行ヘッダを右クリックすると次のようになります。これがSpreadJSの既定のコンテキストメニューです。

デフォルトのコンテキストメニュー

それでは、行ヘッダを右クリックして表示されるコンテキストメニューの先頭に独自のメニュー項目を追加して、選択行の背景色を赤色に変更できるようにしましょう。

「app.js」を次のように変更することで独自のコンテキストメニュー項目を追加できます。

・・・(中略)・・・
document.addEventListener("DOMContentLoaded", function () {
    GC.Spread.Common.CultureManager.culture('ja-jp');
    const spread = new GC.Spread.Sheets.Workbook(document.querySelector("#ss"));
    SetContextMenuA(spread); // <== 追加するコード
});

// コンテキストメニューの追加:commandパラメータに設定する方法
function SetContextMenuA(spread){
    // 選択行の背景色を設定する機能の追加
    spread.contextMenu.menuData.splice(0, 0, {
        text: "背景色を変更",
        name: "setRowBackColorMenu",
        workArea: "rowHeader",
        command: function (){
            const sheet = spread.getActiveSheet();
            const selections = sheet.getSelections();
            const style = new GC.Spread.Sheets.Style();
            style.backColor = "red";
            sheet.suspendPaint();
            if (selections[0].row == -1 && selections[0].col == -1) {
                sheet.clearSelection();
                sheet.getRange(-1, -1, -1, -1, GC.Spread.Sheets.SheetArea.viewport).setStyle(style);
            } else {
                selections.forEach(function(s){
                    sheet.getRange(s.row, -1, s.rowCount, -1, GC.Spread.Sheets.SheetArea.viewport).setStyle(style);
                });
            }
            sheet.resumePaint();
        }
    });

    // 区切り線の追加
    spread.contextMenu.menuData.splice(1, 0, {type: 'separator'});
}

addEventListenerメソッドにはSetContextMenuA関数を呼び出すコードを追加し、SetContextMenuA関数で目的の動作を実装しています。

独自のメニュー項目は、GC.Spread.Sheets.Workbook.ContextMenuクラスのmenuDataプロパティを使って実装します。menuDataにはメニュー項目の配列が保持されているので、配列操作によって任意の位置に独自のメニュー項目を挿入したり、既存の項目を削除したりすることができます。

menuDataで設定しているプロパティの機能は次のとおりです。

プロパティ名説明
command実行するコマンド名またはコマンド
nameメニュー項目のID
textメニュー項目の表示用文字列
typeメニュー項目の種類
workAreaメニュー項目を表示する領域

workAreaプロパティに設定できるオプションは次のとおりです。複数の個所で表示する場合は、設定値をつなげて「viewportcorner」のように設定します。

オプション名対象の領域
cornerシートコーナー
colHeader列ヘッダ
rowHeader行ヘッダ
viewportビューポート
sheetTabシートタブ
tableテーブル
slicerスライサー
timelineタイムラインスライサー
pivotPageFilterピボットテーブルのフィルタ
pivotTopLeftピボットテーブルの左上部分
pivotContentピボットテーブルのコンテンツ部分
pivotHeaderピボットテーブルのヘッダ
pivotGrandTotalピボットテーブルの総計行
pivotEmptyLabelピボットテーブルの空のラベル部分

ページを表示して行ヘッダを右クリックすると、コンテキストメニューが次のように変更されています。

コンテキストメニューに項目を追加

第4行の行ヘッダをクリックし、Ctrlキーを押下した状態で第6行と第8行の行ヘッダをクリックしてから、行ヘッダ上で右クリックしてコンテキストメニューを表示します。メニューから「背景色を変更」を選択すると、第4行、第6行、第8行の背景色が赤色に変更されます。

複数行の背景色をコンテキストメニューで変更

上記のカスタマイズは以下のデモアプリケーションでも確認できます(“Run Project”をクリックするとデモが起動します)。

Undo処理を可能にする

先ほどの方法では、独自のメニュー項目の動作をCommandManagerに登録していなかったので、UndoManagerの機能を使うことができませんでした。具体的には、CtrlZキーやCtrlYキーを使ったUndo/Redo処理を利用できませんでした。

ここでは、menuDataのcommandに処理内容を実装しないで、コマンドをCommandManagerに登録して呼び出す方法を紹介します。

  1. コマンドを作成
  2. 作成したコマンドをCommandManagerに登録
  3. menuDataのcommandにコマンドのIDを設定

「app.js」を次のように変更して、Undo/Redo処理が可能なコンテキストメニュー項目を追加します。

・・・(中略)・・・
document.addEventListener("DOMContentLoaded", function () {
    GC.Spread.Common.CultureManager.culture('ja-jp');
    const spread = new GC.Spread.Sheets.Workbook(document.querySelector("#ss"));
    // SetContextMenuA(spread); // <== コメントアウト
    SetContextMenuB(spread); // <== 追加
});
・・・(中略)・・・
// コンテキストメニューの追加:commandManagerに登録する方法(Undo可能)
function SetContextMenuB(spread){
    // commandManagerにUndo処理を許可した独自のコマンドを登録
    spread.commandManager().register("setRowBackColorCommand", {
        canUndo: true,
        execute: function (spread, options, isUndo) {
            const Commands = GC.Spread.Sheets.Commands;
            if (isUndo) {
                Commands.undoTransaction(spread, options);
                return true;
            } else {
                Commands.startTransaction(spread, options);
                spread.suspendPaint();
                const sheet = spread.getSheetFromName(options.sheetName);;
                const selections = options.selections;
                const style = new GC.Spread.Sheets.Style();
                style.backColor = "red";
                if (selections[0].row == -1 && selections[0].col == -1) {
                    sheet.clearSelection();
                    sheet.getRange(-1, -1, -1, -1, GC.Spread.Sheets.SheetArea.viewport).setStyle(style);
                } else {
                    selections.forEach(function(s){
                        sheet.getRange(s.row, -1, s.rowCount, -1, GC.Spread.Sheets.SheetArea.viewport).setStyle(style);
                    });
                }
                spread.resumePaint();
                Commands.endTransaction(spread, options);
                return true;
            }
        }
    });

    // 登録したコマンドをコンテキストメニューに追加
    spread.contextMenu.menuData.splice(0, 0, {
        text: "背景色を変更",
        name: "setRowBackColorMenu",
        workArea: "rowHeader",
        command: "setRowBackColorCommand"
    });

    // 区切り線の追加
    spread.contextMenu.menuData.splice(1, 0, {type: 'separator'});
}

addEventListenerメソッドにはSetContextMenuB関数を呼び出すコードを追加し、SetContextMenuB関数で目的の動作を実装しています。

Undo/Redo処理を有効にしたコマンドの作成方法についてはこちらをご覧ください。

それでは、ページを表示して動作を確認してみましょう。

行ヘッダを右クリックしてコンテキストメニューを表示して「背景色を変更」を選択すると、クリックした行の背景色が赤色に変化します。続いてキーボードでCtrlZキーを押下すると、Undo処理が行われて背景色が白色にもどります。さらにキーボードでCtrlYキーを押下すると、Redo処理が行われて先ほど設定した赤色になります。

上記のカスタマイズは以下のデモアプリケーションでも確認できます(“Run Project”をクリックするとデモが起動します)。

コンテキストメニューの利用方法について、下記のヘルプ、APIリファレンス、およびデモで解説しているので、こちらもご参考にしていただければと思います。

さいごに

今回はSpreadJSのコンテキストメニューに独自のメニュー項目を追加する方法を紹介いたしました。次回はSpreadJSのコンテキストメニューに対して、表示する項目を動的に制御する方法をご紹介します。

SpreadJSは、このほかにもフィルタ、表計算、チャート、条件付き書式、ピボットテーブルなどのExcel互換機能を豊富に搭載しています。エンドユーザーに馴染みのあるExcelライクな操作性を提供するSpreadJSをご検討いただけますと幸いです。

製品サイトでは、SpreadJSの機能を手軽に体験できるデモアプリケーションやトライアル版も公開しておりますので、こちらもご確認ください。

また、ご導入前の製品に関するご相談、ご導入後の各種サービスに関するご質問など、お気軽にお問合せください。

\  この記事をシェアする  /