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

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

本連載の第2回ではSpreadJSのコンテキストメニューの項目を条件に応じて制御する方法をご紹介しましたが、リボンコンテナを使用した場合はコンテキストメニューの制御方法が異なるため、そのときのコードは使用できません。

第4回目となる今回は、第3回で作成したアプリケーションをベースに、リボンコンテナを使用している場合のコンテキストメニューでメニュー項目を条件に応じて動的に制御する方法をご紹介します。

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

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

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

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

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

メニュー項目を動的に制御する

メニュー項目を条件に応じて動的に制御するために、第2回と同じようにContextMenuクラスのonOpenMenuメソッドを使用しますが、前述のようにリボンコンテナでは、コンテキストメニューの制御方法がSpreadJSとは大きく異なります。

SpreadJSでは、メニュー項目の活性/非活性は各メニュー項目のdisableプロパティで直接設定しますが、リボンコンテナではGC.Spread.Sheets.Designer名前空間にあるDesignerクラスのsetDataメソッドを使って各メニュー項目のenableContextを切り替えます。

また、SpreadJSのコンテキストメニューをリボンコンテナが上書きする仕組みになっているので、onOpenMenuの最後で「return designerOnOpenMenu.apply(this, arguments);」という処理が必要になります。

それでは、前回の「Undo処理を可能にする」の状態から「app.js」を次のように変更して、第2回と同じように、特定のセルに値が入力されていない場合にコンテキストメニューの項目が非活性になるようにしましょう。

SetRibbonContextMenuCは、ほとんど前回紹介したSetRibbonContextMenuBと同じですが、enableContextパラメータが追加されている点だけが異なっています。

・・・(中略)・・・
document.addEventListener("DOMContentLoaded", function () {
    const designer = new GC.Spread.Sheets.Designer.Designer("designerHost");
    const spread = designer.getWorkbook();
    SetRibbonContextMenuC(designer, spread); // <== SetRibbonContextMenuBから変更
    SwitchMenuEnabled(designer, spread); // <== 追加
});

// コンテキストメニューの追加:commandManagerに登録する方法(Undo可能)
function SetRibbonContextMenuC(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: "背景色を変更",
            enableContext: "enableCustomMenu", // <== SetRibbonContextMenuBにはなかった設定
            commandName: "setRowBackColorCommand",
            visibleContext: "ClickRowHeader"
        }
    }

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

// 第2回のSwitchMenuEnabledとは異なる手法です
function SwitchMenuEnabled(designer, spread) {
    // コンテキストメニューの動的な変更:CommandMapのenableContextパラメータを使用
    const designerOnOpenMenu = spread.contextMenu.onOpenMenu;
    spread.contextMenu.onOpenMenu = function (menuData, itemsDataForShown, hitInfo, spread) {
        if (spread.getActiveSheet().getValue(0, 1) == null) {
            designer.setData('enableCustomMenu', false);
        } else {
            designer.setData('enableCustomMenu', true)
        }
        return designerOnOpenMenu.apply(this, arguments);
    };

    // シートの設定
    const sheet = spread.getSheet(0);
    sheet.getCell(0, 1).watermark("ここに値を入力してください。");
    sheet.setColumnWidth(1, 250);
}

ページを表示して行ヘッダを右クリックすると次のようになります。この時点では、第1行第2列のセルに値が設定さていないので、独自メニュー項目の「背景色を変更」が非活性になっています。

コンテキストメニューを非活性化

第1行第2列のセルに値を入力してから任意の行の行ヘッダを右クリックすると、コンテキストメニューの「背景色を変更」メニュー項目が活性化され、該当行の背景色を変更できるようになります。

コンテキストメニューを活性化

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

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

さいごに

今回はSpreadJSのリボンコンテナのコンテキストメニューに対して、表示する項目を動的に制御する方法を紹介いたしました。SpreadJSのコンテキストメニューのカスタマイズ方法に関しては全4回の連載記事として公開していますので、これまでの記事も是非ご覧ください。

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

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

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

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