簡體   English   中英

使用VB.NET為VBA IDE構建加載項

[英]Build add-in for VBA IDE using VB.NET

我在其他地方問了這個問題,但是從來沒有發現任何人知道如何使用VB.NET為VBA IDE構建一個加載項。 它甚至可能嗎? 有人能給我一個例子嗎?

您可能需要使用IDTExtensibility2接口編寫com插件,從新項目中選擇共享插件項目模板。

編輯

否則,要從頭開始創建此插件,您需要執行以下操作:

  1. 創建一個新的項目類庫
  2. 添加對“可擴展性”的引用,它應該在列表中。 您可能需要為您的辦公室版本下載PIA。 (也許是VSTO,但我不確定這一點)
  3. 再次添加對“Microsoft.Vbe.Interop”的引用應該與PIA一起使用。
  4. 選中屬性選項卡中的“注冊Com Interop”框。
  5. 可選在調試設置選項卡中,將啟動更改為外部程序,並在programfiles文件夾中輸入excel exe的路徑(如果這是針對excel的),這是為了允許項目可調試。
  6. 可選在命令選項中,在工作表中添加一個條目,或者在啟動時使用宏顯示addin對話框的word文檔,以便進行開發,這樣可以簡化調試體驗。 例如“C:\\ vbe.xlsm”
  7. 可選還設置工作表目錄的啟動路徑,例如“C:\\”
  8. 實現“可擴展性”程序集中的“IDTExtensibility2”接口。
  9. 將此類命名為“Connect”(這只是一個偏好)
  10. 使用以下內容對類進行屬性

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

下面是一個讓你入門的實現,首先用你的AppName替換“YourAddinName”並為“YourGeneratedGuid”創建一個Guid。 您需要將Addin注冊到正確的注冊表位置,查看后面的注冊表項以獲取想法,還要替換注冊表項中的一些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

這是注冊Addin的注冊表.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”必須包含大括號{}並且與上面attrib中的Guid相同,標記“YourAssemblyNameFullTypeName”必須是程序集全名,標記“YourAddinName.Connect”必須是相同的ProgId設置在上面的attrib。

邊注

也發現這有用,可能會節省你幾個小時的谷歌搜索。

'HKEY_CURRENT_USER\Software\Microsoft\VBA\6.0\Common
'FontFace=Courier New (STRING - Default if missing)
'FontHeight=10 (DWORD - Default if missing)                

不幸的是almog.ori的步驟對我不起作用。 這是我的版本,以幫助未來的人們:

  1. 創建名為“VBEAddIn”的C#或VB.NET類庫項目

    使用“項目”,“添加引用...”菜單,“瀏覽”選項卡添加以下Interop程序集作為對項目的引用。

  2. 可擴展性(C:\\ Program Files \\ Microsoft Visual Studio 10.0 \\ Visual Studio工具用於Office \\ PIA \\ Common \\ Extensibility.dll) - 如果它不在那里嘗試C:\\ Program Files(x86)\\如果您使用的是x64 PC。

  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工具用於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
    }
}

在項目的“項目屬性”窗口中:

  1. 在“應用程序”選項卡中,確保程序集名稱和根命名空間都設置為“VBEAddIn”。

  2. 在“編譯”選項卡中,確保選中“注冊COM互操作”復選框。 我們不會為使用正確的regasm.exe工具手動注冊COM Interop程序集而煩惱。 但請注意,“注冊COM互操作”復選框只會將加載項dll注冊為32位COM庫,而不是64位COM庫。

  3. 在“編譯”選項卡的“高級編譯選項”按鈕中,確保“目標CPU”組合框設置為“AnyCPU”,這意味着程序集可以執行為64位或32位,具體取決於執行加載它的.NET Framework。

  4. 在“簽名”選項卡中,確保未簽名“簽署程序集”。

接下來添加注冊表項,將下面的代碼段保存為帶有reg擴展名的ASCI文件,然后雙擊它將值添加到注冊表中。

重要說明:在執行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. 在Visual Studio中構建VBE加載項並打開Excel。
  2. 打開其VBA編輯器(Alt + F11)。
  3. 轉到“加載項”,“加載項管理器...”菜單以檢查加載項是否已正確注冊。
  4. 加載加載項。 您應該看到消息框“在VBA編輯器中加載VBEAddIn.Connect”

如果您收到此錯誤:

在此輸入圖像描述

無法加載'VBEAddIn'。

從可用的加載項列表中刪除它?

它可能你沒有改變路徑“CodeBase”=“file:/// C:\\ Dev \\ VBEAddIn \\ VBEAddIn \\ bin \\ Debug \\ VBEAddIn.dll”

並檢查CodeBase密鑰是否在注冊表中(如果CodeBase不存在,則添加一個帶有CodeBase的字符串regkey):

在此輸入圖像描述

然后關閉Office應用程序,再次從Visual Studio,Open Office(Excel,Outlook,Word等)和Alt + F11,AddIns菜單> AddIn Manager構建VBE AddIn,並選擇AddIn和Tick Loaded / UnLoaded。

最后的伎倆克服這個問題:

如果仍然失敗,請關閉Office應用程序,轉到Visual Studio,項目屬性>構建選項卡>勾選注冊COM Interop>構建解決方案,然后打開Office添加> Alt + F11> AddIns菜單> AddIn Manager,然后單擊已加載/已卸載。


這個答案使用了我修改過的Carlo's Quintero(MZTools)中的一些信息,參考: http ://www.mztools.com/articles/2012/MZ2012013.aspx

我還發現這個引用有助於從C#或VB.NET制作VBA DLL:

  1. 創建一個新的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; } } } 
  2. 配置項目屬性以使其可見。

  3. 注冊COM Interop。
  4. 編譯項目。
  5. 將類型庫文件復制到Windows系統文件夾。
  6. 從Access VBA編輯器引用類型庫。
  7. 在VBA代碼中使用DLL。

     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提供

我想你可以從你的VBA代碼中調用一個.NET DLL(我自己從未真正做過)。 只需創建一個VB類庫項目並創建一個在VBA中使用的DLL。

快速谷歌之后看起來你需要在Project Properties-> Build下設置“Register for Com Interop”= True,但就像我說的那樣,我以前從未嘗試過這個。

還要注意項目的Guid(在assamblyInfo.cs中的c#的情況下)與類“Connect”的Guid不同。

在檢查時,具有相同的Guid導致“無法轉換為類型庫” - 錯誤:項目屬性>構建選項卡>注冊COM Interop

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM