hohlick Пользователь Сообщений: 4660 Microsoft MVP 2018-2022 |
#1 11.06.2014 13:46:42 Есть такой код, по которому юзер должен указать исходный диапазон ячеек для последующей обработки в виде Range
Если юзер нажимает кнопку «Cancel», то макрос прерывается по ошибке 424: Object required Как сделать чтобы по нажатию отмены происходил выход из макроса или переход к нужной метке в коде? F1 творит чудеса |
||
Hugo Пользователь Сообщений: 23699 |
#2 11.06.2014 13:50:46
и обрабатываете ошибку. |
||
Юрий М Модератор Сообщений: 60912 Контакты см. в профиле |
#3 11.06.2014 13:53:11
|
||
hohlick Пользователь Сообщений: 4660 Microsoft MVP 2018-2022 |
#4 11.06.2014 14:14:45 Юрий М , а причем тут String, если нужен Range?
Да, спасибо, пришлось долго рыть гугл, пока правильно запрос не сформулировал. Сделал так:
Просто в справке написано, что F1 творит чудеса |
||||
Юрий М Модератор Сообщений: 60912 Контакты см. в профиле |
#5 11.06.2014 14:19:49
А причём тут Range, если нужно отследить нажатие кнопки «Cancel»? |
||
Игорь Пользователь Сообщений: 3671 |
Юрий М
, спасибо за пример макроса Коллеги, кто-нибудь пользуется ещё функцией StrPtr()? |
Hugo Пользователь Сообщений: 23699 |
#7 11.06.2014 15:10:16
вероятно это было думано не для типа 8 |
||
ктулху Пользователь Сообщений: 9709 |
давно набредал на статейку, ссылку сохранил, но использовать так и не получилось пока… http://vb.mvps.org/tips/varptr.asp Изменено: ктулху — 11.06.2014 15:46:11 фрилансер Excel, VBA — контакты в профиле |
hohlick Пользователь Сообщений: 4660 Microsoft MVP 2018-2022 |
#9 11.06.2014 15:50:57
При том, что: функция InputBox , которая не задает тип вводимых данных (это важно для примера и лишения юзера возможности вводить абракадабру вместо адреса обрабатываемого диапазона). Т.е. ваш пример кода хорош для обработки именно нажатия Cancel в функции InputBox и переменных типа String, т.к. она тогда возвращает vbNullString.
В то время как
F1 творит чудеса |
||||||
Sub InputBox()
That procedure is implicitly Public
. Presumably being written in a standard module, that makes it globally scoped.
Link = InputBox("give me some input")
This means to invoke the VBA.Interaction.InputBox
function, and would normally succeed. Except by naming your procedure InputBox
, you’ve changed how VBA resolves this identifier: it no longer resolves to the global-scope VBA.Interaction.InputBox
function; it resolves to your InputBox
procedure, because VBAProject1.Module1.InputBox
(assuming your VBA project and module name are respectively VBAProject1
and Module1
) are always going to have priority over any other function defined in any other referenced type library — including the VBA standard library.
When VBA resolves member calls, it only looks at the identifier. If the parameters mismatch, it’s not going to say «hmm ok then, not that one» and continue searching the global scope for more matches with a different signature — instead it blows up and says «I’ve found the procedure you’re looking for, but I don’t know what to do with these parameters».
If you change your signature to accept a String
parameter, you get a recursive call:
Sub InputBox(ByVal msg As String)
That would compile and run… and soon blow up the call stack, because there’s a hard limit on how deep the runtime call stack can go.
So one solution could be to properly qualify the InputBox
call, so that the compiler knows exactly where to look for that member:
Link = VBA.Interaction.InputBox("give me some input")
Another solution could be to properly name your procedure so that its name starts with a verb, roughly describes what’s going on, and doesn’t collide with anything else in global scope:
Sub TestInputBox()
Another solution/work-around could be to use a similar function that happens to be available in the Excel object model, as QHarr suggested:
Link = Application.InputBox("give me some input")
This isn’t the function you were calling before though, and that will only work in a VBA host that has an InputBox
member on its Application
class, whereas the VBA.Interaction.InputBox
global function is defined in the VBA standard library and works in any VBA host.
A note about this:
If Link <> "" Then
This condition will be False
, regardless of whether the user clicked OK or cancelled the dialog by «X-ing out». The InputBox
function returns a null string pointer when it’s cancelled, and an actual empty string when it’s okayed with, well, an empty string input.
So if an empty string needs to be considered a valid input and you need to be able to tell it apart from a cancelled inputbox, you need to compare the string pointers:
If StrPtr(Link) <> 0 Then
This condition will only be False
when the user explicitly cancelled, and will still evaluate to True
if the user provided a legit empty string.
Instead of using the InputBox function, another approach would be to use the InputBox method of the Application object, which contains built-in error handling.
Sub Inputbox_Clarity()
Dim feeding As Variant
feeding = Application.InputBox("Enter a number >= 1000 and <= 3000", "Number", Type:=1)
If feeding = False Then Exit Sub
If feeding < 1000 Or feeding > 3000 Then Exit Sub
ActiveSheet.Range("A100") = feeding
End Sub
Alternatively, you can use a Do/Loop to continue prompting for a valid number or until the Cancel button is pressed.
Sub Inputbox_Clarity()
Dim feeding As Variant
Do
feeding = Application.InputBox("Enter a number >= 1000 and <= 3000", "Number", Type:=1)
If feeding = False Then Exit Sub
Loop While feeding < 1000 Or feeding > 3000
ActiveSheet.Range("A100") = feeding
End Sub
Hope this helps!
-
#1
I have an input box set up to prompt the user to select a range of cells. When i select cancel and no data range was selected, i get a run-time error ’13: type mismatch. Clicking on debug it refers me to my set calculated_range line of code. Not sure what i am doing wrong. The code works perfectly when a range is selected.
Also, if you have link to a video or website that you would recommend for learning vba i would appreciate it.
Here’s my code:
Code:
Sub Button3_Click()
Dim Calculated_Range
Set Calculated_Range = Application.InputBox("Calculate Weekly Hours", "Select a Range from Column 'F'", "Enter Range", , , , , 8)
If Calculated_Range = "" Then
MsgBox "No Range Selected"
GoTo ending
Else
MsgBox "Range Selected: " & Calculated_Range.Address
End If
Range("R3").Formula = "=Sum(" & Calculated_Range.Address & ")"
ending:
End Sub
Last edited by a moderator:
Which Excel functions can ignore hidden rows?
The SUBTOTAL and AGGREGATE functions ignore hidden rows. AGGREGATE can also exclude error cells and more.
-
#2
When you cancel an Application.InputBox it returns False. Which is not a Range object, hense the mismatch
Try
Code:
On Error Resume Next
Set Calculated_Range = Application.InputBox("Calculate Weekly Hours", "Select a Range from Column 'F'", "Enter Range", , , , , 8)
On Error Goto 0
If Calculated_Range Is Nothing Then
MsgBox "No Range Selected"
GoTo ending
Else
MsgBox "Range Selected: " & Calculated_Range.Address
End If
Fluff
MrExcel MVP, Moderator
-
#4
this comment was edited to quote the commentor
Last edited:
-
#5
When you cancel an Application.InputBox it returns False. Which is not a Range object, hense the mismatch
Try
Code:
On Error Resume Next Set Calculated_Range = Application.InputBox("Calculate Weekly Hours", "Select a Range from Column 'F'", "Enter Range", , , , , 8) On Error Goto 0 If Calculated_Range Is Nothing Then MsgBox "No Range Selected" GoTo ending Else MsgBox "Range Selected: " & Calculated_Range.Address End If
This results in an object error on If Calculated_Range Is Nothing Then. However, i changed «Is Nothing» to = «» and it worked. Thanks for your help.
-
#6
so changing the is nothing then part of the code to = «» then allows the message box to work for a cancel selection on the input box but then gives a type mismatch error for the range calculation. Switching it back to is nothing then, allows the range calculation to work but again gives me an error when cancel is selected. Something is still missing.
RoryA
MrExcel MVP, Moderator
-
#7
You should have this declaration in your code:
Code:
Dim Calculated_Range As Range
-
#8
You should have this declaration in your code:
Code:
Dim Calculated_Range As Range
Thanks Rory this helped alot. In addition i moved the code that puts the selected range into R3 to before the end of the if statement. All works good now. Thanks all for your help on this. Here’s the code in case someone else runs into a similar problem:
Sub Button3_Click()
Dim Calculated_Range As Range
On Error Resume Next
Set Calculated_Range = Application.InputBox(«Calculate Weekly Hours», «Select a Range from Column ‘F'», «Enter Range», , , , ,
On Error GoTo 0
If Calculated_Range Is Nothing Then
MsgBox «No Range Selected»
Else
MsgBox «Range Selected: » & Calculated_Range.Address
Range(«R3»).Formula = «=Sum(» & Calculated_Range.Address & «)»
End If
End Sub
A common requirement in VBA programs is to display an input box, and get the
user to type in an integer. Here is a routine which will allow you to do
just that:
Function GetInteger() As Long
Dim InputString As String
InputString = InputBox(«Input a number»)
If Len(InputString) = 0 Then
GetInteger = -1
Exit Function
End If
On Error GoTo NotInteger
GetInteger = CLng(InputString)
Exit Function
NotInteger:
GetInteger = -1
End Function
Here is how you could call this routine to get a whole number (integer), then
display its square:
Sub SquareNumber()
Dim NumberToSquare As Long
NumberToSquare = GetInteger
If NumberToSquare = -1 Then
MsgBox «You must enter an integer»
Exit Sub
End If
MsgBox «Square of » & NumberToSquare & _
» is » & (NumberToSquare ^ 2)
End Sub
When you run the SquareNumber routine, if you enter text
into the input box it will trigger an error and pass control to the
NotInteger label. This in turn will set the value of the function
to -1.
If you type in text like this, the code will trigger an error when you try to convert it to an integer.
You will then see an error message like this:
The message which will appear if you leave the input box blank or type in something which isn’t a whole number.
This is a typical use of error trapping:
- We know we are about to do something which sometimes won’t
work; - We set an error trap giving a label to jump to in the event
of an error; - We run the code, secure in the knowledge that it will do the
right thing whether or not the user reacts in the correct way.
That’s pretty much the complete story about error-trapping, but
error-trapping aficionados might like to read the final part of this series, in
which you can raise your own errors and learn how error messages bubble up
through the call stack!