Knowledgebase (2311)
Children categories
How to Generate & Create QR Code in ASP.NET C# (Full Example)
2025-08-08 05:38:37 Written by zaki zou
QR codes have become a standard feature in modern web applications, widely used for user authentication, contactless transactions, and sharing data like URLs or contact information. For developers working with ASP.NET, implementing QR code generation using C# is a practical requirement in many real-world scenarios.
In this article, you’ll learn how to generate QR codes in ASP.NET using Spire.Barcode for .NET. We’ll walk through a complete example based on an ASP.NET Core Web App (Razor Pages) project, including backend logic and a simple UI to display the generated code. The same approach can be easily adapted to MVC, Web API, and Web Forms applications.
Article Overview
- 1. Project Setup and Dependencies
- 2. Generate QR Code in ASP.NET Using C#
- 3. Customize QR Code Output
- 4. Apply Logic in MVC, Web API, and Web Forms
- 5. Conclusion
- FAQs
1. Project Setup and Dependencies
Prerequisites
To follow along, make sure you have:
- Visual Studio 2019 or newer
- .NET 6 or later
- ASP.NET Core Web App (Razor Pages Template)
- NuGet package: Spire.Barcode for .NET
Install Spire.Barcode for .NET
Install the required library using NuGet Package Manager Console:
Install-Package Spire.Barcode
Spire.Barcode is a fully self-contained .NET barcode library that supports in-memory generation of QR codes without external APIs. You can also use Free Spire.Barcode for .NET for smaller projects.
2. Generate QR Code in ASP.NET Using C#
This section describes how to implement QR code generation in an ASP.NET Core Web App (Razor Pages) project. The example includes a backend C# handler that generates the QR code using Spire.Barcode for .NET, and a simple Razor Page frontend for user input and real-time display.
Step 1: Add QR Code Generation Logic in PageModel
The backend logic resides in the Index.cshtml.cs file. It processes the form input, generates a QR code using Spire.Barcode, and returns the result as a Base64-encoded image string that can be directly embedded in HTML.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Spire.Barcode;
public class IndexModel : PageModel
{
[BindProperty]
public string InputData { get; set; }
public string QrCodeBase64 { get; set; }
public void OnPost()
{
if (!string.IsNullOrWhiteSpace(InputData))
{
QrCodeBase64 = GenerateQrCodeBase64(InputData);
}
}
private string GenerateQrCodeBase64(string input)
{
var settings = new BarcodeSettings
{
Type = BarCodeType.QRCode, // QR code type
Data = input, // Main encoded data
Data2D = input, // Required for 2D barcode, usually same as Data
QRCodeDataMode = QRCodeDataMode.Byte, // Byte mode (supports multilingual content)
QRCodeECL = QRCodeECL.M, // Medium error correction (15%)
X = 3, // Module size (affects image dimensions)
ShowText = false, // Hide default barcode text
ShowBottomText = true, // Show custom bottom text
BottomText = input // Bottom text to display under the QR code
};
var generator = new BarCodeGenerator(settings);
using var ms = new MemoryStream();
var qrImage = generator.GenerateImage();
qrImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return Convert.ToBase64String(ms.ToArray());
}
}
Key Components:
-
BarcodeSettings: Specifies the QR code's core configuration, such as type (QRCode), data content, encoding mode, and error correction level.
-
BarCodeGenerator: Takes the settings and generates the QR code image as a System.Drawing.Image object using the GenerateImage() method.
-
Base64 Conversion: Converts the image to a Base64 string so it can be directly embedded into the HTML page without saving to disk.
This approach keeps the entire process in memory, making it fast, portable, and suitable for serverless or cloud-hosted applications.
Step 2: Create the Razor Page for User Input and QR Code Display and Download
The following Razor markup in the Index.cshtml file defines a form for entering text or URLs, displays the generated QR code upon submission, and provides a button to download the QR code image.
@page
@model IndexModel
@{
ViewData["Title"] = "QR Code Generator";
}
<h2>QR Code Generator</h2>
<form method="post">
<label for="InputData">Enter text or URL:</label>
<input type="text" id="InputData" name="InputData" style="width:300px;" required />
<button type="submit">Generate QR Code</button>
</form>
@if (!string.IsNullOrEmpty(Model.QrCodeBase64))
{
<div style="margin-top:20px">
<img src="data:image/png;base64,@Model.QrCodeBase64" alt="QR Code" />
<br />
<a href="data:image/png;base64,@Model.QrCodeBase64" download="qrcode.png">Download QR Code</a>
</div>
}
The Base64-encoded image is displayed directly in the browser using a data: URI. This eliminates the need for file storage and allows for immediate rendering and download.
The following screenshot shows the result after submitting text input.

If you need to scan QR codes instead, please refer to How to Scan QR Codes in C#.
3. Customize QR Code Output
Spire.Barcode provides several customization options through the BarcodeSettings class to control the appearance and behavior of the generated QR code:
| Property | Function | Example |
|---|---|---|
| QRCodeDataMode | Text encoding mode | QRCodeDataMode.Byte |
| QRCodeECL | Error correction level | QRCodeECL.H (high redundancy) |
| X | Module size (resolution) | settings.X = 6 |
| ImageWidth/Height | Control dimensions of QR image | settings.ImageWidth = 300 |
| ForeColor | Set QR code color | settings.ForeColor = Color.Blue |
| ShowText | Show or hide text below barcode | settings.ShowText = false |
| BottomText | Custom text to display below barcode | settings.BottomText = "Scan Me" |
| ShowBottomText | Show or hide the custom bottom text | settings.ShowBottomText = true |
| QRCodeLogoImage | Add a logo image to overlay at QR code center | settings.QRCodeLogoImage = System.Drawing.Image.FromFile("logo.png"); |
These properties help you tailor the appearance of your QR code for branding, readability, or user interaction purposes.
To explore more QR code settings, refer to the BarcodeSettings API reference.
4. Apply Logic in MVC, Web API, and Web Forms
The same QR code generation logic used in Razor Pages can also be reused in other ASP.NET frameworks such as MVC, Web API, and Web Forms.
MVC Controller Action
In an MVC project, you can add a Generate action in a controller (e.g., QrController.cs) to generate and return the QR code image directly:
public class QrController : Controller
{
public ActionResult Generate(string data)
{
var settings = new BarcodeSettings
{
Type = BarCodeType.QRCode,
Data = data,
QRCodeDataMode = QRCodeDataMode.Byte,
QRCodeECL = QRCodeECL.M,
X = 5
};
var generator = new BarCodeGenerator(settings);
using var ms = new MemoryStream();
generator.GenerateImage().Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return File(ms.ToArray(), "image/png");
}
}
This method returns the QR code as a downloadable PNG file, ideal for server-side rendering.
Web API Endpoint
For Web API, you can define a GET endpoint in a controller such as QrApiController.cs that responds with the generated image stream:
[ApiController]
[Route("api/[controller]")]
public class QrApiController : ControllerBase
{
[HttpGet("generate")]
public IActionResult GetQr(string data)
{
var settings = new BarcodeSettings
{
Type = BarCodeType.QRCode,
Data = data
};
var generator = new BarCodeGenerator(settings);
using var ms = new MemoryStream();
generator.GenerateImage().Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return File(ms.ToArray(), "image/png");
}
}
This approach is suitable for frontends built with React, Vue, Angular, or any JavaScript framework.
Web Forms Code-Behind
In ASP.NET Web Forms, you can handle QR code generation in the code-behind of a page like Default.aspx.cs:
protected void btnGenerate_Click(object sender, EventArgs e)
{
var settings = new BarcodeSettings
{
Type = BarCodeType.QRCode,
Data = txtInput.Text
};
var generator = new BarCodeGenerator(settings);
using var ms = new MemoryStream();
generator.GenerateImage().Save(ms, System.Drawing.Imaging.ImageFormat.Png);
imgQR.ImageUrl = "data:image/png;base64," + Convert.ToBase64String(ms.ToArray());
}
The generated image is embedded directly into an asp:Image control using a Base64 data URI.
5. Conclusion
With Spire.Barcode for .NET, you can seamlessly generate and customize QR codes across all ASP.NET project types — Razor Pages, MVC, Web API, or Web Forms. The solution is fully offline, fast, and requires no third-party API.
Returning images as Base64 strings simplifies deployment and avoids file management. Whether you're building authentication tools, ticketing systems, or contact sharing, this approach is reliable and production-ready.
FAQs
Q: Does Spire.Barcode support Unicode characters like Chinese or Arabic?
A: Yes. Use QRCodeDataMode.Byte for full Unicode support.
Q: Can I adjust QR code size and color?
A: Absolutely. Use properties like X, ForeColor, and ImageWidth.
Q: Is this solution fully offline?
A: Yes. It works without any external API calls or services.
Q: Can I expose this QR logic via API?
A: Yes. Use ASP.NET Web API to serve generated images to client apps.
Export Database to Excel in C#: Practical Guide with SQL Example
2025-08-06 01:59:33 Written by zaki zou
Exporting data from a database to Excel using C# is a frequent requirement in business applications—be it for internal reporting, audit logs, data migration, or ad-hoc analysis. Excel's portability and familiarity make it a go-to format for sharing structured data with both technical and non-technical users.
In this guide, you'll learn how to export database records to Excel using C# and Spire.XLS for .NET. We’ll walk through retrieving data from a SQL Server database and writing it into a well-formatted Excel file. The same workflow applies to other relational databases such as SQLite, MySQL, or Oracle with only minimal adjustments.
Table of Contents:
- Prerequisites and Environment Setup
- Exporting Data from SQL Database to Excel in C#
- Format the Excel Output
- Alternative Approaches to Read Data
- Common Issues and Troubleshooting
- Conclusion
- FAQ
Prerequisites and Environment Setup
Before we dive into code, ensure your development environment is ready:
-
.NET Version: .NET Framework or .NET Core / .NET 6 / .NET 8
-
IDE: Visual Studio (Community or higher)
-
Database: A relational database (e.g., SQL Server, SQLite, MySQL, Oracle). This tutorial uses SQL Server Express as the example. By default, the connection uses Windows Authentication, but you can switch to SQL Authentication if needed.
-
Libraries:
- Spire.XLS for .NET (Install via NuGet: Install-Package Spire.XLS)
- Microsoft.Data.SqlClient (Install via NuGet if using SQL Server)
Sample Data
In the following examples, we'll use a simple Employees table stored in SQL Server Express. Here's the SQL script to create and populate it:
CREATE TABLE Employees (
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(100) NOT NULL,
Department NVARCHAR(50) NOT NULL,
Position NVARCHAR(50),
HireDate DATE NOT NULL,
Salary DECIMAL(10, 2) NOT NULL,
IsFullTime BIT NOT NULL
);
INSERT INTO Employees (Name, Department, Position, HireDate, Salary, IsFullTime) VALUES
('Alice Johnson', 'Human Resources', 'HR Manager', '2018-05-01', 5500.00, 1),
('Bob Smith', 'IT', 'Software Engineer', '2020-09-15', 7200.50, 1),
('Charlie Lee', 'Finance', 'Accountant', '2019-11-20', 6300.75, 0),
('Diana Chen', 'Marketing', 'Content Specialist', '2021-02-10', 4800.00, 1);
If you're using another database system like MySQL or SQLite, just adjust the SQL syntax and connection string accordingly. The export logic remains the same.
Exporting Data from SQL Database to Excel in C#
Let’s walk through how to retrieve data from a database and export it to an Excel file using Spire.XLS for .NET.
Step 1: Connect to the SQL Server Database
We start by establishing a connection to the database using SqlConnection. Here's an example connection string targeting SQL Server Express:
string connectionString = @"Data Source=YourServer\SQLEXPRESS;Initial Catalog=YourDatabaseName;Integrated Security=True;";
The above connection string uses Windows Authentication (Integrated Security=True). If you prefer SQL Server Authentication, replace it with: User ID=yourUsername;Password=yourPassword;Encrypt=True;TrustServerCertificate=True;
Make sure that your SQL Server Express instance is running, and that the specified database and table exist.
Step 2: Retrieve Data into a DataTable
To make the data ready for export, we use SqlDataAdapter to fill a DataTable with the results of a SQL query:
using System.Data;
using Microsoft.Data.SqlClient;
DataTable dataTable = new DataTable();
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
string query = "SELECT * FROM Employees";
using (SqlDataAdapter adapter = new SqlDataAdapter(query, conn))
{
adapter.Fill(dataTable);
}
}
Spire.XLS can directly import data from a DataTable using InsertDataTable, which makes it ideal for structured exports from relational databases.
Step 3: Export the DataTable to Excel Using Spire.XLS
Once the DataTable is populated, we can use Spire.XLS to write its contents into a new Excel worksheet:
using Spire.Xls;
// Create a new workbook
Workbook workbook = new Workbook();
// Clear the default sheets and create a new one
workbook.Worksheets.Clear();
Worksheet sheet = workbook.Worksheets.Add("Employees");
// Insert data starting from row 1, column 1, and include column headers
sheet.InsertDataTable(dataTable, true, 1, 1);
// Save the workbook as an Excel xlsx file
workbook.SaveToFile("Employees.xlsx", ExcelVersion.Version2013);
Key classes and methods used:
- Workbook: The main entry point for creating or loading Excel files.
- Worksheet: Represents a single sheet in the workbook. Use workbook.Worksheets[] to access a sheet, or Worksheets.Add() to add more.
- InsertDataTable(DataTable dataTable, bool columnHeaders, int firstRow, int firstColumn):
- columnHeaders = true tells Spire.XLS to write column names as the first row.
- firstRow, firstColumn specify where the data begins (1-based index).
- Workbook.SaveToFile(string fileName, ExcelVersion version): Saves the workbook to a file. Spire.XLS supports saving Excel workbooks to various formats, including .xlsx, .xls, and .csv. You can also save to a stream using SaveToStream().
Here’s what the resulting Excel file looks like with the raw data exported from the database.

Step 4: Format the Excel Output (Optional but Recommended)
While the data is already exported, applying some formatting can significantly improve readability for end users:
// Write data to Excel, including column names, starting at row 1, column 1
sheet.InsertDataTable(dataTable, true, 1, 1);
// Make header row bold and highlight with background color
sheet.Rows[0].Style.Font.IsBold = true;
sheet.Rows[0].Style.Font.Size = 14;
sheet.Rows[0].Style.HorizontalAlignment = HorizontalAlignType.Center;
sheet.Rows[0].Style.Color = System.Drawing.Color.LightGray;
// Format data rows
for (int i = 1; i < sheet.Rows.Count(); i++)
{
CellRange dataRow = sheet.Rows[i];
dataRow.Style.Font.Size = 12;
dataRow.Style.HorizontalAlignment = HorizontalAlignType.Left;
}
// Set font name
sheet.AllocatedRange.Style.Font.FontName = "Arial";
// Set borders
sheet.AllocatedRange.BorderAround(LineStyleType.Thin, System.Drawing.Color.Black);
sheet.AllocatedRange.BorderInside(LineStyleType.Medium, System.Drawing.Color.Black);
// Auto-fit columns
sheet.AllocatedRange.AutoFitColumns();
Here's what the Excel file looks like after formatting.

Spire.XLS provides full access to cell styles, fonts, colors, borders, alignment, and more—making it suitable for generating production-quality Excel reports.
If you need advanced number formatting, learn how to set number formats for Excel cells using C#.
Alternative Approaches to Read Data
The export process relies on having a DataTable, but how you populate it can vary based on your application architecture:
A. Using Entity Framework (ORM)
If you use EF Core or EF6, you can load data via LINQ and manually insert it into Excel:
var employees = dbContext.Employees.ToList();
To export, either convert this list into a DataTable, or use a loop to write rows manually using sheet.Range[row, col].Value = value.
B. Using Stored Procedures
Stored procedures allow encapsulating SQL logic. You can execute them using SqlCommand and fill the result into a DataTable:
SqlCommand cmd = new SqlCommand("GetEmployees", conn);
cmd.CommandType = CommandType.StoredProcedure;
C. Reading from SQLite
For lightweight scenarios, replace the connection string and class:
using (SQLiteConnection conn = new SQLiteConnection("Data Source=mydb.db"))
Export logic remains identical—fill a DataTable and use InsertDataTable.
D. Reading from MySQL or Oracle
Same pattern applies—just change the connection class:
using (MySqlConnection conn = new MySqlConnection("server=localhost;uid=root;pwd=123;database=test"))
Make sure to install the appropriate ADO.NET data provider (e.g., Microsoft.Data.SqlClient, Microsoft.Data.Sqlite, or MySql.Data) via NuGet when connecting to different databases.
As long as you populate a DataTable, Spire.XLS handles the Excel generation the same way.
You may also like: How to Import Data from Excel to Database – learn how to complete the full data exchange cycle using Spire.XLS.
Common Issues and Troubleshooting
| Issue | Solution |
|---|---|
| Excel file opens empty | Ensure the DataTable has data before calling InsertDataTable() |
| Access denied on save | Check folder permissions or file path conflicts |
| Connection fails | Verify your database server, credentials, and connection string |
| Special characters not displaying | Use NVARCHAR in SQL and Unicode-compatible fonts in Excel |
| Login failed or authentication error | Check authentication method: use Integrated Security=True for Windows, or provide User ID and Password for SQL Authentication. |
Conclusion
Exporting a database to Excel in C# can be done efficiently using Spire.XLS for .NET. By retrieving data into a DataTable and exporting it with InsertDataTable(), you can automate reporting and data extraction without needing Microsoft Office installed.
This solution can also be integrated into scheduled tasks, background services, or web applications for automated report generation.
To unlock all features during development or testing, you can apply for a free 30-day temporary license. For smaller projects, Free Spire.XLS for .NET may also be sufficient.
FAQ
How do I export SQL to Excel in C#?
Use SqlConnection to retrieve data into a DataTable, and export it using Spire.XLS’s InsertDataTable() method.
Can I use this method with SQLite or MySQL?
Yes. Just change the connection type and query, then pass the resulting DataTable to Spire.XLS.
Do I need Excel installed to use Spire.XLS?
No. Spire.XLS is a standalone library and does not require Microsoft Excel on the machine.
Can I export multiple tables to Excel?
Yes. Use Workbook.Worksheets.Add() to create additional worksheets, and export each DataTable separately.

Exporting a DataTable to Excel in C# is a common task in .NET development, such as generating reports, exporting logs, or preparing data for sharing across systems. By using a standalone component, developers can quickly export data and apply formatting to create professional, ready-to-use Excel files from DataTables without relying on complex setup or external dependencies.
To streamline this process, Spire.XLS for .NET offers a lightweight and fully independent library. In this article, you'll learn how to export a DataTable to Excel (.xlsx or .xls) in C#, apply formatting to improve readability, and address common export scenarios effectively.
Quick Navigation
- Install and Configure Spire.XLS
- Step-by-Step: Export DataTable to Excel
- Format and Style the Exported Excel File
- Common Issues and Solutions
- Conclusion
- Frequently Asked Questions
Install and Configure Spire.XLS
Before you start, make sure your project includes Spire.XLS for .NET.
Install Spire.XLS via NuGet
Run this command in the NuGet Package Manager Console:
Install-Package Spire.XLS
Spire.XLS works with .NET Framework, .NET Core, .NET 6/7+, and ASP.NET projects — no Microsoft Office installation required.
Step-by-Step: Export DataTable to Excel in C#
The following steps demonstrate how to export a DataTable to an Excel file using Spire.XLS, including data preparation, file generation, optional streaming, and output formatting.
1. Create a Sample DataTable
First, create a DataTable and add some sample rows:
DataTable dt = new DataTable("Employees");
// Insert columns
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Department", typeof(string));
dt.Columns.Add("Join Date", typeof(DateTime));
dt.Columns.Add("Salary", typeof(double));
dt.Columns.Add("Full-Time", typeof(bool));
dt.Columns.Add("Bonus Rate", typeof(decimal));
// Insert rows
dt.Rows.Add(1001, "Alice", "HR", new DateTime(2021, 5, 10), 55000.5, true, 0.05m);
dt.Rows.Add(1002, "Bob", "IT", new DateTime(2020, 11, 23), 72000.0, false, 0.03m);
dt.Rows.Add(1003, "Carol", "Finance", new DateTime(2019, 8, 15), 63000.75, true, 0.07m);
dt.Rows.Add(1004, "David", "Marketing", new DateTime(2022, 3, 8), 48800.0, true, 0.06m);
Tip: This is just sample data — you can bind any DataTable your app generates.
2. Import DataTable and Save to Excel File
Next, initialize the Excel workbook, import the DataTable into a worksheet, and save the file:
// Create a new workbook
Workbook workbook = new Workbook();
// Clear the default worksheets and add a new one
workbook.Worksheets.Clear();
Worksheet sheet = workbook.Worksheets.Add(dt.TableName);
// Import the DataTable starting at cell A1
sheet.InsertDataTable(dt, true, 1, 1);
// Save as XLSX (recommended)
workbook.SaveToFile("EmployeeData.xlsx", FileFormat.Version2016);
// Or save as XLS (older format)
workbook.SaveToFile("EmployeeData.xls", FileFormat.Version97to2003);
Explanation:
- Workbook is the container for your Excel file.
- InsertDataTable(dataTable, includeColumnHeaders, startRow, startColumn) maps the entire table to the Excel grid.
- SaveToFile() writes the file to disk in your chosen format.
Output Preview
Example of the exported Excel file:

3. Export Excel File as Stream in ASP.NET
When building a web app, you might want to export the file directly as a stream instead of saving to disk:
MemoryStream stream = new MemoryStream();
workbook.SaveToStream(stream, FileFormat.Version2013);
stream.Position = 0;
Return this MemoryStream in your ASP.NET controller to trigger a file download in the browser.
For additional tips on managing Excel files in C#, check out How to Create and Manipulate Excel Files in C#.
Format and Style the Exported Excel File
Formatting is optional but recommended for creating professional Excel files. Below is how you can format the exported content using Spire.XLS.
// Style the header row
CellRange header = sheet.Rows[0];
header.Style.Font.IsBold = true;
header.Style.Font.FontName = "Arial";
header.Style.Font.Size = 13;
header.Style.Color = Color.LightGray;
header.Style.Borders[BordersLineType.EdgeBottom].LineStyle = LineStyleType.Thick;
// Style the data rows
for (int i = 1; i < sheet.Rows.Length; i++)
{
CellRange dataRow = sheet.Rows[i];
dataRow.Style.Font.FontName = "Times New Roman";
dataRow.Style.Font.Size = 11;
dataRow.BorderInside();
}
// Format date column to display as date
CellRange dateColumn = sheet.Range[2, 4, sheet.Rows.Length + 1, 4];
dateColumn.Style.NumberFormat = "yyyy-mm-dd";
// Auto-fit columns
sheet.AllocatedRange.AutoFitColumns();
Key Properties and Methods:
- Style: Applies font, color, border, number formatting, etc. to cells.
- AutoFitColumns(): Automatically adjusts column width to fit content.
- NumberFormat: Sets how dates or numbers are displayed in Excel, e.g., "yyyy-mm-dd".
- BorderInside(): Adds internal borders to improve table readability.
Formatted Output Preview
Excel file with formatted header and date column:

For more advanced number formatting options, see how to set number format in Excel using C#.
Common Issues and Solutions
- File won’t open or shows corruption error
Ensure streams are closed properly and file extensions match the format.
- Special characters or non-English text look garbled
Confirm strings are UTF-8 encoded and use appropriate fonts.
- Columns too narrow
Use AutoFitColumns() to adjust widths automatically or use CellRange.ColumnWidth to set a fixed column width.
Conclusion
Exporting a DataTable to Excel in C# is straightforward with Spire.XLS. This approach lets you create .xlsx or .xls files easily without relying on Office, while giving you full control over the output layout for both desktop and web applications.
If needed, you can also request a free temporary license to unlock the full feature set for evaluation.
Frequently Asked Questions
Q1: How to convert DataTable to Excel in C#?
You can use sheet.InsertDataTable() from Spire.XLS to load a DataTable into a worksheet, then save it as an Excel file using workbook.SaveToFile().
Q2: Is there a free library to export a DataTable to Excel in C#?
Yes — Free Spire.XLS for .NET is a standalone library that lets you create and export Excel files directly in C# without needing to install Microsoft Office.
Q3: Can I export DataTable to Excel in ASP.NET?
Yes, the same logic can be applied in ASP.NET by generating the workbook in a controller and streaming it back as a downloadable file.
Q4: What's the difference between .xlsx and .xls export?
.xlsx is the newer Office Open XML format, compatible with Excel 2007 and later. .xls supports legacy Excel 97–2003 but is limited to 65,536 rows.