基于 Spread,在 Blazor 框架中导入 / 导出 Excel

引言

在现代 Web 应用开发中,处理 Excel 文件的导入和导出是一项常见且重要的需求。Blazor 框架是微软推出的用于构建具有 .NET 强大功能的交互式客户端 Web UI 的相对较新的框架。而 Spread.net(是一个非常强大且可扩展的 JavaScript 电子表格组件,它能使在 Blazor 框架中进行 Excel 文件的导入和导出变得更加简单。本文将详细介绍如何基于 SpreadJS,在 Blazor 框架中实现 Excel 文件的导入和导出功能。

Blazor 框架与 SpreadJS 简介

Blazor 框架允许开发者使用 .NET 构建交互式 Web UI,一个常见的应用场景是将现有的 Excel 文件导入 Blazor 应用程序,将电子表格数据呈现给用户,并支持在线 Excel 编辑。用户可以对表格进行各种操作和修改,之后可以将数据再次导出为 Excel 文件或将其保存到数据库。通过 Blazor + WebAssembly,还能在前端以更高的性能处理大型 Excel 文件。

SpreadJS 则为实现这一过程提供了强大支持,它能够简化 Excel 文件处理的复杂性,让开发者更便捷地实现所需功能。

在 Blazor 中使用 SpreadJS 的准备工作

创建 SpreadJS Blazor 组件

在将 SpreadJS 集成到 Blazor 应用程序之前,需要创建一个 Blazor 组件来封装 SpreadJS 前端组件。具体步骤如下:

  1. 创建 Razor 类库:使用 Visual Studio 2022,创建一个名为 "SpreadJS_Blazor_Lib" 的 Razor 类库项目。
  2. 配置项目:将 SpreadJS 相关的 JS 和 CSS 文件复制到 "wwwroot" 文件夹。同时,编辑 "exampleJSInterop.js" 文件,添加有助于将 C# 代码对接 SpreadJS 的 JavaScript 代码逻辑,示例代码如下:
javascript 复制代码
window.sjsAdaptor = {
    init: function (host, config) {
        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);
    },
    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);
            })
        }
    }
};
  1. 重命名组件文件:将默认的 "Component1.razor" 文件重命名为 "SpreadJS.razor",作为包装器组件,示例代码如下:
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.init", host, new Dictionary<string, object>() {
                { "sheetCount", SheetCount},
                { "hostStyle", HostStyle }
            });
        }
    }
}

创建 Blazor 应用程序并集成组件

  1. 添加新项目:使用 "Blazor WebAssemblyApp" 模板添加一个新项目。
  2. 添加项目引用:在解决方案资源管理器中右键单击新项目的依赖项,选择 "添加项目引用",添加之前创建的 "SpreadJS_Blazor_Lib" 组件。
  3. 编辑 Index.razor 文件:设置 HTML 的代码隐藏,示例代码如下:
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";
}

2.编辑 index.html 文件:添加对 SpreadJS JavaScript 和 CSS 文件的引用,示例代码如下:

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="https://cdn.grapecity.com/spreadjs/hosted/css/gc.spread.sheets.excel2013white.16.0.5.css" rel="stylesheet" />
    <script type="text/javascript" src="https://cdn.grapecity.com/spreadjs/hosted/scripts/gc.spread.sheets.all.16.0.5.min.js"> </script>
    <script type="text/javascript" src="https://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.charts.16.0.5.min.js"> </script>
    <script type="text/javascript" src="https://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.shapes.16.0.5.min.js"> </script>
    <script type="text/javascript" src="https://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.slicers.16.0.5.min.js"> </script>
    <script type="text/javascript" src="https://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.print.16.0.5.min.js"></script>
    <script type="text/javascript" src="https://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.barcode.16.0.5.min.js"> </script>
    <script type="text/javascript" src="https://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.pdf.16.0.5.min.js"> </script>
    <script type="text/javascript" src="https://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.tablesheet.16.0.5.min.js"></script>
    <script type="text/javascript" src="https://cdn.grapecity.com/spreadjs/hosted/scripts/interop/gc.spread.excelio.16.0.5.min.js"> </script>
    <script src="_content/SJS_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>
  1. 进一步编辑 Index.razor 文件:添加输入框和按钮,用于操作表格和导入 Excel 文件,示例代码如下:
razor 复制代码
@page "/"
@using SJS_Blazor_Lib
<h1>Hello, SpreadJS!</h1>
<table>
    <tr>
        <td>
            <label>Sheet Index</label>
            <input @bind-value="@SheetIndex" />
        </td>
        <td>
            <label>Row Index</label>
            <input @bind-value="@Row" />
        </td>
        <td>
            <label>Column Index</label>
            <input @bind-value="@Column" />
        </td>
        <td>
            <lable>Value</lable>
            <input @bind-value="@Value" />
        </td>
    </tr>
    <tr>
        <td>
            <button @onclick="doSomething">Update Text</button>
        </td>
    </tr>
    <tr>
        <td>
            <input type="file" @ref="inputFileEle" />
        </td>
        <td>
            <button @onclick="ImportExcel">Import File</button>
        </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);
    }
}

在 Blazor 应用中实现 Excel 导入和导出功能

Excel 导入

在上述代码基础上,通过编辑 Index.razor 文件,添加用于选定并打开 Excel 文件的代码,即可实现 Excel 文件的导入。由于前面已经在 "SpreadJS_Blazor_Lib" 项目中的 "SpreadJS.razor" 和 "exampleJsInterop.js" 文件中添加了相关代码,所以可以直接使用。示例代码如下:

razor 复制代码
@page "/"
@using SpreadJS_Blazor_Lib
<h1>Hello, SpreadJS!</h1>
<table>
    <tr>
        <td>
            <label>Sheet Index</label>
            <input @bind-value="@SheetIndex" />
        </td>
        <td>
            <label>Row Index</label>
            <input @bind-value="@Row" />
        </td>
        <td>
            <label>Column Index</label>
            <input @bind-value="@Column" />
        </td>
        <td>
            <lable>Value</lable>
            <input @bind-value="@Value" />
        </td>
    </tr>
    <tr>
        <td>
            <button @onclick="doSomething">Update Text</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);
    }
}

Excel 导出

要实现 Excel 文件的导出功能,需要进行以下操作:

  1. 修改 exampleJsInterop.js 文件:添加保存 Excel 文件的函数,示例代码如下:
javascript 复制代码
window.sjsAdaptor = {
    // 原有代码...
    saveExcel: function (host) {
        var spread = GC.Spread.Sheets.findControl(host);
        if (spread) {
            var json = spread.toJSON();
            var excelIO = new GC.Spread.Excel.IO();
            excelIO.save(json, function (blob) {
                saveAs(blob, "export.xlsx");
            }, function (e) {
                console.log(e);
            });
        }
    }
};

2.修改 index.html 文件:添加对 FileSaver 库的引用,示例代码如下:

html 复制代码
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.0/FileSaver.min.js"></script>

3.修改 Index.razor 文件:添加导出按钮和导出函数调用,示例代码如下:

razor

razor 复制代码
@page "/"
@using SpreadJS_Blazor_Lib
<h1>Hello, SpreadJS!</h1>
<table>
    <!-- 原有代码... -->
    <tr>
        <td>
            <button @onclick="ExportExcel">Export File</button>
        </td>
    </tr>
</table>
<br />
<SpreadJS SheetCount="3" HostStyle="@HostStyle" @ref="ss" />
@code {
    // 原有代码...
    private void ExportExcel()
    {
        ss.SaveExcel();
    }
}
  1. 修改 SpreadJS.razor 文件:添加指向 "exampleJsInterop.js" 文件中保存 Excel 函数的代码,示例代码如下:
razor 复制代码
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime
<div @ref="host"></div>
@code {
    // 原有代码...
    public void SaveExcel()
    {
        JSRuntime.InvokeVoidAsync("sjsAdaptor.saveExcel", host);
    }
    // 原有代码...
}

结论

通过以上步骤,我们成功地基于 SpreadJS,在 Blazor 框架中实现了 Excel 文件的导入和导出功能。利用 SpreadJS 的强大功能和 Blazor 框架的 .NET 支持,开发者可以更便捷地处理 Excel 文件,满足 Web 应用中常见的 Excel 数据交互需求。如果你想尝试该功能或查看 SpreadJS 的其他惊人功能,可前往葡萄城官网立即下载试用版。

SpreadJS,可嵌入您系统的在线 Excel