VBA предоставляет два основных типа процедур: функции и стандартные подпрограммы.
Вы получаете доступ к функции VBA непосредственно из камеры в листе как функции формулы. Используйте функциональные процедуры, когда исходный MATLAB® функция принимает один или несколько входов и возвращает нулевые выходы.
Вы получаете доступ к стандартной подпрограмме как общий макрос. Используйте процедуру стандартной подпрограммы, когда исходная функция MATLAB возвращает массив значений или несколько выходов, потому что вы должны сопоставить эти выходные параметры с несколькими ячейками/диапазонами в листе.
Когда вы создаете компонент, MATLAB Compiler™ создает модуль VBA (.bas
файл). Этот файл содержит простые оболочки вызовов, каждый из которых реализован как функциональная процедура для каждого метода класса.
Прежде чем использовать какой-либо компонент 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
функция
New
оператор
Этот метод использует интерфейс прикладного программирования (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 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 UDT
s. Также можно пройти 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
В 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 имеем дело с преобразованиями типов отдельных элементов массива.
Флаги преобразования данных изменяют выбранное поведение процесса преобразования данных из Variant
s к типам 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
данные о входе или для создания массива Variant
s или одно 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 Variant
s с каждым элементом, содержащим 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, всегда находятся в форме массива Variant
s (например 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 ожидает double
s для обоих аргументов, этот код может вызвать ошибку. Одним из решений является назначение 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.