How to overcome ThreadAbortException while saving an Excel file using XlsIO.Base assembly
This article explains how to overcome ThreadAbortException while saving an Excel file using the XlsIO.Base assembly in web platforms.
Why is the exception thrown?
XlsIO.Base uses the Response.End method internally for saving a workbook. So, when a workbook is saved with HttpResponse, this Response.End method throws a ThreadAbortException. You can use a try-catch statement to catch this exception. The Response.End method ends the page execution and shifts the execution to the Application_EndRequest event in the application's event pipeline. The line of code that follows Response.End is not executed.
To overcome this problem, the SendStream method is used in XlsIO. The following sample code explains it.
Sample to avoid ThreadAbortException
// Saves workbook as a stream with specified ExcelSaveType
workbook.SaveAs(stream, ExcelSaveType.SaveAsXLS);
// Adds header for specified HttpContentType
SendStream(stream, "output.xlsx", ExcelHttpContentType.Excel2016);
The following C#/VB complete code snippet shows how to avoid the exception while saving a file with HttpResponse using XlsIO.
C#
using System;
using System.IO;
using Syncfusion.XlsIO;
namespace CreateSpreadsheet
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnCreateExcel_Click(object sender, EventArgs e)
{
using (ExcelEngine excelEngine = new ExcelEngine())
{
// Instantiate the Excel application object
IApplication application = excelEngine.Excel;
// Setting default version.
application.DefaultVersion = ExcelVersion.Excel2016;
// Create workbook
IWorkbook workbook = application.Workbooks.Create(1);
IWorksheet sheet = workbook.Worksheets[0];
// Adding data into worksheet
sheet[1, 1].Text = "Products";
sheet[1, 2].Text = "Qtr1";
sheet[1, 3].Text = "Qtr2";
sheet.Range["A1:C1"].HorizontalAlignment = ExcelHAlign.HAlignCenter;
sheet.Range["A1:C1"].CellStyle.Font.Bold = true;
sheet[2, 1].Text = "Alfreds Futterkiste";
sheet[2, 2].Number = 744.6;
sheet[2, 3].Number = 162.56;
sheet[3, 1].Text = "Antonio Moreno Taqueria";
sheet[3, 2].Number = 5079.6;
sheet[3, 3].Number = 1249.2;
sheet[4, 1].Text = "Around the Horn";
sheet[4, 2].Number = 1267.5;
sheet[4, 3].Number = 1062.5;
sheet[5, 1].Text = "Bon app";
sheet[5, 2].Number = 1418;
sheet[5, 3].Number = 756;
sheet[6, 1].Text = "Eastern Connection";
sheet[6, 2].Number = 4728;
sheet[6, 3].Number = 4547.92;
sheet[7, 1].Text = "Ernst Handel";
sheet[7, 2].Number = 943.89;
sheet[7, 3].Number = 349.6;
sheet.SetColumnWidth(1, 25.0);
sheet.SetColumnWidth(2, 12.0);
sheet.SetColumnWidth(3, 12.0);
MemoryStream stream = new MemoryStream();
// Save and close the document
workbook.SaveAs(stream, ExcelSaveType.SaveAsXLS);
SendStream(stream, "output.xlsx", ExcelHttpContentType.Excel2016);
}
}
/// <summary>
/// Adds HttpResponse
/// </summary>
/// <param name="stream">Stream to generate HttpResponse</param>
/// <param name="fileName">Name of the file output file</param>
/// <param name="contentType">Content type to use</param>
private void SendStream(MemoryStream stream, string fileName, ExcelHttpContentType contentType)
{
Response.Clear();
Response.ContentType = GetContentTypeString(contentType);
Response.AddHeader("Content-Disposition", String.Format("{0}; filename={1};", "attachment", fileName));
Response.OutputStream.Write(stream.ToArray(), 0, Convert.ToInt32(stream.Length));
Response.Flush();
Response.Close();
}
/// <summary>
/// Returns the string that corresponds to contentType
/// </summary>
/// <param name="contentType">Content type for browser</param>
/// <returns>String that corresponds to contentType</returns>
private string GetContentTypeString(ExcelHttpContentType contentType)
{
switch (contentType)
{
case ExcelHttpContentType.Excel97:
return "Application/x-msexcel";
case ExcelHttpContentType.Excel2000:
return "Application/vnd.ms-excel";
case ExcelHttpContentType.Excel2007:
case ExcelHttpContentType.Excel2010:
case ExcelHttpContentType.Excel2013:
case ExcelHttpContentType.Excel2016:
return "Application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
case ExcelHttpContentType.CSV:
return "text/csv";
case ExcelHttpContentType.ODS:
return "application/vnd.oasis.opendocument.spreadsheet";
default:
throw new ArgumentOutOfRangeException("contentType");
}
}
}
}
VB
Imports System
Imports System.IO
Imports Syncfusion.XlsIO
Namespace CreateSpreadsheet
Public Class _Default
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
End Sub
Protected Sub btnCreateExcel_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim excelEngine As ExcelEngine = New ExcelEngine
'Instantiate the Excel application object
Dim application As IApplication = excelEngine.Excel
'Setting default version.
application.DefaultVersion = ExcelVersion.Excel2016
'Create workbook
Dim workbook As IWorkbook = application.Workbooks.Create(1)
Dim sheet As IWorksheet = workbook.Worksheets(0)
'Adding data into worksheet
sheet(1, 1).Text = "Products"
sheet(1, 2).Text = "Qtr1"
sheet(1, 3).Text = "Qtr2"
sheet.Range("A1:C1").HorizontalAlignment = ExcelHAlign.HAlignCenter
sheet.Range("A1:C1").CellStyle.Font.Bold = True
sheet(2, 1).Text = "Alfreds Futterkiste"
sheet(2, 2).Number = 744.6
sheet(2, 3).Number = 162.56
sheet(3, 1).Text = "Antonio Moreno Taqueria"
sheet(3, 2).Number = 5079.6
sheet(3, 3).Number = 1249.2
sheet(4, 1).Text = "Around the Horn"
sheet(4, 2).Number = 1267.5
sheet(4, 3).Number = 1062.5
sheet(5, 1).Text = "Bon app"
sheet(5, 2).Number = 1418
sheet(5, 3).Number = 756
sheet(6, 1).Text = "Eastern Connection"
sheet(6, 2).Number = 4728
sheet(6, 3).Number = 4547.92
sheet(7, 1).Text = "Ernst Handel"
sheet(7, 2).Number = 943.89
sheet(7, 3).Number = 349.6
sheet.SetColumnWidth(1, 25)
sheet.SetColumnWidth(2, 12)
sheet.SetColumnWidth(3, 12)
Dim stream As MemoryStream = New MemoryStream
'Save and close the document
workbook.SaveAs(stream, ExcelSaveType.SaveAsXLS)
Me.SendStream(stream, "output.xlsx", ExcelHttpContentType.Excel2016)
End Sub
'<summary>
'Adds HttpResponse
'</summary>
'<param name="stream">Stream to generate HttpResponse</param>
'<param name="fileName">Name of the file output file</param>
'<param name="contentType">Content type to use</param>
Private Sub SendStream(ByVal stream As MemoryStream, ByVal fileName As String, ByVal contentType As ExcelHttpContentType)
Response.Clear()
Response.ContentType = Me.GetContentTypeString(contentType)
Response.AddHeader("Content-Disposition", String.Format("{0}; filename={1};", "attachment", fileName))
Response.OutputStream.Write(stream.ToArray, 0, Convert.ToInt32(stream.Length))
Response.Flush()
Response.Close()
End Sub
'<summary>
'Returns the string that corresponds to contentType
'</summary>
'<param name="contentType">Content type for browser</param>
'<returns>String that corresponds to contentType</returns>
Private Function GetContentTypeString(ByVal contentType As ExcelHttpContentType) As String
Select Case (contentType)
Case ExcelHttpContentType.Excel97
Return "Application/x-msexcel"
Case ExcelHttpContentType.Excel2000
Return "Application/vnd.ms-excel"
Case ExcelHttpContentType.Excel2007, ExcelHttpContentType.Excel2010, ExcelHttpContentType.Excel2013, ExcelHttpContentType.Excel2016
Return "Application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Case ExcelHttpContentType.CSV
Return "text/csv"
Case ExcelHttpContentType.ODS
Return "application/vnd.oasis.opendocument.spreadsheet"
Case Else
Throw New ArgumentOutOfRangeException("contentType")
End Select
End Function
End Class
End Namespace
Take a moment to peruse the documentation, where you can find basic worksheet data manipulation options along with features like Conditional Formatting, worksheet calculations through formulas, adding charts in worksheets or workbooks, organizing and analyzing data through tables and pivot tables, appending multiple records to a worksheet using template markers, and most importantly, PDF and image conversions, etc., with code examples.
Refer here to explore the rich set of Syncfusion Essential XlsIO features.
Note:
Starting with v16.2.0.x, if you reference Syncfusion assemblies from the trial setup or from the NuGet feed, include a license key in your projects. Refer to this link to learn about generating and registering a Syncfusion license key in your application to use the components without a trial message.
Conclusion:
I hope you enjoyed learning about how to overcome ThreadAbortException while saving an Excel file using the XlsIO.Base assembly.
You can refer to our XlsIO’s feature tour page to learn about its other groundbreaking features. Explore our UG documentation and online demos to understand how to manipulate data in Excel documents.
If you are an existing user, you can access our latest components from the License and Downloads page. For new users, you can try our 30-day free trial to check out XlsIO and other Syncfusion components.
If you have any queries or require clarification, please let us know in the comments below or contact us through our support forums or feedback portal. We are always happy to assist you!