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

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

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

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

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

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

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

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

Для выполнения этой инициализации вызовите функцию библиотеки утилит 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 Compiler, может включать вызов InitModule в начале, чтобы убедиться, что инициализация всегда выполняется по мере необходимости.

Создание образца класса

Обзор

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

Функция CreateObject

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

Чтобы использовать этот метод, объявите переменную типа 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 оператор для создания образца класса. Это предполагает, что перед  вызовом этой функции вы выбрали mycomponent 1.0 Type Library из списка Available References.

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; второе приводит к более быстрому выполнению кода. Второй метод имеет дополнительное преимущество, заключающееся в том, что он позволяет пользователям Auto- Списка Members и Auto-Quick-Info редактора 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 Runtime разделяется между классами

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

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

Вызов методов образца класса

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

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

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

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

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

Первый пример является функцией формулы, которая принимает два входов и возвращает один выход. Эта функция отправляет вызов в метод класса, который соответствует функции 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 

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

Следующий пример обрабатывает varargout параметр в три отдельных Range Excels. Эта функция использует 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 Code

В 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 Compiler предоставляет одно свойство чтения/записи с именем MWFlags типа MWFlags. The MWFlags свойство состоит из двух наборов констант:   флагов форматирования массивов и   флагов преобразования данных. Array formatting flags влияют на преобразование массивов, в то время как data conversion flags имеем дело с преобразованиями типов отдельных элементов массива.

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

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

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

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

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

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 Compiler (mycomponent) как упомянуто в New Operator.

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

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

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

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

aClass.MWFlags.ArrayFormatFlags.InputArrayFormat = 
mwArrayFormatCell

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

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

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

The 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

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

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 Compiler.

Для просмотра документации необходимо авторизоваться на сайте