主要内容

使用VBA集成组件

何时使用公式函数或子程序

VBA提供了两种基本过程类型:功能和子例程。

可以直接从工作表中的单元格作为公式函数访问VBA函数。使用函数程序时的原始MATLAB®函数返回一个或没有输出。

将子例程作为通用宏访问。当原始MATLAB函数返回值数组或多个输出时,使用子例程过程,因为您需要将这些输出映射到工作表中的多个单元格/范围。

创建组件时,MATLAB编译器™产生VBA模组(.bas文件)。该文件包含简单的调用包装器,每个包装器都作为类的每个方法的函数过程实现。有关更多信息,请参见Excel插件编译如何工作

初始化MATLAB编译器库与微软Excel

在你使用任何MATLAB编译器组件的当前实例初始化支持库金宝app微软®Excel®.为使用?的Excel会话执行此操作一次MATLAB编译器组件。

Microsoft COM Components">要进行此初始化,请调用实用程序库函数MWInitApplication的成员MWUtil类。这个类是MWComUtil图书馆。详细信息请参见类MWUtil

将此初始化代码添加到VBA模块中的一种方法是提供一个子例程,该子例程只执行一次初始化,并在所有后续调用时退出。以下微软Visual Basic®代码示例使用当前Excel实例初始化库。类型的全局变量对象命名MCLUtil对象的实例MWUtil类和另一个类型的全局变量布尔命名bModuleInitialized存储初始化进程的状态。私有子例程InitModule ()属性的实例MWComUtil类,并调用MWInitApplication参数为的方法应用程序.一旦此函数成功,所有后续调用将退出而不重新初始化。

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函数

此方法使用微软Visual Basic应用程序编程接口CreateObject函数创建类的实例。微软将CreateObject调用为后期绑定和使用作为早期绑定

要使用此方法,请声明一个类型变量对象使用昏暗的保存对类实例和调用的引用CreateObject使用类编程标识符(ProgID)作为参数,如下例所示:

函数foo(x1作为变量,x2作为变量)作为变量将aClass作为对象错误Goto Handle_Error设置aClass = CreateObject("mycomponent.myclass.1_0")(在aClass上调用一些方法)退出函数Handle_Error: foo = Err。结束

新的操作符

此方法使用Visual Basic显式标注为要创建的类的变量上的运算符。在使用此方法之前,必须在当前VBA项目中引用包含该类的类型库。通过选择工具菜单,然后选择参考文献显示可用的引用列表。从该列表中选择必要的类型库。

属性的使用示例如下操作符来创建类实例。它假设您已经进行了选择mycomponent 1.0类型库可用的引用列表,然后调用此函数。

函数foo(x1 As Variant, x2 As Variant)myclass On Error Goto Handle_Error Set aClass = New mycomponent。myclass(在aClass上调用一些方法)退出函数Handle_Error: foo = Err。结束

在本例中,类实例可以简单地进行维数划分myclass.表格中的完整声明<组件名称>。<类名称>如果当前项目中的其他库包含命名的类型,则防止可能发生的名称冲突myclass

使用这两种CreateObject而且生成一个维类实例。第一种方法不需要引用VBA项目中的类型库;第二种方法可以更快地执行代码。方法的附加优势是启用Auto-List-Members而且Auto-Quick-Info的能力微软Visual Basic编辑器来使用您的类。为每个构建的组件创建的默认函数包装器都使用第一个方法来创建对象。

在前面两个例子中,用于进行方法调用的类实例是过程的一个局部变量。这将为每个调用创建和销毁一个新的类实例。另一种方法是声明一个单独的模块作用域类实例,由所有函数调用重用,如前面示例的初始化代码中所示。

下面的例子用第二种方法说明了这个技巧:

作为我的组件。myclassFunction 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类在应用程序中实例化。这MATLAB运行时在组件内的所有后续类实例之间重用和共享,从而更有效地使用内存并消除MATLAB运行时每个后续类实例化中的启动成本。

所有类实例共享一个MATLAB工作空间,并共享用于构建组件的MATLAB文件中的全局变量。这使得COM类的属性表现为静态属性,而不是按实例的属性。

调用类实例的方法

创建类实例后,可以调用类方法来访问已编译的MATLAB函数。MATLAB编译器将原始MATLAB函数语法的标准映射应用到方法的参数列表。有关从MATLAB函数映射到COM类方法调用的详细描述,请参见参考实用工具类

当一个方法有输出参数时,第一个参数总是nargout,这是类型.这个输入参数通过普通的MATLABnargout参数设置为已编译函数,并指定请求多少输出。没有输出参数的方法不会传递nargout论点。后nargout为输出参数,其顺序与原始MATLAB函数左侧的输出参数相同。接下来是与原始MATLAB函数右侧相同顺序列出的输入参数。所有输入和输出参数的类型为变体,默认的Visual Basic数据类型。

变体type可以保存任何基本VBA类型、任何类型的数组和对象引用。有关如何转换的详细说明变体任意基本类型与MATLAB数据类型之间的转换,请参见数据转换规则.一般来说,你可以提供任何Visual Basic类型作为类方法的参数,除了Visual BasicUDT你也可以通过Microsoft Excel范围对象直接作为输入和输出参数。

当你通过一个简单的变体类型作为输出参数,则被调用的方法分配接收到的数据并释放变体.在这种情况下,将每个输出参数划分为单个维度就足够了变体.当一个对象类型(如Excel范围)作为输出参数传递,对象引用在两个方向上传递,对象的价值属性接收数据。

下面的示例说明了将输入和输出参数从VBA传递到MATLAB编译器组件类方法。

第一个例子是一个公式函数,它接受两个输入并返回一个输出。该函数将调用分派给与该窗体的MATLAB函数对应的类方法函数y = foo(x1,x2)

函数foo(x1 As Variant, x2 As Variant)作为变量将类作为对象Dim y作为变量错误Goto Handle_Error设置类=新的mycomponent。myclass aClass = CreateObject("mycomponent.myclass.1_0")调用aClass.foo(1,y,x1,x2) foo = y退出函数Handle_Error: foo = Err。结束

第二个示例将相同的函数重写为子例程,并使用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")调用aClass.foo(1,Rout,Rin1,Rin2)退出Sub Handle_Error: MsgBox(Err.Description)结束Sub

带变量参数的程序

处理varargin和varargout参数

变长度输入宗量和/或varargout,则这些参数将被添加到类方法的参数列表中,作为列表中的最后一个输入/输出参数。您可以传递多个参数作为变长度输入宗量数组,通过创建变体数组,将数组的每个元素赋给各自的输入参数。

下面的示例创建一个变长度输入宗量数组调用由窗体的MATLAB函数生成的方法Y = foo(varargin)

函数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")调用MCLUtil。MWPack(v, x1, x2, x3, x4, x5)调用类。foo(1, y, v) foo = y退出函数Handle_Error: foo = Err。结束

Microsoft COM Components">的MWUtil类包含在MWComUtil实用程序库提供MWPack要创建的Helper函数变长度输入宗量参数。看到类MWUtil欲知详情。

下一个示例处理avarargout参数输入到三个单独的Excel中范围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)结束Sub

传递一个空的varargin微软Visual Basic代码

在MATLAB中,变长度输入宗量函数的输入是可选的,可以在函数调用中出现或省略。然而,从微软Visual Basic,函数签名更加严格- if变长度输入宗量存在于MATLAB函数输入中,VBA调用必须包括变长度输入宗量,即使你希望它是空的。通过一个空变长度输入宗量,传递变量,传递时转换为空的MATLAB单元格数组。

从VBA代码中传递一个空变量。下面的示例说明如何传递null变量以传递空值变长度输入宗量

函数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退出函数Handle_Error: foo = Err。结束

更多信息

有关使用变长参数的详细信息,请参见使用多个MATLAB函数创建宏

修改标志

每一个MATLAB编译器组件公开一个名为MWFlags类型的MWFlags.的MWFlags属性由两组常量组成:数组格式化标志而且数据转换标志数组格式化标志影响数组的转换,而数据转换标志处理单个数组元素的类型转换。

数据转换标志更改数据转换过程的选定行为变体s到MATLAB类型,反之亦然。默认情况下,MATLAB编译器组件允许在类级别上通过MWFlags类属性。类的类型除外,这适用于所有Visual Basic类型MATLAB编译器MWStructMWFieldMWComplexMWSparse,MWArg类型。每一种类型都公开了自己的类型MWFlags属性,并忽略正在调用其方法的类的属性。的MWArg类是专门为特定参数需要不同于默认类属性的设置时提供的。

本节将对如何设置这些标志及其作用进行一般性讨论。进行了详细的讨论MWFlags类型,以及其他代码示例,请参见类MWFlags(MATLAB编译器SDK)

数组格式化标志

数组格式化标志指导数据转换,以产生MATLAB单元格数组或通用矩阵变体数据输入或生成数组变体S或者单键变体在输出上包含基本类型的数组。

下面的示例假设您已经引用了MWComUtil在当前项目的库中进行选择工具>参考资料并选择MWComUtil 7.5类型库以下是清单:

作为我的组件。myclass昏暗的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

此外,这些示例假设您已经引用了使用MATLAB编译器mycomponent),详见新的操作符

在这里,两个变体变量,var1而且var2是用相同的数值数据构造的,但内部结构不同:var12 × 2数组是变体S,每个元素包含一个1乘1矩阵,而var2是1乘1吗变体的2 × 2数组年代。

MATLAB编译器,当使用默认设置时,这两个数组都将转换为2 × 2的数组s.这并不遵循COM VARIANT中列出的MATLAB转换规则的一般约定。根据这些规则,var1转换为2 × 2单元格数组,其中每个单元格由1 × 1的双精度数占据var2直接转换为2 × 2的双矩阵。

的默认值,这两个数组都转换为双矩阵InputArrayFormat国旗是mwArrayFormatMatrix.的InputArrayFormat标志控制如何处理这两种类型的数组。之所以使用此默认值,是因为源自Excel范围的数组数据始终采用数组的形式变体年代(如var1), MATLAB函数最常处理矩阵参数。

但如果你想要单元格数组呢?在本例中,设置InputArrayFormat旗帜mwArrayFormatCell.通过在创建类之后和方法调用之前添加以下行来做到这一点:

aClass.MWFlags.ArrayFormatFlags.InputArrayFormat = mwArrayFormatCell

设置此标志会将编译后的MATLAB函数的所有数组输入显示为单元格数组。

类也可以操作输出参数的格式OutputArrayFormat国旗。方法修改数组输出AutoResizeOutput而且TransposeOutput旗帜。

AutoResizeOutput用于Excel范围对象直接作为输出参数传递。设置此标志时,目标范围自动调整大小以适应结果数组。如果未设置此标志,则目标范围必须至少与输出数组一样大,否则数据将被截断。

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。myclassaClass.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。请看下面的例子:

作为我的组件。myclass昏暗的var1,var2As 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类型的变体/整数到一个int16而且var2类型的变体/双到一个

如果原MATLAB函数期望如果两个参数都是S,这段代码可能会导致错误。一种解决方案是分配一个var1,但这可能是不可能或不可取的。在这种情况下,设置CoerceNumericToType旗帜mwTypeDouble,导致数据转换器将所有数字输入转换为.在前面的例子中,在创建类之后和调用方法之前放置以下一行:

aClass.MWFlags.DataConversionFlags.CoerceNumericToType = mwTypeDouble

InputDateFormat标志控制VBA日期类型转换。下面的例子将当前日期和时间作为输入参数发送,并将其转换为字符串:

作为我的组件。myclass昏暗的来day 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

处理方法调用中的错误

创建类实例时或类方法期间发生的错误会在当前过程中创建异常。微软Visual Basic方法提供异常处理功能On Error Goto 语句,其中程序执行跳转到<标识>发生错误时。(<标识>必须位于与错误转到声明)。所有错误都是这样处理的,包括原始MATLAB代码中的错误。异常创建Visual BasicErrObject对象在当前上下文中调用的变量犯错.(有关VBA错误处理的详细讨论,请参阅Visual Basic for Applications文档。)本节中的所有示例都说明了用于函数调用包装器的典型错误捕获逻辑MATLAB编译器组件。