关于在ASP.NET中以DCOM方式操作Excel的几个问题

一、Excel操作权限问题,有两种方法:
1、使用模拟帐户,在Web.config文件中加入
<!identity impersonate="true" userName="administrator" password=""/>
2、在DCOM组件服务中给MICROSOFT.EXCEL组件 赋予ASP.NET的操作权限,具体步骤:
1)打开开始菜单的运行对话框,输入dcomcnfg命令,确定,这时会弹出组件服务窗口
(2)展开计算机-〉我的电脑-〉DCOM配置,找到Microsoft Excel应用程序节点
(3)单击右键-〉属性,选中“安全”选项,在下面三个项目都选择“自定义”,并单击编辑按钮
(4)在启动权限对话框中点击添加按钮,添加相应的用户(注意:如果是WIN2000,XP,则添加“机器名/ASPNET”用户,我这里是以WIN2003为例,WIN2003是添加“NETWORK Service”用户),并赋予最大权限

二、结束Excel进程
1、我在上篇随笔中用的是判断进程启动时间来结束Excel进程,虽然看起来有点不妥,但是我用了还从没出过问题,从没错杀其他Excel进程
2、释放所用到的所有Excel对象的资源,这里拷贝一段代码:
这段代码来自:http://community.csdn.net/Expert/topic/3486/3486601.xml?temp=2.860659E-02

object missing = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Excel.Application myExcel
=new Microsoft.Office.Interop.Excel.ApplicationClass();
myExcel.Visible
= false;
//打开新文件
Microsoft.Office.Interop.Excel.Workbooks myBooks =  myExcel.Workbooks;
Microsoft.Office.Interop.Excel.Workbook myBook 
= myBooks.Open(sourceFile,missing,missing,missing,missing,missing,missing,missing,missing,missing,missing, missing,missing,missing,missing); 
Microsoft.Office.Interop.Excel.Worksheet curSheet 
= (Microsoft.Office.Interop.Excel.Worksheet)myBook.ActiveSheet;

Microsoft.Office.Interop.Excel.Range rans 
= (Microsoft.Office.Interop.Excel.Range)curSheet.Cells;
Microsoft.Office.Interop.Excel.Range ran 
= null;
Microsoft.Office.Interop.Excel.Range ranMerge 
= null;
Microsoft.Office.Interop.Excel.Range ranRows 
= null;
Microsoft.Office.Interop.Excel.Range ranCells 
= null;
forint i=0; i < 10; i++ )
{
forint j=0; j < 10; j++ )
{
ran 
= (Microsoft.Office.Interop.Excel.Range)rans[i+1,j+1];

ranMerge
= ran.MergeArea;
ranRows
= ranMerge.Rows;
int mergeRows= ranRows.Count;
ranCells
= ranMerge.Cells;
int mergeCells= ranCells.Count;
Response.Write( 
"<br/>" + i + ":" ++ "   : " + ran.Text );

System.Runtime.InteropServices.Marshal.ReleaseComObject (ranCells);
ranCells 
= null;

System.Runtime.InteropServices.Marshal.ReleaseComObject (ranRows);
ranRows 
= null;

System.Runtime.InteropServices.Marshal.ReleaseComObject (ranMerge);
ranMerge 
= null;

System.Runtime.InteropServices.Marshal.ReleaseComObject (ran);
ran 
= null;
}

}


System.Runtime.InteropServices.Marshal.ReleaseComObject (rans);
rans 
= null;

System.Runtime.InteropServices.Marshal.ReleaseComObject (curSheet);
curSheet 
= null;

myBook.Close(
false,Type.Missing,Type.Missing);
System.Runtime.InteropServices.Marshal.ReleaseComObject (myBook);
myBook 
= null;

myBooks.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject (myBooks);
myBooks 
= null;

myExcel.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject (myExcel);
myExcel 
= null;

GC.Collect();
GC.WaitForPendingFinalizers();


暂时总结这两个问题,这些解决办法都来源于网上,我这里只是总结一下,顺便把我收集的几个Excel控件给大家下载:
http://files.cnblogs.com/lingyun_k/ExcelWriter.rar

这个有破解
http://files.cnblogs.com/lingyun_k/Aspose%20Excel%20V2.3.1.1.NET.rar

还有一个是ExcelQuicker,功能也挺强的,大家搜一下就可以找到,不过我觉得金质打印王的对Excel操作比它要方便,但是不支持WebForm

 

posted @ 2005-08-01 22:26 kalman 阅读(9182) 评论(19) 编辑 收藏

 回复 引用   
#1楼 2005-08-01 23:39 CsOver[未注册用户]
有时间的话,自己开发个适应自己的控件.对自己的技术是一个极大的挑战.
 回复 引用 查看   
#2楼 2005-08-02 08:34 可乐加冰      
我也整理了 一个,包括对word的操作的。
这个权限问题确实让人郁闷,前者简单,但是会不会存在安全隐患?
后者好象有点麻烦

 回复 引用 查看   
#3楼 2005-08-02 09:04 可乐加冰      
用了后面一个方法,问题解决了!对于word也同样好用
 回复 引用   
#4楼 2005-08-02 10:11 lost0[未注册用户]
关于结束进程
我同事在
1.
把数据导入到一个.CSV文件中
作一个EXCEL模板里面写个宏
宏的作用是从.CSV文件中读取数据
保存在EXCEL文件中

 回复 引用   
#5楼 2005-08-15 12:11 liziyu[未注册用户]
我在xp上开发的时候,用ASP.net操作word,将其转换为html,没有问题,
在2003下按照你说的设置了network service账号的权限
,可我在用IE访问的时候提示我命令错误,
而在这之前提示我拒绝访问,

请问有什么好办法么?

谢谢。。

 回复 引用 查看   
#6楼[楼主] 2005-08-16 20:37 lingyun_k      
没碰到过这种问题
 回复 引用   
#7楼 2005-08-24 17:05 vs[未注册用户]
作者说:
还有一个是ExcelQuicker,功能也挺强的,大家搜一下就可以找到,不过我觉得金质打印王的对Excel操作比它要方便,但是不支持WebForm

确实,金质打印通的对Excel操作确实棒

我查到它的主页了:

www.webmis.com.cn

 回复 引用   
#8楼 2005-10-12 16:52 11111[未注册用户]
1111111111111111111111
 回复 引用   
#9楼 2005-10-28 09:22 henrymiao[未注册用户]
Excel操作权限问题,有两种方法,经过我测试后,只有把两个方法均配置好!
才能运用下面的killProcess.去掉相应的进程!!
我试验的方式是服务器端是win2003,
客户端IE访问服务器端,去Kill服务器端进程中的EXCEL.EXE

 回复 引用 查看   
#10楼[楼主] 2005-10-29 10:41 lingyun_k      
用假扮用户的方式最保险,不会出问题;而设置Excel组件的访问权限在有的系统就不行
 回复 引用 查看   
#11楼 2005-10-31 17:20 smartstone      
好东西啊
 回复 引用   
#12楼 2005-11-05 15:59 郑彬[未注册用户]
Excel操作权限问题方法2对 Excel有效果,但是对Word2003没有效果了.
我也很想知道是怎么回事呢.把标识改成交互式用户启动也不行.

 回复 引用 查看   
#13楼 2005-11-05 23:57 317768      
我用了你的这种方法,还是不行,我都快急疯了,我的配置是 win2000+Excel2000原代码
如下:




namespace testzjh
{
/// <summary>
/// WebForm1 的摘要说明。
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.DataGrid DataGrid1;
protected System.Web.UI.WebControls.Button Button1;
protected static DataSet ds;


private void Page_Load(object sender, System.EventArgs e)
{
// 在此处放置用户代码以初始化页面
if(!Page.IsPostBack)
binddata();
}
private void binddata()
{

SqlConnection sqlconn=new SqlConnection("server=localhost;uid=sa;database=pubs");
SqlDataAdapter sqldap=new SqlDataAdapter ("select * from jobs",sqlconn);
sqlconn.Open();
ds=new DataSet();
sqldap.Fill(ds,"kk");
DataGrid1.DataSource=ds.Tables[0].DefaultView;
DataGrid1.DataBind();
}


#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.Button1.Click += new System.EventHandler(this.Button1_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void Button1_Click(object sender, System.EventArgs e)
{
doFunction();
}

private void doFunction()
{ GenerateReport();
//kk();
//ResponseExcel();
//ResponseExcel();
}


private void GenerateReport()
{
Excel.Application oExcelApp;
Excel.Workbooks myWorkbooks;
Excel.Workbook myOneWorkbook;
Excel.Worksheet myWorkSheet;
Object oMissing = System.Reflection.Missing.Value;
Excel.Workbook obook;
Excel.Range r;
Excel.Range r1;

//***1
oExcelApp= new Excel.ApplicationClass();
   if( oExcelApp == null) return;  
   oExcelApp.Visible = false;
oExcelApp.SheetsInNewWorkbook =1;

string TempExcelFile=Server.MapPath("MyTemplate.xls");
obook = oExcelApp.Workbooks.Add(TempExcelFile);
myWorkbooks = oExcelApp.Workbooks;
myOneWorkbook = myWorkbooks[1];
myWorkSheet = (Excel.Worksheet)myOneWorkbook.Worksheets[1];
myWorkSheet.Name ="开户代理业务电子化凭证明细查询报表";

//写标题
r = myWorkSheet.get_Range("A1","G1");
   object [] objHeader = {"序号","结算点代号","代办点代号",
"凭证本号"};
r.Value2 = objHeader;
//copy格式
r1= myWorkSheet.get_Range("A3","G3");
r.Copy(r1);

r = myWorkSheet.get_Range("A1","C1");
r1= myWorkSheet.get_Range("A5","C5");
r.Copy(r1);

System.Runtime.InteropServices.Marshal.ReleaseComObject (r);
r = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject (r1);
r1 = null;

//写数据:
r = myWorkSheet.get_Range("A2",Missing.Value);   
   r = r.get_Resize(10,8);
DumpData(ds,ref r);
//System.Runtime.InteropServices.Marshal.ReleaseComObject (r);
r = null;
//save
oExcelApp.Workbooks[1].SaveAs(Server.MapPath("aa.xls"),
Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value,
Excel.XlSaveAsAccessMode.xlExclusive,Missing.Value,Missing.Value,
Missing.Value,Missing.Value);



//在这里写结束进程的方法


Excel.Range rans = (Excel.Range) myWorkSheet.Cells;
Excel.Range ran = null;
Excel.Range ranMerge = null;
Excel.Range ranRows = null;
Excel.Range ranCells = null;
for( int i=0; i < 10; i++ )
{
for( int j=0; j < 10; j++ )
{
ran = (Excel.Range)rans[i+1,j+1];


ranMerge= ran.MergeArea;


ranRows= ranMerge.Rows;
int mergeRows= ranRows.Count;
ranCells= ranMerge.Cells;
int mergeCells= ranCells.Count;

System.Runtime.InteropServices.Marshal.ReleaseComObject (ranCells);
ranCells = null;

System.Runtime.InteropServices.Marshal.ReleaseComObject (ranRows);
ranRows = null;

System.Runtime.InteropServices.Marshal.ReleaseComObject (ranMerge);
ranMerge = null;

System.Runtime.InteropServices.Marshal.ReleaseComObject (ran);
ran = null;
}
}

System.Runtime.InteropServices.Marshal.ReleaseComObject (rans);
rans = null;

System.Runtime.InteropServices.Marshal.ReleaseComObject (myWorkSheet);
myWorkSheet = null;

myOneWorkbook.Close(false,Type.Missing,Type.Missing);
System.Runtime.InteropServices.Marshal.ReleaseComObject (myOneWorkbook);
myOneWorkbook = null;

myWorkbooks.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject (myWorkbooks);
myWorkbooks = null;

oExcelApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject (oExcelApp);
oExcelApp = null;

GC.Collect();
GC.WaitForPendingFinalizers();

}




//将DATASET的数据内容导出到Excel的单元格中去
private void DumpData(DataSet ds, ref Excel.Range rag)
{
object[] ary;
// object [,] objData = new Object[10,8];

object [,] objData = new Object[20,28];
DataRow dr;
int iRow,iCol;
  //将数据导出到相应的单元格
  for( iRow =0 ;iRow<ds.Tables[0].Rows.Count ;iRow++)
{
    dr = ds.Tables[0].Rows[iRow];
   ary = dr.ItemArray;
   for( iCol = 0;iCol< ary.Length;iCol++)
objData[iRow , iCol] = ary[iCol].ToString();

}
rag.Value = objData;
   rag.EntireColumn.AutoFit();


System.Runtime.InteropServices.Marshal.ReleaseComObject (rag);
rag= null;




}

}
}

这样还是不行呀,谁可以告诉我为什么,应该怎么办?
我的邮箱:hnszzyh@163.com
QQ: 121587955


 回复 引用   
#14楼 2005-11-22 21:18 mandi[未注册用户]
求教
为什么我用using excel系统体是不正确啊?

还有我有了一个excelwriter.dll
放到了.net和我的项目所在的bin中,using excelwriter还是不行

急!谢!

 回复 引用 查看   
#15楼[楼主] 2005-11-23 14:42 lingyun_k      
将程序集添加引用到项目中,在项目引用列表找到这个程序集,然后右键-〉在对象浏览器中查看,找到你要引用的对象的命名空间,复制一下再粘贴到using 后面就行了
 回复 引用   
#16楼 2006-02-20 16:58 morphy[未注册用户]
请问如何设置导出excel中单元格或者行的底色啊? 急!!!谢谢大家
 回复 引用   
#17楼 2006-02-21 13:15 kly[未注册用户]
Excel.Range rng = workSheet.get_Range("B3","C3");
Excel.Interior interior = rng.Interior;
interior.ColorIndex = 48

 回复 引用   
#18楼 2006-11-20 15:12 游客[未注册用户]
请问如何将一个SHEET从一个WORKBOOK COPY到另一个WORKBOOK中呢?请指教,高人!
 回复 引用 查看   
#19楼[楼主] 2006-11-20 16:16 lingyun_k      
/// <summary>
/// 将一个工作表拷贝到另一个工作表后面,并重命名
/// </summary>
/// <param name="srcSheetIndex">拷贝源工作表索引</param>
/// <param name="aimSheetIndex">参照位置工作表索引,新工作表拷贝在该工作表后面</param>
/// <param name="newSheetName"></param>
public void CopyWorkSheet(int srcSheetIndex,int aimSheetIndex,string newSheetName)
{
if(srcSheetIndex > this.WorkSheetCount || aimSheetIndex > this.WorkSheetCount)
{
this.KillExcelProcess();
throw new Exception("索引超出范围,WorkSheet索引不能大于WorkSheet数量!");
}

try
{
Excel.Worksheet srcSheet = (Excel.Worksheet)workBook.Sheets.get_Item(srcSheetIndex);
Excel.Worksheet aimSheet = (Excel.Worksheet)workBook.Sheets.get_Item(aimSheetIndex);

srcSheet.Copy(this.missing,aimSheet);

//重命名
workSheet = (Excel.Worksheet)aimSheet.Next; //获取新拷贝的工作表
workSheet.Name = newSheetName;
}
catch(Exception e)
{
this.KillExcelProcess();
throw e;
}
}