我将在ASP.NET应用程序(VB.NET代码隐藏)中添加一个部分,允许用户将数据作为Excel文件返回给它们,我将根据数据库数据生成该文件.虽然有几种方法可以做到这一点,但每种方法都有其自身的缺点.将如何您返回的数据?我正在寻找尽可能干净和简单的东西.
优点:
简单
缺点:
它可能无法在其他语言环境或不同的Excel配置(即列表分隔符)中工作
无法应用格式,公式等
优点:
还是很简单
支持简单的格式化和公式化
缺点:
您必须将文件命名为xls,Excel可能会警告您打开非本机Excel文件
每个工作簿一个工作表
优点:
原生Excel格式
支持所有Excel功能
不要需要一个安装的Excel拷贝
可以生成数据透视表
可以使用开源项目EPPlus生成
缺点:
Excel 2007之外的兼容性有限(现在应该不是问题)
除非您使用的是第三方组件,否则很复杂
优点:
与原生Excel格式相比较简单
支持大多数Excel功能:格式化,样式,公式,每个工作簿多个工作表
不需要安装Excel即可使用它
不需要第三方库 - 只需写出你的xml
可以通过Excel XP/2003/2007打开文档
缺点:
缺乏良好的文档
旧版Excel(2000年以前版本)不支持
只写,一旦打开它并从Excel进行更改,它就会转换为本机Excel.
优点:
使用所有格式化,公式等生成本机Excel文件.
缺点:
花钱
添加依赖项
优点:
使用本机Microsoft库
阅读对本机文档的支持
缺点:
非常慢
依赖/版本匹配问题
读取时Web使用的并发/数据完整性问题
非常慢
扩展Web使用的问题(与并发性不同):需要在服务器上创建大量Excel应用程序的实例
需要Windows
我提到它很慢吗?
您可以将数据输出为html表格单元格,在其上粘贴.xls
或.xlsx
扩展,Excel将打开它,就像它是本机文档一样.您甚至可以通过这种方式进行有限的格式化和公式计算,因此它比CSV更强大.此外,从ASP.Net等网络平台输出html表应该很容易;)
如果在Excel工作簿中需要多个工作表或命名工作表,则可以通过调用的XML模式执行类似的操作SpreadSheetML
.这不是 Office 2007附带的新格式,而是与Excel 2000一样完全不同的东西.解释其工作原理的最简单方法是使用示例:
Your_name_here Your_name_here 20080625 ABC Inc 10.2625 6135 8445 240 120 False False
|
1 | 2 | |
3 | 4 | |
5 | 6 | |
7 | 8 |
|
A | B | |
C | D | |
E | F | |
G | H |
如果来自DataTable:
public static void DataTabletoXLS(DataTable DT, string fileName)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Charset = "utf-16";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
HttpContext.Current.Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.xls", fileName));
HttpContext.Current.Response.ContentType = "application/ms-excel";
string tab = "";
foreach (DataColumn dc in DT.Columns)
{
HttpContext.Current.Response.Write(tab + dc.ColumnName.Replace("\n", "").Replace("\t", ""));
tab = "\t";
}
HttpContext.Current.Response.Write("\n");
int i;
foreach (DataRow dr in DT.Rows)
{
tab = "";
for (i = 0; i < DT.Columns.Count; i++)
{
HttpContext.Current.Response.Write(tab + dr[i].ToString().Replace("\n", "").Replace("\t", ""));
tab = "\t";
}
HttpContext.Current.Response.Write("\n");
}
HttpContext.Current.Response.End();
}
从Gridview:
public static void GridviewtoXLS(GridView gv, string fileName)
{
int DirtyBit = 0;
int PageSize = 0;
if (gv.AllowPaging == true)
{
DirtyBit = 1;
PageSize = gv.PageSize;
gv.AllowPaging = false;
gv.DataBind();
}
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Charset = "utf-8";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
HttpContext.Current.Response.AddHeader(
"content-disposition", string.Format("attachment; filename={0}.xls", fileName));
HttpContext.Current.Response.ContentType = "application/ms-excel";
using (StringWriter sw = new StringWriter())
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// Create a table to contain the grid
Table table = new Table();
// include the gridline settings
table.GridLines = gv.GridLines;
// add the header row to the table
if (gv.HeaderRow != null)
{
Utilities.Export.PrepareControlForExport(gv.HeaderRow);
table.Rows.Add(gv.HeaderRow);
}
// add each of the data rows to the table
foreach (GridViewRow row in gv.Rows)
{
Utilities.Export.PrepareControlForExport(row);
table.Rows.Add(row);
}
// add the footer row to the table
if (gv.FooterRow != null)
{
Utilities.Export.PrepareControlForExport(gv.FooterRow);
table.Rows.Add(gv.FooterRow);
}
// render the table into the htmlwriter
table.RenderControl(htw);
// render the htmlwriter into the response
HttpContext.Current.Response.Write(sw.ToString().Replace("£", ""));
HttpContext.Current.Response.End();
}
if (DirtyBit == 1)
{
gv.PageSize = PageSize;
gv.AllowPaging = true;
gv.DataBind();
}
}
private static void PrepareControlForExport(Control control)
{
for (int i = 0; i < control.Controls.Count; i++)
{
Control current = control.Controls[i];
if (current is LinkButton)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as LinkButton).Text));
}
else if (current is ImageButton)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as ImageButton).AlternateText));
}
else if (current is HyperLink)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as HyperLink).Text));
}
else if (current is DropDownList)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as DropDownList).SelectedItem.Text));
}
else if (current is CheckBox)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as CheckBox).Checked ? "True" : "False"));
}
if (current.HasControls())
{
Utilities.Export.PrepareControlForExport(current);
}
}
}
这是一个围绕SpreadML的免费包装器 - 它运行良好.
http://www.carlosag.net/Tools/ExcelXmlWriter/
根据给出的答案以及与同事的协商,最佳解决方案似乎是生成XML文件或HTML表格并将其作为附件下推.我的同事推荐的一个改变是数据(即HTML表)可以直接写入Response对象,因此无需写出文件,由于权限问题,I/O可能会很麻烦争用,并确保发生计划的清除.
这是代码的片段......我还没有检查过这个,我还没有提供所有被调用的代码,但我认为它代表了这个想法.
Dim uiTable As HtmlTable = GetUiTable(groupedSumData) Response.Clear() Response.ContentType = "application/vnd.ms-excel" Response.AddHeader("Content-Disposition", String.Format("inline; filename=OSSummery{0:ddmmssf}.xls", DateTime.Now)) Dim writer As New System.IO.StringWriter() Dim htmlWriter As New HtmlTextWriter(writer) uiTable.RenderControl(htmlWriter) Response.Write(writer.ToString) Response.End()