Принудительная загрузка надстройки в Excel / автоматизация - PullRequest
0 голосов
/ 28 октября 2019

У меня есть надстройка Excel Automation, предоставляющая набор пользовательских функций. Я хочу, чтобы эти пользовательские функции работали даже при открытии Excel через Interop API. Я знаю, что при открытии Excel через Interop APIs Excel запускается с параметром /automation, который заставляет Excel не загружать надстройки . Чтобы противостоять этому, я добавил следующее событие Workbook_Open():

Private Sub Workbook_Open()
    Application.AddIns("SomeApp.DemoAddin").Installed = False
    Application.AddIns("SomeApp.DemoAddin").Installed = True
End Sub

Этот код успешно загружает надстройку. Я проверил это, используя некоторые записи в надстройке.

Я собрал тестовую рабочую книгу, которая вызывает UDF =myDemoFunction(). При открытии этой книги с помощью "C:\path\to\EXCEL.exe" /automation C:\path\to\workbook.xlsm я наблюдаю следующее поведение. Сначала ячейка с UDF отображает правильный результат (в данном случае «15.0»). Тем не менее, формула отображается как =SomeApp.DemoAddin.myDemoFunction(), что обычно имеет место только тогда, когда надстройка не загружена. При выполнении пересчета с помощью CTRL+ALT+F9 или Application.CalculationFullRebuild в VBA или даже при маркировке всех заполненных ячеек как грязных с использованием ThisWorkbook.Worksheets(1).UsedRange.Dirty все ячейки с UDF отображают #NAME?. При редактировании одной из ячеек UDF (выберите F2, Return), тогда все UDF на этом одном листе (не на других листах, также использующих этот UDF) неожиданно снова вернут правильный результат, и формула снова изменится на =myDemoFunction().

Итак, мой вопрос: как я могу заставить Excel распознавать надстройку программным способом?


Моя база кода намного больше, но ниже приведена урезанная версия Automationнадстройка, показывающая это поведение (в VB.net):

Imports Extensibility
Imports System.Runtime.InteropServices
Imports Excel = Microsoft.Office.Interop.Excel

<GuidAttribute("352B1C10-DC5A-4BF8-9D31-DB9913B07364"),
ProgIdAttribute("SomeApp.DemoAddin"),
ClassInterface(ClassInterfaceType.AutoDual)>
Public Class DemoAddin
    Implements IDTExtensibility2

    Private excelApp As Excel.Application

    Public Sub OnBeginShutdown(ByRef custom As Array) Implements IDTExtensibility2.OnBeginShutdown
    End Sub
    Public Sub OnAddInsUpdate(ByRef custom As Array) Implements IDTExtensibility2.OnAddInsUpdate
    End Sub
    Public Sub OnStartupComplete(ByRef custom As Array) Implements IDTExtensibility2.OnStartupComplete
    End Sub

    Public Sub OnDisconnection(RemoveMode As ext_DisconnectMode, ByRef custom As Array) Implements IDTExtensibility2.OnDisconnection
        Marshal.ReleaseComObject(excelApp)
        excelApp = Nothing
    End Sub

    Public Sub OnConnection(application As Object, connectMode As ext_ConnectMode, addInInst As Object, ByRef custom As Array) Implements IDTExtensibility2.OnConnection
        excelApp = CType(application, Excel.Application)
    End Sub

    Public Function myDemoFunction() As String
        Return excelApp.Version
    End Function
End Class

1 Ответ

0 голосов
/ 28 октября 2019

Достаточно вызвать все UDF, которые не работают с VBA. Так что обновленный Workbook_Open() делает свое дело. Приведенный ниже код также делает некоторые попытки не перезагружать надстройку без необходимости, но это , а не необходимо. Настоящая магия находится во второй последней строке Application.Run "myDemoFunction".

Private Sub Workbook_Open()
    ensureAddinLoaded
End Sub

Public Sub ensureAddinLoaded()
    Debug.Print "Probing for addin"
    On Error GoTo NotLoaded
    Application.Run "myDemoFunction"
    Exit Sub
NotLoaded:
    Debug.Print "Addin not loaded. Reloading."
    Application.AddIns("SomeApp.DemoAddin").Installed = False
    Application.AddIns("SomeApp.DemoAddin").Installed = True
    Application.Run "myDemoFunction"
End Sub

Это решение требует знания того, какие существуют UDF, поэтому оно неоптимально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...