I am attempting to export a datagrid to excel via a popup. I am able to successfully export to excel when removing the code from my application, however, when attempting to export to excel using the exact same code within my application, I receive the following errors:
From my try/catch:
Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.
...and from the console:
Error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed.
My server-side code is as follows:
protected void btnExportToExcel_Click(object sender, EventArgs e)
{
ExportDataSetToExcel();
}
private void ExportDataSetToExcel()
{
try
{
DataTable dt = new DataTable("GridView_Data");
foreach (TableCell cell in gvPatientRoster.HeaderRow.Cells)
{
dt.Columns.Add(cell.Text);
}
foreach (GridViewRow row in gvPatientRoster.Rows)
{
dt.Rows.Add();
for (int i = 0; i < row.Cells.Count; i++)
{
dt.Rows[dt.Rows.Count - 1][i] = row.Cells[i].Text;
}
}
if (dt != null && dt.Rows.Count > 0)
{
Response.ContentType = "application/vnd.ms-excel";
Response.AppendHeader("Content-Disposition",
string.Format("attachment; filename=PatientRoster.xls"));
System.IO.StringWriter tw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter hw =
new System.Web.UI.HtmlTextWriter(tw);
DataGrid dgGrid = new DataGrid();
dgGrid.DataSource = dt;
//Report Header
hw.WriteLine("<b><u><font size='5'>" +
"Patient Roster</font></u></b>");
hw.WriteLine("<br><br>");
//hw.Write(BuildCriteriaString());
hw.WriteLine("<br>");
// Get the HTML for the control.
dgGrid.HeaderStyle.Font.Bold = true;
dgGrid.DataBind();
dgGrid.RenderControl(hw);
// Write the HTML back to the browser.
this.EnableViewState = false;
Response.Write(tw.ToString());
Response.End();
}
}
catch (Exception ex)
{
lblErrorMessage.Text = ex.Message;
}
}
I added the following to the PageLoad() and the export now works:
ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
scriptManager.RegisterPostBackControl(this.btnExportToExcel);
It looks like the UpdatePanel and ScriptManager were elements that I overlooked. When I separated the functionality from the main application, I did not include all HTML that was in the main application. Since the ScriptManager and UpdatePanel were not part of the isolated functionality, it worked properly. I will be sure to post the HTML next time
This was a solution from the following post:
Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed
I would suggest using one of the many good, free C# "Export to Excel" libraries out there.
You've already written the code to read your DataView into a DataTable, and once it's in this format, using the following free C# library...
ExportToExcel library
...you'd be able to export the data into a "real" Excel 2007 file in one line of code....
// Export the DataTable into an Excel file, and write it to the web Response
CreateExcelFile.CreateExcelDocument(dt, "SomeFilename.xlsx", Response);
Okay, okay, two lines of code. I added a comment.
But you get the point !
Related
Okay, so i have an excel file (.xlsx) which will be downloaded when user clicks a button. The file is stored in a folder and will be processed by adding data validation and such before sending it to user. In my case i'm only adding dropdowns which will be filled from another sheet.
Here is my code that generates the file:
public IActionResult DownloadTemplateExcelFile(string type)
{
string fullFilePath = "../TemplateFiles/";
string fileName = "";
if (type != "")
{
fileName = type + ".xlsx";
fullFilePath += fileName;
}
var fileData = ExcelHelper.CreateExcelFile(type, fullFilePath);
return this.File(fileData, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",fileName);
}
And this code below is the file processing:
public static class ExcelHelper{
public static byte[] CreateExcelFile(string type, string fullFilePath){
using (var package = new ExcelPackage(new FileInfo(fullFilePath))){
// Getting list of values and set it for dropdown values
// List<string> dropdown1 = .. list string is loaded from database
ExcelWorksheet sheetDropdown1 = package.Workbook.Worksheets.Add("Dropdowns1");
var mainSheet= package.Workbook.Worksheets["Sheet1"];
sheetDropdown1.Cells["A1"].LoadFromCollection(dropdown1);
var dropdown1Addr = mainSheet.Cells[3,5,300,5].Address;
var dropdown1Formula = "='Dropdowns1'!$A:$A";
var validation = mainSheet.DataValidations.AddListValidation(dropdown1Addr);
validation.ShowErrorMessage = true;
validation.ErrorStyle = OfficeOpenXml.DataValidation.ExcelDataValidationWarningStyle.stop;
validation.ErrorTitle = "An invalid value was entered";
validation.Error = "Select a value from the list";
validation.AllowBlank = true;
validation.Formula.ExcelFormula = dropdown1Formula;
validation.Validate();
var excelFile = package.GetAsByteArray();
package.Dispose();
return excelFile;
}
}
}
When i opened the file in Excel 2010+ it worked just fine, the dropdown is loaded nicely and the cells in which the data validation is applied is working. However in excel 2007 when i tried to open it showed an error need to repair if i want to open it in 2007. If i do so however, the dropdown function is lost and unusable.
I've racked my brain but still haven't found any solution yet. How can i "Fix" this? I'm using EPPlus 6 for reference.
Like the title says. Lots of examples online for uploading files to backend but I'm after verification client side/offline followed by an upload of data only (no files). In theory, anything that runs on .Net5 should be able to run in WASM at a close performance. I'm trying to unload those hefty operations to clients' machines.
I've had some success with ClosedXML but when the file is a few 1000 rows it becomes incredibly slow. Using ClosedXML in Blazor Server-Side loads 100,000's rows with ease.
Notes:
Using MudBlazor UI Components
I have a stream from file instead of a file path for ClosedXML (like I would on a console app), I think this is the only way in WASM but I may be wrong.
I've ran the same in NPOI with similar results (slow in WASM, fast in Server Side).
I'd prefer to avoid EPPlus unless it has a magical fix.
Page:
#page "/upload"
#inject HttpClient Http
<h1>Upload Data</h1>
<p>This component demonstrates uploading data from Excel.</p>
<InputFile id="fileInput" OnChange="UploadFiles" hidden single />
<MudButton HtmlTag="label"
Variant="Variant.Filled"
Color="Color.Primary"
StartIcon="#Icons.Filled.CloudUpload"
for="fileInput">
Upload Files
</MudButton>
#if (dataTable == null)
{
<p><em>Please upload Excel File</em></p>
}
else
{
<MudTable Items="#dataTable.AsEnumerable().Take(500)" Hover="true" Breakpoint="Breakpoint.Sm" T="DataRow" RowsPerPage="100">
<HeaderContent>
#foreach (DataColumn col in dataTable.Columns)
{
<MudTh>#col.ColumnName</MudTh>
}
</HeaderContent>
<RowTemplate>
#foreach (var cell in context.ItemArray)
{
<MudTd>#cell.ToString()</MudTd>
}
</RowTemplate>
</MudTable>
}
#code {
//private IList<IBrowserFile> files = new List<IBrowserFile>();
private DataTable dataTable;
protected override async Task OnInitializedAsync()
{
}
private async Task UploadFiles(InputFileChangeEventArgs e)
{
dataTable = await ExcelHelper.GetDataTableFromExcel(e.File);
}
}
Function:
public static async Task<DataTable> GetDataTableFromExcel(IBrowserFile file)
{
DataTable dtTable = new DataTable();
using (MemoryStream memStream = new MemoryStream())
{
await file.OpenReadStream(file.Size).CopyToAsync(memStream);
using (XLWorkbook workBook = new XLWorkbook(memStream, XLEventTracking.Disabled))
{
//Read the first Sheet from Excel file.
IXLWorksheet workSheet = workBook.Worksheet(1);
//Loop through the Worksheet rows.
bool firstRow = true;
foreach (IXLRow row in workSheet.Rows())
{
//Use the first row to add columns to DataTable.
if (firstRow)
{
foreach (IXLCell cell in row.Cells())
{
dtTable.Columns.Add(cell.Value.ToString());
}
firstRow = false;
}
else
{
//Add rows to DataTable.
dtTable.Rows.Add();
int i = 0;
foreach (IXLCell cell in row.Cells(row.FirstCellUsed().Address.ColumnNumber, row.LastCellUsed().Address.ColumnNumber))
{
dtTable.Rows[dtTable.Rows.Count - 1][i] = cell.Value.ToString();
i++;
}
}
}
}
}
return dtTable;
}
The line causing the delay is:
using (XLWorkbook workBook = new XLWorkbook(memStream, XLEventTracking.Disabled))
I need help fixing the slow reading of the xlsx file, or a completely different approach if there's a better way! A better way achieving this goal, no cheating/uploading files to the server :)
I am working n exporting excel using Aspose.Cells. In that i need to show some HTML formatted comment in specific column. But when i set note in comment using HTML string then it automatically modify that HTML. I am usiing below code
Workbook workbook = GetExcelWorkbook<AuditLogExport>(auditLogExportData, templatePath);
CommentCollection comments = workbook.Worksheets[0].Comments;
for (int i = 0; i < exportData.Count; i++)
{
if (exportData[i].IsDetailedChange)
{
int commentIndex = comments.Add(string.Format("E{0}", (i + 2)));
Aspose.Cells.Comment comment = comments[commentIndex];
**comment.HtmlNote = GetAuditLogCommentNote(exportData[i]);**
comment.WidthCM = 8.0;
comment.HeightCM = 20.0;
}
}
public static string GetAuditLogCommentNote(AuditLog auditLog)
{
string note = string.Empty;
note = "<table width='400px' style='border:solid 1px black'><tr><th>Changed Field</th><th>Previous</th><th>Current</th></tr>";
foreach (var history in auditLog.DetailChanges)
{
note += string.Format("<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>", history.FieldName, history.FirstChange, history.LastChange);
}
note += "</table>";
return note;
}
When i am assigning value to HtmlNote property of comment it automatically change html with font tags and strip all table tags from string. Can someone please help on this?
Update-1
Well, we think, your requirement is not achievable using Microsoft Excel. If something is not possible with Microsoft Excel, then it will also not be possible with Aspose.Cells or any other API automatically.
Please see the following screenshot. It shows how your HTML looks like when it is viewed in Web Browser and when it is copied/pasted to Excel comment.
If you think, your requirement is doable using Microsoft Excel, please provide us your sample Excel file that you have created manually using Microsoft Excel. We will check it and investigate this issue further.
Update-2
We tested this issue with the following code and found that if we try to create comment with HtmlNote property, it does not work.
We have logged this issue in our database for investigation and for a fix. Once, the issue is resolved, we will update you in this post.
This issue has been logged as
CELLSNET-46210 - Creating Comment using HtmlNote property does not work
C#
Workbook wb = new Workbook();
Worksheet ws = wb.Worksheets[0];
int idx = ws.Comments.Add("E4");
Comment cm = ws.Comments[idx];
//cm.HtmlNote = "<Font Style=\"FONT-WEIGHT: bold;FONT-FAMILY: Tahoma;FONT-SIZE: 9pt;COLOR: #000000;TEXT-ALIGN: left;\">Heading: </Font><Font Style=\"FONT-FAMILY: Tahoma;FONT-SIZE: 9pt;COLOR: #000000;TEXT-ALIGN: left;\">This is some para. </Font><Font Style=\"FONT-WEIGHT: bold;FONT-FAMILY: Tahoma;FONT-SIZE: 9pt;COLOR: #000000;TEXT-ALIGN: left;\">Heading2:</Font><Font Style=\"FONT-FAMILY: Tahoma;FONT-SIZE: 9pt;COLOR: #000000;TEXT-ALIGN: left;\"> This is some para2.</Font>";
cm.HtmlNote = new Workbook("input.xlsx").Worksheets[0].Comments[0].HtmlNote;
cm.IsVisible = true;
wb.Save("output.xlsx");
Update-3
Your issue logged as CELLSNET-46210 has been fixed in Aspose.Cells for .NET v18.7. Please download it from this link.
https://www.nuget.org/packages/Aspose.Cells/18.7.0
Note: I am working as Developer Advocate at Aspose
I have a really frustrating issue where whenever I call
RefreshAll() from Microsoft.Interop.Excel it does not refresh the data when I open the workbook in excel and I have to manually click the refresh all button within excel... I have even tried calling refresh all via vba and it still does not refresh the data... I am always prompted with:
"The PivotTable report was saved without underlying data. Use the
Refresh Data command to update the report."
Despite the fact that I already called the "Refresh all command."
public void applyMacro(string excelFile)
{
var excelApplication = new Microsoft.Office.Interop.Excel.Application { Visible = false };
var targetExcelFile = excelApplication.Workbooks.Open(excelFile);
try
{
string[] macros = addMacros(ref targetExcelFile);
for (int i = 0; i < 2; i++)
excelApplication.Run(macros[i]);
targetExcelFile.RefreshAll();
targetExcelFile.Save();
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadKey();
}
finally
{
excelApplication.Quit();
}
}
and in vba have tried adding the following before calling the refresh:
For Each ws In Worksheets
For Each qt In ws.QueryTables
qt.Refresh BackGroundQuery:=False
next qt
Next ws
Any ideas??
You can use this on your pivot table :
YourPivotTable.PivotCache().RefreshOnFileOpen = true;
YourPivotTable.SaveData = true;
I have an UpdatePanel with a dynamically created table and I am trying to use the save stream as excel function of EPPlus. However I keep getting an error when I call my SaveToExcel() method.
The method works fine if I have it in an empty website so I believe it has something to do with the postback/UpdatePanel.
The error:
Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed.
The code causing the error from the [dynamic]:
function Sys$WebForms$PageRequestManager$_endPostBack(error, executor, data) {
if (this._request === executor.get_webRequest()) {
this._processingRequest = false;
this._additionalInput = null;
this._request = null;
}
var handler = this._get_eventHandlerList().getHandler("endRequest");
var errorHandled = false;
if (handler) {
var eventArgs = new Sys.WebForms.EndRequestEventArgs(error, data ? data.dataItems : {}, executor);
handler(this, eventArgs);
errorHandled = eventArgs.get_errorHandled();
}
if (error && !errorHandled) {
throw error;
}
}
This is how i end my SaveToExcel() method:
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=Bulk Swap HDDs.xlsx");
package.SaveAs(Response.OutputStream);
Response.End();
Is there something really obvious I'm missing? If I place the SaveToExcel into another aspx page and just do a PostBackUrl="~/SaveToExcel.aspx", it also works fine (but then my submit button crashes).