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 Editor, и затем выбора References, чтобы отобразить Доступный список Ссылок. Из этого списка выберите необходимую библиотеку типов.
Следующий пример иллюстрирует использование оператора New
, чтобы создать экземпляр класса. Это принимает, что вы выбрали библиотеку типов 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 Compiler создает один MATLAB Runtime, когда первая Microsoft COM class инстанцируют в приложении. Этот MATLAB Runtime снова используется и общий для все последующие экземпляры класса в компоненте, приводящем к более эффективному использованию памяти и устраняющем стоимость запуска MATLAB Runtime в каждом последующем инстанцировании класса.
Все экземпляры класса совместно используют одно рабочее пространство MATLAB и совместно используют глобальные переменные в файлах MATLAB, используемых, чтобы создать компонент. Это заставляет свойства COM-класса вести себя как статические свойства вместо мудрых экземпляром свойств.
После того, как вы создали экземпляр класса, можно вызвать методы класса получить доступ к скомпилированным функциям MATLAB. MATLAB Compiler применяет стандартное отображение от исходного синтаксиса функции MATLAB до списка аргументов метода. Смотрите Ссылочные Служебные Классы для подробного описания отображения от функций MATLAB до вызовов метода COM-класса.
Когда метод имеет выходные аргументы, первым аргументом всегда является nargout
, который имеет тип Long
. Этот входной параметр передает нормальный MATLAB параметр nargout
скомпилированной функции и задает, сколько требуют выходные параметры. Методы, которые не имеют выходных аргументов, не передают аргумент nargout
. Следующий nargout
является выходными параметрами, перечисленными в том же порядке, как они появляются на левой стороне исходной функции MATLAB. Затем существуйте входные параметры, перечисленные того же порядка, как они появляются на правой стороне исходной функции MATLAB. Все аргументы ввода и вывода вводятся как Variant
, тип данных Visual Basic по умолчанию.
Тип Variant
может содержать любой из основных типов VBA, массивы любого типа и ссылки на объект. См. Правила Преобразования Данных для подробного описания того, как преобразовать типы Variant
любого основного типа к и от типов данных MATLAB. В целом можно предоставить любой тип Visual Basic в качестве аргумента к методу класса, за исключением Visual Basic UDT
s. Можно также передать Microsoft Excel, которому Range
возражает непосредственно в качестве аргументов ввода и вывода.
Когда вы передаете простой тип Variant
как выходной параметр, вызываемый метод выделяет полученные данные и освобождает исходное содержимое 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
Класс MWUtil
, включенный в сервисную библиотеку MWComUtil
, обеспечивает функцию помощника MWPack
, чтобы создать параметры varargin
. Смотрите Класс MWUtil для получения дополнительной информации.
Следующий пример обрабатывает параметр varargout
в три отдельных Excel Range
s. Эта функция использует функцию 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, когда передано.
Передайте Пустой varargin из Кода VBA. Следующий пример иллюстрирует, как передать пустой вариант в порядке передать пустой 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
. Свойство MWFlags
состоит из двух наборов констант: флаги форматирования массивов и флаги преобразования данных. Array formatting flags влияет на преобразование массивов, тогда как соглашение data conversion flags с преобразованиями типов отдельных элементов массива.
Преобразование данных отмечает изменение выбранные поведения процесса преобразования данных от Variant
s к типам MATLAB и наоборот. По умолчанию компоненты MATLAB Compiler позволяют устанавливать флаги преобразования данных на уровне класса через свойство класса MWFlags
. Это сохраняется для всех типов Visual Basic, за исключением MATLAB Compiler MWStruct
, MWField
, MWComplex
, MWSparse
и типы MWArg
. Каждый из этих типов представляет свое собственное свойство MWFlags
и игнорирует свойства класса, метод которого называется. Класс MWArg
предоставляется специально для случая, когда конкретному аргументу нужны различные настройки из свойств класса по умолчанию.
Этот раздел обеспечивает общее обсуждение того, как установить эти флаги и что они делают. Смотрите Класс MWFlags (MATLAB Compiler SDK) для детального обсуждения типа MWFlags
, а также выборок дополнительного кода.
Флаги форматирования массивов ведут преобразование данных, чтобы произвести или массив ячеек MATLAB или матрицу от общих данных Variant
по входу или произвести массив Variant
s или одного Variant
, содержащего массив основного типа на выводе.
Следующие примеры принимают, что вы сослались на библиотеку MWComUtil
в текущем проекте путем выбора Tools> References и выбора библиотеки типов 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 Compiler (mycomponent
), как упомянуто в Новом Операторе.
Здесь, две переменные Variant
, var1
и var2
создаются с теми же числовыми данными, но внутренне они структурированы по-другому: var1
является массивом 2 на 2 Variant
s с каждым элементом, содержащим Double
1 на 1, в то время как var2
является Variant
1 на 1, содержащий массив 2 на 2 Double
s.
В MATLAB Compiler, при использовании настроек по умолчанию, оба из этих массивов будут преобразованы в массивы 2 на 2 double
s. Это не следует общему соглашению, перечисленному в COM VARIANT к Правилам Преобразования MATLAB. Согласно этим правилам, var1
преобразовывает в массив ячеек 2 на 2 с каждой ячейкой, занятой двойным 1 на 1, и var2
преобразовывает непосредственно в двойную матрицу 2 на 2.
Эти два массива оба преобразовывают, чтобы удвоить матрицы, потому что значением по умолчанию для флага InputArrayFormat
является mwArrayFormatMatrix
. Флаг InputArrayFormat
управляет, как обработаны массивы этих двух типов. Это значение по умолчанию используется, потому что данные массива, происходящие из областей значений Excel, всегда в форме массива Variant
s (как var1
предыдущего примера), и функции MATLAB чаще всего имеют дело с матричными аргументами.
Но что, если вы хотите массив ячеек? В этом случае вы устанавливаете флаг InputArrayFormat
на mwArrayFormatCell
. Сделайте это путем добавления следующей строки после создания класса и перед вызовом метода:
aClass.MWFlags.ArrayFormatFlags.InputArrayFormat = mwArrayFormatCell
Установка этого флага представляет весь вход массивов скомпилированной функции MATLAB как массивы ячеек.
Точно так же можно управлять форматом выходных аргументов с помощью флага OutputArrayFormat
. Можно также изменить массив вывод с флагами TransposeOutput
и AutoResizeOutput
.
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 ожидает double
s для обоих аргументов, этот код может вызвать ошибку. Одно решение состоит в том, чтобы присвоить double
var1
, но это не может быть возможно или желательно. В таком случае устанавливает флаг CoerceNumericToType
на mwTypeDouble
, заставляя преобразователь данных преобразовать весь числовой вход в double
. В предыдущем примере поместите следующую строку после создания класса и прежде, чем вызвать методы:
aClass.MWFlags.DataConversionFlags.CoerceNumericToType = mwTypeDouble
Флаг 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
. (См. документацию Visual Basic for Applications для детального обсуждения обработки ошибок VBA.) Все примеры в этом разделе иллюстрируют типичную логику обнаружения ошибок, используемую в обертках вызова функции для компонентов MATLAB Compiler.