主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

使用 Visual Basic 表单控件实现用户界面

概述

此示例说明如何创建一个全面的 Excel® 应用程序来执行光谱分析。它需要了解 Visual Basic® 表单和控件以及 Excel 工作簿事件。有关这些主题的完整讨论,请参阅 VBA 文档。

您使用对输入数据集执行快速傅里叶变换 (FFT) 并绘制功率谱密度的函数创建 Excel 加载项。该函数返回 FFT 结果、频率点数数组和输入数据的功率谱密度。然后,您创建一个带有表单控件的自定义 VBA 宏来指定当前工作表中的输入和输出范围。从 Excel 工具菜单调用光谱分析应用程序。

要创建加载项:

  1. 从 MATLAB® 代码构建 Excel 加载项。

  2. 实现必要的 VBA 代码来收集输入并将调用分派到您的组件。此代码还为 Excel 中的应用程序创建一个菜单项。

  3. 使用表单控件创建 UI。

  4. 保存完成的 Excel 加载项并打包应用程序部署所需的所有必要组件。

在创建 Excel 加载项之前,请验证您已满足所有 MATLAB Compiler™Excel 目标要求。有关详细信息,请参阅MATLAB Compiler 的 Excel 目标要求和限制

编译 Excel 加载项

  1. 将随 MATLAB 一起提供的 xlspectral 文件夹复制一份。

    copyfile(fullfile(matlabroot,'toolbox','matlabxl','examples','xlspectral'))
  2. 检查 MATLAB 函数 computefft.mplotfft.m

     computefft.m

     plotfft.m

  3. 使用 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 类型库的引用,然后保存加载项。然后,您可以跳至测试加载项

  1. 启动 Excel。

  2. 打开生成的 Excel 加载项。

  3. Developer 选项卡中,点击 Visual Basic,或按 ALT + F11 打开 Visual Basic Editor。在旧版本的 Excel 中,它可能位于 Tools > Macro > Visual Basic Editor 下。

  4. 在 Visual Basic 编辑器中,选择 Tools > References 以打开 Project References 对话框。

  5. 选择与您生成的 Excel 加载项相对应的 Fourier 1.0 类型库条目以及与您的 MATLAB 或 MATLAB Runtime 版本相对应的 MWComUtil X.X 类型库。点击确定以添加引用。

创建主 VB 代码模块

该加载项需要初始化代码和全局变量来在函数调用之间保存应用程序状态。实现 Visual Basic 代码模块来管理这些任务。

  1. 如果 Modules 下还没有模块,请右键点击工程窗口中的 VBAProject 项,然后选择 Insert > Module

    VBA 工程中的模块下会出现一个新模块。

  2. 在模块属性页中,将 Name 属性从 Module1 更改为 FourierMain。您可能需要按 F4 来显示属性窗口。

  3. 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 编辑器为您的加载项开发用户界面。

  1. 在 VBA 工程窗口中右键点击 VBAProject,然后选择 Insert,再选择 UserForm

    VBA 工程窗口的 Forms 下会出现一个新表单。

  2. 在表单属性页中,将 Name 属性设置为 frmFourier,将 Caption 属性设置为 Spectral Analysis

  3. 将以下控件添加到空白表单:

    光谱分析控件

    控制类型控件名称属性目的

    CheckBox

    chkPlot

    Caption = Plot time domain signal and power spectral density

    绘制输入数据和功率谱密度。

    CommandButton

    btnOK

    Caption = OK

    Default = True

    执行该函数并关闭对话框。

    CommandButton

    btnCancel

    Caption = Cancel

    Cancel = True

    关闭对话框而不执行该函数。

    Frame

    Frame1

    Caption = Input Data

    将所有输入控件分组。

    Frame

    Frame2

    Caption = Output Data

    将所有输出控件分组。

    Label

    Label1

    Caption = Input Data:

    为输入数据的 RefEdit 添加标签。

    RefEdit

    refedtInput

     

    选择输入数据的范围。

    Label

    Label2

    Caption = Sampling Interval:

    为采样间隔的 TextBox 添加标签。

    TextBoxedtSample 选择采样间隔。

    Label

    Label3

    Caption = Frequency:

    为频率输出的 RefEdit 添加标签。

    RefEdit

    refedtFreq

     

    选择频率点的输出范围。

    Label

    Label4

    Caption = FFT - Real Part:

    为 FFT 的实部的 RefEdit 添加标签。

    RefEdit

    refedtReal

     

    选择输入数据的 FFT 实部的输出范围。

    Label

    Label5

    Caption = FFT - Imaginary Part:

    为 FFT 的虚部的 RefEdit 添加标签。

    RefEdit

    refedtImag

     

    选择输入数据的 FFT 虚部的输出范围。

    Label

    Label6

    Caption = Power Spectral Density

    为功率谱密度的 RefEdit 添加标签。

    RefEdit

    refedtPowSpect

     

    选择输入数据功率谱密度的输出范围。

    您的表单应与下图类似。框内的文字仅供参考。

    Spectral Analysis form

  4. 当表单和控件完成后,右键点击表单并选择 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

将事件处理程序添加到工作簿

  1. 右键点击 VBA 工程窗口中的 ThisWorkbook 项,并选择查看代码

  2. 将以下代码放入 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

    代码为安装和卸载菜单项的工作簿事件 AddinInstallAddinUninstall 添加了事件处理程序。该菜单项调用 LoadFourier 模块中的 FourierMain 函数。

  3. 完成后,点击保存图标或按 CTRL + S 保存加载项。

测试加载项

在分发该加载项之前,先用一个示例问题来测试它。频谱分析通常用于查找隐藏在噪声时域信号中的信号频率分量。创建包含两个不同分量的信号的数据表示,并向其中添加一个随机分量。该数据连同输出一起存储在 Excel 工作表的列中,您可以绘制时域信号以及功率谱密度。

创建测试问题

  1. 使用空白工作簿启动新的 Excel 会话。

  2. Developer 选项卡中,选择 Excel 加载项

  3. 在“加载项”对话框中,点击浏览

  4. 浏览到 Fourier.xla 并点击确定

    光谱分析加载项出现在可用 Add-Ins 列表中,并带有一个复选框。

  5. 点击确定以加载加载项。

此加载项在 Excel 加载项菜单下安装一个菜单项。

创建数据

调用加载项之前,创建包含 15 Hz 和 40 Hz 分量信号的测试数据。以 0.01 秒的采样率对信号进行 10 秒采样。将时间点放入 A 列,将信号点放入 B 列。

  1. 在当前工作表的 A1 单元格中输入 0

  2. F5CTRL + G 启动 Go To 对话框。添加引用 A2:A1001,然后点击 OK 以选择单元格。

  3. 输入公式 = A1 + 0.01,然后按 CTRL + Enter 将该公式应用于选定的单元格。

    此过程将使用间隔 0-10 并以 0.01 为增量填充范围 A1:A1001。

  4. 重复 Go To 过程,将以下公式输入到 B1:B1001 区域中的每个单元格中:

    = SIN(2*PI()*15*A1) + SIN(2*PI()*40*A1) + RAND()

运行测试

使用数据列(B 列)测试加载项。

  1. 要显示光谱分析 UI,请选择加载项> 光谱分析

  2. 点击输入数据框。

  3. 从工作表中选择 B1:B1001 范围,或在输入数据字段中输入该范围。

  4. 采样间隔字段中,键入 0.01

  5. 选择绘制时域信号和功率谱密度

  6. 输入 C1:C1001 作为频率输出,同样输入 D1:D1001E1:E1001F1:F1001 作为 FFT 实部、FFT 虚部和谱密度。

  7. 点击确定以运行分析。

下图显示了输出的示例。

功率谱密度显示两个信号分别为 15 Hz 和 40 Hz。

另请参阅

|

主题