首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > asp.net >

分享帖:施用Excel COM组件导出数据后释放Excel资源

2012-12-26 
分享帖:使用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一样的!

热点排行