开发Interop的另一种方法

笔者曾经有若干篇文章介绍了在BDS 2006下开发Interop程序的一般步骤。有兴趣的读者可以参考这些文章的汇总:http://www.go4pro.org/cate_list.asp?cate=20

上面提到的开发方法,是建立一个程序,然后创建Excel的应用对象(Application),再获得相应接口(如Workbook,Worksheet,Cells)的引用并对其进行进一步的操作。调用方式是通过由外(自己开发的程序)到内(Excel)。

今天我要介绍一种新的利用.NET开发Interop应用的方法。这种方法与上述方法最大的不同就在于它是由内(Excel)到外(自己开发的程序)进行的。

一、开发工具和准备工作:

这次我使用的是免费的C#开发工具:SharpDeveloper。大家可以免费下载,免费使用。操作系统是Vista Business,但是XP平台应该一样可用。Office平台是2003. 同样的,要使用Office的Interop PIA,必须在安装时(或在安装后)选择各个Office应用(Word/Excel/…)的.NET编程支持,详细的步骤见前文描述,这里不再重复。

二、建立Excel加载项

启动#Developer后,选择File|New|Solution,在弹出窗口中选择C#模板中的Class Library。设置项目的位置、名称后单击“Create”,即可。

00017_01.jpg

Developer会自动创建程序的项目文件,这时界面如下:

00017_02.jpg

我们首先要在左侧的Solution Explorer中的References节点下加入对Excel PIA的引用。右击References节点,并选择Add Reference,在弹出窗口中选择GAC中的Microsoft.Office.Interop.Excel如下:

00017_03.jpg

注意,必须使用GAC中的类!而不是COM中的类!

我们对IDE自动生成的MyClass.cs文件要做一些修改,增加两行代码(以粗体标出):

using System;
using System.Collections.Generic; 

using Excel=Microsoft.Office.Interop.Excel;
[assembly: System.ComponentModel.DescriptionAttribute(OfficeStartupClass, Version=1.0, Class=TestOLE.MyClass)]

其中的using子句是常规的。而特别重要的,而且是必须要加的是[assembly: …]这一行。用户可能需要修改的是Class=TestOLE.MyClass。在我的应用中,我创建的DLL的namespace是 TestOLE,而其中的类是MyClass。

在MyClass类中,需要创建两个Excel调用的特定函数:_Startup/_Shutdown。

代码如下:

public void _Startup(object thisApp, object thisWorkbook) {
  this.MyApp=thisApp as Excel.Application;
  this.MyWorkBook=thisWorkbook as Excel.Workbook;
  this.MyWorksheet=MyWorkBook.Worksheets[1] as Excel.Worksheet;
  MyWorksheet.Cells[1,1]='The add-on starts!'; 
}

public void _Shutdown() {
  MyApp=null;
  MyWorkBook=null;
  MyWorksheet=null;
}

其中的MyApp/MyWorkBook/MyWorksheet是一些自己定义的变量。此时我们可以编译该程序,生成MyClass.dll了。

三、安全因素

值得注意的是,即使我们是在.NET 2.0/3.0下开发我们的DLL,但是这个DLL的安全性需要在.NET 1.x下进行配置。有关.NET 1.x的安全性配置,可以参考其它文档,这里不再赘述。

四、与Excel的工作簿链接

现在我们的程序虽然已经编译完毕,但是还没有和一个Excel工作簿关联。要做到这一步,需要创建(或者打开)一个工作簿,对该工作簿做一些修改。

在菜单中选择“文件|属性”,在弹出的对话框中选择“自定义”:

00017_04.jpg

我们需要加入两个自定义属性:_AssemblyLocation0和_AssemblyName0。第一个属性设置为我们的DLL所在的位置,在我的应用中是D:\Go4Pro\Programs\0017\Bin\Debug,而第二个属性是我们的DLL的名称,我的是TestOLE。

保存这个文件,然后重新打开,可以看到在A1这个单元格中显示:“The add-on starts!”字样。这证明我们编写的DLL已经被该工作簿加载并执行。

五、交互

只有这样的功能显然不是我们想要的。我们需要加入一个交互的过程,让用户最终控制工作簿的行为。在这里我选择修改工作簿的标题作为演示。

首先我们在MyClass.cs中创建两个方法,一个消息响应:

private Excel.WorkbookEvents_SheetFollowHyperlinkEventHandler followHyperlinksEvent;
public void _Startup(object thisApp, object thisWorkbook) {
  this.MyApp=thisApp as Excel.Application;
  this.MyWorkBook=thisWorkbook as Excel.Workbook;
  this.MyWorksheet=MyWorkBook.Worksheets[1] as Excel.Worksheet;
  MyWorksheet.Cells[1,1]='The add-on starts!';

  followHyperlinksEvent=new Excel.WorkbookEvents_SheetFollowHyperlinkEventHandler (ThisWorkbook_SheetFollowHyperlink);
  MyWorkBook.SheetFollowHyperlink+=followHyperlinksEvent;
}

protected void ThisWorkbook_SheetFollowHyperlink(System.Object s, Excel.Hyperlink l) {
  switch (l.SubAddress) {
    case ChangeTitle: ChangeTitle(); break;
    default: break;
    }
}

public void ChangeTitle() {
  MyApp.Caption='Invoked from Excel (supported by C#)';
}

在ThisWorkbook_SheetFollowHyperlink中,我们可以看到我们采用的是超链接的方式来激活相应的方法。这就还需要我们在Excel工作簿中进行一些工作。

在我们刚才的工作簿中,随便选择一个单元格,输入一些内容,诸如“Click here to change the title!”。然后将该单元格命名为ChangeTitle(这个名字必须和上面代码中case段的内容一致)。然后在该单元格选中的情况下,选择菜单 “插入|超链接”:

00017_05.jpg

选择“本文档中的位置”中的“定义的名称”中的ChangeTitle即可。保存Excel文件并再次打开,点击“Click here to change the title!”单元格,我们可以看到工作簿的名称得以改变:

00017_06.jpg

六、与以前方法的比较

显然,这个方法比以前的方法更加灵活而友好,因为用户将在一个界面中进行操作,而不用在两个界面中进行切换。而且只要关闭工作簿就可以结束DLL,不用再关闭另一个主程序。

但是,这个方法需要我们开启.NET 1.x的安全性,需要一些额外的设置,并不一定是每个终端用户都能胜任的。

孰优孰劣,留待开发者和用户进行判断。

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *