不删除其代码的情况下模拟关闭或者禁止其他宏的消息提示

0. 背景和提示

在一个Excel和Access联动的大型Excel宏文件中,假设只能通过一个新的Excel宏文件去操控而不能改变原有的文件,且原文件会产生一些提示性的弹窗(例如“程序运行结束”)。如果要实现源文件在指定条件下循环开启和关闭,则需要解决弹窗的关闭或禁用,以下是一些可能得方法。

自动化关闭弹窗的方法都存在一定的不确定性,并且可能会在不同的环境和情况下产生不同的结果。在没有修改原始宏代码的情况下,任何自动处理弹窗的尝试都应该非常谨慎,并在一个受控的环境中多次进行充分的测试。

1. 弹窗(消息显示)

在VBA (Visual Basic for Applications) 中,用于显示弹窗的函数是MsgBox。这个函数可以用来显示不同类型的对话框,并且可以返回用户点击的按钮的值。

MsgBox函数的基本语法如下:

MsgBox(prompt[, buttons][, title][, helpfile, context])
  • prompt 是必需的,表示对话框中显示的文本信息。
  • buttons 是可选的,用来指定对话框中显示的按钮类型和图标类型。
  • title 是可选的,用来指定对话框的标题。
  • helpfilecontext 是可选的,用来指定帮助文件和帮助文件中上下文的ID号。

buttons 参数可以是以下值的组合:

  • 按钮类型:

    • vbOKOnly:只显示“OK”按钮。
    • vbOKCancel:显示“OK”和“Cancel”按钮。
    • vbAbortRetryIgnore:显示“Abort”、“Retry”和“Ignore”按钮。
    • vbYesNoCancel:显示“Yes”、“No”和“Cancel”按钮。
    • vbYesNo:显示“Yes”和“No”按钮。
    • vbRetryCancel:显示“Retry”和“Cancel”按钮。
    • vbCancelTryAgainContinue:显示“Cancel”、“Try Again”、“Continue”按钮(VBA 6.0 之后版本)。
  • 图标类型:

    • vbCritical:显示严重错误图标。
    • vbQuestion:显示警告查询图标。
    • vbExclamation:显示警告消息图标。
    • vbInformation:显示信息图标。
  • 默认按钮:

    • vbDefaultButton1:第一个按钮为默认按钮。
    • vbDefaultButton2:第二个按钮为默认按钮。
    • vbDefaultButton3:第三个按钮为默认按钮。
    • vbDefaultButton4:第四个按钮为默认按钮(如果有的话)。
  • 模态性:

    • vbApplicationModal:应用程序模态,用户必须先响应该消息框,然后才能继续在当前应用程序中工作。
    • vbSystemModal:系统模态,所有应用程序都被挂起,直到用户响应了消息框。

MsgBox 函数返回值是一个整数,表示用户点击的按钮,如下:

  • vbOK:点击了“OK”。
  • vbCancel:点击了“Cancel”。
  • vbAbort:点击了“Abort”。
  • vbRetry:点击了“Retry”。
  • vbIgnore:点击了“Ignore”。
  • vbYes:点击了“Yes”。
  • vbNo:点击了“No”。
  • vbTryAgain:点击了“Try Again”(VBA 6.0 之后版本)。
  • vbContinue:点击了“Continue”(VBA 6.0 之后版本)。

这是MsgBox函数的一个基本示例:

Sub ShowMessageBox()
    Dim response As Integer
    ' 显示一个简单的对话框,有一个“OK”按钮和一个标题
    response = MsgBox("这是一个简单的消息框", vbOKOnly, "示例标题")
    
    If response = vbOK Then
        ' 用户点击了"OK"
        MsgBox "用户点击了OK"
    End If
End Sub

2. 方法一:预防性策略

在运行这些宏之前,如果可能,最好的解决方案是沟通并协调修改宏的代码,以便于它们在特定条件下不显示弹窗。在 Excel VBA 中,可以通过多种方式实现控制宏运行时是否显示弹窗的机制。一种常见且简单的方法是使用一个全局变量作为标志来控制弹窗的显示。通过这种方式,可以灵活地控制宏在运行时是否弹出消息框,而无需删除或注释掉原有的 MsgBox 调用,从而使得宏的行为可以根据上下文的需要动态调整。以下是在宏内部实现这种检查机制的步骤:

2.1 定义全局变量

在 VBA 编辑器的一个模块中定义一个全局变量。这个变量将用来指示是否显示弹窗。

' 在模块的顶部定义全局变量
Global SuppressMessages As Boolean

2.2 修改宏以检查全局变量

在可能弹出消息框的宏代码中,添加条件检查,根据全局变量 SuppressMessages 的值决定是否显示弹窗。

Sub MacroThatShowsMessage()
    ' 检查是否应该显示弹窗
    If Not SuppressMessages Then
        MsgBox "这是一个重要的消息。"
    End If
    ' 其他宏代码...
End Sub

2.3 控制全局变量

在调用宏之前,根据需要设置 SuppressMessages 变量的值。如果想要隐藏弹窗,就在调用宏之前设置它为 True

Sub RunMacroWithoutMessages()
    ' 设置变量以抑制消息
    SuppressMessages = True

    ' 调用可能会显示消息的宏
    Call MacroThatShowsMessage

    ' 重置变量,以便后续的宏调用可以正常显示消息
    SuppressMessages = False
End Sub

2.4 确保全局变量的状态

最好的实践是在宏结束时重置全局变量,以确保它不会影响到其他宏。

Sub MacroThatShowsMessage()
    ' 保存原始的SuppressMessages值
    Dim originalSuppressMessages As Boolean
    originalSuppressMessages = SuppressMessages

    ' 检查是否应该显示弹窗
    If Not SuppressMessages Then
        MsgBox "这是一个重要的消息。"
    End If

    ' 其他宏代码...

    ' 重置SuppressMessages到宏开始前的值
    SuppressMessages = originalSuppressMessages
End Sub

2.5 额外tips

  • 如果宏被存储在一个添加了密码的工作簿中,可能需要在调用宏之前先解锁VBA项目。
  • 如果宏是由其他应用程序(如通过 COM 对象的 Excel 实例)触发的,确保设置全局变量的代码在正确的上下文中执行。
  • 如果有多个宏可能会弹出消息框,则需要确保所有这些宏都检查了 SuppressMessages 变量。

3. 方法二:Windows API

通过调用 Windows API (Application Programming Interface) 函数来增强宏的功能和模拟用户交互。
API 函数执行许多在 VBA 中不直接可用的操作,例如访问低级系统信息、创建复杂的窗口消息框或修改窗口的行为。但这种方法应谨慎使用,因为它可能会影响用户的其他操作,并且可能会受到 Excel 安全设置的限制。以下是如何使用 Windows API 来控制宏运行时是否显示弹窗的示例:

3.1 声明 API 函数

首先,需要在 VBA 中声明将要使用的 API 函数。对于弹窗控制,MessageBox API 函数是一个可用的选择。需要在模块的顶部用 Declare 语句声明这个函数。

' 声明API函数
#If VBA7 Then
    Declare PtrSafe Function MessageBox Lib "user32" Alias "MessageBoxA" ( _
        ByVal hwnd As LongPtr, _
        ByVal lpText As String, _
        ByVal lpCaption As String, _
        ByVal uType As Long) As Long
#Else
    Declare Function MessageBox Lib "user32" Alias "MessageBoxA" ( _
        ByVal hwnd As Long, _
        ByVal lpText As String, _
        ByVal lpCaption As String, _
        ByVal uType As Long) As Long
#End If

这里使用了条件编译来区分 32 位和 64 位的 VBA 环境。PtrSafe 关键字在 64-bit 环境中是必须的,以确保指针的正确使用。

3.2 使用 API 函数

接着,使用声明的 MessageBox 函数来显示自定义的消息框。可以根据需要控制消息框的内容和样式。

Sub ApiMessageBoxDemo()
    ' 使用 MessageBox API 函数来显示弹窗
    Dim response As Long
    response = MessageBox(0, "这是通过 Windows API 显示的消息。", "API 消息框", 0)
    ' 根据用户响应执行操作
    If response = 1 Then ' 用户点击了“确定”按钮
        ' 执行相关操作
    End If
End Sub

3.3 条件控制显示

为了控制是否显示弹窗,可以引入一个全局变量作为开关。

Global ShowApiMessageBox As Boolean

Sub ControlApiMessageBox()
    ShowApiMessageBox = False ' 设置为 True 或 False 来控制是否显示弹窗
    If ShowApiMessageBox Then
        ApiMessageBoxDemo
    End If
End Sub

在这个例子中,ShowApiMessageBox 将控制是否调用 ApiMessageBoxDemo 过程来显示消息。

3. 4 警告

  • 当调用 Windows API 时,必须理解该函数的所有参数,因为错误的使用可能会导致不稳定的行为甚至崩溃。
  • 由于 Windows API 函数是在操作系统层面上运行的,因此错误的参数或调用可能会导致更加严重的后果,比在 VBA 环境中出错要严重。
  • 当分发包含 API 调用的工作簿时,请确保目标计算机的操作系统与 API 函数兼容。
  • 此策略可能违反某些公司的IT政策。

4. 方法三:SendKeys 方法

SendKeys 是 VBA 提供的一个方法,它模拟键盘输入,向 Windows 环境发送一个或多个按键。这个方法的一个常见用途是自动化一些不能直接通过 VBA 控制的用户界面操作,比如在没有直接方法可用的情况下点击按钮。下面是如何在 VBA 中使用 SendKeys 方法:

4.1 SendKeys 基本语法

SendKeys 方法接受一个字符串参数,代表要发送的按键,以及一个可选的布尔值,用于指示操作是否为等待模式。字符串中的特定字符可以代表不同的按键或按键组合。例如:

  • {ENTER} 代表回车键。
  • +{F1} 代表 Shift+F1。
  • %{F4} 代表 Alt+F4。
  • ^{ESC} 代表 Ctrl+Esc。

4.2 在宏中使用 SendKeys

在宏中使用 SendKeys 来模拟按键。以下是两个简单的例子:

Sub CloseActiveWindow()
    ' 用 Alt+F4 组合键来关闭当前活动窗口
    SendKeys "%{F4}", True
End Sub
Sub CopyPasteUsingSendKeys()
    ' 选定要复制的范围
    Range("A1:A10").Select
    ' 模拟 Ctrl+C 复制
    SendKeys "^c"
    ' 等待一小段时间确保复制完成
    Application.Wait Now + TimeValue("00:00:01")
    ' 选择粘贴的目标单元格
    Range("B1").Select
    ' 模拟 Ctrl+V 粘贴
    SendKeys "^v"
End Sub

在这段代码中,^c^v 分别模拟了 Ctrl+C 和 Ctrl+V 的按键操作,用于复制和粘贴数据。

如果弹窗只是一个简单的确认对话框(OK按钮),发送 Enter 键的按键即可关闭它。

Sub ClickOKButton()
    Application.DisplayAlerts = False
    ' ... 其余代码 ...

    ' 在运行宏之前发送 Enter 键的按键
    SendKeys "~", True

    ' 调用其他工作簿中的宏
    Application.Run "'******.xlsm'!import"
    Application.Run "'******.xlsm'!output"

    ' ... 其余代码 ...
    Application.DisplayAlerts = True
End Sub

在上述代码中,SendKeys "~", True 表示发送 Enter 键(“~” 是 Enter 键的符号),True 参数表示等待按键被处理。

这种方法存在缺点,最大的问题是它依赖于弹窗的出现时机必须与 SendKeys 调用精确同步。如果弹窗延迟出现,或者 SendKeys 在弹窗出现之前执行,那么按键将不会关闭弹窗。此外,SendKeys 可能会影响用户的其他操作,因为它是在全局范围内模拟按键。

4.3 警告

  • SendKeys 是一个不稳定的方法,因为它依赖于当前的屏幕焦点。如果焦点突然改变(比如用户点击了鼠标或按了键盘),SendKeys 发送的按键可能会被发送到错误的应用程序。
  • SendKeys 方法在执行时不会等待前一个命令完成。如果需要在发送键之间有时间间隔,可以使用 Application.WaitSleep 函数(后者需要声明 Windows API)。
  • 使用 SendKeys 时,确保关闭所有可能会拦截按键的屏幕保护程序或其他安全软件。
  • 如果代码需要在不同机器上运行,那么 SendKeys 方法可能因为系统设置的差异而不可靠。

5. 其他方法

Sub ClickOKButton()
    ' 禁用弹窗
    Application.DisplayAlerts = False
    
    ' 调用其他工作簿中的宏
    Application.Run "'******.xlsm'!import"
    Application.Run "'******.xlsm'!output"

    ' 启用弹窗
    Application.DisplayAlerts = True
End Sub

在VBA中,Application.DisplayAlerts 属性用于控制大多数情况下由Excel自动生成的警告和提示消息框的显示。将 Application.DisplayAlerts 设置为 False 会关闭这些警告框,例如在删除工作表或关闭工作簿时弹出的确认框。

然而,Application.DisplayAlerts 并不能关闭所有的弹窗。特别是,它不会关闭通过VBA代码显示的消息框(MsgBox 函数创建的),或者由其他程序创建的对话框。如果 importoutput 宏中有使用 MsgBox 显示的消息框,那么将 Application.DisplayAlerts 设置为 False 并不会阻止这些消息框的显示。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值