【问题标题】:Determining if a cell is linked to a QueryTable via VBA in Excel确定单元格是否通过 Excel 中的 VBA 链接到 QueryTable
【发布时间】:2016-11-07 22:19:36
【问题描述】:

我正在使用运行良好的 QueryTables 将 Excel 工作表链接到数据源。我想引入逻辑来检查给定的单元格并确定该单元格是否是现有 QueryTable 的左上角。这在概念上似乎微不足道,但在实践中证明是难以捉摸的。如果我尝试检查与 QueryTable 相关的单元格的任何属性,则会出现错误。即,如果rng 未链接到 QueryTable,rng.querytable 将引发错误 1004。所以我根据我在网上找到的一些讨论来测试rng.ListObject is nothing。事实证明,rng.ListObject 是某个单元格是一个表,即使该表不是 QueryTable。所以那里没有骰子。

那么如何测试目标单元格是否包含 QueryTable?

这是我从Mr. Excel 获得的函数存根:

Public Function IsRangeInQueryTable(rngCheck As Range) As Boolean
    Dim QT As QueryTable

    For Each QT In rngCheck.Parent.QueryTables

        If Not Intersect(rngCheck, QT.ResultRange) Is Nothing Then
            IsRangeInQueryTable = True
            Exit Function
        End If

    Next QT

    'If it got to here then the specified range does not lie
    'in the result range of any query
    IsRangeInQueryTable = False

End Function

上面的函数在很多情况下都有效,但是如果我的 QueryTables 已经与它们的目的地分离(这在实践中似乎发生),代码会抛出错误 1004,因为 QueryTable 没有目的地。以下是 QueryTable 与目的地分离时手表显示的内容:

FWIW,我还尝试以相反的方式处理此问题并遍历工作表中的每个 QueryTable。事实证明,如果有一个 QueryTable 的目的地被删除,询问 QueryTable 的QueryTable.Destination 会引发应用程序错误。所以我也想不出一种可靠的方法来实现这种方法。

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    这比它需要的更冗长,但是因为“OnError”语句重定向所有错误,我想消除意外处理错误错误的可能性,例如如果rngNothing

    Public Function cell_has_query(rng As Range) As Boolean
    
        If rng Is Nothing Then
           cell_has_query = False
           Exit Function
        End If
    
        If rng.ListObject Is Nothing Then
            cell_has_query = False
            Exit Function
        End If
    
    On Error GoTo ErrHandler
        If Not rng.ListObject.QueryTable Is Nothing Then
            cell_has_query = True
        End If
        Exit Function
    
    ErrHandler:
        If Err.Number = 1004 Then 'Application-Defined or Object-Defined Error
            cell_has_query = False
        Else
            On Error GoTo 0
            Resume
        End If
    End Function
    

    @JDLong VBA 错误处理很奇怪。错误的默认设置是On Error GoTo 0,这意味着(取决于您的 VBA IDE 设置;工具-->选项-->常规)将弹出一个未处理错误的消息框。如果你想明确地捕捉和处理错误,你可以创建一个标签(例如“ErrHandler”),然后通过以Exit Function结束函数来确保该部分代码正常无法访问。在标签后面的代码块中,您可以检查Err 对象属性并选择Resume 重试导致错误的代码行,Resume Next 运行以下行出错的那个,或者只是处理错误并让函数正常退出。您还可以通过将模式设置回On Error GoTo 0 然后Resume 来重新引发错误。

    【讨论】:

    • 我早先走了那条路,发现 rng.ListObject 如果 rng 是一个表,即使它没有查询表也是如此。所以这种情况最终会通过第一次检查(listobject 是什么),然后在第二次检查时抛出错误。
    • @JDLong 我明白你的意思了——我刚刚尝试使用 Excel 表格。这实际上不是问题,因为您可以使用 VBA 错误处理来捕获它。如果该行代码抛出 1004 错误,则可以断定它不是 QueryTable。一秒钟,我会重写
    • 我一直在努力如何在没有 try/catch 的情况下做到这一点(VBA 显然不是我最习惯思考的语言)
    • @JDLong 我从 C++ 开始,用了几年的 Java,然后在过去的几年里被 VBA 卡住了 - 我感觉到你的痛苦:P
    【解决方案2】:

    由于某些我不清楚的原因,我的查询表不在列表对象中。我认为所有查询表都在 listobjects 中,但我已经运行了足够的测试来向自己证明我的不是。所以我稍微编辑了@blackhawk的功能:

    Public Function cell_has_query(rng As Range) As Boolean
    
        If rng Is Nothing Then
           cell_has_query = False
           Exit Function
        End If
    
    On Error GoTo ErrHandler
        If Not rng.QueryTable Is Nothing Then
            cell_has_query = True
        End If
        Exit Function
    
    ErrHandler:
        If Err.Number = 1004 Then 'Application-Defined or Object-Defined Error - this throws if there is a querytable with no destination
            cell_has_query = False
        Else
            On Error GoTo 0
            Resume
        End If
    End Function
    

    【讨论】:

    • Excel 对象模型具有相当不错的底层层次结构(“具有”父/子关系),但除此之外,事物在各处都相互关联,这使事情变得复杂......在这种情况下,父 Worksheet 有 Range 和 QueryTable 子级,但是这两者之间的任何直接关系都不会那么直接
    • 我会打印出来向我女儿解释爸爸为什么喝酒。
    • @JDLong,无法解释原因,因为我不愿意调试,但您的答案对于函数与 stackoverflow.com/a/40476268/5079799 有正确的布尔结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2016-05-21
    相关资源
    最近更新 更多