错误信息:
原因分析:
解决方法:
如果是开发者可以看代码:
/// <summary>
/// 释放资源
/// </summary>
/// <param name="o"></param>
private void NAR(object o)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
o = null;
}
}
/// <summary>
/// 将数据集中的数据导出到EXCEL文件
/// </summary>
/// <param name="context">Http请求</param>
/// <param name="ds">需要导出的Dataset</param>
/// <param name="DownloadFilePath">导出文件的文件名</param>
public void ExportExcel(HttpContext context, DataSet ds, string DownloadFilePath)
{
object objOpt = Missing.Value;
Application excel = new Application();
excel.Visible = false;
excel.DisplayAlerts = false;
Workbook wkb = excel.Workbooks.Add(objOpt);
Worksheet wks = (Worksheet)wkb.ActiveSheet;
wks.Visible = XlSheetVisibility.xlSheetVisible;
int rowIndex = 1;
int colIndex = 0;
// DataTable table = ds.Tables[0];
foreach (DataColumn col in ds.Tables[0].Columns)
{
colIndex++;
excel.Cells[1, colIndex] = col.ColumnName;
}
foreach (DataRow row in ds.Tables[0].Rows)
{
rowIndex++;
colIndex = 0;
foreach (DataColumn col in ds.Tables[0].Columns)
{
colIndex++;
excel.Cells[rowIndex, colIndex] = row[col.ColumnName].ToString();
}
}
if (!File.Exists(DownloadFilePath))
{
string fileName = Path.GetFileName(DownloadFilePath);
FileStream fs = new FileStream(fileName, FileMode.Create);
fs.Close();
fs.Dispose();
}
//将导出的excel文件先保存到服务器本地
wkb.SaveAs(DownloadFilePath, XlFileFormat.xlWorkbookNormal, null, null, false, false, XlSaveAsAccessMode.xlNoChange, null, null, null, null, null);
NAR(wks);
wkb.Close(false, objOpt, objOpt);
NAR(wkb);
excel.Quit();
NAR(excel);
//上面这几个操作 释放资源
//下载excel文件
if (File.Exists(DownloadFilePath))
{
using (FileStream fs = new FileStream(DownloadFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
const int size = 4096;
byte[] buffer = new byte[size];
int pos = 0;
long dataToRead = fs.Length;
long arrange = 0;
if (context.Request.Headers["Range"] != null)
{
context.Response.StatusCode = 206;
arrange = long.Parse(context.Request.Headers["Range"].Replace("bytes=", "").Replace("-", ""));
}
if (arrange != 0)
{
context.Response.AddHeader("Content-Range", "bytes " + arrange.ToString() + "-" + ((long)(dataToRead - 1)).ToString() + "/" + dataToRead.ToString());
}
context.Response.AddHeader("Content-Length", ((long)(dataToRead - arrange)).ToString());
//context.Response.ContentType = "application/octet-stream";
context.Response.ContentType = "application/ms-excel";
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + System.Web.HttpUtility.UrlEncode(System.Text.Encoding.GetEncoding(65001).GetBytes(Path.GetFileName(DownloadFilePath))));
fs.Position = arrange;
dataToRead = dataToRead - arrange;
while (dataToRead > 0)
{
if (context.Response.IsClientConnected)
{
pos = fs.Read(buffer, 0, size);
context.Response.OutputStream.Write(buffer, 0, pos);
context.Response.Flush();
dataToRead = dataToRead - pos;
}
else
{
dataToRead = -1;
}
}
}
}
}
部署到服务器上可能存在的问题:
方法一:
||、如果有”Microsoft Excel应用程序”
运行dcomcnfg打开组件服务。
依次展开”组件服务”->”计算机”->”我的电脑”->”DCOM配置”。
找到”Microsoft Excel应用程序”。
右键打开属性对话框,点击”安全”选项卡,把”启动和激活权限”、”配置权限”都选择为自定义,然后依次点击它们的编辑,把当前用户添加进去,并加入所有的权限。
|||、如果找不到”Microsoft Excel应用程序”时可以从其他电脑的注册表中复制。
1. 在运行中输入:regedit,进入注册表编辑器,查看HKEY_LOCAL_MACHINE\Software\Microsoft\Office下是否有excel、word等其他的注册表,若没有进行第二步。
2. 查看HKEY_CLASSES_ROOT\AppID\下是否有{00020812-0000-0000-C000-000000000046},这个是excel注册键,若没有则DCOM配置是找不到Microsoft Excel Appliction的。(这个取决于每个人系统,有些安装office之后马上就会显示有这个键,但是有些机子没有显示,至于为什么我也没搞清楚。)
3. 手动导出该键:
我所使用解决办法是:在另一台已安装相同版本的office的win8 64位机上找到HKEY_CLASSES_ROOT\AppID\下是否有{00020812-0000-0000-C000-000000000046},如下图:
右击,点击“导出”,生成.reg后缀名的文件后,再将其复制到自己的电脑上(即要进行DCOM配置找不到Microsoft Excel Appliction的电脑上),最后双击此注册文件,自动导入注册表中了。
再去HKEY_CLASSES_ROOT\AppID\下查看,这时就会有{00020812-0000-0000-C000-000000000046}了。
4.最后,输入MMC -32:文件——>添加/删除单元管理——>选择最后一个即组件服务——>添加——>确定——>双击组件服务——>计算机——>我的电脑——>DCOM配置,这时会发现能找到Microsoft Excel Appliction。
方法二:
一、服务器上没有装office
在服务器上装了一个2003精简版也可以, 我开发是用的2007。
二、 "80080005异常"
"80080005异常"是应用程序对COM组件操作权限不足引起的。于是有了下面的操作:
1)控制面板->管理工具->组件服务->计算机->我的电脑->DCOM-> Microsoft Excel 应用程序
2)单击属性打开此应用程序的属性对话框。
3) 单击标识选项卡,然后选择交互式用户。
4) 单击默认安全性选项卡。设置当前服务器与ASP.NET相关的用户的访问权限。
5)单击启动权限的编辑默认值。设置ASP.NET相关的用户的访问权限。
6)主要是network service账户
三、 检索COM类工厂中CLSID的组件时失败80070005
跟前面的方法差不多 具体配置方法如下:
1:在服务器上安装office的Excel软件.
2:在"开始"->"运行"中输入dcomcnfg.exe启动"组件服务"
3:依次双击"组件服务"->"计算机"->"我的电脑"->"DCOM配置"
4:在"DCOM配置"中找到"Microsoft Excel 应用程序",在它上面点击右键,然后点击"属性",弹出"Microsoft Excel 应用程序属性"对话框
5:点击"标识"标签,选择"交互式用户"
6:点击"安全"标签,在"启动和激活权限"上点击"自定义",然后点击对应的"编辑"按钮,在弹出的"安全性"对话框中填加一个"NETWORK SERVICE"用户(注意要选择本计算机 名),并给它赋予"本地启动"和"本地激活"权限.
7:依然是"安全"标签,在"访问权限"上点击"自定义",然后点击"编辑",在弹出的"安全性"对话框中也填加一个"NETWORK SERVICE"用户,然后赋予"本地访问"权限.
8.如果交互式用户设置后出现错误8000401a,可取消交互式用户,指定为administratr,可暂时解决此问题。进一步的解决方式还有待探讨。
另外说明:光按以上设置并不能完全保证不出问题,因为调用OFFICE的操作可能涉及其他的系统资源,很可能依然权限不够而导致问题,只是设置EXCEL应用程序后,还是可能会报80070005的错误,最保险的是应该在dcomcnfg中选中我的电脑然后右键属性->com安全,将里面的访问权限,启动和激活权限全都编辑默认,在当中加上network service(iis 5.0的话,要加的是asp.net用户),并如前面对networkservice设置上相同的权限,这样基本上能保证不会再出什么问题。
四、"异常来自 HRESULT:0x800A03EC "的原因
两种情况,1、Excel的行列都是从1开始的,如果我们习惯性的给worksheet.Cells[0, 0]或者worksheet.Cells[1, 0]或者worksheet.Cells[0, 1]赋值,就会引发该异常。
2、这里容易出错
“excel.ActiveWorkbook.SaveAs(FilePath + filename, Excel.XlFileFormat.xlExcel7, null, null, false, false, Excel.XlSaveAsAccessMode.xlNoChange, null, null, null, null, null);”
在上面代码保存的时候,格式很重要,每个版本的值都有所不同,最开始我在2007上另存成2003版本得到的是56(也就是xlExcel8),然而真正在代码中却是39(也就是xlExcel7)
如果这里不能确定excel版本,请选择xlWorkbookNormal来替代xlExcel?等。