Сборка надстройки для VBA IDE с использованием VB.NET
Я спрашивал об этом в другом месте, но так и не нашел, чтобы кто-нибудь знал, как создать надстройку для VBA IDE с использованием VB.NET. Это вообще возможно? Может ли кто-нибудь указать мне на пример?
6 ответов
Возможно, вам нужно написать ком-надстройку, используя интерфейс IDTExtensibility2, выбрать общий шаблон проекта надстройки из нового проекта.
РЕДАКТИРОВАТЬ
В противном случае, чтобы создать это дополнение с нуля, вам нужно будет сделать следующее:
- Создать новую библиотеку классов проекта
- Добавьте ссылки на "Расширяемость", она должна быть в списке. Возможно, вам придется скачать PIA для вашей версии офиса. (и, возможно, VSTO, но я не уверен в этом)
- Добавить ссылки на "Microsoft.Vbe.Interop" снова следует с помощью PIA.
- Установите флажок "Зарегистрироваться для Com Interop" на вкладке свойств.
- ДОПОЛНИТЕЛЬНО На вкладке параметров отладки измените запуск на внешнюю программу и введите путь к Excel exe в папке программных файлов (если это предназначено для Excel), чтобы проект можно было отлаживать.
- ДОПОЛНИТЕЛЬНО В опциях команды добавьте запись на лист или слово doc, которое будет отображать диалоговое окно надстройки с использованием макроса при запуске, для разработки имеет смысл упростить процесс отладки. например, "C:\vbe.xlsm"
- НЕОБЯЗАТЕЛЬНО Также укажите путь запуска для каталога рабочей таблицы, например "C:\"
- Реализуйте интерфейс "IDTExtensibility2", найденный в сборке "Extensibility".
- Назовите этот класс "Connect" (это просто предпочтение)
- Приписать класс следующим
[ComVisible(true), Guid("YourGeneratedGuid"), ProgId("YourAddinName.Connect")]
Вот реализация, с которой можно начать. Во-первых, замените "YourAddinName" на свое AppName и создайте Guid для "YourGeneratedGuid". Вам нужно будет зарегистрировать надстройку в нужном месте реестра, посмотреть разделы реестра, которые следуют, чтобы получить представление, а также заменить некоторые переменные в разделах реестра.
Imports System
Imports System.Drawing
Imports System.Linq
Imports System.Runtime.InteropServices
Imports Extensibility
Imports Microsoft.Vbe.Interop
Namespace VBEAddin
''' <summary>
''' The object for implementing an Add-in.
''' </summary>
''' <seealso class='IDTExtensibility2' />
<Guid("YourGeneratedGuid"), ProgId("YourAddinName.Connect")> _
Public Class Connect
Implements IDTExtensibility2
Private _application As VBE 'Interop VBE application object
#Region "IDTExtensibility2 Members"
''' <summary>
''' Implements the OnConnection method of the IDTExtensibility2 interface.
''' Receives notification that the Add-in is being loaded.
''' </summary>
''' <param term='application'>
''' Root object of the host application.
''' </param>
''' <param term='connectMode'>
''' Describes how the Add-in is being loaded.
''' </param>
''' <param term='addInInst'>
''' Object representing this Add-in.
''' </param>
''' <seealso class='IDTExtensibility2' />
Public Sub OnConnection(ByVal application As Object, ByVal connectMode As ext_ConnectMode, ByVal addInInst As Object, ByRef [custom] As Array)
_application = CType(Application,VBE)
End Sub
Private Sub onReferenceItemAdded(ByVal reference As Reference)
'TODO: Map types found in assembly using reference.
End Sub
Private Sub onReferenceItemRemoved(ByVal reference As Reference)
'TODO: Remove types found in assembly using reference.
End Sub
Private Sub BootAddin()
'Detect change in active window.
End Sub
''' <summary>
''' Implements the OnDisconnection method of the IDTExtensibility2 interface.
''' Receives notification that the Add-in is being unloaded.
''' </summary>
''' <param term='disconnectMode'>
''' Describes how the Add-in is being unloaded.
''' </param>
''' <param term='custom'>
''' Array of parameters that are host application specific.
''' </param>
''' <seealso class='IDTExtensibility2' />
Public Sub OnDisconnection(ByVal disconnectMode As ext_DisconnectMode, ByRef [custom] As Array)
End Sub
''' <summary>
''' Implements the OnAddInsUpdate method of the IDTExtensibility2 interface.
''' Receives notification that the collection of Add-ins has changed.
''' </summary>
''' <param term='custom'>
''' Array of parameters that are host application specific.
''' </param>
''' <seealso class='IDTExtensibility2' />
Public Sub OnAddInsUpdate(ByRef [custom] As Array)
End Sub
''' <summary>
''' Implements the OnStartupComplete method of the IDTExtensibility2 interface.
''' Receives notification that the host application has completed loading.
''' </summary>
''' <param term='custom'>
''' Array of parameters that are host application specific.
''' </param>
''' <seealso class='IDTExtensibility2' />
Public Sub OnStartupComplete(ByRef [custom] As Array)
'Boot dispatcher
End Sub
''' <summary>
''' Implements the OnBeginShutdown method of the IDTExtensibility2 interface.
''' Receives notification that the host application is being unloaded.
''' </summary>
''' <param term='custom'>
''' Array of parameters that are host application specific.
''' </param>
''' <seealso class='IDTExtensibility2' />
Public Sub OnBeginShutdown(ByRef [custom] As Array)
End Sub
#End Region
End Class
End Namespace
Вот скрипт реестра.key для регистрации надстройки, обратите внимание, вам нужно будет изменить некоторые параметры, чтобы правильно зарегистрировать его.
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\VBA\VBE\6.0\Addins\YourAddinName.Connect]
"CommandLineSafe"=dword:00000000
"Description"="Description for your new addin"
"LoadBehavior"=dword:00000000
"FriendlyName"="YourAddinName"
[HKEY_CLASSES_ROOT\CLSID\{YourGeneratedGuid}]
@="YourAddinName.Connect"
[HKEY_CLASSES_ROOT\CLSID\{YourGeneratedGuid}\Implemented Categories]
[HKEY_CLASSES_ROOT\CLSID\{YourGeneratedGuid}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="YourAddinName.Connect"
"Assembly"="YourAssemblyNameFullTypeName"
"RuntimeVersion"="v2.0.50727"
"CodeBase"="file:///PathToAssembly"
[HKEY_CLASSES_ROOT\CLSID\{YourGeneratedGuid}\ProgId]
@="YourAddinName.Connect"
ВНИМАНИЕ: токены "YourGeneratedGuid" должны иметь фигурные скобки {} и быть такими же, как Guid в атрибуте выше, токен "YourAssemblyNameFullTypeName" должен быть полным именем сборки, токен "YourAddinName.Connect" должен быть таким же ProgId установите в атрибуте выше.
ПРИМЕЧАНИЕ
Также нашел это полезным, может сэкономить пару часов гуглить.
'HKEY_CURRENT_USER\Software\Microsoft\VBA\6.0\Common
'FontFace=Courier New (STRING - Default if missing)
'FontHeight=10 (DWORD - Default if missing)
К сожалению, шаги almog.ori не сработали для меня. Вот моя версия, чтобы помочь людям в будущем:
Создайте проект библиотеки классов C# или VB.NET с именем "VBEAddIn"
Добавьте следующие сборки Interop в качестве ссылок на проект, используя меню "Проект", "Добавить ссылку...", вкладку "Обзор".
Расширяемость (C:\Program Files\Microsoft Visual Studio 10.0\ Инструменты Visual Studio для Office \ PIA \ Common \ Extensibility.dll) - если его нет, попробуйте C:\Program Files (x86)\, если вы используете компьютер x64.
Microsoft.Office.Interop.Excel (C:\Program Files\Microsoft Visual Studio 10.0\ Инструменты Visual Studio для Office \ PIA \ Office14 \ Microsoft.Office.Interop.Excel.dll)
Microsoft.Vbe.Interop (C:\Program Files\Microsoft Visual Studio 10.0\ Инструменты Visual Studio для Office \ PIA \ Office14 \ Microsoft.Vbe.Interop.dll)
(необязательно) Microsoft.Vbe.Interop.Forms (C:\Program Files\Microsoft Visual Studio 10.0\ Инструменты Visual Studio для Office\PIA\Office14\Microsoft.Vbe.Interop.Forms.dll)
Добавьте класс в ваш проект с помощью следующего кода:
VB.Net:
Imports Microsoft.Office.Interop
Imports Extensibility
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports Microsoft.Vbe.Interop
<ComVisible(True), Guid("3599862B-FF92-42DF-BB55-DBD37CC13565"), ProgId("VBEAddInVB.Net.Connect")> _
Public Class Connect
Implements Extensibility.IDTExtensibility2
Private _VBE As VBE
Private _AddIn As AddIn
Private Sub OnConnection(Application As Object, ConnectMode As Extensibility.ext_ConnectMode, _
AddInInst As Object, ByRef custom As System.Array) Implements IDTExtensibility2.OnConnection
Try
_VBE = DirectCast(Application, VBE)
_AddIn = DirectCast(AddInInst, AddIn)
Select Case ConnectMode
Case Extensibility.ext_ConnectMode.ext_cm_Startup
Case Extensibility.ext_ConnectMode.ext_cm_AfterStartup
InitializeAddIn()
End Select
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub
Private Sub OnDisconnection(RemoveMode As Extensibility.ext_DisconnectMode, _
ByRef custom As System.Array) Implements IDTExtensibility2.OnDisconnection
End Sub
Private Sub OnStartupComplete(ByRef custom As System.Array) _
Implements IDTExtensibility2.OnStartupComplete
InitializeAddIn()
End Sub
Private Sub OnAddInsUpdate(ByRef custom As System.Array) Implements IDTExtensibility2.OnAddInsUpdate
End Sub
Private Sub OnBeginShutdown(ByRef custom As System.Array) Implements IDTExtensibility2.OnBeginShutdown
End Sub
Private Sub InitializeAddIn()
MessageBox.Show(_AddIn.ProgId & " loaded in VBA editor version " & _VBE.Version)
End Sub
End Class
C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using Extensibility;
using Microsoft.Vbe.Interop;
using System.Windows.Forms;
namespace VBEAddin
{
[ComVisible(true), Guid("3599862B-FF92-42DF-BB55-DBD37CC13565"), ProgId("VBEAddIn.Connect")]
public class Connect : IDTExtensibility2
{
private VBE _VBE;
private AddIn _AddIn;
#region "IDTExtensibility2 Members"
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
try
{
_VBE = (VBE)application;
_AddIn = (AddIn)addInInst;
switch (connectMode)
{
case Extensibility.ext_ConnectMode.ext_cm_Startup:
break;
case Extensibility.ext_ConnectMode.ext_cm_AfterStartup:
InitializeAddIn();
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void onReferenceItemAdded(Reference reference)
{
//TODO: Map types found in assembly using reference.
}
private void onReferenceItemRemoved(Reference reference)
{
//TODO: Remove types found in assembly using reference.
}
public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
{
}
public void OnAddInsUpdate(ref Array custom)
{
}
public void OnStartupComplete(ref Array custom)
{
InitializeAddIn();
}
private void InitializeAddIn()
{
MessageBox.Show(_AddIn.ProgId + " loaded in VBA editor version " + _VBE.Version);
}
public void OnBeginShutdown(ref Array custom)
{
}
#endregion
}
}
В окне свойств проекта проекта:
На вкладке "Приложение" убедитесь, что для имени сборки и корневого пространства имен установлено значение "VBEAddIn".
На вкладке "Компиляция" убедитесь, что флажок "Зарегистрироваться для взаимодействия COM" установлен. Мы не будем вручную регистрировать сборку для COM Interop с помощью соответствующего инструмента regasm.exe. Однако обратите внимание, что флажок "Register for COM interop" регистрирует только dll надстройки как 32-битную библиотеку COM, а не как 64-битную библиотеку COM.
На вкладке "Компиляция", кнопка "Дополнительные параметры компиляции", убедитесь, что в поле со списком "Target CPU" установлено значение "AnyCPU", что означает, что сборка может выполняться как 64-битная или 32-битная, в зависимости от выполнения..NET Framework, который его загружает.
На вкладке "Подписывание" убедитесь, что флажок "Подписать сборку" снят.
Затем добавьте ключи реестра, сохраните приведенный ниже фрагмент в виде файла ASCI с расширением reg и дважды щелкните его, чтобы добавить значения в реестр.
Важное примечание: перед выполнением reg-файла измените путь: "CodeBase"="file:///C:\Dev\VBEAddIn\VBEAddIn\bin\Debug\VBEAddIn.dll"
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\VBA\VBE\6.0\Addins\VBEAddIn.Connect]
"CommandLineSafe"=dword:00000000
"Description"="Description for your new addin"
"LoadBehavior"=dword:00000000
"FriendlyName"="VBEAddIn"
[HKEY_CLASSES_ROOT\CLSID\{3599862B-FF92-42DF-BB55-DBD37CC13565}]
@="VBEAddIn.Connect"
[HKEY_CLASSES_ROOT\CLSID\{3599862B-FF92-42DF-BB55-DBD37CC13565}\Implemented Categories]
[HKEY_CLASSES_ROOT\CLSID\{3599862B-FF92-42DF-BB55-DBD37CC13565}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="VBEAddIn.Connect"
"Assembly"="VBEAddIn"
"RuntimeVersion"="v2.0.50727"
"CodeBase"="file:///C:\Dev\VBEAddIn\VBEAddIn\bin\Debug\VBEAddIn.dll"
[HKEY_CLASSES_ROOT\CLSID\{3599862B-FF92-42DF-BB55-DBD37CC13565}\ProgId]
@="VBEAddIn.Connect"
- Создайте надстройку VBE в Visual Studio и откройте Excel.
- Откройте редактор VBA (Alt + F11).
- Перейдите в меню "Надстройки", "Менеджер надстроек...", чтобы проверить правильность регистрации надстройки.
- Загрузите надстройку. Вы должны увидеть окно сообщения "VBEAddIn.Connect загружен в VBA редактор"
Если вы получили эту ошибку:
"VBEAddIn" не может быть загружен.
Удалить его из списка доступных надстроек?
Вероятно, вы не изменили путь "CodeBase" = "file: /// C: \ Dev \ VBEAddIn \ VBEAddIn \ bin \ Debug \ VBEAddIn.dll"
И убедитесь, что ключ CodeBase находится в реестре (добавьте строку regkey с CodeBase, если он не существует):
Затем закройте приложение Office, снова создайте VBE AddIn из Visual Studio, Open Office (Excel, Outlook, Word и т. Д.) И Alt + F11, меню AddIns> AddIn Manager и выберите AddIn и отметьте Loaded/UnLoaded.
Последний трюк, чтобы преодолеть эту проблему:
Если это не помогло, закройте приложение Office, перейдите в Visual Studio, Свойства проекта> Вкладка "Сборка"> "Регистрация тиков" для COM-взаимодействия> Построить решение и откройте "Надстройка Office"> "Alt + F11"> "Меню дополнений"> "Диспетчер надстроек" и нажмите "Загружен / выгружен".
В этом ответе используется некоторая информация из Кинтеро Карло (MZTools), которую я изменил, ссылка: http://www.mztools.com/articles/2012/MZ2012013.aspx
Я также нашел эту ссылку полезной при создании VBA DLL из C# или VB.NET:
Создайте новый C# (или VB.Net) проект и выберите Class Library в качестве типа шаблона.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SimpleCalc { public class Calc { private int numberOne = 0; private int numberTwo = 0; public void SetNumberOne(int number) { numberOne = number; } public void SetNumberTwo(int number) { numberTwo = number; } // Add two integers public int Add() { return numberOne + numberTwo; } } }
Настройте свойства проекта, чтобы сделать его видимым для COM.
- Зарегистрируйтесь для COM Interop.
- Скомпилируйте проект.
- Скопируйте файл библиотеки типов в системную папку Windows.
- Ссылка на библиотеку типов из редактора Access VBA.
Используйте DLL в своем коде VBA.
Public Function test() Dim lngResult As Long Dim objCalc As SimpleCalc.Calc Set objCalc = New SimpleCalc.Calc objCalc.SetNumberOne (3) objCalc.SetNumberTwo (6) lngResult = objCalc.Add() End Function
Сделано доступным GeeksEngine.com
Также позаботьтесь о том, чтобы Guid проекта (в случае C# в assamblyInfo.cs) отличался от Guid класса "Connect".
Наличие одинакового Guid приводит к ошибке "невозможно преобразовать в библиотеку типов" при проверке: Свойства проекта> Вкладка "Сборка"> Регистрация для COM-взаимодействия
Я полагаю, что вы можете вызвать.NET DLL из вашего кода VBA (на самом деле никогда не делал это сам). Просто создайте проект библиотеки классов VB и создайте DLL для использования в своем VBA.
После быстрого поиска в Google вы увидите, что вам нужно установить "Зарегистрироваться для Com Interop" = "Истина" в "Свойствах проекта" -> "Сборка", но, как я уже сказал, я никогда раньше не пробовал этого.
Я полностью согласен с ответом Джереми Томпсона выше. Однако я потратил часы, пытаясь заставить работать пример VBEAddin. Пока я не заметил в коде класса Connect, что атрибут ProgID был «VBEAddInVB.Net.Connect», но текст реестра, предназначенный для создания файла .reg, содержал все ссылки на имя программы как «VBEAddIn.Connect». Поэтому я попробовал изменить атрибут ProgId на «VBEAddIn.Connect» в классе Connect, перестроил его, и это сработало! Я считаю, что названия должны соответствовать друг другу. Я надеюсь, что это сэкономит другим время.