本例将MATLAB的矩阵运算函数生成为插件,然后在Excel的VBA环境中引用它,并利用它对指定的矩阵进行求幂、求对数和求逆运算。[大谦MATLAB,dqmatlab点com]
1 编写M文件
在MATLAB中编写M文件mypowm.m, mylogm.m和myinv.m,它们包含的函数分别为:
mypowm.m:
function y=mypowm(x,n)
y=x^n;
mylogm.m:
function y=mylogm(x)
y=logm(x);
myinv.m:
function y=myinv(x)
y=inv(x);
2 生成Excel插件和VBA代码模块
注意: MATLAB库编译器创建Excel插件之前,以本书采用的MATLAB 2023b版本为例,需要先安装微软Visual Studio 10.0以上版本,并且MATLAB要在安装该软件以后再安装。
在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。
图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二次开发环境中。
图4-11 编译器生成的目录和文件
图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文件中函数的输入参数。
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次幂,可以改变该值。
图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,选择它们,单击“确定”按钮。
图4-14 “引用”对话框
然后编写代码。前面生成插件的时候,同时生成了一个VBA模块。现在可以利用该模块,在该模块的基础上进行编程。变量声明和私有过程InitModule与该模块给出的一样。但其它3个函数需要有所改变。主要有两点改变,一是函数改为过程,这样可以作为宏进行调用;二是输入和输出参数用Range类型的对象进行指定。程序的完整代码如下所示。
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所示。
图4-15 “宏”对话框
图4-16 运行结果