使用 Visual Basic 表单控件实现用户界面
概述
此示例说明如何创建一个全面的 Excel® 应用程序来执行光谱分析。它需要了解 Visual Basic® 表单和控件以及 Excel 工作簿事件。有关这些主题的完整讨论,请参阅 VBA 文档。
您使用对输入数据集执行快速傅里叶变换 (FFT) 并绘制功率谱密度的函数创建 Excel 加载项。该函数返回 FFT 结果、频率点数数组和输入数据的功率谱密度。然后,您创建一个带有表单控件的自定义 VBA 宏来指定当前工作表中的输入和输出范围。从 Excel 工具菜单调用光谱分析应用程序。
要创建加载项:
从 MATLAB® 代码构建 Excel 加载项。
实现必要的 VBA 代码来收集输入并将调用分派到您的组件。此代码还为 Excel 中的应用程序创建一个菜单项。
使用表单控件创建 UI。
保存完成的 Excel 加载项并打包应用程序部署所需的所有必要组件。
在创建 Excel 加载项之前,请验证您已满足所有 MATLAB Compiler™Excel 目标要求。有关详细信息,请参阅MATLAB Compiler 的 Excel 目标要求和限制。
编译 Excel 加载项
将随 MATLAB 一起提供的
xlspectral文件夹复制一份。copyfile(fullfile(matlabroot,'toolbox','matlabxl','examples','xlspectral'))
检查 MATLAB 函数
computefft.m和plotfft.m。使用 Excel 加载项编译器或
compiler.build.excelAddIn构建 Excel 加载项。将以下信息用于您的工程:
加载项名称 Fourier类名 Fourier要编译的文件 plotfft.m注意
在这个示例中,使用
fourier类的应用程序不会直接调用computefft。只有computefft方法才需要plotfft方法。因此,您不需要手动将computefft函数添加到包中,因为编译器会在依赖关系分析期间自动将其包含进去。例如,如果您使用的是
compiler.build.excelAddIn,请输入:buildResults = compiler.build.excelAddIn('plotfft.m',... 'AddInName','Fourier',... 'ClassName','Fourier',... 'GenerateVisualBasicFile','on',... 'Verbose','on');
您的组件有一个类,其中包含两种方法:
computefft- 计算输入数据的 FFT 和功率谱密度,并根据输入数据的长度和采样间隔计算频率点向量。plotfft- 执行与computefft相同的操作,并在 MATLAB 图形窗口中绘制输入数据和功率谱密度。
实现 VBA 代码
构建组件后,实现必要的 VBA 代码以将其集成到 Excel 中。
注意
Fourier.xla 文件夹中附带的 Excel 加载项 xlspectral 已包含以下 VBA 代码。要使用附带的加载项,请在 Excel 中打开它,在 Excel Visual Basic 编辑器中添加对 Fourier 1.0 类型库和 MWComUtil X.X 类型库的引用,然后保存加载项。然后,您可以跳至测试加载项。
启动 Excel。
打开生成的 Excel 加载项。
在 Developer 选项卡中,点击 Visual Basic,或按 ALT + F11 打开 Visual Basic Editor。在旧版本的 Excel 中,它可能位于 Tools > Macro > Visual Basic Editor 下。
在 Visual Basic 编辑器中,选择 Tools > References 以打开 Project References 对话框。
选择与您生成的 Excel 加载项相对应的 Fourier 1.0 类型库条目以及与您的 MATLAB 或 MATLAB Runtime 版本相对应的 MWComUtil
X.X类型库。点击确定以添加引用。
创建主 VB 代码模块
该加载项需要初始化代码和全局变量来在函数调用之间保存应用程序状态。实现 Visual Basic 代码模块来管理这些任务。
如果 Modules 下还没有模块,请右键点击工程窗口中的 VBAProject 项,然后选择 Insert > Module。
VBA 工程中的模块下会出现一个新模块。
在模块属性页中,将
Name属性从Module1更改为FourierMain。您可能需要按 F4 来显示属性窗口。在
FourierMain模块中输入以下代码并关闭代码窗口。' ' FourierMain - Main module stores global state of controls ' and provides initialization code ' Public theFourier As Fourier.Fourier 'Global instance of Fourier object Public theFFTData As MWComplex 'Global instance of MWComplex to accept FFT Public InputData As Range 'Input data range Public Interval As Double 'Sampling interval Public Frequency As Range 'Output frequency data range Public PowerSpect As Range 'Output power spectral density range Public bPlot As Boolean 'Holds the state of plot flag Public theUtil As MWUtil 'Global instance of MWUtil object Public bInitialized As Boolean 'Module-is-initialized flag Private Sub LoadFourier() 'Initializes globals and Loads the Spectral Analysis form Dim MainForm As frmFourier On Error GoTo Handle_Error Call InitApp Set MainForm = New frmFourier Call MainForm.Show Exit Sub Handle_Error: MsgBox (Err.Description) End Sub Private Sub InitApp() 'Initializes classes and libraries. Executes once 'for a given session of Excel If bInitialized Then Exit Sub On Error GoTo Handle_Error If theUtil Is Nothing Then Set theUtil = New MWUtil Call theUtil.MWInitApplication(Application) End If If theFourier Is Nothing Then Set theFourier = New Fourier.Fourier End If If theFFTData Is Nothing Then Set theFFTData = New MWComplex End If bInitialized = True Exit Sub Handle_Error: MsgBox (Err.Description) End Sub
创建 Visual Basic 窗体
使用 Visual Basic 编辑器为您的加载项开发用户界面。
在 VBA 工程窗口中右键点击 VBAProject,然后选择 Insert,再选择 UserForm。
VBA 工程窗口的
Forms下会出现一个新表单。在表单属性页中,将
Name属性设置为frmFourier,将Caption属性设置为Spectral Analysis。将以下控件添加到空白表单:
光谱分析控件
控制类型 控件名称 属性 目的 CheckBoxchkPlotCaption =
Plot time domain signal and power spectral density绘制输入数据和功率谱密度。
CommandButtonbtnOKCaption =
OKDefault = True
执行该函数并关闭对话框。
CommandButtonbtnCancelCaption =
CancelCancel = True
关闭对话框而不执行该函数。
FrameFrame1Caption =
Input Data将所有输入控件分组。
FrameFrame2Caption =
Output Data将所有输出控件分组。
LabelLabel1Caption =
Input Data:为输入数据的
RefEdit添加标签。RefEditrefedtInput选择输入数据的范围。
LabelLabel2Caption =
Sampling Interval:为采样间隔的
TextBox添加标签。TextBoxedtSample选择采样间隔。 LabelLabel3Caption =
Frequency:为频率输出的
RefEdit添加标签。RefEditrefedtFreq选择频率点的输出范围。
LabelLabel4Caption =
FFT - Real Part:为 FFT 的实部的
RefEdit添加标签。RefEditrefedtReal选择输入数据的 FFT 实部的输出范围。
LabelLabel5Caption =
FFT - Imaginary Part:为 FFT 的虚部的
RefEdit添加标签。RefEditrefedtImag选择输入数据的 FFT 虚部的输出范围。
LabelLabel6Caption =
Power Spectral Density为功率谱密度的
RefEdit添加标签。RefEditrefedtPowSpect选择输入数据功率谱密度的输出范围。
您的表单应与下图类似。框内的文字仅供参考。

当表单和控件完成后,右键点击表单并选择 View code。
在表单代码窗口中输入以下代码。如果您对任何控件或任何全局变量使用了不同的名称,请更改此代码以反映这些差异。
'
'frmFourier Event handlers
'
Private Sub UserForm_Activate()
'UserForm Activate event handler. This function gets called before
'showing the form, and initializes all controls with values stored
'in global variables.
On Error GoTo Handle_Error
If theFourier Is Nothing Or theFFTData Is Nothing Then Exit Sub
'Initialize controls with current state
If Not InputData Is Nothing Then
refedtInput.Text = InputData.Address
End If
edtSample.Text = Format(Interval)
If Not Frequency Is Nothing Then
refedtFreq.Text = Frequency.Address
End If
If Not IsEmpty (theFFTData.Real) Then
If IsObject(theFFTData.Real) And TypeOf theFFTData.Real Is Range Then
refedtReal.Text = theFFTData.Real.Address
End If
End If
If Not IsEmpty (theFFTData.Imag) Then
If IsObject(theFFTData.Imag) And TypeOf theFFTData.Imag Is Range Then
refedtImag.Text = theFFTData.Imag.Address
End If
End If
If Not PowerSpect Is Nothing Then
refedtPowSpect.Text = PowerSpect.Address
End If
chkPlot.Value = bPlot
Exit Sub
Handle_Error:
MsgBox (Err.Description)
End Sub
Private Sub btnCancel_Click()
'Cancel button click event handler. Exits form without computing fft
'or updating variables.
Unload Me
End Sub
Private Sub btnOK_Click()
'OK button click event handler. Updates state of all variables from controls
'and executes the computefft or plotfft method.
Dim R As Range
If theFourier Is Nothing Or theFFTData Is Nothing Then GoTo Exit_Form
On Error Resume Next
'Process inputs
Set R = Range(refedtInput.Text)
If Err <> 0 Then
MsgBox ("Invalid range entered for Input Data")
Exit Sub
End If
Set InputData = R
Interval = CDbl(edtSample.Text)
If Err <> 0 Or Interval <= 0 Then
MsgBox ("Sampling interval must be greater than zero")
Exit Sub
End If
'Process Outputs
Set R = Range(refedtFreq.Text)
If Err = 0 Then
Set Frequency = R
End If
Set R = Range(refedtReal.Text)
If Err = 0 Then
theFFTData.Real = R
End If
Set R = Range(refedtImag.Text)
If Err = 0 Then
theFFTData.Imag = R
End If
Set R = Range(refedtPowSpect.Text)
If Err = 0 Then
Set PowerSpect = R
End If
bPlot = chkPlot.Value
'Compute the fft and optionally plot power spectral density
If bPlot Then
Call theFourier.plotfft(3, theFFTData, Frequency, PowerSpect, _
InputData, Interval)
Else
Call theFourier.computefft(3, theFFTData, Frequency, PowerSpect, _
InputData, Interval)
End If
GoTo Exit_Form
Handle_Error:
MsgBox (Err.Description)
Exit_Form:
Unload Me
End Sub将事件处理程序添加到工作簿
右键点击 VBA 工程窗口中的 ThisWorkbook 项,并选择查看代码。
将以下代码放入
ThisWorkbook中。Private Sub Workbook_AddinInstall() 'Called when Addin is installed Call AddFourierMenuItem End Sub Private Sub Workbook_AddinUninstall() 'Called when Addin is uninstalled Call RemoveFourierMenuItem End Sub Private Sub AddFourierMenuItem() Dim ToolsMenu As CommandBarPopup Dim NewMenuItem As CommandBarButton 'Remove if already exists Call RemoveFourierMenuItem 'Find Tools menu Set ToolsMenu = Application.CommandBars(1).FindControl(ID:=30007) If ToolsMenu Is Nothing Then Exit Sub 'Add Spectral Analysis menu item Set NewMenuItem = ToolsMenu.Controls.Add(Type:=msoControlButton) NewMenuItem.Caption = "Spectral Analysis..." NewMenuItem.OnAction = "LoadFourier" End Sub Private Sub RemoveFourierMenuItem() Dim CmdBar As CommandBar Dim Ctrl As CommandBarControl On Error Resume Next 'Find tools menu and remove Spectral Analysis menu item Set CmdBar = Application.CommandBars(1) Set Ctrl = CmdBar.FindControl(ID:=30007) Call Ctrl.Controls("Spectral Analysis...").Delete End Sub代码为安装和卸载菜单项的工作簿事件
AddinInstall和AddinUninstall添加了事件处理程序。该菜单项调用LoadFourier模块中的FourierMain函数。完成后,点击保存图标或按 CTRL + S 保存加载项。
测试加载项
在分发该加载项之前,先用一个示例问题来测试它。频谱分析通常用于查找隐藏在噪声时域信号中的信号频率分量。创建包含两个不同分量的信号的数据表示,并向其中添加一个随机分量。该数据连同输出一起存储在 Excel 工作表的列中,您可以绘制时域信号以及功率谱密度。
创建测试问题
使用空白工作簿启动新的 Excel 会话。
从 Developer 选项卡中,选择 Excel 加载项。
在“加载项”对话框中,点击浏览。
浏览到
Fourier.xla并点击确定。光谱分析加载项出现在可用 Add-Ins 列表中,并带有一个复选框。
点击确定以加载加载项。
此加载项在 Excel 加载项菜单下安装一个菜单项。
创建数据
调用加载项之前,创建包含 15 Hz 和 40 Hz 分量信号的测试数据。以 0.01 秒的采样率对信号进行 10 秒采样。将时间点放入 A 列,将信号点放入 B 列。
在当前工作表的 A1 单元格中输入
0。按 F5 或 CTRL + G 启动 Go To 对话框。添加引用 A2:A1001,然后点击 OK 以选择单元格。
输入公式
= A1 + 0.01,然后按 CTRL + Enter 将该公式应用于选定的单元格。此过程将使用间隔 0-10 并以 0.01 为增量填充范围 A1:A1001。
重复 Go To 过程,将以下公式输入到 B1:B1001 区域中的每个单元格中:
= SIN(2*PI()*15*A1) + SIN(2*PI()*40*A1) + RAND()
运行测试
使用数据列(B 列)测试加载项。
要显示光谱分析 UI,请选择加载项> 光谱分析。
点击输入数据框。
从工作表中选择
B1:B1001范围,或在输入数据字段中输入该范围。在采样间隔字段中,键入
0.01。选择绘制时域信号和功率谱密度。
输入
C1:C1001作为频率输出,同样输入D1:D1001、E1:E1001和F1:F1001作为 FFT 实部、FFT 虚部和谱密度。点击确定以运行分析。
下图显示了输出的示例。

功率谱密度显示两个信号分别为 15 Hz 和 40 Hz。
另请参阅
Excel 加载项编译器 | compiler.build.excelAddIn
