如何⽤C#开发Excel扩展插件
毫⽆疑问,微软公司的Excel是⼀个⾮常成功的应⽤软件。它不仅本⾝功能强,⽽且还允许⽤户根据⾃⼰需要进⾏再开发以扩展其功能。传统上,我们可以⽤C/C++语⾔或者VBA对Excel进⾏扩展性开发。C/C++功能强⼤,但是开发⼯作⽐较复杂;VBA使⽤起来⾮常⽅便,但是功能有限。.NET的推出为我们提供了⼀种能够结合这两者长处的再开发⼿段。基于.NET的解决⽅案可以利⽤所有.NET开发平台提供的强⼤功能,例如多线程编程、分布式计算等。这都是VBA难以做到的,事实上即使使⽤C/C++,我们也很难实现这些功能。不仅如此,我们还可以充分利⽤Visual Studio的整体开发环境,例如版本控制之类的功能。这些功能对于团队开发⾮常重要,但是在VBA开发环境下则⾮常困难。
本⽂将以C#为例介绍对Excel进⾏再开发的⽅法和技巧。我们通常有三种⽅法来对Excel进⾏再开发:
⼀是扩展插件(AddIn)。这是开发Excel⽤户⾃定义函数的⾸选。
⼆是VSTO(Visual Studio Tool for Office)。这是开发Excel内嵌功能的⾸选(例如按钮、菜单等等)。
三是RTD(Real Time Data)。这是开发Excel实时数据应⽤程序的⾸选。
尽管它们针对的⽤途不同,但是开发的基本⼿段和过程是⾮常类似的。在技术细节上,这三种⽅法主要的不同是需要实施不同的接⼝。在本⽂中,我们将主要介绍利⽤C#开发Excel扩展插件的⽅法。读者可以依
次类推在需要的时候开发其它两类的程序。
⾸先,创建⼀个C#库程序(library)并指定这个类程序库“控件可见”(Com Visible)。这通常是通过项⽬属性、Assembly属性来指定的,如下图所⽰。(注意不同版本的Visual Studio可能对话框的样⼦不同)。
为了⽅便起见,我们还可以让程序⾃动注册成控件。这可以通过项⽬属性、编译属性来指定,如下图所⽰。如果我们不指定这个属性的话,或者我们需要在其它计算机上使⽤这个程序的话,我们可以使⽤.NET平台⾃带的来⼿⼯进⾏注册。
其次,我们的项⽬需要添加以下两个引⽤:
Ø (.NET)Extensibility
Ø (COM)Microsoft Office Excel Object Library(选⽤最新版本)
然后,输⼊以下程序。程序中的注释已经对各部分的作⽤作了适当说明。注意,这个类程序并不是Excel⽤户⾃定义函数本⾝,⽽是包含了所有需要的基本架构函数。有了这个基类以后,我们就可以编写⼀个简单的⼦类仅仅包含我们需要的Excel⽤户⾃定义函数。
using System;
using System.Runtime.InteropServices;
using Extensibility;
using MyWin32 = Microsoft.Win32;
using MsExcel = Microsoft.Office.Interop.Excel;
namespace MyExcelAddIn
{
///
/// Excel⽤户⾃定义函数的基类,包含了所有必需的基础架构类函数。它的⼦类则可以专注于⽤户⾃定义函数的编写。
///
public class ExcelUDFBase : IDTExtensibility2
{
/// 这个函数将在我们的AddIn被注册时调⽤。
///
///
[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type_)
{
MyWin32.Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type_,"Programmable"));
// 以下这两个函数调⽤不是必须的。但是省略它们的话,每次我们从EXCEL中引⽤或取掉这个AddIn时,EXCEL都会提⽰不到mscoree.dll,问你
// 是否要删掉这个AddIn。当然我们应该回答“不”。
MyWin32.RegistryKey key = MyWin32.Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type_, "InprocServer32"), true);
key.SetValue(""
, String.Format("{0}\\mscoree.dll", System.Environment.SystemDirectory)
, MyWin32.RegistryValueKind.String
);
}
///
/// 这个函数将在我们的AddIn被注销时调⽤。
///
///
[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type_)
{
MyWin32.Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type_,"Programmable"));
}
///
/// ⼯具函数。
///
///
///
private static string GetSubKeyName(Type type_, String sub_key_ame_)
{
return String.Format("CLSID\\{{{0}}}\\{1}", type_.GUID.ToString().ToUpper(), sub_key_ame_);
}
#region IDTExtensibility2 Members
///
/// 这个变量将指向Excel应⽤程序。
///
protected MsExcel.Application MyExcelAppInstance { get; private set; }
///
/// 这个变量将指向我们的AddIn。
///
protected object MyAddInInstance { get; private set; }
///
/
// 这个函数和以下四个函数都是为了实施IDTExtensibility2接⼝。实施IDTExtensibility2接⼝并不是必须的。但是如果我们不实施这个接⼝的
/// 话,我们将⽆法得到,从⽽⽆法编写Volatile函数。
///
///
public void OnAddInsUpdate(ref Array custom)
{
}
///
///
///
public void OnBeginShutdown(ref Array custom)
{
}
///
///
///
字符串函数怎么用///
///
///
public void OnConnection(object Application, ext_ConnectMode ConnectMode, objectAddInInst, ref Array custom) {
MyExcelAppInstance = (MsExcel.Application)Application;
MyAddInInstance = AddInInst;
}
///
///
///
///
public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom)
{
}
///
///
///
public void OnStartupComplete(ref Array custom)
{
}
#endregion
}
}
最后我们可以输⼊以下程序来创建了我们第⼀个⽤户⾃定义函数。(当然,另写⼀个类不是必须的,我们也可以把这个函数直接写
在ExcelUDFBase类⾥。)
using System;
using System.Runtime.InteropServices;
using MsExcel = Microsoft.Office.Interop.Excel;
namespace MyExcelAddIn
{
///
/// 这个类包括我们真正需要的⽤户⾃定义函数。它的两个类属性是必须的。但是每个这样的类应该具有唯⼀的GUID值。GUID可以⽤Visual Studio⾃⼰⽣成。
/// 我们只要选择菜单中的⼯具(Tools),然后选择GUID选项就可以了。
///
[ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
[Guid("348E9F3A-96E4-42da-A5B9-FAD52E7744BB")]
public class MyFunctions : ExcelUDFBase
{
///
/// 这是个简单的样例函数。它的逻辑⾮常简单,⽆需过多解释。需要指出的是这个函数的返回值是object以及其内部的try . . . catch程序结构。
/// 当程序出错的时候,这样的结构可以使我们的⽤户⾃定义函数返回合适的错误信息。
///
///
///
///
public object MyDivid(double Value1, double Value2)
{
try
{
return Value1 / Value2;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论