由于项目需要导出excel,网上文章一大把,只参考了一部分,但部署到服务器才发现,问题很多!
导出和下载关键代码!(WebExcel.ashx.cs)
private
void
NAR(
object
o)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
}
catch
(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
o
=
null
;
}
}
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();
}
}
//
excel.Sheets[0] = "sss";
wkb.SaveAs(DownloadFilePath, Microsoft.Office.Interop.Excel.XlFileFormat.xlExcel7,
null
,
null
,
false
,
false
, XlSaveAsAccessMode.xlNoChange,
null
,
null
,
null
,
null
,
null
);
NAR(wks);
wkb.Close(
false
, objOpt, objOpt);
NAR(wkb);
excel.Quit();
NAR(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
;
}
}
}
}
}
针对以下问题,作下回顾
一、服务器上没有装office
如果要用MS的,这个问题基本不用考虑,只有安装才能解决,没有其它办法! (即使有牛人弄出来 了,估计也是给自己找麻烦)
不过,我只在服务器上装了一个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)