VBA:如果用户删除单元格,Range对象会发生什么变化?

假设我在vba中有一些模块,里面有一些types为Rangevariablesr 。 假设在某个时候,我在那里存储一个Range对象(例如活动单元格)。 现在我的问题是:如果用户删除单元格(单元格,不仅是它的值), r的值会发生什么变化?

我试图在VBA中弄清楚,但没有成功。 结果很奇怪。 r不是Nothingr的值被报告为Rangetypes,但是如果我试图在debugging器窗口中查看它的属性,每个属性的值都被报告为“object required”。

我怎样才能以编程的方式确定variablesr是否处于这种状态?

我可以做到这一点,而不会产生错误,并捕捉它?

很好的问题! 我从来没有想过这个,但是我认为这个函数将确定一个被初始化的范围 – 不是Nothing,而是现在处于“Object Required”状态,因为它的单元被删除了:

 Function RangeWasDeclaredAndEntirelyDeleted(r As Range) As Boolean Dim TestAddress As String If r Is Nothing Then Exit Function End If On Error Resume Next TestAddress = r.Address If Err.Number = 424 Then 'object required RangeWasDeclaredAndEntirelyDeleted = True End If End Function 

你可以testing是这样的:

 Sub test() Dim r As Range Debug.Print RangeWasDeclaredAndEntirelyDeleted(r) Set r = ActiveSheet.Range("A1") Debug.Print RangeWasDeclaredAndEntirelyDeleted(r) r.EntireRow.Delete Debug.Print RangeWasDeclaredAndEntirelyDeleted(r) End Sub 

我相信,当您在VBA中使用Set关键字时,它会在您指定的工作表(每个单元格是工作表单元格的单元格集合中的某个给定范围的对象)的工作表的Range对象的背景中创build一个指针。 当范围在内存中被引用时被删除时,Rangevariables指向的对象的内存已被释放。

然而,你的Rangevariables最有可能仍然包含指向最近删除的Range对象的指针,这就是为什么它不是什么,但是不pipe它指向什么都不存在,当你试图再次使用variables时会导致问题。

看看这个代码,看看我的意思是:

 Public Sub test2() Dim r As Excel.Range Debug.Print ObjPtr(r) ' 0 Set r = ActiveSheet.Range("A1") Debug.Print ObjPtr(r) ' some address r.Value = "Hello" r.Delete Debug.Print ObjPtr(r) ' same address as before End Sub 

看看这篇文章更多关于ObjPtr()的信息: http : //support.microsoft.com/kb/199​​824

所以虽然你有一个有效的地址对象,不幸的是,该对象已经不存在了,因为它已被删除。 而且看起来“Is Nothing”只是检查指针中的地址(我认为VBA认为variables是“Set”)。

至于如何解决这个问题,不幸的是我现在看不到一个干净的方法(如果有人find一个优雅的方式来处理这个问题,请张贴它!)。 您可以使用On Error Resume Next,如下所示:

 Public Sub test3() Dim r As Excel.Range Debug.Print ObjPtr(r) ' 0 Set r = ActiveSheet.Range("A1") Debug.Print ObjPtr(r) ' some address r.Value = "Hello" r.Delete Debug.Print ObjPtr(r) ' same address as before On Error Resume Next Debug.Print r.Value If (Err.Number <> 0) Then Debug.Print "We have a problem here..."; Err.Number; Err.Description End If On Error GoTo 0 End Sub 

我怎样才能以编程的方式确定variablesr是否处于这种状态?

我可以做到这一点,而不会产生错误,并捕捉它?

没有。

据我所知,你不能可靠地testing这个条件:不是没有提升和捕捉错误。

你的问题已经在其他地方引起注意和讨论 :Excel / VBA博客中的两个大名(Dick Kusleika和Rob Bovey)已经研究过了,你可能会在那里发现一些信息。 但答案是否定的

总而言之,这是一个相当令人担忧的回答。

要testing范围对象是否当前无效,我使用这个函数:

 Public Function InvalidRangeReference(r As Range) As Boolean On Error Resume Next If r.Count = 0 Then InvalidRangeReference = Err End If End Function