跳至頁尾內容
USING IRONXL

如何在 Blazor 中使用 IronXL 匯出 Excel 文件

將資料匯出到Excel是幾乎每個Blazor網路應用程式所需的功能—無論是生成銷售報告、庫存清單還是客戶發票。 在Blazor Server應用程式中,若要在不需要Microsoft Office的情況下可靠地完成此操作,可能令人感到棘手。 IronXL使這一過程變得簡單:您可以直接從伺服器建立、格式化並下載Excel文件,而無需安裝Office。 本指南將指導您使用IronXL在Blazor中建立一個生產就緒的Excel匯出功能—從項目設置、服務設計到高級格式化和多表報告。

如何在Blazor Server項目中設置IronXL?

在撰寫任何匯出邏輯之前,您需要將IronXL新增到Blazor Server項目中並配置一個瀏覽器端下載輔助程式。

建立Blazor Server項目

首先,使用Visual Studio 2022或更高版本建立一個新的Blazor Server項目,目標設定為.NET 10。當項目準備就緒後,通過NuGet包管理器主控台安裝IronXL:

Install-Package IronXL.Excel

IronXL與.NET 6及更高版本相容,因此現有的Blazor項目可以在不升級框架的情況下使用它。 如需其他安裝方法,比如NuGet UI或CLI,請參見IronXL安裝指南

新增JavaScript下載輔助程式

Blazor Server在伺服器端運行,因此觸發文件下載需要一個小型JavaScript橋樑。 在您的excelExport.js的文件:

window.downloadFileFromStream = async (fileName, contentStreamReference) => {
    const arrayBuffer = await contentStreamReference.arrayBuffer();
    const blob = new Blob([arrayBuffer]);
    const url = URL.createObjectURL(blob);
    const anchorElement = document.createElement('a');
    anchorElement.href = url;
    anchorElement.download = fileName ?? 'export.xlsx';
    anchorElement.click();
    anchorElement.remove();
    URL.revokeObjectURL(url);
}
window.downloadFileFromStream = async (fileName, contentStreamReference) => {
    const arrayBuffer = await contentStreamReference.arrayBuffer();
    const blob = new Blob([arrayBuffer]);
    const url = URL.createObjectURL(blob);
    const anchorElement = document.createElement('a');
    anchorElement.href = url;
    anchorElement.download = fileName ?? 'export.xlsx';
    anchorElement.click();
    anchorElement.remove();
    URL.revokeObjectURL(url);
}
JAVASCRIPT

將此腳本包含在您的_Host.cshtml文件中(或在.NET 8+中使用App.razor):

<script src="~/excelExport.js"></script>
<script src="~/excelExport.js"></script>
HTML

此函式將Blazor的字節流轉換為臨時blob URL,觸發瀏覽器下載,然後清除URL物件以防止記憶體洩漏。 它設計為儘量簡約—繁重的工作在伺服器上的C#中完成。

現在開始使用IronXL。
green arrow pointer

如何在C#中建立Excel匯出服務?

將Excel生成與Razor組件分開可使程式碼可以在多個頁面上進行測試和重用。 以下模式將IronXL包裹在一個專用的服務類中。

構建ExcelExportService

建立一個新的文件Services/ExcelExportService.cs

using IronXL;
using System.IO;
using ExportExcel.Models;

public class ExcelExportService
{
    public byte[] GenerateSalesReport(List<SalesData> salesData)
    {
        var workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        workbook.Metadata.Author = "Sales Department";

        var worksheet = workbook.CreateWorkSheet("Monthly Sales");

        // Add column headers
        worksheet["A1"].Value = "Date";
        worksheet["B1"].Value = "Product";
        worksheet["C1"].Value = "Quantity";
        worksheet["D1"].Value = "Revenue";
        worksheet["E1"].Value = "Profit Margin";

        // Style the header row
        var headerRange = worksheet["A1:E1"];
        headerRange.Style.Font.Bold = true;
        headerRange.Style.BackgroundColor = "#4472C4";
        headerRange.Style.Font.Color = "#FFFFFF";

        // Populate data rows
        int row = 2;
        foreach (var sale in salesData)
        {
            worksheet[$"A{row}"].Value = sale.Date.ToString("yyyy-MM-dd");
            worksheet[$"B{row}"].Value = sale.Product ?? "Unknown";
            worksheet[$"C{row}"].Value = sale.Quantity;
            worksheet[$"D{row}"].Value = sale.Revenue;
            worksheet[$"E{row}"].Value = $"=D{row}*0.15";
            row++;
        }

        worksheet.AutoSizeColumn(0, true);

        using var ms = workbook.ToStream();
        return ms.ToArray();
    }
}
using IronXL;
using System.IO;
using ExportExcel.Models;

public class ExcelExportService
{
    public byte[] GenerateSalesReport(List<SalesData> salesData)
    {
        var workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        workbook.Metadata.Author = "Sales Department";

        var worksheet = workbook.CreateWorkSheet("Monthly Sales");

        // Add column headers
        worksheet["A1"].Value = "Date";
        worksheet["B1"].Value = "Product";
        worksheet["C1"].Value = "Quantity";
        worksheet["D1"].Value = "Revenue";
        worksheet["E1"].Value = "Profit Margin";

        // Style the header row
        var headerRange = worksheet["A1:E1"];
        headerRange.Style.Font.Bold = true;
        headerRange.Style.BackgroundColor = "#4472C4";
        headerRange.Style.Font.Color = "#FFFFFF";

        // Populate data rows
        int row = 2;
        foreach (var sale in salesData)
        {
            worksheet[$"A{row}"].Value = sale.Date.ToString("yyyy-MM-dd");
            worksheet[$"B{row}"].Value = sale.Product ?? "Unknown";
            worksheet[$"C{row}"].Value = sale.Quantity;
            worksheet[$"D{row}"].Value = sale.Revenue;
            worksheet[$"E{row}"].Value = $"=D{row}*0.15";
            row++;
        }

        worksheet.AutoSizeColumn(0, true);

        using var ms = workbook.ToStream();
        return ms.ToArray();
    }
}
Imports IronXL
Imports System.IO
Imports ExportExcel.Models

Public Class ExcelExportService
    Public Function GenerateSalesReport(salesData As List(Of SalesData)) As Byte()
        Dim workbook = WorkBook.Create(ExcelFileFormat.XLSX)
        workbook.Metadata.Author = "Sales Department"

        Dim worksheet = workbook.CreateWorkSheet("Monthly Sales")

        ' Add column headers
        worksheet("A1").Value = "Date"
        worksheet("B1").Value = "Product"
        worksheet("C1").Value = "Quantity"
        worksheet("D1").Value = "Revenue"
        worksheet("E1").Value = "Profit Margin"

        ' Style the header row
        Dim headerRange = worksheet("A1:E1")
        headerRange.Style.Font.Bold = True
        headerRange.Style.BackgroundColor = "#4472C4"
        headerRange.Style.Font.Color = "#FFFFFF"

        ' Populate data rows
        Dim row As Integer = 2
        For Each sale In salesData
            worksheet($"A{row}").Value = sale.Date.ToString("yyyy-MM-dd")
            worksheet($"B{row}").Value = If(sale.Product, "Unknown")
            worksheet($"C{row}").Value = sale.Quantity
            worksheet($"D{row}").Value = sale.Revenue
            worksheet($"E{row}").Value = $"=D{row}*0.15"
            row += 1
        Next

        worksheet.AutoSizeColumn(0, True)

        Using ms = workbook.ToStream()
            Return ms.ToArray()
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

註冊服務

將服務新增到Program.cs中的DI容器:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<ExcelExportService>();

var app = builder.Build();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<ExcelExportService>();

var app = builder.Build();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
Imports Microsoft.AspNetCore.Builder
Imports Microsoft.Extensions.DependencyInjection

Dim builder = WebApplication.CreateBuilder(args)

builder.Services.AddRazorPages()
builder.Services.AddServerSideBlazor()
builder.Services.AddScoped(Of ExcelExportService)()

Dim app = builder.Build()
app.MapBlazorHub()
app.MapFallbackToPage("/_Host")
app.Run()
$vbLabelText   $csharpLabel

此服務展示了IronXL的幾個關鍵功能。 您可以通過單個方法調用建立新的工作簿和工作表,應用樣式化的標題,從任何資料來源填充行,並嵌入Excel公式=D2*0.15AutoSizeColumn調用確保列的寬度足以正確顯示其內容,無論資料的長度如何。 如需更多格式選項,請參見單元格樣式指南

如何從Blazor組件觸發Excel下載?

一旦服務就緒,您需要一個調用它的Razor組件,並將結果字節傳遞給瀏覽器。

撰寫Razor組件

Pages/ExcelExportDashboard.razor建立一個頁面:

@page "/excel-export"
@using ExportExcel.Models
@inject ExcelExportService ExcelService
@inject IJSRuntime JS

<h3>Excel Export Dashboard</h3>

<div class="export-section">
    <button class="btn btn-primary" @onclick="ExportSalesReport" disabled="@isExporting">
        @if (isExporting)
        {
            <span>Generating...</span>
        }
        else
        {
            <span>Export Sales Report</span>
        }
    </button>

    @if (!string.IsNullOrEmpty(errorMessage))
    {
        <div class="alert alert-danger mt-2">@errorMessage</div>
    }
</div>

@code {
    private bool isExporting = false;
    private string errorMessage = "";

    private async Task ExportSalesReport()
    {
        try
        {
            isExporting = true;
            errorMessage = "";

            var salesData = GetSalesData();
            var fileBytes = ExcelService.GenerateSalesReport(salesData);

            using var stream = new MemoryStream(fileBytes);
            using var streamRef = new DotNetStreamReference(stream);
            await JS.InvokeVoidAsync(
                "downloadFileFromStream",
                $"SalesReport_{DateTime.Now:yyyyMMdd}.xlsx",
                streamRef
            );
        }
        catch (Exception)
        {
            errorMessage = "Export failed. Please try again.";
        }
        finally
        {
            isExporting = false;
        }
    }

    private List<SalesData> GetSalesData()
    {
        return new List<SalesData>
        {
            new() { Date = DateTime.Now, Product = "Widget A", Quantity = 100, Revenue = 5000 },
            new() { Date = DateTime.Now.AddDays(-1), Product = "Widget B", Quantity = 75, Revenue = 3750 }
        };
    }
}
@page "/excel-export"
@using ExportExcel.Models
@inject ExcelExportService ExcelService
@inject IJSRuntime JS

<h3>Excel Export Dashboard</h3>

<div class="export-section">
    <button class="btn btn-primary" @onclick="ExportSalesReport" disabled="@isExporting">
        @if (isExporting)
        {
            <span>Generating...</span>
        }
        else
        {
            <span>Export Sales Report</span>
        }
    </button>

    @if (!string.IsNullOrEmpty(errorMessage))
    {
        <div class="alert alert-danger mt-2">@errorMessage</div>
    }
</div>

@code {
    private bool isExporting = false;
    private string errorMessage = "";

    private async Task ExportSalesReport()
    {
        try
        {
            isExporting = true;
            errorMessage = "";

            var salesData = GetSalesData();
            var fileBytes = ExcelService.GenerateSalesReport(salesData);

            using var stream = new MemoryStream(fileBytes);
            using var streamRef = new DotNetStreamReference(stream);
            await JS.InvokeVoidAsync(
                "downloadFileFromStream",
                $"SalesReport_{DateTime.Now:yyyyMMdd}.xlsx",
                streamRef
            );
        }
        catch (Exception)
        {
            errorMessage = "Export failed. Please try again.";
        }
        finally
        {
            isExporting = false;
        }
    }

    private List<SalesData> GetSalesData()
    {
        return new List<SalesData>
        {
            new() { Date = DateTime.Now, Product = "Widget A", Quantity = 100, Revenue = 5000 },
            new() { Date = DateTime.Now.AddDays(-1), Product = "Widget B", Quantity = 75, Revenue = 3750 }
        };
    }
}
Imports ExportExcel.Models
Imports Microsoft.JSInterop

@page "/excel-export"

@inject ExcelExportService ExcelService
@inject IJSRuntime JS

<h3>Excel Export Dashboard</h3>

<div class="export-section">
    <button class="btn btn-primary" @onclick="ExportSalesReport" disabled="@isExporting">
        @If isExporting Then
            <span>Generating...</span>
        Else
            <span>Export Sales Report</span>
        End If
    </button>

    @If Not String.IsNullOrEmpty(errorMessage) Then
        <div class="alert alert-danger mt-2">@errorMessage</div>
    End If
</div>

@code {
    Private isExporting As Boolean = False
    Private errorMessage As String = ""

    Private Async Function ExportSalesReport() As Task
        Try
            isExporting = True
            errorMessage = ""

            Dim salesData = GetSalesData()
            Dim fileBytes = ExcelService.GenerateSalesReport(salesData)

            Using stream As New MemoryStream(fileBytes)
                Using streamRef As New DotNetStreamReference(stream)
                    Await JS.InvokeVoidAsync(
                        "downloadFileFromStream",
                        $"SalesReport_{DateTime.Now:yyyyMMdd}.xlsx",
                        streamRef
                    )
                End Using
            End Using
        Catch ex As Exception
            errorMessage = "Export failed. Please try again."
        Finally
            isExporting = False
        End Try
    End Function

    Private Function GetSalesData() As List(Of SalesData)
        Return New List(Of SalesData) From {
            New SalesData() With {.Date = DateTime.Now, .Product = "Widget A", .Quantity = 100, .Revenue = 5000},
            New SalesData() With {.Date = DateTime.Now.AddDays(-1), .Product = "Widget B", .Quantity = 75, .Revenue = 3750}
        }
    End Function
}
$vbLabelText   $csharpLabel

組件的功能

isExporting標誌在生成期間禁用按鈕,以防止重複請求。 SalesReport_20260228.xlsx的時間戳文件名保持下載有序,無需額外配置。

當您在瀏覽器中導航到/excel-export時,儀表板頁面將載入一個匯出按鈕:

Blazor 匯出到 Excel:使用 IronXL 在 C# 中的完整指南:圖片 1 - 範例 Blazor 頁面

點擊按鈕生成電子表格,瀏覽器會自動下載文件:

Blazor 匯出到 Excel:使用 IronXL 在 C# 中的完整指南:圖片 2 - 資料匯出到 Excel 文件

可以對Excel匯出應用哪些高級格式化?

基本的資料匯出滿足許多使用案例,但生產應用程式經常需要條件格式化、多個工作表或資料驗證。 IronXL天然支援這些功能。

庫存報告的條件格式化

下面的服務將低庫存項目以紅色高亮顯示—這是倉庫或庫存管理應用程式的常見需求:

using IronXL;
using ExportExcel.Models;
using System.IO;

public class InventoryExportService
{
    public byte[] GenerateInventoryReport(List<InventoryItem> items)
    {
        var workbook = WorkBook.Create();
        var details = workbook.CreateWorkSheet("Inventory Details");

        // Column headers
        details["A1"].Value = "SKU";
        details["B1"].Value = "Name";
        details["C1"].Value = "Quantity";
        details["D1"].Value = "Reorder Level";
        details["E1"].Value = "Status";

        var headerRange = details["A1:E1"];
        headerRange.Style.Font.Bold = true;
        headerRange.Style.BackgroundColor = "#2E75B6";
        headerRange.Style.Font.Color = "#FFFFFF";

        for (int i = 0; i < items.Count; i++)
        {
            int row = i + 2;
            var item = items[i];

            details[$"A{row}"].Value = item.SKU;
            details[$"B{row}"].Value = item.Name;
            details[$"C{row}"].Value = item.Quantity;
            details[$"D{row}"].Value = item.ReorderLevel;
            details[$"E{row}"].Value = item.Quantity < item.ReorderLevel
                ? "Reorder Required"
                : "OK";

            if (item.Quantity < item.ReorderLevel)
            {
                // Highlight the entire row for low-stock items
                details[$"A{row}:E{row}"].Style.BackgroundColor = "#FFB6B6";
                details[$"C{row}"].Style.Font.Bold = true;
            }
        }

        details.AutoSizeColumn(0, true);
        details.AutoSizeColumn(1, true);

        using var stream = workbook.ToStream();
        return stream.ToArray();
    }
}
using IronXL;
using ExportExcel.Models;
using System.IO;

public class InventoryExportService
{
    public byte[] GenerateInventoryReport(List<InventoryItem> items)
    {
        var workbook = WorkBook.Create();
        var details = workbook.CreateWorkSheet("Inventory Details");

        // Column headers
        details["A1"].Value = "SKU";
        details["B1"].Value = "Name";
        details["C1"].Value = "Quantity";
        details["D1"].Value = "Reorder Level";
        details["E1"].Value = "Status";

        var headerRange = details["A1:E1"];
        headerRange.Style.Font.Bold = true;
        headerRange.Style.BackgroundColor = "#2E75B6";
        headerRange.Style.Font.Color = "#FFFFFF";

        for (int i = 0; i < items.Count; i++)
        {
            int row = i + 2;
            var item = items[i];

            details[$"A{row}"].Value = item.SKU;
            details[$"B{row}"].Value = item.Name;
            details[$"C{row}"].Value = item.Quantity;
            details[$"D{row}"].Value = item.ReorderLevel;
            details[$"E{row}"].Value = item.Quantity < item.ReorderLevel
                ? "Reorder Required"
                : "OK";

            if (item.Quantity < item.ReorderLevel)
            {
                // Highlight the entire row for low-stock items
                details[$"A{row}:E{row}"].Style.BackgroundColor = "#FFB6B6";
                details[$"C{row}"].Style.Font.Bold = true;
            }
        }

        details.AutoSizeColumn(0, true);
        details.AutoSizeColumn(1, true);

        using var stream = workbook.ToStream();
        return stream.ToArray();
    }
}
Imports IronXL
Imports ExportExcel.Models
Imports System.IO

Public Class InventoryExportService
    Public Function GenerateInventoryReport(items As List(Of InventoryItem)) As Byte()
        Dim workbook = WorkBook.Create()
        Dim details = workbook.CreateWorkSheet("Inventory Details")

        ' Column headers
        details("A1").Value = "SKU"
        details("B1").Value = "Name"
        details("C1").Value = "Quantity"
        details("D1").Value = "Reorder Level"
        details("E1").Value = "Status"

        Dim headerRange = details("A1:E1")
        headerRange.Style.Font.Bold = True
        headerRange.Style.BackgroundColor = "#2E75B6"
        headerRange.Style.Font.Color = "#FFFFFF"

        For i As Integer = 0 To items.Count - 1
            Dim row As Integer = i + 2
            Dim item = items(i)

            details($"A{row}").Value = item.SKU
            details($"B{row}").Value = item.Name
            details($"C{row}").Value = item.Quantity
            details($"D{row}").Value = item.ReorderLevel
            details($"E{row}").Value = If(item.Quantity < item.ReorderLevel, "Reorder Required", "OK")

            If item.Quantity < item.ReorderLevel Then
                ' Highlight the entire row for low-stock items
                details($"A{row}:E{row}").Style.BackgroundColor = "#FFB6B6"
                details($"C{row}").Style.Font.Bold = True
            End If
        Next

        details.AutoSizeColumn(0, True)
        details.AutoSizeColumn(1, True)

        Using stream = workbook.ToStream()
            Return stream.ToArray()
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

IronXL在生成時根據資料值應用單元格級樣式。您也可以聲明性地應用條件格式規則,或在同一工作簿中管理多個工作表—例如,一個用於當前庫存,另一個用於歷史訂單。

將多個工作表新增到單個匯出中

將資料分成邏輯表頁提高了可讀性,而無需單獨下載:

public byte[] GenerateMultiSheetReport(
    List<SalesData> sales,
    List<InventoryItem> inventory)
{
    var workbook = WorkBook.Create(ExcelFileFormat.XLSX);

    // Sheet 1 -- Sales summary
    var salesSheet = workbook.CreateWorkSheet("Sales");
    salesSheet["A1"].Value = "Date";
    salesSheet["B1"].Value = "Revenue";
    salesSheet["A1:B1"].Style.Font.Bold = true;

    for (int i = 0; i < sales.Count; i++)
    {
        salesSheet[$"A{i + 2}"].Value = sales[i].Date.ToString("yyyy-MM-dd");
        salesSheet[$"B{i + 2}"].Value = sales[i].Revenue;
    }

    // Sheet 2 -- Inventory snapshot
    var invSheet = workbook.CreateWorkSheet("Inventory");
    invSheet["A1"].Value = "SKU";
    invSheet["B1"].Value = "Name";
    invSheet["C1"].Value = "Quantity";
    invSheet["A1:C1"].Style.Font.Bold = true;

    for (int i = 0; i < inventory.Count; i++)
    {
        invSheet[$"A{i + 2}"].Value = inventory[i].SKU;
        invSheet[$"B{i + 2}"].Value = inventory[i].Name;
        invSheet[$"C{i + 2}"].Value = inventory[i].Quantity;
    }

    using var stream = workbook.ToStream();
    return stream.ToArray();
}
public byte[] GenerateMultiSheetReport(
    List<SalesData> sales,
    List<InventoryItem> inventory)
{
    var workbook = WorkBook.Create(ExcelFileFormat.XLSX);

    // Sheet 1 -- Sales summary
    var salesSheet = workbook.CreateWorkSheet("Sales");
    salesSheet["A1"].Value = "Date";
    salesSheet["B1"].Value = "Revenue";
    salesSheet["A1:B1"].Style.Font.Bold = true;

    for (int i = 0; i < sales.Count; i++)
    {
        salesSheet[$"A{i + 2}"].Value = sales[i].Date.ToString("yyyy-MM-dd");
        salesSheet[$"B{i + 2}"].Value = sales[i].Revenue;
    }

    // Sheet 2 -- Inventory snapshot
    var invSheet = workbook.CreateWorkSheet("Inventory");
    invSheet["A1"].Value = "SKU";
    invSheet["B1"].Value = "Name";
    invSheet["C1"].Value = "Quantity";
    invSheet["A1:C1"].Style.Font.Bold = true;

    for (int i = 0; i < inventory.Count; i++)
    {
        invSheet[$"A{i + 2}"].Value = inventory[i].SKU;
        invSheet[$"B{i + 2}"].Value = inventory[i].Name;
        invSheet[$"C{i + 2}"].Value = inventory[i].Quantity;
    }

    using var stream = workbook.ToStream();
    return stream.ToArray();
}
Public Function GenerateMultiSheetReport( _
    sales As List(Of SalesData), _
    inventory As List(Of InventoryItem)) As Byte()

    Dim workbook = WorkBook.Create(ExcelFileFormat.XLSX)

    ' Sheet 1 -- Sales summary
    Dim salesSheet = workbook.CreateWorkSheet("Sales")
    salesSheet("A1").Value = "Date"
    salesSheet("B1").Value = "Revenue"
    salesSheet("A1:B1").Style.Font.Bold = True

    For i As Integer = 0 To sales.Count - 1
        salesSheet($"A{i + 2}").Value = sales(i).Date.ToString("yyyy-MM-dd")
        salesSheet($"B{i + 2}").Value = sales(i).Revenue
    Next

    ' Sheet 2 -- Inventory snapshot
    Dim invSheet = workbook.CreateWorkSheet("Inventory")
    invSheet("A1").Value = "SKU"
    invSheet("B1").Value = "Name"
    invSheet("C1").Value = "Quantity"
    invSheet("A1:C1").Style.Font.Bold = True

    For i As Integer = 0 To inventory.Count - 1
        invSheet($"A{i + 2}").Value = inventory(i).SKU
        invSheet($"B{i + 2}").Value = inventory(i).Name
        invSheet($"C{i + 2}").Value = inventory(i).Quantity
    Next

    Using stream = workbook.ToStream()
        Return stream.ToArray()
    End Using
End Function
$vbLabelText   $csharpLabel

為完整的API參考涵蓋工作簿屬性、範圍操作和圖表支援,請存取IronXL API文件

Blazor 匯出到 Excel:使用 IronXL 在 C# 中的完整指南:圖片 3 - 高級功能範例輸出

如何高效處理錯誤和大資料集?

Excel匯出操作可能會在大資料集中默默失敗或性能下降。 以下模式解決了這兩個問題。

服務層的錯誤處理

將生成邏輯包裹在服務中(而不是組件)可保持所有呼叫者的錯誤處理一致。 推薦的模式是讓IronXL異常傳播,然後將其包裹在具有失敗報告上下文的領域特定異常中:

InvalidOperationException("Failed to generate sales report", ex)。 在Blazor組件中,捕捉InvalidOperationException並顯示使用者友好的資訊,而不洩露內部細節。 使用ILogger<t>注入到服務構造函式中來記錄內部異常,這樣開發團隊可以追溯到特定的工作簿操作失敗。 絕不要將原始異常資訊呈現給終端使用者—文件路徑、記憶體位址或堆疊跟蹤可能洩露伺服器內部。

請參見官方Microsoft文件中的錯誤處理最佳實踐,以獲取Blazor中的結構化錯誤日誌的指導。 如需更多.NET中可測試服務的指導,Microsoft相依性注入文件解釋了如何註冊和解決作用域服務,這正是這裡使用ExcelExportService的模式。

大資料集的性能考量

對於超過幾千行的資料集,請考慮以下方法:

Excel匯出性能策略
策略 何時使用 IronXL支援
直接流式傳輸到響應 Files >10 MB workbook.ToStream()
在匯出前分頁資料 UI驅動的帶篩選條件匯出 在建立工作簿之前在服務中應用
背景工作+下載連結 Reports taking >5 seconds 與SignalR或輪詢結合
禁用大表上的AutoSizeColumn Sheets with >500 rows 設置固定列寬代替

IronXL的ToStream()方法直接寫入輸出流,而不首先將整個文件載入到字節陣列中,這樣可以降低大工作簿的記憶體使用量。 如需更多性能指導,請參見使用IronXL讀取和寫入大型Excel文件。

IronXL支援哪些其他Excel功能?

除了基本匯出外,IronXL提供了範圍廣泛的Excel功能,以滿足現實世界的報告需求。

公式、命名範圍和數字格式化

您可以使用與在單元格中直接輸入相同的語法嵌入任何Excel公式。 IronXL在讀取時評估公式,因此生成文件的使用者打開電子表格時即可看到計算結果。 命名範圍使公式更具可讀性和可維護性:

// Aggregate formulas on a summary row
worksheet["E2"].Value = "=SUM(D2:D100)";
worksheet["F2"].Value = "=AVERAGE(C2:C100)";
worksheet["G2"].Value = "=COUNTIF(B2:B100,\"Widget A\")";

// Named ranges improve formula readability
worksheet["D2:D100"].Name = "RevenueColumn";
worksheet["E2"].Value = "=SUM(RevenueColumn)";

// Number and date formatting prevents type misinterpretation
worksheet["D2"].Value = 12345.67m;
worksheet["D2"].FormatString = "#,##0.00";
worksheet["A2"].Value = DateTime.Now;
worksheet["A2"].FormatString = "dd/MM/yyyy";
// Aggregate formulas on a summary row
worksheet["E2"].Value = "=SUM(D2:D100)";
worksheet["F2"].Value = "=AVERAGE(C2:C100)";
worksheet["G2"].Value = "=COUNTIF(B2:B100,\"Widget A\")";

// Named ranges improve formula readability
worksheet["D2:D100"].Name = "RevenueColumn";
worksheet["E2"].Value = "=SUM(RevenueColumn)";

// Number and date formatting prevents type misinterpretation
worksheet["D2"].Value = 12345.67m;
worksheet["D2"].FormatString = "#,##0.00";
worksheet["A2"].Value = DateTime.Now;
worksheet["A2"].FormatString = "dd/MM/yyyy";
' Aggregate formulas on a summary row
worksheet("E2").Value = "=SUM(D2:D100)"
worksheet("F2").Value = "=AVERAGE(C2:C100)"
worksheet("G2").Value = "=COUNTIF(B2:B100,""Widget A"")"

' Named ranges improve formula readability
worksheet("D2:D100").Name = "RevenueColumn"
worksheet("E2").Value = "=SUM(RevenueColumn)"

' Number and date formatting prevents type misinterpretation
worksheet("D2").Value = 12345.67D
worksheet("D2").FormatString = "#,##0.00"
worksheet("A2").Value = DateTime.Now
worksheet("A2").FormatString = "dd/MM/yyyy"
$vbLabelText   $csharpLabel

定義命名範圍並顯式設置數字格式,IronXL將二者曝光為範圍物件的屬性。 這可以防止Excel將貨幣值視為普通文字—這是從資料庫中匯出金融資料時常見的問題。

受支援的Excel文件格式

IronXL可以讀取和寫入多個Excel格式,包括.tsv。 格式在保存時確定,因此同一服務類可以通過更改一個小參數支援Excel和CSV匯出。

// Export as CSV for systems that consume flat files
workbook.SaveAs("report.csv");

// Or stream as CSV for download
using var ms = workbook.ToStream(ExcelFileFormat.CSV);
// Export as CSV for systems that consume flat files
workbook.SaveAs("report.csv");

// Or stream as CSV for download
using var ms = workbook.ToStream(ExcelFileFormat.CSV);
' Export as CSV for systems that consume flat files
workbook.SaveAs("report.csv")

' Or stream as CSV for download
Using ms As Stream = workbook.ToStream(ExcelFileFormat.CSV)
End Using
$vbLabelText   $csharpLabel

這種靈活性在下游系統(如ERP平台或資料倉庫)期望特定文件格式的整合中尤為重要。 如需IronXL與其他Excel庫的完整功能對比,請存取IronXL功能頁面

如需要了解.xlsx文件的內部結構以除錯意外輸出,Microsoft提供了一個良好的參考,用於理解OOXML文件格式。 IronXL的NuGet包也在NuGet.org上列出,附完整版本歷史和相容性注釋。

如何開始在Blazor專案中使用IronXL?

IronXL提供免費的開發授權,讓您可以無時間限制地開發和測試。 對於生產應用,需要部署授權。

您可以直接從NuGet下載免費試用—無需註冊即可開始。 當您準備部署時,查看IronXL授權選項以找到適合應用規模的計劃。

IronXL適用於所有主要的.NET應用程式型別—Blazor Server、Blazor WebAssembly(伺服器渲染)、ASP.NET Core MVC、控制檯應用程式和Windows桌面應用程式。程式庫的目標設定為.NET Standard 2.0,因此與從.NET Framework 4.6.2到.NET 10的每個支援.NET版本都相容。如果專案還需要PDF生成,IronPDF可以與IronXL整合,無衝突,允許您從同一服務層匯出為Excel或PDF。

若要探索更多Blazor專屬範例,請參見Blazor Excel匯出教程ASP.NET Core匯出指南。 對於閱讀現有電子表格,C# Excel閱讀器教程涵蓋常見的導入場景。 您還可以查看如何從頭建立一個新的Excel工作簿,適用於需要編程生成文件而非從模板建立的專案。

常見問題

如何在Blazor伺服器應用中將資料匯出至Excel?

您可以使用IronXL將資料匯出至Blazor伺服器應用中的Excel。IronXL允許您直接在伺服器上建立、格式化和下載Excel文件,無需Microsoft Office。

使用IronXL在Blazor中是否需要安裝Microsoft Office?

不,您不需要安裝Microsoft Office。IronXL允許您在Blazor伺服器應用中獨立處理Excel文件。

是否可以在Blazor應用中使用IronXL格式化Excel文件?

是的,IronXL提供了格式化Excel文件的工具,允許您直接從Blazor伺服器應用自定義您的資料外觀。

IronXL是否與Blazor伺服器應用相容?

是的,IronXL無縫整合到Blazor伺服器應用中,允許輕鬆匯出和處理Excel文件。

在Blazor中使用IronXL進行Excel匯出的優點是什麼?

IronXL提供了一個簡單的方法來建立和操作Excel文件,而不需要Office,使其成為Blazor應用中資料匯出的高效解決方案。

IronXL能夠在Blazor伺服器應用中處理大型Excel文件嗎?

是的,IronXL設計用於在Blazor伺服器應用中高效處理大型Excel文件。

在Blazor應用中,我可以使用IronXL建立哪些型別的Excel文件?

使用IronXL,您可以在Blazor應用中直接建立各種型別的Excel文件,包括XLSX、XLS和CSV。

是否可以使用IronXL從Blazor伺服器應用中下載Excel文件?

是的,IronXL支持直接從Blazor伺服器應用下載Excel文件,為終端使用者提供無縫體驗。

與其他解決方案相比,IronXL如何改善Blazor中的Excel匯出功能?

IronXL通過消除Microsoft Office的需求並直接與伺服器應用整合,簡化了在Blazor中匯出Excel文件的過程。

什麼使IronXL成為Blazor開發者的好選擇?

IronXL對Blazor開發者而言是一個好選擇,因為它提供了強大的Excel處理能力,無需Office安裝,且易於整合至Blazor伺服器應用。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話