我创建了一个报告工具作为内部 Web 应用程序的一部分。该报告在 GridView 中显示所有结果,我使用 JavaScript 将 GridView 的内容逐行读取到 Excel 对象中。JavaScript 继续在不同的工作表上创建数据透视表。
不幸的是,我没想到如果返回超过几天,GridView 的大小会导致浏览器出现过载问题。该应用程序每天有几千条记录,假设每月 60k,理想情况下,我希望能够返回长达一年的所有结果。行数导致浏览器挂起或崩溃。
我们在带有 SQL Server 的 Visual Studio 2010 上使用 ASP.NET 3.5,预期的浏览器是 IE8。该报告由一个网格视图组成,该视图根据用户选择的人群从少数几个存储过程中的一个中获取数据。网格视图位于更新面板中:
<asp:UpdatePanel ID="update_ResultSet" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btn_Submit" />
</Triggers>
<ContentTemplate>
<asp:Panel ID="pnl_ResultSet" runat="server" Visible="False">
<div runat="server" id="div_ResultSummary">
<p>This Summary Section is Automatically Completed from Code-Behind</p>
</div>
<asp:GridView ID="gv_Results" runat="server"
HeaderStyle-BackColor="LightSkyBlue"
AlternatingRowStyle-BackColor="LightCyan"
Width="100%">
</asp:GridView>
</div>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
我对我的团队来说相对较新,所以我遵循他们将存储过程返回到 DataTable 并将其用作后面代码中的 DataSource 的典型做法:
List<USP_Report_AreaResult> areaResults = new List<USP_Report_AreaResult>();
areaResults = db.USP_Report_Area(ddl_Line.Text, ddl_Unit.Text, ddl_Status.Text, ddl_Type.Text, ddl_Subject.Text, minDate, maxDate).ToList();
dtResults = Common.LINQToDataTable(areaResults);
if (dtResults.Rows.Count > 0)
{
PopulateSummary(ref dtResults);
gv_Results.DataSource = dtResults;
gv_Results.DataBind();
(我知道你在想什么!但是,是的,从那以后我学到了更多关于参数化的知识。)
LINQToDataTable 函数没有什么特别之处,只是将列表转换为数据表。
有几千条记录(最多几天),这很好用。GridView 显示结果,并且有一个按钮供用户单击以启动 JScript 导出器。外部 JavaScript 函数将每一行读入 Excel 工作表,然后使用它来创建数据透视表。数据透视表很重要!
function exportToExcel(sMyGridViewName, sTitleOfReport, sHiddenCols) {
//sMyGridViewName = the name of the grid view, supplied as a text
//sTitleOfReport = Will be used as the page header if the spreadsheet is printed
//sHiddenCols = The columns you want hidden when sent to Excel, separated by semicolon (i.e. 1;3;5).
// Supply an empty string if all columns are visible.
var oMyGridView = document.getElementById(sMyGridViewName);
//If no data is on the GridView, display alert.
if (oMyGridView == null)
alert('No data for report');
else {
var oHid = sHiddenCols.split(";"); //Contains an array of columns to hide, based on the sHiddenCols function parameter
var oExcel = new ActiveXObject("Excel.Application");
var oBook = oExcel.Workbooks.Add;
var oSheet = oBook.Worksheets(1);
var iRow = 0;
for (var y = 0; y < oMyGridView.rows.length; y++)
//Export all non-hidden rows of the HTML table to excel.
{
if (oMyGridView.rows[y].style.display == '') {
var iCol = 0;
for (var x = 0; x < oMyGridView.rows(y).cells.length; x++) {
var bHid = false;
for (iHidCol = 0; iHidCol < oHid.length; iHidCol++) {
if (oHid[iHidCol].length !=0 && oHid[iHidCol] == x) {
bHid = true;
break;
}
}
if (!bHid) {
oSheet.Cells(iRow + 1, iCol + 1) = oMyGridView.rows(y).cells(x).innerText;
iCol++;
}
}
iRow++;
}
}
我正在尝试做的事情:创建一个可以处理这些数据并将其处理到 Excel 中的解决方案(可能是客户端)。有人可能会建议使用HtmlTextWriter,但是 afaik 不允许自动生成数据透视表并创建令人讨厌的弹出警告......
我试过的:
- 填充 JSON 对象——我仍然认为这有潜力,但我还没有找到让它工作的方法。
- 使用 SQLDataSource - 我似乎无法使用它来获取任何数据。
- 分页和循环浏览页面——混合进度。虽然一般来说很难看,但我仍然有一个问题,即为每个显示的页面查询并返回整个数据集。
更新: 我仍然对替代解决方案持开放态度,但我一直在追求 JSON 理论。我有一个可以从 DataTable 生成 JSON 对象的有效服务器端方法。我不知道如何将该 JSON 传递到(外部)exportToExcel JavaScript 函数中......
protected static string ConstructReportJSON(ref DataTable dtResults)
{
StringBuilder sb = new StringBuilder();
sb.Append("var sJSON = [");
for (int r = 0; r < dtResults.Rows.Count; r++)
{
sb.Append("{");
for (int c = 0; c < dtResults.Columns.Count; c++)
{
sb.AppendFormat("\"{0}\":\"{1}\",", dtResults.Columns[c].ColumnName, dtResults.Rows[r][c].ToString());
}
sb.Remove(sb.Length - 1, 1); //Truncate the trailing comma
sb.Append("},");
}
sb.Remove(sb.Length - 1, 1);
sb.Append("];");
return sb.ToString();
}
任何人都可以展示如何将此 JSON 对象携带到外部 JS 函数中的示例吗?或用于导出到 Excel 的任何其他解决方案。