Создание надстройки для VBA IDE с помощью VB.NET

Я спрашивал об этом в другом месте, но так и не нашел, чтобы кто-нибудь знал, как создать надстройку для VBA IDE с помощью VB.NET. Это вообще возможно? Может ли кто-нибудь указать мне пример?


person Oorang    schedule 21.12.2009    source источник


Ответы (5)


Возможно, вам нужно написать надстройку com, используя интерфейс IDTExtensibility2, выберите общий шаблон проекта надстройки из нового проекта.

ИЗМЕНИТЬ

В противном случае, чтобы создать эту надстройку с нуля, вам нужно будет сделать следующее:

  1. Создайте новую библиотеку классов проекта
  2. Добавьте ссылки на "Расширяемость", она должна быть в списке. Возможно, вам потребуется загрузить PIA для вашей версии Office. (и, возможно, VSTO, но я не уверен в этом)
  3. Добавить ссылки на «Microsoft.Vbe.Interop» снова следует вместе с PIA.
  4. Установите флажок «Зарегистрироваться для Com Interop» на вкладке свойств.
  5. НЕОБЯЗАТЕЛЬНО На вкладке настроек отладки измените запуск на внешнюю программу и введите путь к excel exe в папке programfiles (если это предназначено для excel), чтобы разрешить отладку проекта.
  6. НЕОБЯЗАТЕЛЬНО В параметрах команды добавьте запись на рабочий лист или документ Word, который будет отображать диалоговое окно надстройки с помощью макроса при запуске. Для разработки это имеет смысл, чтобы упростить процесс отладки. например "C:\vbe.xlsm"
  7. НЕОБЯЗАТЕЛЬНО Также укажите путь запуска к каталогу рабочего листа, например, "C:\"
  8. Реализовать интерфейс «IDTExtensibility2», найденный в сборке «Расширяемость».
  9. Назовите этот класс "Connect" (это просто предпочтение)
  10. Атрибут класса со следующим

[ComVisible(true), Guid("YourGeneratedGuid"), ProgId("YourAddinName.Connect")]

Вот реализация, с которой можно начать. Сначала замените «YourAddinName» на ваше AppName и создайте Guid для «YourGeneratedGuid». Вам нужно будет зарегистрировать надстройку в правильном месте реестра, см. следующие разделы реестра, чтобы получить представление, а также заменить некоторые vars в разделах реестра.

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, который указан в атрибуте выше.

ПРИМЕЧАНИЕ

Также нашел это полезным, может сэкономить вам пару часов поиска в Google.

'HKEY_CURRENT_USER\Software\Microsoft\VBA\6.0\Common
'FontFace=Courier New (STRING - Default if missing)
'FontHeight=10 (DWORD - Default if missing)                
person almog.ori    schedule 21.12.2009
comment
Привет, Ори, проблема, с которой я столкнулся, заключается в том, что я использую экспресс-версию VB.Net. Одним из ограничений версии Express является сокращенный набор шаблонов. Я полагаю, вы все еще можете это сделать, вам просто нужно создать его с нуля. Любые идеи, с чего начать? Я проверил ресурсы MZ-Tools, но их информация не применима к VBA IDE из .Net. Это проблема, которую я продолжаю бить везде. Вся информация, которую я могу найти, это re:VB6. - person Oorang; 22.12.2009
comment
Вау, это довольно много. +1 за усилия. Мне нужно время, чтобы попробовать это, если работает, я соглашусь :) Спасибо :) - person Oorang; 23.12.2009
comment
Привет ORI, извините за задержку. Я болезненно новичок в этом, поэтому, пожалуйста, потерпите меня. Я начал попытку реализовать эти инструкции, и первым препятствием, с которым я столкнулся, было то, что (используя экспресс-версию VB 2010 года) нет доступного общего шаблона проекта надстройки (ни в онлайн-коллекции). Я знаю, что он есть в полной версии VS, поэтому я предполагаю, что он просто отсутствует в дополнении Express. Вы знаете обходной путь к этой проблеме? Извините, что усложняю ситуацию. - person Oorang; 29.12.2009

К сожалению, шаги almog.ori мне не помогли. Вот моя версия, чтобы помочь людям в будущем:

  1. Создайте проект библиотеки классов C# или VB.NET с именем «VBEAddIn».

    Добавьте следующие сборки Interop в качестве ссылок на проект, используя меню «Проект», «Добавить ссылку...», вкладку «Обзор».

  2. Расширяемость (C:\Program Files\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Common\Extensibility.dll) — если ее нет, попробуйте C:\Program Files (x86)\, если вы используете x64 ПК.

  3. Microsoft.Office.Interop.Excel (C:\Program Files\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14\Microsoft.Office.Interop.Excel.dll)

  4. Microsoft.Vbe.Interop (C:\Program Files\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Office14\Microsoft.Vbe.Interop.dll)

  5. (необязательно) Microsoft.Vbe.Interop.Forms (C:\Program Files\Microsoft Visual Studio 10.0\Visual Studio Tools for 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

С#:

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
    }
}

В окне свойств проекта проекта:

  1. На вкладке «Приложение» убедитесь, что для имени сборки и корневого пространства имен задано значение «VBEAddIn».

  2. На вкладке «Компиляция» убедитесь, что установлен флажок «Зарегистрировать для COM-взаимодействия». Мы не будем регистрировать сборку для COM Interop вручную с помощью соответствующего инструмента regasm.exe. Однако обратите внимание, что флажок «Зарегистрировать для COM-взаимодействия» регистрирует надстройку dll только как 32-разрядную библиотеку COM, а не как 64-разрядную библиотеку COM.

  3. На вкладке «Компиляция» нажмите кнопку «Дополнительные параметры компиляции» и убедитесь, что в поле со списком «Целевой ЦП» установлено значение «Любой ЦП», что означает, что сборка может выполняться как 64-битная или 32-битная, в зависимости от исполняемого .NET Framework, который его загружает.

  4. На вкладке «Подписание» убедитесь, что флажок «Подписать сборку» не установлен.

Затем добавьте ключи реестра, сохраните приведенный ниже фрагмент как файл 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"
  1. Создайте надстройку VBE в Visual Studio и откройте Excel.
  2. Откройте его редактор VBA (Alt + F11).
  3. Перейдите в меню «Надстройки», «Диспетчер надстроек...», чтобы проверить правильность регистрации надстройки.
  4. Загрузите надстройку. Вы должны увидеть окно сообщения «VBEAddIn.Connect загружен в редакторе VBA».

Если вы получили эту ошибку:

введите здесь описание изображения

«VBEAddIn» не может быть загружен.

Удалить его из списка доступных надстроек?

Вероятно, вы не изменили путь "CodeBase"="file:///C:\Dev\VBEAddIn\VBEAddIn\bin\Debug\VBEAddIn.dll"

И убедитесь, что ключ CodeBase находится в реестре (добавьте строку regkey с CodeBase, если он не существует):

введите здесь описание изображения

Затем закройте приложение Office, снова создайте надстройку VBE из Visual Studio, откройте Office (Excel, Outlook, Word и т. д.) и нажмите Alt + F11, меню надстроек > Диспетчер надстроек и выберите надстройку и установите флажок Загружено/Выгружено.

Последний прием для решения этой проблемы:

Если это по-прежнему не удается, закройте приложение Office, перейдите в Visual Studio, выберите «Свойства проекта» > вкладка «Сборка» > установите флажок «Регистрация для COM-взаимодействия» > «Создать решение» и откройте надстройку Office > Alt + F11 > Меню надстроек > Диспетчер надстроек и нажмите «Загружено/Выгружено».


В этом ответе используется некоторая информация из Quintero Карло (MZTools), которую я изменил, ссылка: http://www.mztools.com/articles/2012/MZ2012013.aspx

person Jeremy Thompson    schedule 02.09.2013

Я также нашел эту ссылку полезной при создании DLL VBA из С# или VB.NET:

  1. Создайте новый проект C# (или VB.Net) и выберите библиотеку классов в качестве типа шаблона.

    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;
            }
        }
    }
    
  2. Настройте свойства проекта, чтобы сделать его COM-видимым.

  3. Зарегистрируйтесь для COM-взаимодействия.
  4. Скомпилируйте проект.
  5. Скопируйте файл библиотеки типов в системную папку Windows.
  6. Ссылка на библиотеку типов из редактора Access VBA.
  7. Используйте 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

person Curtis Inderwiesche    schedule 02.03.2012

Я бы предположил, что вы можете вызвать .NET DLL из своего кода VBA (сам никогда этого не делал). Просто создайте проект библиотеки классов VB и создайте DLL для использования в вашем VBA.

После быстрого поиска в Google кажется, что вам нужно установить «Регистрация для Com Interop» = True в разделе «Свойства проекта» -> «Сборка», но, как я уже сказал, я никогда раньше не пробовал этого.

person Seth Moore    schedule 21.12.2009
comment
Я думаю, что он ищет надстройку для самой среды разработки. - person almog.ori; 22.12.2009

Также позаботьтесь о том, чтобы Guid проекта (в случае c# в assamblyInfo.cs) отличался от Guid класса Connect.

Наличие одного и того же Guid приводит к ошибке «не удалось преобразовать в библиотеку типов» при проверке: «Свойства проекта» > «Вкладка «Сборка»» > «Зарегистрировать для COM-взаимодействия».

person Gener4tor    schedule 11.07.2018