ASP.NET Core Blazorでは、.NETのメソッドからJavaScriptの関数を呼び出したり、逆にJavaScriptの関数から.NETのメソッドを呼び出したりする、「JavaScript相互運用」が可能です。
今回の記事では、Blazor WebAssemblyのアプリケーション上で、ExcelライクなJavaScriptスプレッドシートライブラリ「SpreadJS(スプレッドJS)」のラッパーを作成して使用する方法をご紹介します。
Blazorアプリケーションの作成
開発環境
- Visual Studio 2019(Version 16.7.4)
- SpreadJS V13.2J(13.2.3)
まずはBlazor WebAssemblyのアプリケーションを作成します。Blazor WebAssemblyについてはこちらの記事もご覧ください。
Visual Studioのプロジェクトテンプレートから[Blazor アプリ]を選択します。
プロジェクト名を「SpreadJS-Blazor-App」として進みます。
次にホスティングモデルを選択します。今回は[Blazor WebAssembly App]を選択します。
Blazorコンポーネントの作成
Blazor WebAssemblyのプロジェクトを作成したら、次はそこにBlazor用のコンポーネントを追加していきます。
ソリューションを右クリックし、[追加]⇒[新しいプロジェクト]を選択し、[Razor クラス ライブラリ]を追加します。
プロジェクト名を「SpreadJS_Blazor_Lib」として進みます。
プロジェクトが作成されたら、SpreadJSの製品版、またはトライアル版のZipファイルからJSファイルとCSSファイルをwwwroot
配下にコピーします。
exampleJsInterop.js
を以下のように修正します。こちらのコードがC#からJavaScriptのコードを実行するためのブリッジの役割を果たします。
window.sjsAdaptor = { init: function (host, config) { // GC.Spread.Sheets.LicenseKey = "ライセンスキーがある場合は設定します。"; if (config.hostStyle) { var hostStyle = config.hostStyle; var styles = hostStyle.split(';'); styles.forEach((styleStr) => { var style = styleStr.split(':'); host.style[style[0]] = style[1]; }); delete config.hostStyle; } return new GC.Spread.Sheets.Workbook(host, config); }, setCulture: function (locale) { GC.Spread.Common.CultureManager.culture(locale); } };
プロジェクトにデフォルトで追加されるComponent1.razor
のファイル名をSpreadJS.razor
に変更し、以下のコードを記述します。
@using Microsoft.JSInterop @inject IJSRuntime JSRuntime <div @ref="host"></div> @code { [Parameter] public int SheetCount { get; set; } [Parameter] public string HostStyle { get; set; } private ElementReference host; protected override void OnAfterRender(bool firstRender) { if (firstRender) { JSRuntime.InvokeVoidAsync("sjsAdaptor.setCulture", "ja-jp"); JSRuntime.InvokeVoidAsync("sjsAdaptor.init", host, new Dictionary<string, object>() { { "sheetCount", SheetCount}, { "hostStyle", HostStyle } }); } } }
BlazorアプリケーションからBlazorコンポーネントを呼び出す
次に、作成したBlazorコンポーネントをBlazorアプリケーションから参照して実行します。
「SpreadJS_Blazor_App」プロジェクトを右クリックし、[追加]⇒[プロジェクト参照]をクリックし、「SpreadJS_Blazor_Lib」を追加します。
「SpreadJS_Blazor_App」のPages/Index.razor
を以下のように修正します。
@page "/" @using SpreadJS_Blazor_Lib <h1>Hello, SpreadJS!</h1> <SpreadJS SheetCount="3" HostStyle="@HostStyle" /> @code { private string HostStyle { get; set; } = "width:90wh;height:70vh;border: 1px solid darkgray"; }
wwwroot/index.html
を以下のように修正して、SperadJSのスクリプトとCSSファイルへの参照を追加します。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <title>BlazorApp1</title> <base href="/" /> <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" /> <link href="css/app.css" rel="stylesheet" /> <link href="_content/SpreadJS_Blazor_Lib/SpreadJS/css/gc.spread.sheets.excel2013white.13.2.3.css" rel="stylesheet" /> <script src="_content/SpreadJS_Blazor_Lib/SpreadJS/scripts/gc.spread.sheets.all.13.2.3.min.js" type="text/javascript"></script> <script src="_content/SpreadJS_Blazor_Lib/SpreadJS/scripts/resources/ja/gc.spread.sheets.resources.ja.13.2.3.min.js" type="text/javascript"></script> <script src="_content/SpreadJS_Blazor_Lib/exampleJsInterop.js" type="text/javascript"></script> </head> <body> <app>Loading...</app> <div id="blazor-error-ui"> An unhandled error has occurred. <a href="" class="reload">Reload</a> <a class="dismiss">🗙</a> </div> <script src="_framework/blazor.webassembly.js"></script> </body> </html>
「SpreadJS_Blazor_App」をスタートアッププロジェクトに設定して実行すると、以下のようにBlazorの画面上にSpreadJSが表示できます。
SpreadJSの機能の使用
SpreadJSをBlazorの画面に表示することができたので、次はSpreadJSの各種機能を使用してみます。今回は指定したセルに値を設定する「setValueメソッド」と「Excelファイルのインポート機能」をそれぞれ追加してみます。
「SpreadJS_Blazor_Lib」のexampleJsInterop.js
を以下のように書き換えます。
window.sjsAdaptor = { init: function (host, config) { //GC.Spread.Sheets.LicenseKey = "ライセンスキーがある場合は設定します。"; if (config.hostStyle) { var hostStyle = config.hostStyle; var styles = hostStyle.split(';'); styles.forEach((styleStr) => { var style = styleStr.split(':'); host.style[style[0]] = style[1]; }); delete config.hostStyle; } return new GC.Spread.Sheets.Workbook(host, config); }, setCulture: function (locale) { GC.Spread.Common.CultureManager.culture(locale); }, setValue: function (host, sheetIndex, row, col, value) { var spread = GC.Spread.Sheets.findControl(host); if (spread) { var sheet = spread.getSheet(sheetIndex); sheet.setValue(row, col, value); } }, openExcel: function (host, inputFile) { var spread = GC.Spread.Sheets.findControl(host); if (spread) { var excelIO = new GC.Spread.Excel.IO(); excelIO.open(inputFile.files[0], function (json) { spread.fromJSON(json); }) } } };
SpreadJS.razor
を以下のように書き換えます。
@using Microsoft.JSInterop @inject IJSRuntime JSRuntime <div @ref="host"></div> @code { [Parameter] public int SheetCount { get; set; } [Parameter] public string HostStyle { get; set; } private ElementReference host; public void setValue(int sheetIndex, int row, int col, object value) { JSRuntime.InvokeVoidAsync("sjsAdaptor.setValue", host, sheetIndex, row, col, value); } public void OpenExcel(ElementReference inputFile) { JSRuntime.InvokeVoidAsync("sjsAdaptor.openExcel", host, inputFile); } protected override void OnAfterRender(bool firstRender) { if (firstRender) { JSRuntime.InvokeVoidAsync("sjsAdaptor.setCulture", "ja-jp"); JSRuntime.InvokeVoidAsync("sjsAdaptor.init", host, new Dictionary<string, object>() { { "sheetCount", SheetCount}, { "hostStyle", HostStyle } }); } } }
「SpreadJS_Blazor_App」のwwwroot/index.html
を以下のように書き換えます。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <title>BlazorApp1</title> <base href="/" /> <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" /> <link href="css/app.css" rel="stylesheet" /> <link href="_content/SpreadJS_Blazor_Lib/SpreadJS/css/gc.spread.sheets.excel2013white.13.2.3.css" rel="stylesheet" /> <script src="_content/SpreadJS_Blazor_Lib/SpreadJS/scripts/gc.spread.sheets.all.13.2.3.min.js" type="text/javascript"></script> <script src="_content/SpreadJS_Blazor_Lib/SpreadJS/scripts/resources/ja/gc.spread.sheets.resources.ja.13.2.3.min.js" type="text/javascript"></script> <script src="_content/SpreadJS_Blazor_Lib/SpreadJS/scripts/interop/gc.spread.excelio.13.2.3.min.js" type="text/javascript"></script> <script src="_content/SpreadJS_Blazor_Lib/SpreadJS/scripts/plugins/gc.spread.sheets.shapes.13.2.3.min.js" type="text/javascript"></script> <script src="_content/SpreadJS_Blazor_Lib/SpreadJS/scripts/plugins/gc.spread.sheets.charts.13.2.3.min.js" type="text/javascript"></script> <script src="_content/SpreadJS_Blazor_Lib/exampleJsInterop.js" type="text/javascript"></script> </head> <body> <app>Loading...</app> <div id="blazor-error-ui"> An unhandled error has occurred. <a href="" class="reload">Reload</a> <a class="dismiss">🗙</a> </div> <script src="_framework/blazor.webassembly.js"></script> </body> </html>
Pages/Index.razor
を以下のように修正します。
@page "/" @using SpreadJS_Blazor_Lib <h1>Hello, SpreadJS!</h1> <table> <tr> <td> <label>シート</label> <input @bind-value="@SheetIndex" /> </td> <td> <label>行</label> <input @bind-value="@Row" /> </td> <td> <label>列</label> <input @bind-value="@Column" /> </td> <td> <lable>値</lable> <input @bind-value="@Value" /> </td> </tr> <tr> <td> <button @onclick="doSomething">アップデート</button> </td> </tr> <tr> <td> <input type="file" @ref="inputFileEle" @onchange="ImportExcel" /> </td> </tr> </table> <br /> <SpreadJS SheetCount="3" HostStyle="@HostStyle" @ref="ss" /> @code { private SpreadJS ss; private ElementReference inputFileEle; public int SheetIndex { get; set; } = 0; public int Row { get; set; } = 0; public int Column { get; set; } = 0; public string Value { get; set; } = ""; private string HostStyle { get; set; } = "width:90wh;height:70vh;border: 1px solid darkgray"; private void doSomething() { ss.setValue(SheetIndex, Row, Column, Value); } private void ImportExcel() { ss.OpenExcel(inputFileEle); } }
実行結果
実行結果は以下の通りです。
setValueを実行
Excelインポートを実行
おわりに
JavaScript相互運用は、ファイルアクセスなどBlazorに足りない機能を補うために欠かせないものです。また、SpreadJSのような高機能なJavaScriptライブラリをそのまま使えるというのも魅力の一つです。
今回作成したサンプルは以下で公開しています。
製品WebサイトではSpreadJSの機能を手軽に試せるデモをご用意していますので、ぜひご覧ください。