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