exponenta event banner

Интеграция компонентов с помощью приложения Visual Basic

Когда использовать функцию формулы или подпрограмму

VBA предоставляет два основных типа процедур: функции и подпрограммы.

Доступ к функции VBA осуществляется непосредственно из ячейки документа в качестве формульной функции. Используйте функциональные процедуры, когда исходная функция MATLAB ® принимает один или несколько входов и возвращает нулевые выходы.

Доступ к подпрограмме осуществляется как к общему макросу. Используйте процедуру подпрограммы, когда исходная функция MATLAB возвращает массив значений или несколько выходов, поскольку необходимо сопоставить эти выходы в нескольких ячейках/диапазонах в документе.

При создании компонента MATLAB Compiler™ создает модуль VBA (.bas файл). Этот файл содержит простые оболочки вызовов, каждая из которых реализована как функциональная процедура для каждого метода класса.

Инициализация библиотек компиляторов MATLAB с помощью Microsoft Excel

Перед использованием любого компонента компилятора MATLAB инициализируйте библиотеки поддержки с текущим экземпляром Microsoft ® Excel ®. Сделайте это один раз для сеанса Excel, в котором используются компоненты компилятора MATLAB.

Для выполнения инициализации вызовите функцию библиотеки утилит. MWInitApplication, который является членом MWUtil класс. Этот класс является частью MWComUtil библиотека. См. Класс MWUtil.

Одним из способов добавления этого кода инициализации в модуль VBA является предоставление подпрограммы, которая выполняет инициализацию один раз и просто выходит для всех последующих вызовов. Следующий пример кода Microsoft Visual Basic ® инициализирует библиотеки с текущим экземпляром Excel. Глобальная переменная типаObject названный MCLUtil содержит экземпляр MWUtil класс и другая глобальная переменная типа Boolean названный bModuleInitialized сохраняет статус процесса инициализации. Частная подпрограмма InitModule() создает экземпляр MWComUtil класс и вызывает MWInitApplication метод с аргументом Application. После успешного выполнения этой функции все последующие вызовы завершаются без повторной инициализации.

Dim MCLUtil As Object
Dim bModuleInitialized As Boolean

Private Sub InitModule()
   If Not bModuleInitialized Then
      On Error GoTo Handle_Error
      If MCLUtil Is Nothing Then
         Set MCLUtil = CreateObject("MWComUtil.MWUtil")
      End If
      Call MCLUtil.MWInitApplication(Application)
      bModuleInitialized = True
      Exit Sub
Handle_Error:
      bModuleInitialized = False
   End If
End Sub

Этот код аналогичен коду инициализации по умолчанию, сгенерированному в модуле VBA, созданном при построении компонента. Каждая функция, использующая компоненты компилятора MATLAB, может включать вызов InitModule в начале, чтобы гарантировать, что инициализация всегда выполняется по мере необходимости.

Создание экземпляра класса

Обзор

Перед вызовом метода класса (скомпилированная функция MATLAB) необходимо создать экземпляр класса, который содержит метод. Для этого VBA предлагает два метода:

Функция CreateObject

Этот метод использует интерфейс прикладного программирования (API) Microsoft Visual Basic CreateObject для создания экземпляра класса. Microsoft ссылается на вызов CreateObject как на позднюю привязку и использование new как раннее связывание.

Для использования этого метода объявите переменную типа Object использование Dim для удержания ссылки на экземпляр класса и вызова CreateObject по программному идентификатору класса (ProgID) в качестве аргумента, как показано в следующем примере:

Function foo(x1 As Variant, x2 As Variant) As Variant
       Dim aClass As Object
	 
       On Error Goto Handle_Error
       Set aClass = CreateObject("mycomponent.myclass.1_0") 
       ' (call some methods on aClass)
       Exit Function
Handle_Error:
   foo = Err.Description
End Function 

Новый оператор

Этот метод использует Visual Basic New для переменной, явно определяемой как создаваемый класс. Перед использованием этого метода необходимо сослаться на библиотеку типов, содержащую класс в текущем проекте VBA. Для этого выберите меню Сервис (Tools) в редакторе Visual Basic, а затем выберите Ссылки (References), чтобы отобразить список Доступные ссылки (Available References). В этом списке выберите нужную библиотеку типов.

Следующий пример иллюстрирует использование New для создания экземпляра класса. Предполагается, что перед  вызовом этой функции в списке Доступные ссылки (Available References) выбрана библиотека типов mycomponent 1.0.

Function foo(x1 As Variant, x2 As Variant) As Variant
   Dim aClass As mycomponent.myclass

   On Error Goto Handle_Error
   Set aClass = New mycomponent.myclass
   ' (call some methods on aClass)
   Exit Function
Handle_Error:
   foo = Err.Description
End Function 

В этом примере экземпляр класса можно определить как простой myclass. Полная декларация в форме <component-name>.<class-name> защищает от конфликтов имен, которые могут возникнуть, если другие библиотеки в текущем проекте содержат типы с именами myclass.

Использование обоих CreateObject и New создайте экземпляр класса с размерами. Первый метод не требует ссылки на библиотеку типов в проекте VBA; второе приводит к более быстрому выполнению кода. Второй метод обладает дополнительным преимуществом, заключающимся в том, что в редакторе Microsoft Visual Basic для работы с классами доступны функции автоматического списка участников и автоматической всплывающей информации. Оболочки функций по умолчанию, созданные с каждым встроенным компонентом, используют первый метод создания объекта.

В двух предыдущих примерах экземпляр класса, использовавшийся для вызова метода, был локальной переменной процедуры. Это создает и уничтожает новый экземпляр класса для каждого вызова. Альтернативный подход заключается в объявлении одного экземпляра класса в области модуля, который повторно используется всеми вызовами функций, как в коде инициализации предыдущего примера.

Следующий пример иллюстрирует этот метод со вторым методом:

Dim aClass As mycomponent.myclass

Function foo(x1 As Variant, x2 As Variant) As Variant
   On Error Goto Handle_Error
   If aClass Is Nothing Then
      Set aClass = New mycomponent.myclass
   End If
   ' (call some methods on aClass)
   Exit Function
Handle_Error:
   foo = Err.Description
End Function

Способ совместного использования среды выполнения MATLAB классами

Компилятор MATLAB создает один экземпляр среды выполнения MATLAB при создании экземпляра первого COM-класса Microsoft в приложении. Эта среда выполнения MATLAB используется повторно и совместно используется всеми последующими экземплярами класса в компоненте, что приводит к более эффективному использованию памяти и исключению затрат на запуск среды выполнения MATLAB в каждом последующем экземпляре класса.

Все экземпляры класса совместно используют одну рабочую область MATLAB и глобальные переменные в файлах MATLAB, используемых для построения компонента. Это заставляет свойства COM-класса вести себя как статические свойства, а не как свойства экземпляра.

Вызов методов экземпляра класса

После создания экземпляра класса можно вызвать методы класса для доступа к скомпилированным функциям MATLAB. Компилятор MATLAB применяет стандартное сопоставление из исходного синтаксиса функции MATLAB к списку аргументов метода. Подробное описание отображения функций MATLAB на вызовы методов COM-классов см. в разделе Справочные классы утилит.

Если метод имеет выходные аргументы, первый аргумент всегда nargout, который имеет тип Long. Этот входной параметр передает нормальный MATLAB nargout параметр для скомпилированной функции и указывает, сколько выходов запрашивается. Методы, не имеющие выходных аргументов, не передают nargout аргумент. Следующее nargout - выходные параметры, перечисленные в том же порядке, в котором они отображаются в левой части исходной функции MATLAB. Далее следуют входные параметры, перечисленные в том же порядке, что и в правой части исходной функции MATLAB. Все входные и выходные аргументы набраны как Variant, тип данных Visual Basic по умолчанию.

Variant тип может содержать любые базовые типы VBA, массивы любого типа и ссылки на объекты. Подробное описание способа преобразования см. в разделе Правила преобразования данных. Variant типы любого базового типа для типов данных MATLAB и из них. Как правило, в качестве аргумента метода класса можно указать любой тип Visual Basic, за исключением Visual Basic. UDTс. Также можно передать Microsoft Excel Range непосредственно в качестве входных и выходных аргументов.

Когда вы проходите простой Variant тип в качестве выходного параметра, вызываемый метод распределяет полученные данные и освобождает исходное содержимое Variant. В этом случае достаточно измерить каждый выходной аргумент как один Variant. Когда тип объекта (например, Excel Range) передается как выходной параметр, ссылка на объект передается в обоих направлениях, и объект Value свойство получает данные.

Следующие примеры иллюстрируют процесс передачи входных и выходных параметров из VBA в методы класса компонентов компилятора MATLAB.

Первый пример - функция формулы, которая принимает два входа и возвращает один выход. Эта функция отправляет вызов метода класса, соответствующего функции MATLAB формы. function y = foo(x1,x2).

Function foo(x1 As Variant, x2 As Variant) As Variant
   Dim aClass As Object
   Dim y As Variant
   
   On Error Goto Handle_Error
   Set aClass = New mycomponent.myclass
   aClass = CreateObject("mycomponent.myclass.1_0")
   Call aClass.foo(1,y,x1,x2)
   foo = y
   Exit Function
Handle_Error:
   foo = Err.Description
End Function

Второй пример перезаписывает ту же функцию, что и подпрограмма, и использует диапазоны Excel для ввода и вывода.

Sub foo(Rout As Range, Rin1 As Range, Rin2 As Range)
   Dim aClass As Object

   On Error Goto Handle_Error
   aClass = CreateObject("mycomponent.myclass.1_0")
   Call aClass.foo(1,Rout,Rin1,Rin2)
   Exit Sub
Handle_Error:
   MsgBox(Err.Description)
End Sub

Программа с переменными аргументами

Процесс вараргин и вараргоут Аргументы

Когда varargin и/или varargout присутствуют в функции MATLAB, используемой для компонента Excel, эти параметры добавляются в список аргументов метода класса в качестве последних параметров ввода/вывода в списке. Можно передать несколько аргументов как varargin путем создания массива Variant , присваивая каждый элемент массива соответствующему входному аргументу.

В следующем примере создается varargin массив для вызова метода, полученного из функции MATLAB формы y = foo(varargin):

Function foo(x1 As Variant, x2 As Variant, x3 As Variant, _ 
             x4 As Variant, x5 As Variant) As Variant 
   Dim aClass As Object 
   Dim v As Variant 
   Dim y As Variant 
   Dim MCLUtil As Object 
    
   On Error GoTo Handle_Error 
   set aClass = CreateObject("mycomponent.myclass.1_0") 
   Set MCLUtil = CreateObject("MWComUtil.MWUtil") 
   Call MCLUtil.MWPack(v, x1, x2, x3, x4, x5) 
   Call aClass.foo(1, y, v) 
   foo = y 
   Exit Function 
Handle_Error: 
   foo = Err.Description 
End Function 

MWUtil класс включен в MWComUtil библиотека утилит обеспечивает MWPack вспомогательная функция для создания varargin параметры. Дополнительные сведения см. в разделе Класс MWUtil.

Следующий пример обрабатывает varargout параметр в три отдельных элемента Excel Ranges. Эта функция использует MWUnpack в библиотеке утилит. Используется функция MATLAB varargout = foo(x1,x2).

Sub foo(Rout1 As Range, Rout2 As Range, Rout3 As Range, _
        Rin1 As Range, Rin2 As Range)
   Dim aClass As Object
   Dim aUtil As Object
   Dim v As Variant
    
   On Error Goto Handle_Error
   aUtil = CreateObject("MWComUtil.MWUtil")
   aClass = CreateObject("mycomponent.myclass.1_0")
   Call aClass.foo(3,v,Rin1,Rin2)
   Call aUtil.MWUnpack(v,0,True,Rout1,Rout2,Rout3)
   Exit Sub
Handle_Error:
   MsgBox(Err.Description)
End Sub

Передать пустой вараргин из кода Microsoft Visual Basic

В MATLAB, varargin входы в функции являются необязательными и могут присутствовать или отсутствовать в вызове функции. Однако из Microsoft Visual Basic сигнатуры функций более строгие - еслиvarargin присутствует среди входов функции MATLAB, вызов VBA должен включать varargin, даже если ты хочешь, чтобы он был пуст. Для передачи пустого varargin, пройти Null вариант, который при передаче преобразуется в пустой массив ячеек MATLAB.

Передача пустого вараргина из кода VBA.  Следующий пример иллюстрирует передачу варианта NULL для передачи пустого varargin:

Function foo(x1 As Variant, x2 As Variant, x3 As Variant, _ 
             x4 As Variant, x5 As Variant) As Variant 
   Dim aClass As Object 
   Dim v(1 To 5) As Variant 
   Dim y As Variant 
    
   On Error Goto Handle_Error 
   v(1) = x1 
   v(2) = x2 
   v(3) = x3 
   v(4) = x4 
   v(5) = x5 
   aClass = CreateObject("mycomponent.myclass.1_0") 

   'Call aClass.foo(1,y,v) 
   Call aClass.foo(1,y,Null) 

   foo = y 
   Exit Function 
Handle_Error: 
   foo = Err.Description 
End Function

Для получения дополнительной информации

Дополнительные сведения о работе с аргументами переменной длины см. в разделе Работа с входами и выходами переменной длины.

Изменить флаги

Обзор

Каждый компонент компилятора MATLAB предоставляет одно свойство чтения/записи с именем MWFlags типа MWFlags. MWFlags свойство состоит из двух наборов констант:   флагов форматирования массива и   флагов преобразования данных. Флаги форматирования массива влияют на преобразование массивов, в то время как флаги преобразования данных имеют отношение к преобразованиям типов отдельных элементов массива.

Флаги преобразования данных изменяют выбранное поведение процесса преобразования данных из Variants для типов MATLAB и наоборот. По умолчанию компоненты компилятора MATLAB позволяют устанавливать флаги преобразования данных на уровне класса через MWFlags свойство класса. Это справедливо для всех типов Visual Basic, за исключением компилятора MATLAB MWStruct, MWField, MWComplex, MWSparse, и MWArg типы. Каждый из этих типов предоставляет свой собственный MWFlags и игнорирует свойства класса, метод которого вызывается. MWArg класс предоставляется специально для случая, когда для конкретного аргумента требуются параметры, отличные от свойств класса по умолчанию.

В этом разделе представлено общее обсуждение того, как устанавливать эти флаги и что они делают. Подробное обсуждение см. в разделе Class MWFlags (MATLAB Compiler SDK) MWFlags тип, а также дополнительные образцы кода.

Флаги форматирования массива

Флаги форматирования массива определяют преобразование данных для создания массива ячеек MATLAB или матрицы из общего Variant данные на входе или для создания массива Variants или одиночный Variant содержит массив базового типа на выходе.

Следующие примеры предполагают, что вы ссылаетесь на MWComUtil в текущем проекте выберите «Сервис» > «Ссылки» и выберите «Библиотека типов MWComUtil 7.5» из списка:

Sub foo( )
   Dim aClass As mycomponent.myclass
   Dim var1(1 To 2, 1 To 2), var2 As Variant
   Dim x(1 To 2, 1 To 2) As Double
   Dim y1,y2 As Variant
   
   On Error Goto Handle_Error
   var1(1,1) = 11#
   var1(1,2) = 12#
   var1(2,1) = 21#
   var1(2,2) = 22#
   x(1,1) = 11
   x(1,2) = 12
   x(2,1) = 21
   x(2,2) = 22
   var2 = x
   Set aClass = New mycomponent.myclass
   Call aClass.foo(1,y1,var1)
   Call aClass.foo(1,y2,var2)
   Exit Sub
Handle_Error:
   MsgBox(Err.Description)
End Sub

Кроме того, в этих примерах предполагается, что вы ссылаетесь на COM-объект, созданный с помощью компилятора MATLAB (mycomponent), как указано в разделе «Новый оператор».

Вот, два Variant переменные, var1 и var2 строятся с одинаковыми числовыми данными, но внутренне они структурированы по-разному: var1 является массивом 2 на 2 Variants с каждым элементом, содержащим 1 на 1 Double, пока var2 является 1 на 1 Variant содержащий массив 2 на 2 Doubles.

В компиляторе MATLAB при использовании настроек по умолчанию оба этих массива будут преобразованы в массивы 2 на 2 из doubles. Это не соответствует общему соглашению, приведенному в COM VARIANT к правилам преобразования MATLAB. Согласно этим правилам, var1 преобразуется в массив ячеек 2 на 2, при этом каждая ячейка занята двойником 1 на 1, и var2 преобразует непосредственно в двойную матрицу 2 на 2.

Оба массива преобразуются в двойные матрицы, поскольку значение по умолчанию для InputArrayFormat флаг - mwArrayFormatMatrix. InputArrayFormat флаг управляет обработкой массивов этих двух типов. Это значение по умолчанию используется, поскольку данные массива, полученные из диапазонов Excel, всегда имеют вид массива Variants (как var1 предыдущего примера), а функции MATLAB чаще всего имеют дело с аргументами матрицы.

Но что, если вам нужен массив ячеек? В этом случае устанавливается InputArrayFormat флаг для mwArrayFormatCell. Для этого добавьте следующую строку после создания класса и перед вызовом метода:

aClass.MWFlags.ArrayFormatFlags.InputArrayFormat = 
mwArrayFormatCell

Установка этого флага представляет все входные данные массива для скомпилированной функции MATLAB в виде массивов ячеек.

Аналогично, можно манипулировать форматом выходных аргументов с помощью OutputArrayFormat флаг. Можно также изменить выходные данные массива с помощью AutoResizeOutput и TransposeOutput флаги.

AutoResizeOutput используется для Excel Range объекты, передаваемые непосредственно в качестве выходных параметров. При установке этого флажка целевой диапазон автоматически изменяется в соответствии с размером результирующего массива. Если этот флаг не установлен, целевой диапазон должен быть по крайней мере таким же большим, как выходной массив, или данные усечены.

TransposeOutput флаг транспонирует все выходные данные массива. Этот флаг полезен при работе с функциями MATLAB, которые выводят одномерные массивы. По умолчанию MATLAB реализует одномерные массивы как матрицы 1 на n (векторы строк), которые становятся строками на листе Excel.

Совет

Например, если функция MATLAB специально возвращает вектор строки, убедитесь, что в Excel назначен аналогичный вектор строки ячеек.

Можно выбрать столбцы листа из вывода вектора строки. В этом примере автоматически изменяется и переносится диапазон выходных данных:

Sub foo(Rout As Range, Rin As Range )
   Dim aClass As mycomponent.myclass

   On Error Goto Handle_Error
   Set aClass = New mycomponent.myclass
   aClass.MWFlags.ArrayFormatFlags.AutoResizeOutput = True
   aClass.MWFlags.ArrayFormatFlags.TransposeOutput = True
   Call aClass.foo(1,Rout,Rin)
   Exit Sub
Handle_Error:
   MsgBox(Err.Description)
End Sub

Флаги преобразования данных

Флаги преобразования данных имеют отношение к преобразованиям типов отдельных элементов массива. два флага преобразования данных, CoerceNumericToType и InputDateFormat, определяет способ преобразования числовых типов и типов дат из VBA в MATLAB. Рассмотрим пример:

Sub foo( )
   Dim aClass As mycomponent.myclass
   Dim var1, var2 As Variant
   Dim y As Variant
   
   On Error Goto Handle_Error
   var1 = 1
   var2 = 2#
   Set aClass = New mycomponent.myclass
   Call aClass.foo(1,y,var1,var2)
   Exit Sub
Handle_Error:
   MsgBox(Err.Description)
End Sub

В этом примере выполняется преобразование var1 типа Variant/Integer в int16 и var2 типа Variant/Double в double.

Если ожидается исходная функция MATLAB doubles для обоих аргументов, этот код может привести к ошибке. Одним из решений является присвоение double кому var1, но это может быть невозможно или желательно. В таком случае установить CoerceNumericToType флаг для mwTypeDouble, заставляя преобразователь данных преобразовывать все числовые входные данные в double. В предыдущем примере после создания класса и перед вызовом методов поместите следующую строку:

aClass.MWFlags.DataConversionFlags.CoerceNumericToType = 
mwTypeDouble

InputDateFormat флаг управляет тем, как VBA Date тип преобразуется. Этот пример отправляет текущую дату и время в качестве входного аргумента и преобразует их в строку:

Sub foo( )
   Dim aClass As mycomponent.myclass
   Dim today As Date
   Dim y As Variant
   
   On Error Goto Handle_Error
   today = Now
   Set aClass = New mycomponent.myclass
   aClass. MWFlags.DataConversionFlags.InputDateFormat = 
mwDateFormatString
   Call aClass.foo(1,y,today)
   Exit Sub
Handle_Error:
   MsgBox(Err.Description)
End Sub

Обработка ошибок при вызове метода

Ошибки, возникающие при создании экземпляра класса или во время метода класса, создают исключение в текущей процедуре. Microsoft Visual Basic предоставляет возможность обработки исключений через On Error Goto <label> оператор, в котором выполнение программы переходит к <label> при возникновении ошибки. (<label> должны находиться в той же процедуре, что и On Error Goto заявление). Все ошибки обрабатываются таким образом, включая ошибки в исходном коде MATLAB. Исключение создает Visual Basic ErrObject объект в текущем контексте в переменной с именем Err. (Подробные сведения об обработке ошибок VBA см. в документации Visual Basic for Applications.) Все примеры в этом разделе иллюстрируют типичную логику отслеживания ошибок, используемую в обертках вызовов функций для компонентов компилятора MATLAB.