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

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

第3回目となる今回は、リボンコンテナを使ったときにコンテキストメニューをカスタマイズする方法をご紹介します。リボンコンテナは、スプレッドシートにリボン、数式バー、ステータスバー、サイドパネルに加えて専用のコンテキストメニューの機能も追加するので、リボンコンテナを使用しなかった第1回で紹介したものとは異なる方法でコンテキストメニューをカスタマイズする必要があります。

今回はリボンコンテナを使用している場合のSpreadJSのコンテキストメニューのカスタマイズ方法を詳しく解説します。

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

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

使用するファイルは次の2つです。

index.htmlページ本体。ページの要素としてリボンコンテナを配置します
app.jsリボンコンテナを作成するコードを記載します

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

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>SpreadJSのコンテキストメニューのカスタマイズ(3)</title>
    <link rel="stylesheet" type="text/css" href="css/gc.spread.sheets.excel2013white.16.1.4.css" />
    <link rel="stylesheet" type="text/css" href="css/gc.spread.sheets.designer.16.1.4.min.css" />
    <script src="scripts/gc.spread.sheets.all.16.1.4.min.js"></script>
    <script src="scripts/plugins/gc.spread.sheets.charts.16.1.4.min.js"></script>
    <script src="scripts/plugins/gc.spread.sheets.shapes.16.1.4.min.js"></script>
    <script src="scripts/plugins/gc.spread.sheets.print.16.1.4.min.js"></script>
    <script src="scripts/plugins/gc.spread.sheets.barcode.16.1.4.min.js"></script>
    <script src="scripts/plugins/gc.spread.sheets.pdf.16.1.4.min.js"></script>
    <script src="scripts/plugins/gc.spread.pivot.pivottables.16.1.4.min.js"></script>
    <script src="scripts/plugins/gc.spread.sheets.io.16.1.4.min.js"></script>
    <script src="scripts/plugins/gc.spread.sheets.slicers.16.1.4.min.js"></script>
    <script src="scripts/plugins/gc.spread.sheets.tablesheet.16.1.4.min.js"></script>
    <script src="scripts/interop/gc.spread.excelio.16.1.4.min.js"></script>
    <script src="scripts/resources/gc.spread.sheets.resources.ja.16.1.4.min.js"></script>
    <script src="scripts/resources/gc.spread.sheets.designer.resource.ja.16.1.4.min.js"></script>
    <script src="scripts/gc.spread.sheets.designer.all.16.1.4.min.js"></script>
    <script src="scripts/app.js"></script>
</head>
<body>
    <div id="designerHost" style="width:100%; height:95vh; border: 1px solid gray;"></div>
</body>
</html>

ヘルプに記載しているように、スプレッドシート参照はリボンコンテナ参照の前に追加する必要があり、リボンコンテナのリソースファイル(gc.spread.sheets.designer.resource.ja.x.x.x.min.js)はリボンコンテナ本体(gc.spread.sheets.designer.all.x.x.x.min.js)よりも先に参照する必要があります。

リボンコンテナを作成する

「app.js」に次のようなコードを記述してリボンコンテナを作成しましょう。ここでは、最初にCultureManagerクラスのcultureメソッドを使ってカルチャを指定してから、Designerクラスのコンストラクタでリボンコンテナを生成します。また、スプレッドシートはリボンコンテナのgetWorkbookメソッドで取得できます。
※ ライセンスキーを設定しない場合トライアル版を示すメッセージが表示されます。ライセンスキーの設定方法についてはこちらをご覧ください。また、リボンコンテナ専用のライセンスキーも設定する必要があります。

// ライセンスキーとカルチャの設定
GC.Spread.Sheets.LicenseKey = 'ここにSpreadJSのライセンスキーを設定します';
GC.Spread.Sheets.Designer.LicenseKey = 'ここにリボンコンテナのライセンスキーを設定します';
GC.Spread.Common.CultureManager.culture('ja-jp');

// リボンコンテナの設定
document.addEventListener("DOMContentLoaded", function () {
    const designer = new GC.Spread.Sheets.Designer.Designer("designerHost");
    const spread = designer.getWorkbook();
});

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

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

既定のコンテキストメニュー

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

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

・・(中略)・・・
document.addEventListener("DOMContentLoaded", function () {
    const designer = new GC.Spread.Sheets.Designer.Designer("designerHost");
    const spread = designer.getWorkbook();
    SetRibbonContextMenuA(designer, spread); 
});

// コンテキストメニューの追加:commandMap.executeパラメータに設定する方法
function SetRibbonContextMenuA(designer, spread) {
    // 既定のConfigの取得
    const config = GC.Spread.Sheets.Designer.DefaultConfig;

    // コンテキストメニュー項目の追加
    config.contextMenu.unshift("separator");
    config.contextMenu.unshift("setRowBackColorMenu");

    // commandMapの設定:executeパラメータに設定する方法
    config.commandMap = {
        "setRowBackColorMenu": {
            text: "背景色を変更",
            commandName: "setRowBackColorCommand",
            visibleContext: "ClickRowHeader",
            execute: () => {
                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();
            }
        }
    }

    // 変更したConfigの設定
    designer.setConfig(config);
}

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

スプレッドシートでは、GC.Spread.Sheets.Workbook.ContextMenuクラスのmenuDataプロパティを使って独自のメニュー項目を実装しましたが、リボンコンテナでは、GC.Spread.Sheets.Designer.IDesignerConfigインタフェースのcontextMenuプロパティとcommandMapプロパティを使って実装します。contextMenuプロパティにはメニュー項目のIDだけを設定し、具体的な内容はcommandMapプロパティに設定します。contextMenuはメニュー項目IDの配列なので、配列操作によって任意の位置に独自のメニュー項目を挿入したり、既存の項目を削除したりすることができます。

commandMapプロパティには「{ [key文字列]: ICommand }」の書式で、メニュー項目IDを表すkey文字列とICommandインタフェースを設定します。ICommandの各プロパティの機能は次のとおりです。

プロパティ名説明
commandName実行するコマンド名
textメニュー項目の表示用文字列
visibleContextメニュー項目を表示する領域

visibleContextプロパティに設定できる文字列は次のとおりです。

設定値対象の領域(右クリックする位置)
ClickCornerシートコーナー
ClickColHeader列ヘッダ
ClickRowHeader行ヘッダ
ClickViewportビューポート
TabStripSelectedシートタブ
ClickViewport && TableClickedテーブル
SlicerSelectedスライサー
TimelineSelectedタイムラインスライサー
PivotTableSelectedピボットテーブル
ShapeSelectedシェイプ
PictureSelectedピクチャシェイプ
TableSheetTabStripSelectedテーブルシートのシートタブ

また、論理演算子を使った次のような設定も可能です。

設定値対象の領域(右クリックする位置)
ClickViewport || ClickCornerシートコーナーとビューポート
!PivotTableSelected && ClickViewportピボットテーブルではないビューポート列ヘッダ
ShapeSelected && AllowEditObject編集可能なシェイプ

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

独自のコンテキストメニューを追加

第1行の行ヘッダを右クリックしてメニューから「背景色を変更」を選択すると、第1行の背景色が赤色に変更されます。

独自のコンテキストメニューを実行

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

Undo処理を可能にする

UndoManagerの機能を使ってCtrlZキーやCtrlYキーによるUndo/Redo処理を利用できるように、独自のメニュー項目の動作をCommandManagerに登録しましょう。

コマンドをCommandManagerに登録する方法は第1回のときと全く同じですが、コマンドのIDを設定する箇所がcommandMapのcommandNameに変わります。

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

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

・・・(中略)・・・
document.addEventListener("DOMContentLoaded", function () {
    const designer = new GC.Spread.Sheets.Designer.Designer("designerHost");
    const spread = designer.getWorkbook();
    // SetRibbonContextMenuA(designer, spread); // <== コメントアウト
    SetRibbonContextMenuB(designer, spread); // <== 追加
});
・・・(中略)・・・
// コンテキストメニューの追加:commandManagerに登録する方法(Undo可能)
function SetRibbonContextMenuB(designer, 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.getActiveSheet();
                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;
            }
        }
    });

    // 既定のConfigの取得
    const config = GC.Spread.Sheets.Designer.DefaultConfig;

    // コンテキストメニュー項目の追加
    config.contextMenu.unshift("separator");
    config.contextMenu.unshift("setRowBackColorMenu");

    // commandMapの設定:独自機能はcommandNameパラメータで指定
    config.commandMap = {
        "setRowBackColorMenu": {
            text: "背景色を変更",
            commandName: "setRowBackColorCommand",
            visibleContext: "ClickRowHeader"
        }
    }

    // 変更したConfigの設定
    designer.setConfig(config);
}

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

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

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

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

この動作は以下のデモアプリケーションでも確認できます(“Run Project”をクリックするとデモが起動します)。

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

さいごに

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

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

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

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

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