分享帖:使用Excel COM组件导出数据后释放Excel资源有个老项目是用VS2003做的,下面是导出数据代码Response.
分享帖:使用Excel COM组件导出数据后释放Excel资源 有个老项目是用VS2003做的, 下面是导出数据代码
Response.ContentType = "application/x-msexcel"; Response.ContentEncoding = System.Text.Encoding.Default; Response.AddHeader("content-disposition","attachment; filename=PhoneModelColor.xls"); DataTable dt = (DataTable)Session["Color"]; StringBuilder sb = new StringBuilder(); sb.Append("<META Http-Equiv='Content-Type' Content='text/html; charset=gb2312'>"); sb.Append("<table border='1'>"); sb.Append("<tr><td>Phone Model</td><td>Color Code</td><td>Chinese</td><td>English</td><td>Description</td></tr>"); for(int i=0;i<dt.Rows.Count;i++) { sb.Append("<tr>"); sb.Append("<td>"+dt.Rows[i]["Name"].ToString()+"</td>"); sb.Append("<td>"+"'"+dt.Rows[i]["Color_Code"].ToString()+"</td>"); sb.Append("<td>"+dt.Rows[i]["NameCh"].ToString()+"</td>"); sb.Append("<td>"+dt.Rows[i]["NameEng"].ToString()+"</td>"); sb.Append("<td>"+dt.Rows[i]["Desc"].ToString()+"</td>"); sb.Append("</tr>"); } sb.Append("</table>"); Response.Write(sb.ToString()); Response.End();由于客户全部将OFFICE升级成2007
上面方法导出的EXCEL出现很多问题。
导出EXCEL控件也有很多,我现在是想说说使用 Microsoft.Office.Interop.Excel.dll 出现的一个大问题:Excel释放(关闭Excel进程)
在网上搜索相关的信息基本上就是2种解决方法。
1,强制垃圾回收。
使用GC.Collect();强制垃圾回收。但是效果不明显,有时候根本不起作用。
2,杀掉Excel进程。
执行完EXCEL然后杀掉进程,虽然这100%能杀掉,但是用户需要权限,还得修改服务器的设置(BS网站很难实现)。再说容易误删,这样做是有效果,但是很危险。
到底是为什么无法释放Excel呢?
最后发现一篇MSDN上文章:http://support.microsoft.com/kb/317109
大家可以看看!
文章的意思是创建的每个对象都得释放掉,Excel进程才会关闭。
如果你写的代码导出Excel老是无法关闭Excel,可以看看我下面的代码。
private void ExportExcel(DataTable dt, string _strTitle) { string newpath = Server.MapPath(".") + @"" + Guid.NewGuid() + ".xls"; _excel.Application app = new _excel.Application(); _excel.Workbooks wbooks = app.Workbooks; _excel.Workbook wbook = wbooks.Add(System.Reflection.Missing.Value); //VS2003中最好不要如下创建 // _excel.Workbook wbook = app.Workbooks.Add(System.Reflection.Missing.Value); _excel.Worksheet tsheet = (_excel.Worksheet)wbook.ActiveSheet; //为 tsheet.Cells 创建 Range ,方便释放资源 _excel.Range rans = (_excel.Range)tsheet.Cells; //创建ran为了下面赋值时候使用 _excel.Range ran = null; for (int i = 0; i < dt.Rows.Count; i++) { for (int j = 0; j < dt.Columns.Count; j++) { ran = (_excel.Range)rans[i + 1, j + 1]; ran.Value2 = dt.Rows[i][j]; NAR(ran); //不要如下方式赋值 //tsheet.Cells[i + 1, j + 1] = dt.Rows[i][j]; } } NAR(rans); NAR(tsheet); //保存信息 wbook.Close(true,newpath, System.Reflection.Missing.Value); NAR(wbook); NAR(wbooks); app.Quit(); NAR(app); } /// <summary> /// 释放资源 /// </summary> /// <param name="o"></param> private void NAR(object o) { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(o); } catch { } finally { o = null; } }
经过测试VS2003 和VS2005中都可以正常的自动关闭Excel。
这是我一天的战利品和大家分享了!
大家帮忙看看有什么问题!
先吃饭去了!
[解决办法] /// <summary>
/// 释放资源
/// </summary>
/// <param name="o"></param>
private void NAR(object o)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
}
catch { }
finally
{
o = null;
}
}
最主要的就是这个方法
[解决办法] 分享快乐,收藏。。。。
[解决办法] 没注意杀掉excel进程的毛病。。
谢谢分享!!
[解决办法] 学习……
[解决办法] 没注意杀掉excel进程的毛病。。
------解决方案--------------------
收藏了
thx
[解决办法] 关注...
word是否同样处理?
[解决办法] 所以一般用myxls来导出.不够导出图文只能用com组件了.
[解决办法] 帮你顶啊。。。
[解决办法] 做过同样的东西,都是用杀掉excel进程,学习了!
[解决办法] 收下啦~ 有時間再過過眼...
[解决办法] 不错,顶下
[解决办法] 谢谢分享,帮顶!
[解决办法] private void ReleaseExcel(Excel.Application app, Excel.Workbook workBook) { workBook.Close(true, Missing.Value, Missing.Value); ReleaseAllRef(workBook); if (app != null) { app.Quit(); ReleaseAllRef(app); } GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); } private void ReleaseAllRef(Object obj) { try { while (System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) > 1) ; } finally { obj = null; } }[解决办法] 学习一下,呵呵,为了避免这个问题,我现在绝大多数时候都是使用的 WordML这一类的东西来直接进行 XML变换,虽然效果还行,但是工作量很大。。。学习一下。。
[解决办法] 学习学习!
[解决办法] 没看到有什么特别的地方,MS不就是推荐 用第二的办法的
[解决办法] 还没遇到过,收藏了,帮顶
------解决方案--------------------
收藏了。好东西
[解决办法] 好东西 学习中
[解决办法] 学习~~~
[解决办法] 不错…
[解决办法] 不知道
[解决办法] 顶啊,
[解决办法] 学习.....
[解决办法] 呵呵
顶!
[解决办法] ---------楼主资料---------
登录名:mmm306306
总技术分:4282
总技术排名:5814
---------结贴情况---------
截至:2010-05-21 19:38:13
总发帖:57个
正常结贴:52个
未结贴:2个
结贴率:96.49%
评语:楼主,你高的结贴率才是我们回答的动力!
--------------------------
[解决办法] 正在学习中了
[解决办法] 正在学习中了
[解决办法] 谢谢分享,收藏了
[解决办法] 学习学习
[解决办法] up up up up
[解决办法] 在不脱离MS环境的情况下,
从OLE处理的视角看,
退出前应先调用CLOSE方法关闭对象
[解决办法] 这问题很郁闷的。我也遇到过。没有解决掉。。。。
[解决办法] DING
[解决办法] hao hao
[解决办法] 正好用这个,看看学习了.
[解决办法] 分享快乐,收藏。。。。
[解决办法] 最近也碰到过 Excel 导出问题(从GridView ,DataList ,Repeater)
不过没有像楼主那样,自己画一个<Table>,我写了一个公共方法,参数为父级Control
调用Control.RenderControl(HtmlTextWriter),直接响应一个写好的Excel文件给用户
不用打开 Excel,感觉通用性还可以
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; /// <summary> /// Common 的摘要说明 /// </summary> public class Common { #region --下载控件内容到 Excel /// <summary> /// 下载控件内容到,Excel 文件 /// </summary> /// <param name="response">Response 引用</param> /// <param name="con">父控件,接受子控件的引用(GridView , DataList , Repeater)</param> /// <param name="fileName">下载文件名</param> public static string DownLoadControlAsExcel(HttpResponse response, Control con, string fileName) { try { //设置文件名,及下载格式 response.AddHeader("Content-Disposition", "attachment; filename=" + fileName + ".xls"); response.ContentType = "application/vnd.ms-excel"; response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312"); //this.EnableViewState = false; System.IO.StringWriter strWriter = new System.IO.StringWriter(); System.Web.UI.HtmlTextWriter hw = new System.Web.UI.HtmlTextWriter(strWriter); //设置到处内容控件(Anyone 父类Control即可) con.RenderControl(hw); response.Write(strWriter.ToString()); //释放资源 strWriter.Dispose(); hw.Dispose(); response.End(); return null; } catch { return "下载数据到Excel异常。"; } } #endregion }
[解决办法] 学习学习
[解决办法] 谢谢楼主啊~\(≧▽≦)/~学习了
[解决办法] 恩·· 程序正好出现了这个问题 还在奇怪呢 谢谢了 !
[解决办法] 太好了 正用上
[解决办法] mark up
[解决办法] ding le xian
[解决办法] 顶顶顶。。。
[解决办法] 编写程序需要养成用完对象要释放的习惯是必需的.对于杀进程也并非不可取.
2,杀掉Excel进程。
执行完EXCEL然后杀掉进程,虽然这100%能杀掉,但是用户需要权限,还得修改服务器的设置(BS网站很难实现)。再说容易误删,这样做是有效果,但是很危险
判断准确,不会出现误杀的情况,在实例化Excel Application对象时可以将实例化的时间记录下来,在杀进程时可以使用进程的StartTime属性和之前记录的时间加以判断.
[解决办法] good 收藏
[解决办法] good 收藏
[解决办法] 呵呵 我在给一个客户做的时候就是直接杀的,时间紧张,没法。
------解决方案--------------------
谢谢楼主分享,这个问题也困扰了我好长时间了
[解决办法] 收下,留着以后用。
[解决办法] 分享快乐,收藏。。。。
[解决办法] 顶下!
[解决办法] 收下,以备后用
[解决办法] 普通释放com的方式是用
1、GC.Collect()
2、System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
但用GC.Collect()强制回收不好,以前我也用
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)来释放excel
后来发现用app.Quit();就OK了(_excel.Application app = new _excel.Application();)
另外LZ漏了非释放过程的捕捉异常情况,当异常发生,接口就释放不了,所以我的方式是try{}
finaly{app.Quit();}
[解决办法] 忘了说,调用app.Quit();前,要把引用的变量设置为Null,如wbook=null;wbooks=null;
[解决办法] 看来我 还差的远呢
[解决办法] 哇 刚注意到 58楼 好漂亮啊
[解决办法] 过来拿点分
[解决办法] 实际上,写两个方法
p..... void 方法1()
{
操作excel........
app.Quit();
}
p..... void 方法2()
{
方法1();
GC.Collect();
}
就是GC.Collect()只会清理栈外的东西,离用这个特性就行了,如果的人Excel是在不同的时段,在不同的方法中执行的,那么,单独销毁应该是更好的方法,如果一个方法搞定,整太复杂意义不大,特别是,如果用上述办法,有些变量,必须循环声明
[解决办法] 实际上,写两个方法
p..... void 方法1()
{
操作excel........
app.Quit();
}
p..... void 方法2()
{
方法1();
GC.Collect();
}
就是GC.Collect()只会清理栈外的东西,利用这个特性就行了,如果操作Excel是在不同的时段,在不同的方法中执行的,那么,单独销毁应该是更好的方法,如果可以一个方法搞定,整得太复杂意义不大,特别是,如果用上述办法时,有些变量,必须循环声明
比如,如果你需要操作50个range,要么声明50个变量,要么释放50次你已经使用过的这个变量
[解决办法] 学习了
[解决办法] 我目前在改公司原来同事代码的时候,他用的就是这些方法。
PS:我公司现在换新组件了。不需要excel
aspose.cells
[解决办法] 谢谢LZ,又学到新东西了。
[解决办法] 谢谢楼主,很有用
[解决办法] 学习了,谢谢分享
------解决方案--------------------
VSTO
[解决办法] 谢谢楼主~!
[解决办法] up up up !
[解决办法] 我上周也遇到这种问题,后来检查程序是发现,原来是在打开Eexcel后,没有释放的原因。
你可以在调试的时候,打开“任务管理器”。
只要Step By Step调试,就会发现问题在那里了。
[解决办法] mark一下
刚弄完2003的excel
[解决办法] 值得一看。。。
[解决办法] 顶、、、、、、、、、、、、、好帖子!
[解决办法] 楼主恭喜你还是不行!
我刚刚测试了!
还是有EXCEL这个进程
[解决办法] 随便说下
我是WIN7系统 2007办公软件
[解决办法] mark up
[解决办法] 引用: 引用: 随便说下 我是WIN7系统 2007办公软件 我的代码 引用的是 Microsoft.Office.Interop.Excel.dll(11.0)office2003! 我在win2003 + office2007中测试没问题。 你重新引用个dll试一试! http://www.myaspx.com/Example/Exce…… 用了该DLL一样的!