应用实例

本例将MATLAB的矩阵运算函数生成为插件,然后在Excel的VBA环境中引用它,并利用它对指定的矩

本例将MATLAB的矩阵运算函数生成为插件,然后在Excel的VBA环境中引用它,并利用它对指定的矩阵进行求幂、求对数和求逆运算。[大谦MATLAB,dqmatlab点com]

1 编写M文件

在MATLAB中编写M文件mypowm.m, mylogm.m和myinv.m,它们包含的函数分别为:

mypowm.m:

code.matlab
function y=mypowm(x,n)
y=x^n;

mylogm.m:

code.matlab
function y=mylogm(x)
y=logm(x);

myinv.m:

code.matlab
function y=myinv(x)
y=inv(x);

2 生成Excel插件和VBA代码模块

注意: MATLAB库编译器创建Excel插件之前,以本书采用的MATLAB 2023b版本为例,需要先安装微软Visual Studio 10.0以上版本,并且MATLAB要在安装该软件以后再安装。

在MATLAB命令窗口键入下面的命令,打开部署工具:

code.matlab
libraryCompiler

打开库编译器,如图4-10所示。在工具栏中的“TYPE”列表框中选择“Excel Add-in”选项,单击“EXPORTED FUNCTIONS”列表框右边的加号按钮,添加前面创建的M文件mypowm.m, mylogm.m和myinv.m,在“Packing Options”部分选择“Runtime included in package”单选钮,编译器下面部分自动生成一个名为Class1的类,添加的3个M文件成为该类的3个方法。修改类名为matrixclass,保存工程,名为matrix.prj。

Document Image

图4-10 MATLAB库编译器

单击工具栏中的“Package”按钮,打包插件。生成的文件和目录如图4-11所示,包括:

for_redistribution目录:包含安装应用程序和MATLAB运行时的文件。

for_testing目录:包含mcc创建的所有文件,用于测试安装。

for_redistribution_files_only目录:包含应用程序重新发布所需要的文件。

PackagingLog.txt:编译器生成的日志文件。

for_redistribution_files_only目录中的文件如图4-12所示。注意,这里生成了一个名为matrix的VBA模块文件,它可以直接用于Excel的VBA二次开发环境中。

Document Image

图4-11 编译器生成的目录和文件

Document Image

图4-12 for_redistribution_files_only目录中的文件

下面是matrix模块所包含的VBA代码。其中,私有过程InitModule对模块进行初始化,它创建MWComUtil库的MWUtil类的一个实例,并调用该实例的MWInitApplication方法。该方法必须被每个使用Excel插件的MATLAB进程调用一次,否则会出错。全局变量bModuleInitialized保存初始化过程的状态。全局变量matrixclass是刚才生成的Excel插件的matrixclass类的实例。函数mypowm, mylogm和myinv分别调用对象matrixclass的对应方法进行计算。需要注意的是,代码中各方法相对于M文件而言,多了两个输入参数,第1个为nargout参数,表示输出参数的个数,第2个为输出参数,后面跟的才是M文件中函数的输入参数。

code.excel vba
Dim MCLUtil As Object
Dim bModuleInitialized As Boolean
Dim matrixclass As Object
Private Sub InitModule()
    If Not bModuleInitialized Then
        On Error GoTo Handle_Error
        If MCLUtil Is Nothing Then
            Set MCLUtil=text-blue-400">CreateObject("MWComUtil.MWUtil")
        End If
        Call MCLUtil.MWInitApplication(text-blue-400">Application)

        bModuleInitialized=True
        Exit Sub
Handle_Error:
        bModuleInitialized=False
    End If
End Sub
Function myinv(Optional x As Variant) As Variant
    Dim y As Variant
    On Error GoTo Handle_Error
    Call InitModule
    If matrixclass Is Nothing Then
        Set matrixclass=text-blue-400">CreateObject("matrix.matrixclass.1_0")
    End If
    Call matrixclass.myinv(1, y, x)
    myinv=y
    Exit Function
Handle_Error:
    myinv="Error in " & Err.Source & ": " & Err.Description
End Function
Function mylogm(Optional x As Variant) As Variant
    Dim y As Variant
    On Error GoTo Handle_Error
    Call InitModule
    If matrixclass Is Nothing Then
        Set matrixclass=text-blue-400">CreateObject("matrix.matrixclass.1_0")
    End If
    Call matrixclass.mylogm(1, y, x)
    mylogm=y
    Exit Function
Handle_Error:
    mylogm="Error in " & Err.Source & ": " & Err.Description
End Function
Function mypowm(Optional x As Variant, Optional n As Variant) As Variant
    Dim y As Variant
    On Error GoTo Handle_Error
    Call InitModule
    If matrixclass Is Nothing Then
        Set matrixclass=text-blue-400">CreateObject("matrix.matrixclass.1_0")
    End If
    Call matrixclass.mypowm(1, y, x, n)
    mypowm=y
    Exit Function
Handle_Error:
    mypowm="Error in " & Err.Source & ": " & Err.Description
End Function

3 在Excel中使用插件和模块

打开Excel,如图4-13进行设置。最上面给出初始矩阵,下面分别给出该矩阵的幂、对数和逆的位置,均用黑色方框示出。幂矩阵前面的“2”表示求2次幂,可以改变该值。

Document Image

图4-13 给出初始矩阵及结果矩阵的位置

在“开发工具”选项卡中选择“VBA”,打开VBA编辑器。该编辑器的窗口布局与VBA的比较接近,左上侧为项目管理器,在右侧编写程序代码。Excel中的VBA实际上是VBA for Application,简称VBA,是一种二次开发工具。但其语法与VBA的基本相同。使用Excel插件,需要在VBA编辑器中编写VBA代码。

在“插入”菜单中单击“模块”选项,添加一个模块。

在编写代码之前,需要引用两个类型库。在VBA编辑器中,单击“工具”菜单中的“引用…”选项,打开“引用”对话框,如图4-14所示。在列表框中找到或通过单击“浏览”按钮找到类型库MWComUtil 24.10 Type Library和matrix 1.0 Type Library,选择它们,单击“确定”按钮。

Document Image

图4-14 “引用”对话框

然后编写代码。前面生成插件的时候,同时生成了一个VBA模块。现在可以利用该模块,在该模块的基础上进行编程。变量声明和私有过程InitModule与该模块给出的一样。但其它3个函数需要有所改变。主要有两点改变,一是函数改为过程,这样可以作为宏进行调用;二是输入和输出参数用Range类型的对象进行指定。程序的完整代码如下所示。

code.excel vba
Dim MCLUtil As Object
Dim bModuleInitialized As Boolean
Dim matrixclass As Object
Private Sub InitModule()
     If Not bModuleInitalized Then
         On Error GoTo Handle_Error
         If MCLUtil Is Nothing Then
             Set MCLUtil=text-blue-400">CreateObject("MWComUtil.MWUtil9.01")
         End If
         Call MCLUtil.MWInitApplication(text-blue-400">Application)
         bModuleInitialized=True
         Exit Sub
         Handle_Error:
         bModuleInitialized=False
     End If
End Sub
Sub mypowm()
     Dim R1 As text-blue-400">Range
     Dim R2 As text-blue-400">Range
     Dim R3 As text-blue-400">Range

     On Error GoTo Handle_Error
     Call InitModule
     Set R1=text-blue-400">Range("B3:D5")     '指定初始矩阵
     Set R2=text-blue-400">Range("A10")       '指定幂次
     Set R3=text-blue-400">Range("B10:D12")     '指定矩阵的幂的存放位置
     If matrixclass Is Nothing Then
         Set matrixclass=text-blue-400">CreateObject("matrix.matrixcalss.1_0")
     End If
     Call matrixclass.mypowm(1,R3,R1,R2)
     Exit Sub
     Handle_Error:
     text-blue-400">MsgBox("错误: " & text-blue-400">Format(Err.Number) & _
             " 源于:  " & Err.Source & " 描述: " & Err.Description)
End Sub
Sub mylogm()
     Dim R1 As text-blue-400">Range
     Dim R2 As text-blue-400">Range

     On Error GoTo Handle_Error
     Call InitModule
     Set R1=text-blue-400">Range("B3:D5")         '指定初始矩阵
     Set R2=text-blue-400">Range("B16:D18")       '指定矩阵对数的存放位置
     If matrixclass Is Nothing Then
         Set matrixclass=text-blue-400">CreateObject("matrix.matrixclass.1_0")
     End If
     Call matrixclass.mylogm(1,R2,R1)
     Exit Sub
     Handle_Error:
     text-blue-400">MsgBox("错误: " & text-blue-400">Format(Err.Number) & _
     " 源于:  " & Err.Source & " 描述: " & Err.Description)
End Sub
Sub myinv()
     Dim R1 As text-blue-400">Range
     Dim R2 As text-blue-400">Range

     On Error GoTo Handle_Error
     Call InitModule
     Set R1=text-blue-400">Range("B3:D5")    	 '指定初始矩阵
     Set R2=text-blue-400">Range("B22:D24")       '指定矩阵的逆矩阵的存放位置
     If matrixclass Is Nothing Then
         Set matrixclass=text-blue-400">CreateObject("matrix.matrixclass.1_0")
     End If
     Call matrixclass.myinv(1,R2,R1)
     Exit Sub
     Handle_Error:
     text-blue-400">MsgBox("错误: " & text-blue-400">Format(Err.Number) & _
     " 源于:  " & Err.Source & " 描述: " & Err.Description)
End Sub

从“开发工具”选项卡中单击“宏”按钮,打开“宏”对话框,如图4-15所示。在列表框中选择一个宏的名称,单击“执行”按钮,即可在Excel电子表格中完成对应的运算和显示。运行三个宏以后的结果如图4-16所示。

Document Image

图4-15 “宏”对话框

Document Image

图4-16 运行结果