EXCEL ADDIN 学习(一)

EXCEL ADDIN 学习

一、加载项简介

Office提供了多种用于扩展Office应用程序功能的模式,常见的
1、Office 自动化程序(Automation Executables)
2、Office加载项(COM or Excel Add-In)
3、Office文档代码或模板(Code Behind an Office Document or Template)
4、Office 智能标签(Smart Tags)

本文重点学习Office的加载项AddIn。


二、注册表加载

要使用EXCEL COM加载项,必须要在注册表内写入加载想的信息。其中有两个注册表位置:
1、HKEY_CURRENT_USER\Software\Microsoft\Office\Excel\AddIn
这个位置是针对于特定用户的,也是推荐的位置。在该位置,有几项是必备的。1)FriendlyName:字符串值,包含了显示在COM对话框中的COM加载项的名称;2)Description:字符串值,包含了COM加载项的简短描述信息;3)LoadBehavior:DWORD类型,用于描述COM加载项的加载方式,通常设置为3(1 + 2).
描述
0 断开,不加载COM加载项
1 连接,加载COM加载项
2 启动时加载,主应用程序启动时加载并连接COM加载项
8 需要时加载,主应用程序需要(触发加载事件)时加载并连接COM加载项
16 首次连接,用户注册加载项后,首次运行主应用程序时加载并连接COM加载项
除了上面的三个,还需要在HKEY_CLASSES_ROOT\CLSID下创建几个注册表项。

扩展知识:

Widows 注册表 HKEY_CLASSES_ROOT

HKEY_CLASSES_ROOT在此关键字之下,可以看到有一个CLSID关键字。在CLSID关键字之下列有系统中安装的所有组件的CLSID。注册表CLSID是一个具有如下格式的串:00000010-0000-0010-8000-00AA006D2EA4。HKEY_CLASSES_ROOT的开头,列出的将是各种应用程序所注册的文件扩展名。在扩展名之后,可以看到许多其他的名字。此类名字的大多数被称作是ProgID,表示是程序员定义的标识符。某些名称表示的不是ProgID而是一些特殊的关键字.如下列:
  • CLSID
  • AppID—此关键字下的子关键字的作用是将某个APPID(应用程序ID)映射成某个远程服务器名称。分式COM(DCOM)将用到此关键字。组件类别—注册表的这一分支可以将CATID(组件类别ID)映射成某个特定的组件类别。
  • Interface—此关键字用于将IID映射成与某个接口相关的信息。这些信息主要用于在跨进程边界使用接口的情况。
  • Licenses—保存的是授权使用COM组件的一些认可信息。
  • TypeLib—类型库关键字所保存的是关于接口成员函数所用参数的信息。另外还有其他一些信息。此关键字可以将一个LIBID映射成存储类型库的文件名称。

 //
// SetRegKeyValue - Private function that updates the registry
// 设置注册表 键和键值
//
static BOOL SetRegKeyValue(
       LPTSTR pszKey,  //主键
       LPTSTR pszSubkey, //子键
       LPTSTR pszValue ) //键值
{
  BOOL bOk = FALSE;
  LONG ec;
  HKEY hKey;
  TCHAR szKey[128];

  lstrcpy(szKey, pszKey);

  if (NULL != pszSubkey) //子键不为空则用"\\"和主键连接在一起
  {
    lstrcat( szKey, "\\" );
    lstrcat( szKey, pszSubkey );
  }

  ec = RegCreateKeyEx(  //创建主键,如果主键下不为空,则相当于在某主键下创建子键
         HKEY_CLASSES_ROOT,
         szKey,
         0,
         NULL,
         REG_OPTION_NON_VOLATILE,
         KEY_ALL_ACCESS,
         NULL,
         &hKey,
         NULL);

  if (ERROR_SUCCESS == ec)
  {
    if (NULL != pszValue)//如键值不为空,则设置键值
    {
      ec = RegSetValueEx(
             hKey,
             NULL,
             0,
             REG_SZ,
             (BYTE *)pszValue,
             (lstrlen(pszValue)+1)*sizeof(TCHAR));
    }
    if (ERROR_SUCCESS == ec)
      bOk = TRUE;
    RegCloseKey(hKey);
  }

  return bOk;
}

//
// CreateComponentCategory - Uses the component categories manager
// to register a specific component category on the local machine.
// 创建组件类别
//
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
{
   ICatRegister* pcr = 0;
   HRESULT hr;
   hr = CoCreateInstance( CLSID_StdComponentCategoriesMgr,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_ICatRegister,
                          (void**)&pcr );
   if (FAILED(hr))
      return hr;

   CATEGORYINFO catinfo;
   catinfo.catid = catid;  //设置组件类别的CLSID
   catinfo.lcid = 0x0409;
   int len = wcslen( catDescription );
   wcsncpy( catinfo.szDescription, catDescription, wcslen( catDescription )); //设置组件类别描述
   catinfo.szDescription[len] = '\0';

   hr = pcr->RegisterCategories( 1, &catinfo );  //注册组件类别
   pcr->Release();

   return hr;
}

//
// RegisterCLSIDInCategory - Uses the component categories
// manager to specify that the given component implements
// the specified component category
// 将组件注册到组件类别下
//
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
   // Register your component categories information.
   ICatRegister* pcr = 0;
   HRESULT hr;
   hr = CoCreateInstance( CLSID_StdComponentCategoriesMgr,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_ICatRegister,
                          (void**)&pcr );
   if (SUCCEEDED(hr))
   {
      CATID rgcatid[1] ;
      rgcatid[0] = catid;
      hr = pcr->RegisterClassImplCategories( clsid, 1, rgcatid );

      pcr->Release();
   }

   return hr;
}

//
// DllRegisterServer - Entry point called by utilities such as
// REGSVR32.EXE to update the registry with the appropriate
// values for each component type in this DLL housing.
//
STDAPI DllRegisterServer(void)
{
    HRESULT  hr = NOERROR;
    CHAR    szModulePath[MAX_PATH];
    CHAR    szID[128];    //GUID值
    CHAR    szCLSID[128];   //"CLSID\\+GUID"

    WCHAR   wszID[128];
    WCHAR   wszCLSID[128];

    GetModuleFileName(
      g_hinstDLL,
      szModulePath,
      sizeof( szModulePath ) / sizeof( CHAR ));

    StringFromGUID2(CLSID_Math, wszID, sizeof( wszID ));
    wcscpy( wszCLSID, L"CLSID\\" );
    wcscat( wszCLSID, wszID ); //设置主键CLSID下的子键
    wcstombs( szID, wszID, sizeof( szID ));
    wcstombs( szCLSID, wszCLSID, sizeof( szID ));

 //
    // Create the ProgID keys.
 // 创建ProgID
 //
    SetRegKeyValue(    //创建主键"Chapter2.Math.1",并设置键值"Chapter2 Math Component"
      "Chapter2.Math.1",
      NULL,
      "Chapter2 Math Component" );
    SetRegKeyValue(    //在主键"Chapter2.Math.1"下创建"CLSID"子键,并设置键值
      "Chapter2.Math.1",
      "CLSID",
      szID);

 //
    // Create version independent ProgID keys.
 // 创建版本无关的ProgID
 //
    SetRegKeyValue(
      "Chapter2.Math",
      NULL,
      "Chapter2 Math Component");
    SetRegKeyValue(    //设置"Chapter2.Math"的现在版本为"Chapter2.Math.1"。
      "Chapter2.Math",
      "CurVer",
      "Chapter2.Math.1");
    SetRegKeyValue(    //设置"Chapter2.Math"的CLSID.
      "Chapter2.Math",
      "CLSID",
      szID);

 //
    // Create entries under CLSID.
 // 创建CLSID主键
 //
    SetRegKeyValue(     //设置CLSID键值
      szCLSID,
      NULL,
      "Chapter 2 Math Component");
    SetRegKeyValue(     //设置子键ProgID的键值
      szCLSID,
      "ProgID",
      "Chapter2.Math.1");
    SetRegKeyValue(     //设置CLSID的版本无关ProgID.
      szCLSID,
      "VersionIndependentProgID",
      "Chapter2.Math");
    SetRegKeyValue(     //设置组件的Dll文件的路径
      szCLSID,
      "InprocServer32",
      szModulePath);

    // Register our component category
    CreateComponentCategory( CATID_ATLDevGuide, L"ATL Developer's Guide Examples" );
    RegisterCLSIDInCategory( CLSID_Math, CATID_ATLDevGuide );

    return S_OK;
}
    2、HKEY_LOCAL_MACHINE\Software\Microsoft\Office\Excel\AddIns
这个位置是针对于所有用户的,但是这些加载项对用户隐藏,即不会出现在COM加载项对话框中。
    这些注册表项如果纯手工写将会非常麻烦,而且容易出错,幸运的是,Visual Studio提供了一组模板来方便的创建Office加载项,但是我们还是应该理解这些注册表项及其代表含义。

四、理解IDTExtensibility2接口

所有Office应用程序都是用IDTExtensibility2接口与COM加载项进行通信,该接口提供了一种通用的初始化机制,并具有在Office应用程序的对象模型中传递数据的能力,因此COM加载项可以与Office应用程序通信。

你可能感兴趣的:(vsto开发指南,excel)