9

我有以下代码:

dim selectRange as Range
Set selectRange = Application.InputBox("Select your range", "Hello", , , , , , 8)

当用户选择取消 InputBox 提示时,它会返回error of Object not set.

我尝试使用 Variant 变量类型,但我无法处理它。取消时返回False,同时选择范围时返回 InputBox 的 Range。

我怎样才能避免这个错误?

4

6 回答 6

9

当使用输入框选择范围时,这是一个问题。Excel 在返回范围之前返回错误,并且在您按取消时会携带此错误。

因此,您应该积极处理此错误。如果您不希望在按下取消时发生任何事情,您可以使用如下代码:

Sub SetRange()
    Dim selectRange As Range

    On Error Resume Next
        Set selectRange = Application.InputBox("Select your range", "Hello", , , , , , 8)
    Err.Clear
    On Error GoTo 0
End Sub 
于 2013-10-26T17:22:39.603 回答
7

虽然这个问题有点老了,但我仍然想展示正确的方法来做到这一点而不会出错。您可以通过函数或使用 sub 来完成它。

您的主要程序是这样的:

Sub test()
  Dim MyRange As Range

  testSub Application.InputBox("dada", , , , , , , 8), MyRange 'doing via Sub
  Set MyRange = testFunc(Application.InputBox("dada", , , , , , , 8)) ' doing via function

  If MyRange Is Nothing Then
    Debug.Print "The InputBox has been canceled."
  Else
    Debug.Print "The range " & MyRange.Address & " was selected."
  End If
End Sub

方式(有趣)将是:

Sub testSub(ByVal a As Variant, ByRef b As Range)
  If TypeOf a Is Range Then Set b = a
End Sub

函数看起来像:

Function testFunc(ByVal a As Variant) As Range
  If TypeOf a Is Range Then Set testFunc = a
End Function

现在只需使用您喜欢的方式并删除未使用的行。

如果调用 sub 或函数,则不需要Set参数。也就是说,无论是否InputBox返回对象都没有关系。您需要做的就是检查参数是否是您想要的对象,然后据此采取行动。

编辑

另一种聪明的方法是对这样的集合使用相同的行为:

Sub test()
  Dim MyRange As Range
  Dim MyCol As New Collection

  MyCol.Add Application.InputBox("dada", , , , , , , 8)
  If TypeOf MyCol(1) Is Range Then Set MyRange = MyCol(1)
  Set MyCol = New Collection

  If MyRange Is Nothing Then
    Debug.Print "The inputbox has been canceled"
  Else
    Debug.Print "the range " & MyRange.Address & " was selected"
  End If
End Sub

如果您仍有任何问题,请尽管提问;)

于 2016-05-31T12:10:46.097 回答
4

我在这里参加聚会迟到了,但这是我能找到的唯一地方,它解释了为什么我在检查我的变量时遇到了麻烦。正如接受的答案中所解释的,vbCancel范围对象上的处理方式与字符串对象的处理方式不同。必须使用错误处理程序来捕获错误。

讨厌错误处理程序。所以我把它隔离成自己的功能

Private Function GetUserInputRange() As Range
    'This is segregated because of how excel handles cancelling a range input
    Dim userAnswer As Range
    On Error GoTo inputerror
    Set userAnswer = Application.InputBox("Please select a single column to parse", "Column Parser", Type:=8)
    Set GetUserInputRange = userAnswer
    Exit Function
inputerror:
    Set GetUserInputRange = Nothing
End Function

现在在我的主子里我可以

dim someRange as range
set someRange = GetUserInputRange
if someRange is Nothing Then Exit Sub

无论如何,这与接受的答案不同,因为它允许用户仅使用特定的错误处理程序来处理此错误,而无需resume next或以相同的方式处理其余过程。以防有人像我一样来到这里。

于 2016-04-14T17:33:15.543 回答
1

我发现检查您提到的“需要对象”错误是处理取消的一种方法。

On Error Resume Next
dim selectRange as Range
' InputBox will prevent invalid ranges from being submitted when set to Type:=8.
Set selectRange = Application.InputBox("Select your range", "Hello", , , , , , 8)
' Check for cancel: "Object required".
If Err.Number = 424 Then
    ' Cancel.
    Exit Sub
End If
On Error GoTo 0
于 2015-10-14T22:26:41.810 回答
1

我采用了更清洁的解决方案:

Dim InputValue As Range
On Error Resume Next
Set InputValue = Application.InputBox("Select Range","Obtain Range", Type:=8)
Err.Clear
If InputValue Is Nothing Then
    GoTo ExitApp:
End If

这将清除错误消息并捕获返回给 InputValue 的“无”值。有用的是,这不会中断没有信息的提交,Excel 只是自动循环回请求输入,但用户可能需要为错误的数据输入添加额外的错误处理。

下代码,添加:

ExitApp:
    Exit Sub

对于退出,可以在多个输入取消处理程序之间有效地共享。

于 2020-08-18T18:04:15.163 回答
-1

如果我在 for 循环中使用 Dirks 第二个答案并且我想退出我的子,在他的 IF 语句中执行 Exit Sub 是不够的,
我发现如果我在 for 循环中独立使用 Exit Sub,我将不会退出我的sub 在所有情况下,然而,在大多数情况下只退出 f​​or 循环。

在这里你有 Dirks 代码

编辑

另一种聪明的方法是对这样的集合使用相同的行为:

 Sub test()
  Dim MyRange As Range
  Dim MyCol As New Collection

  MyCol.Add Application.InputBox("dada", , , , , , , 8)
  If TypeOf MyCol(1) Is Range Then Set MyRange = MyCol(1)
  Set MyCol = New Collection

  If MyRange Is Nothing Then
    Debug.Print "The input box has been canceled"
  Else
    Debug.Print "the range " & MyRange.Address & " was selected"
  End If
 End Sub

如果您仍有任何问题,请尽管提问;)

这是我做的一个例子:

Sub test()
  Dim i as Integer
  Dim boolExit as Boolean
  Dim MyRange As Range
  Dim MyCol As New Collection
  boolExit = False

  For i = 1 To 5 Then
    MyCol.Add Application.InputBox("dada", , , , , , , 8)
    If TypeOf MyCol(1) Is Range Then Set MyRange = MyCol(1)
    Set MyCol = New Collection

    If MyRange Is Nothing Then
      Debug.Print "The inputbox has been canceled"
      boolExit = True
      Exit Sub
    Else
      Debug.Print "the range " & MyRange.Address & " was selected"
    End If
  Next i

  If boolExit = True Then Exit Sub 'Checks if Sub should be exited

  Debug.Print "Program completed"      
End Sub

如果您在五次运行中的任何时候按取消,Sub 将使用上述代码关闭,您将永远不会看到Program completed打印。

但是,如果您从上面删除 boolExit,如果您在任何 1 次以上的运行中按取消,则 For 循环之后的代码仍在运行,即使这不是真的,您也会看到程序已完成。

于 2019-01-04T09:20:20.017 回答