Я создал надстройку COM для Excel 2003 с помощью Visual Studio 2005 Tools for Office. Код надстройки выглядит следующим образом:
[Guid("EAC0992E-AC39-4126-B851-A57BA3FA80B8")]
[ComVisible(true)]
[ProgId("NLog4VBA.Logger")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Logger
{
public double Debug(string context, string message)
{
Trace.WriteLine(message);
return message.Length;
}
[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type)
{
Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type, "Programmable"));
RegistryKey key = Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type, "InprocServer32"), true);
key.SetValue("", System.Environment.SystemDirectory + @"\mscoree.dll", RegistryValueKind.String);
}
[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type)
{
Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type, "Programmable"), false);
}
private static string GetSubKeyName(Type type, string subKeyName)
{
System.Text.StringBuilder s = new System.Text.StringBuilder();
s.Append(@"CLSID\{");
s.Append(type.GUID.ToString().ToUpper());
s.Append(@"}\");
s.Append(subKeyName);
return s.ToString();
}
}
Я настроил проект для регистрации COM-взаимодействия, и я зарегистрировал DLL с:
regasm.exe /tlb NLog4VBA.dll
Когда я открываю Excel, я захожу в Инструменты -> Надстройки, нажимаю Автоматизация и добавляю NLog4VBA.Logger. Затем я могу перейти в меню «Вставка» -> «Функция», выбрать NLogVBA.Logger из списка категорий и выбрать «Отладка».
Конечный результат - это ячейка с содержимым вроде:
=Debug("My Context","My Message")
... и отображаемое значение:
10
Это все как и должно быть. В своем коде VBA я могу перейти в Сервис -> Ссылки и добавить NLog4VBA. Затем я добавляю следующий код для кнопки на моем листе:
Private Sub CommandButton1_Click()
Application.COMAddIns("NLog4VBA.Logger").Object.Debug "My Context", "My Message"
End Sub
Это невозможно, потому что COMAddIns ("NLog4VBA.Logger") завершается с:
Run-time error '9': Subscript out of range
Может кто-нибудь сказать мне, что мне нужно сделать, чтобы метод Debug () был доступен для моего кода VBA (что для меня более полезно, чем возможность вызывать метод из ячейки)?
Я уверен, что мне здесь не хватает чего-то простого.
Отредактировано 2010/09/07: Я обновил фрагмент кода, добавив атрибут [ProgId], как предложено ниже Джимом; проблема сохраняется. Я вижу объект в реестре:
[HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}]
@="NLog4VBA.Logger"
[HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\Implemented Categories]
[HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}]
[HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\InprocServer32]
@="C:\\WINDOWS\\system32\\mscoree.dll"
"ThreadingModel"="Both"
"Class"="NLog4VBA.Logger"
"Assembly"="NLog4VBA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
"RuntimeVersion"="v2.0.50727"
"CodeBase"="file:///C:/projects/nlog4vba/NLog4VBA/bin/Debug/NLog4VBA.dll"
[HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\InprocServer32\1.0.0.0]
"Class"="NLog4VBA.Logger"
"Assembly"="NLog4VBA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
"RuntimeVersion"="v2.0.50727"
"CodeBase"="file:///C:/projects/nlog4vba/NLog4VBA/bin/Debug/NLog4VBA.dll"
[HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\ProgId]
@="NLog4VBA.Logger"
[HKEY_CLASSES_ROOT\CLSID\{EAC0992E-AC39-4126-B851-A57BA3FA80B8}\Programmable]
Кроме того, ProgID отображается в диалоговом окне надстроек:
Я до сих пор не понимаю, почему это не работает: - (