如何为Before/After Refresh事件添加有效错误处理程序?
问题描述
我通过参数化查询从SQL Server导入数据,该查询需要用户输入日期:
- 当用户正确输入开始日期和结束日期时,所有流程均正常完成。
- 但当日期输入错误时,错误处理程序不会触发,宏会继续执行直到AfterRefresh事件。
我已为所有模块添加了错误处理程序,但仍无响应。请问如何为Before/After Refresh事件添加有效的错误处理程序?
Power Query 逻辑代码
let Source = Sql.Database("MyDataBase", [Query="Select Transaction_date, Customer_ID from TransactionList where Transaction_date between @StartDate and @EndDate"]) in Source
VBA 代码
标准模块代码
'========== [ Modules ] ========== Option Explicit Dim colQueries As New Collection Sub Button_RefreshData() On Error GoTo Error_Handler Call InitializeQueries ThisWorkbook.RefreshAll Exit Sub Error_Handler: MsgBox Err.Number & " " & Err.Source & vbNewLine & Err.Description, vbInformation Exit Sub End Sub Sub InitializeQueries() On Error GoTo Error_Handler Dim clsQ As clsQuery Dim WS As Worksheet Dim QT As QueryTable Dim LO As ListObject For Each WS In ThisWorkbook.Worksheets For Each QT In WS.QueryTables Set clsQ = New clsQuery Set clsQ.MyQuery = QT colQueries.Add clsQ Next QT For Each LO In WS.ListObjects Set QT = LO.QueryTable Set clsQ = New clsQuery Set clsQ.MyQuery = QT colQueries.Add clsQ Next LO Next WS Exit Sub Error_Handler: MsgBox Err.Number & " " & Err.Source & vbNewLine & Err.Description, vbInformation Exit Sub End Sub
类模块(clsQuery)代码
'========== [ Class Modules named clsQuery ] ========== Option Explicit Public WithEvents MyQuery As QueryTable Private Sub MyQuery_AfterRefresh (ByVal Success As Boolean) On Error GoTo Error_Handler If Success Then MsgBox ("The entire process is complete.") Exit Sub Error_Handler: MsgBox Err.Number & " " & Err.Source & vbNewLine & Err.Description, vbInformation Exit Sub End Sub Private Sub MyQuery_BeforeRefresh (Cancel As Boolean) On Error GoTo Error_Handler MsgBox ("The process start now.") Exit Sub Error_Handler: MsgBox Err.Number & " " & Err.Source & vbNewLine & Err.Description, vbInformation Exit Sub End Sub
解决方案
问题核心在于:日期输入错误引发的异常发生在Power Query参数验证/数据库查询阶段,不会触发VBA标准模块的错误捕获,且BeforeRefresh事件仅在刷新启动前触发,无法拦截参数输入错误。以下是针对性修复方案:
1. 利用AfterRefresh的Success参数捕获错误
AfterRefresh的Success参数会在刷新失败时返回False,这是捕获此类错误的关键入口。修改类模块的AfterRefresh事件:
Private Sub MyQuery_AfterRefresh(ByVal Success As Boolean) If Success Then MsgBox "数据刷新完成。" Else MsgBox "刷新失败:日期格式错误或查询执行异常,请检查输入后重试。", vbCritical ' 可选:清除错误数据 MyQuery.ResultRange.ClearContents End If End Sub
2. 提前在BeforeRefresh中验证日期输入(推荐)
从源头避免错误,在刷新启动前完成日期合法性校验:
Private Sub MyQuery_BeforeRefresh(Cancel As Boolean) Dim startDate As Date, endDate As Date Dim inputStart As String, inputEnd As String ' 替换为你的实际参数输入逻辑(比如自定义弹窗) inputStart = InputBox("请输入开始日期(格式:YYYY-MM-DD):") inputEnd = InputBox("请输入结束日期(格式:YYYY-MM-DD):") ' 验证日期格式与逻辑 On Error Resume Next startDate = CDate(inputStart) endDate = CDate(inputEnd) On Error GoTo 0 If Not IsDate(startDate) Or Not IsDate(endDate) Then MsgBox "日期格式错误,请输入合法日期(例如:2024-01-01)。", vbCritical Cancel = True ' 取消刷新 Exit Sub End If If startDate > endDate Then MsgBox "开始日期不能晚于结束日期。", vbCritical Cancel = True Exit Sub End If ' 更新QueryTable的参数值(如果使用内置参数配置) With MyQuery.Parameters("StartDate") .Value = startDate .RefreshOnChange = True End With With MyQuery.Parameters("EndDate") .Value = endDate .RefreshOnChange = True End With MsgBox "刷新即将开始。" End Sub
3. 在Power Query中添加错误处理逻辑
如需更精准捕获数据库返回的错误,可在Power Query中加入错误捕获:
let Source = try Sql.Database("MyDataBase", [Query="Select Transaction_date, Customer_ID from TransactionList where Transaction_date between @StartDate and @EndDate"]) otherwise error "查询执行失败:" & try Text.From(Source[Error][Message]) otherwise "未知错误" in Source
当Power Query报错时,VBA的AfterRefresh事件中Success会变为False,可进一步通过VBA读取查询结果中的错误信息。
关键注意事项
- 类模块中的
Error_Handler对参数输入错误无效,因为这类错误不发生在VBA代码执行阶段,而是在Power Query与数据库交互阶段。 ThisWorkbook.RefreshAll是异步执行的,标准模块的错误捕获无法拦截后续刷新过程中的异常,必须依赖类模块的事件处理。
内容的提问来源于stack exchange,提问作者Starbucks
相关产品推荐
相关产品推荐

