VBA - Returning Range or Number from Applilcation.InputBox - excel

I am using Applilcation.InputBox to get a number from the user. Further in the code I am multipying a range of cells with that number.
My problem is that I want to know if the number was written manually or chosen by selecting a cell in the worksheet (that means if the user has written „123“ then „123“ and if he has selected a range then return $A$1).
Code:
Dim output As Variant
Set output = Application.InputBox("Enter Number", "Number for multyplying")
Any advice, please?

I don't think you can do this. Either you set the type to 8, and then you can't enter numbers, or you set it to 1 and then you can't enter references. If you combine it to 9, you still have the problem with Set or no Set.
' Works for ranges
Set Output = Application.InputBox("Enter Number", "Number for multyplying", , , , , , 8)
' Works for literals
Output = Application.InputBox("Enter Number", "Number for multyplying", , , , , , 1)
' Could have worked for both, but it doesn't
Set Output = Application.InputBox("Enter Number", "Number for multyplying", , , , , , 9)
I think the cleanest way to solve this is to implement a UserForm with a RefEdit control.

So, with Application.InputBox I wasn't able to achieve the desired functionality, allthough I still think it's possible somehow... :-)
This is what I came up with (using a UserForm with RefEdit and other tools):
Pay no attention to the picture in the background. I was just trying out stuff... :-) Allthough, I quite like it after all :-)
And this is the code for the commandButton:
(ref_Input being the RefEdit, txb_number the TextBox)
Public gNmr As Variant
Private Sub cmd_OK_Click()
Dim adr As String
If ref_Input.Value <> vbNullString And txb_number.Value <> vbNullString Then
MsgBox "Choose just one option, please.", , "Wrong input"
Exit Sub
Else
If ref_Input.Value = vbNullString And txb_number.Value = vbNullString Then
MsgBox "No input, please try again.", , "Wrong input"
Exit Sub
Else
If txb_number.Value = vbNullString Then
adr = ref_Input.Value
gNmr = adr
Else
If ref_Input.Value = vbNullString Then
gNmr = txb_number.Value
End If
End If
End If
End If
Unload Me
End Sub

Related

VBA listbox updates

i have below VBA code to update long list(1000) of part userform listbox with constant changes to design.
i need help with below 2 issues i am facing with code,
1)somehow, it is only updating only 1st selected item under multiselect listbox. can you pl help to check what is the issue with it to get all selected items updated by command button?
also, there are number of duplicates that i want to updates as well. however, below code updates only one and not other duplicate. can you pl help to correct code so it can update duplicates as well?
Private Sub cmdaction_Click()
Dim t, t1 As String
Dim vrech As Range, lColumn As Range
Dim sh As Worksheet
Dim i As Long
Dim selItem As String
Set sh = ThisWorkbook.Sheets("part bump")
Set lColumn = sh.Range("P1:AZA1").Find(Val(txtchangenumber.Value), , xlValues, xlWhole)
'Set lcolumn1 = sh.Range("F4:F1000")
If UserForm3.txtchangedescrption.Value = "" Then
MsgBox "Please enter Change Description"
Exit Sub
End If
If UserForm3.txtchangenumber.Value = "" Then
MsgBox "Please enter Change Number"
Exit Sub
End If
If UserForm3.cmbaction.Value = "" Then
MsgBox "Please Select part Action"
Exit Sub
End If
If lColumn Is Nothing Then
MsgBox "Change number not found"
Exit Sub
End If
With UserForm3.lstDatabase
For i = 0 To UserForm3.lstDatabase.ListCount - 1
If UserForm3.lstDatabase.Selected(i) = True Then
Set vrech = sh.Range("H4:H250").Find(.Column(7, i), , xlValues, xlWhole)
If Not vrech Is Nothing Then
Select Case cmbaction.Value
Case "RP"
t = Chr(Asc(Mid(.List(i, 7), 2, 1)) + 1)
t1 = Mid(.List(i, 7), 1, 2) & t & Mid(.List(i, 7), 4, 1)
Intersect(vrech.EntireRow, lColumn.EntireColumn) = t1
MsgBox "Selected parts 'RP' Action completed"
Case "RV"
Intersect(vrech.EntireRow, lColumn.EntireColumn) = .List(i, 7)
MsgBox "Selected parts 'RV' Action completed"
Case "DP"
Intersect(vrech.EntireRow, lColumn.EntireColumn) = "Deleted"
vrech.EntireRow.Font.Strikethrough = True
MsgBox "Selected parts 'DP' Action completed"
End Select
End If
End If
Next i
End With
End Sub
Upon further investigation I found that your handling of the Selected property is correct. I have deleted my advice in this regard and apologize for my hasty comment.
I have also re-examined your code and regret, I can't find a reason why it shouldn't deal with all selected items. without access to your workbook i don't have the ability to test and can't help you further.
Your second complaint is caused by this line of code.
Set vrech = sh.Range("H4:H250").Find(.Column(7, i), , xlValues, xlWhole)
It will find the first instance and no others. If you want the search to be repeated a loop will be required that repeats the search. Look up "VBA Find & FindNext MSDN" and you will find code samples how to construct the loop.
Note that in Dim t, t1 As String only t1 is a string. t is defined as a variant by virtue of not having a specified data type. This doesn't appear to be your intention.
I also noted your unusual use of Application.Intersect. Intersect(vrech.EntireRow, lColumn.EntireColumn) should be the equivalent of the simpler Sh.Cells(vrech.Row, lColumn), and it's recommended to specify the Value property when assigning a value to it.

Run time error '1004' Application defined or object defined error on Vlookup function

I am trying to utilize Vlookup function, according to the Textbox1 value user put in in Userform Guntest, automatically looking for corresponding features of the gun.
However the program currently doesn't run as it reminds me
'Runtime error '1004', method 'Range of object' _Global' failed.
The error appears on Retrieve1=…
I will be appreciated if you could help me to check where the problem is as I have really limited knowledge and experience on using VBA.
Thanks in advance.
It looks like some objects is undefined but I can't figure out where.
The module 1 code is:
Public Guncode As String
Option Explicit
Sub Test()
Call Vlookup
End Sub
Sub Vlookup()
Dim Retrieve1 As String
Dim Retrieve2 As String
Dim FinalRow As Long
Dim FinalColumn As Long
Dim WholeRange As String
If GunTest.TextBox1 = "" Then
Exit Sub
If GunTest.TextBox1 <> "" Then
MsgBox Guncode
End If
End If
With Sheets(1)
FinalRow = Range("A65536").End(xlUp).Row
FinalColumn = Range("IV1").End(xlToLeft).Column
WholeRange = "A2:" & CStr(FinalColumn) & CStr(FinalRow)
Retrieve1 = Application.WorksheetFunction.Vlookup(Trim(Guncode), Range(WholeRange), 1, False) 'Locate specific tool according to QR code number
Retrieve2 = Application.WorksheetFunction.Vlookup(Trim(Guncode), Range(WholeRange), 5, False) 'Locate specific gun type according to QR code number
If Guncode = "" Then
MsgBox "This gun doesn't exist in database!"
Else
MsgBox "The tool number is:" & Retrieve1 & vbCrLf & "The gun type is:" & Retrieve2
End If
End With
End Sub
The userform code is:
Option Explicit
Private Sub Label1_Click()
End Sub
Private Sub CommandButton1_Click()
If TextBox1 = "" Then Exit Sub 'Set condition 1 of exiting the program
Guncode = GunTest.TextBox1
With Me
Call Module1.Test
End With
End Sub
Private Sub PartID_Click()
End Sub
Private Sub TextBox1_Change()
End Sub
Private Sub UserForm_Click()
End Sub
It should run properly but it doesn't. Any help would be appreciated, thanks!
First off, you were passing in a number as the column letter value. CSTR() doesnt magically transform it into the letter equivalent but I like your enthusiasm.
Second, your method will bomb if the value isnt found - so you'll need to write your own error handling for it.
Sub Vlookup()
Dim Retrieve1 As String
Dim Retrieve2 As String
Dim FinalRow As Long
Dim FinalColumn As Long
Dim WholeRange As String
Dim vArr
Dim col_Letter As String
If GunTest.TextBox1 = "" Then
Exit Sub
If GunTest.TextBox1 <> "" Then
MsgBox Guncode
End If
End If
With ThisWorkbook.Sheets("Sheet1")
FinalRow = .Range("A65536").End(xlUp).Row
FinalColumn = .Range("IV1").End(xlToLeft).Column
vArr = Split(Cells(1, FinalColumn).Address(True, False), "$")
col_Letter = vArr(0)
WholeRange = "A2:" & col_Letter & CStr(FinalRow) '<---- you were passing a number in as the column value
Retrieve1 = Application.WorksheetFunction.Vlookup(Trim(Guncode), .Range(WholeRange), 1, False) 'Locate specific tool according to QR code number
Retrieve2 = Application.WorksheetFunction.Vlookup(Trim(Guncode), .Range(WholeRange), 5, False) 'Locate specific gun type according to QR code number
If Guncode = "" Then
MsgBox "This gun doesn't exist in database!"
Else
MsgBox "The tool number is:" & Retrieve1 & vbCrLf & "The gun type is:" & Retrieve2
End If
End With
End Sub
1. I am not sure what is the reason using Address(True, False) for row number.
This comes from a combination of these two functions. The true/false setting is telling the funciton to use/not use absolute references in the address.
Split ( expression [,delimiter] [,limit] [,compare] )
https://www.techonthenet.com/excel/formulas/split.php
expression.Address (RowAbsolute, ColumnAbsolute, ReferenceStyle, External, RelativeTo)
https://learn.microsoft.com/en-us/office/vba/api/excel.range.address
Shouldn't Cell (1, FinalColumn) stands for the column number?
No, the cells fucntiosn basically returns an intersection/address of rows & column.
Try this for example: debug.Print; thisworkbook.Sheets("Sheet1").Cells(2,2)
You mentioned CSTR doesn't magically transform to letter equivalent so what would it transform to? Could you further elaborate?
This is a data type conversion function. CSTR(666) essentially does this: this 666 becomes this "666"
2. vArr(0). I am confused with what does the parameter 0 stands for in the bracket. Actually this is a general question I always have regarding to parameter specification.
This is an array position refence. The split function returns an array of strings. Since we're using to capture the column label value, we only need to reference the first position.
(3) I tried copy your code and run it but still reminds me error on the same row.
Works fine for me unless there is no returning value, which returns an error which is what I meant by "bomb."

Handling non integer in inputbox in VBA

I have a variable called "need" that is defined as an integer. An input box come up and prompts the user. If they type an integer it displays Msgbox "Got your number". If I type a string I get Runtime error '13': type mismatch. I thought if I just used an Else statement, it would say try again. It is not doing that though. Do I need error handling in the Else statement? And if so, what would the line(s) be?
Sub gadgetmanuf()
Dim need As Integer
'Dim rawneed As Single
'Dim rawavailable As Single
need = InputBox("How many gadgets are needed?", "Insert a number")
If TypeName(need) = "Integer" Then
MsgBox ("Got your number")
Else
MsgBox ("Try again")
End If
End Sub
Using an Application.InputBox with type 1 forces the user to enter a number (provides its own error message for text, ranges etc). So all you need to handle is the Cancel option, ie
The code below uses a variant to handle this, as using Cancel with an Integer or Long gives 0 - which could be a valid entry.
Sub TaylorWalker()
redo:
vStr = Application.InputBox("How many gadgets are needed?", "Enter a number", , , , , , Type:=1)
If vStr = False Then GoTo redo
End Sub
longer option
Test that the entered variable is greater than 0
Sub EddieBetts()
Dim StrPrompt As String
Dim lngNum As Long
StrPrompt = "How many gadgets are needed?"
redo:
lngNum = Application.InputBox(StrPrompt, "Enter an integer number (numbers will be rounded)", , , , , , Type:=1)
If lngNum < 1 Then
StrPrompt = "How many gadgets are needed - this must be a postive integer"
GoTo redo
End If
MsgBox "User entered " & lngNum
End Sub
In your example 'need' is an integer data type so it will always be an integer.
Have a look at this:
Sub test()
x = Range("A1").Value
If Int(x) / x = 1 Then
MsgBox "Value is an Integer"
Else
MsgBox "Value is not an Integer"
End If
End Sub
or Assuming A1 has the number, put, in any other cell, the formula:
=IF(INT(A1)=A1,"True","False")

Excel VBA Textbox resets to 0 when i press a button

i have a userform with 2 textboxes, 2 labels and a log in button.
On my excel sheet i have a sort of database with id, name, pin and balance.
the problem is whenever i click the login button my ID textbox resets its value to 0, but my pin textbox works fine!
i will paste my complete code:
Dim ID As Integer
Dim PIN As Integer
Dim PINField As String
Dim Balance As Double
Dim Attempts As Integer
Dim BalanceField As String
Private Sub btnLogin_Click()
txtID.Text = ID
Call SetId
Call Authenticate
End Sub
Sub Authenticate()
If txtPin.Text = PIN Then
Call Welcome
ElseIf Attempts > 3 Then
Call Bye
Else
lblWelcome.Caption = "Wrong Pin"
lblWelcome.ForeColor = RGB(255, 0, 0)
Attempts = Attempts + 1
End If
End Sub
Sub SetId()
PINField = "C" & Str(ID)
PINField = Replace(PINField, " ", "")
MsgBox (PINField)
BalanceField = "D" & Str(ID)
BalanceField = Replace(BalanceField, " ", "")
MsgBox (BalanceField)
End Sub
Sub Welcome()
MsgBox ("Login Successful. Welcome")
End Sub
Sub Bye()
MsgBox ("Max Pin Attempts reached. Contact Your Bank")
Unload frmLogin
End Sub
The reason it does this is because you are using a variable which has no value. Since it is an Integer it returns 0.
I'm guessing you probably actually want to have ID = txtID.Text - that is, take the value of the txtID textbox and store the value in the ID variable.
This will probably error though because the Text property of a textbox is a String. You will need to use ID = CInt(txtID.Text). You should also do some checking to make sure that txtID.Text evaluates to an Integer before assignment.
Please make sure there's no reset for the txtID anywhere in the code that you have not shown here. Looking at your code, it doesn't say anything how you are setting values to either ID or PIN... You said it's working fine for PIN, so it makes me very curious...
It could be the case Nick pointed out given this is a Form with textboxes allowing people to enter ID and PIN.. And then you are comparing it against PIN. But what are you comparing against? As you said you have a database kind of a structure in the sheet. You need to assing ID and PIN using it.
Here is the visualization I have for your Sheet, which is my best blind guess:
User needs to enter a value via the Form into txtID. That number is infact the cell number for column C which contains the relevant PIN. Then you compare that PIN with the txtPIN value. Next return the balance from column D based on that PIN.
Try this:
Private Sub btnLogin_Click()
If txtID.Text <> "" Or txtID.value > 0 or txtPIN.Text <> "" Then
ID = CInt(txtID.Text)
Call SetID
Call Authentication
Else
MsgBox "ID and PIN" can't be empty!"
End If
End Sub
Sub Authenticate()
If CInt(txtPin.Text) = PIN Then '-- here
Call Welcome
'-- idealy Blance can be shown at this point...
ElseIf Attempts > 3 Then
Call Bye
Else
lblWelcome.Caption = "Wrong Pin"
lblWelcome.ForeColor = RGB(255, 0, 0)
Attempts = Attempts + 1
End If
End Sub
Sub SetId()
PIN = CInt(Trim(Sheets(1).Range("C" & ID).value))
'-- NOT sure why you are showing this PIN here since you want to authenticate...?
MsgBox PIN
BalanceField = Sheets(1).Range("D" & ID).value
BalanceField = Trim(BalanceField) '--here
'-- doesn't make sense to show Balance before authentication...
MsgBox BalanceField
End Sub
Trim is clearner and faster than Replace..

Is it possible to increase the 256 character limit in excel validation drop down boxes?

I am creating the validation dynamically and have hit a 256 character limit. My validation looks something like this:
Level 1, Level 2, Level 3, Level 4.....
Is there any way to get around the character limit other then pointing at a range?
The validation is already being produced in VBA. Increasing the limit is the easiest way to avoid any impact on how the sheet currently works.
I'm pretty sure there is no way around the 256 character limit, Joel Spolsky explains why here: http://www.joelonsoftware.com/printerFriendly/articles/fog0000000319.html.
You could however use VBA to get close to replicating the functionality of the built in validation by coding the Worksheet_Change event. Here's a mock up to give you the idea. You will probably want to refactor it to cache the ValidValues, handle changes to ranges of cells, etc...
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ValidationRange As Excel.Range
Dim ValidValues(1 To 100) As String
Dim Index As Integer
Dim Valid As Boolean
Dim Msg As String
Dim WhatToDo As VbMsgBoxResult
'Initialise ValidationRange
Set ValidationRange = Sheet1.Range("A:A")
' Check if change is in a cell we need to validate
If Not Intersect(Target, ValidationRange) Is Nothing Then
' Populate ValidValues array
For Index = 1 To 100
ValidValues(Index) = "Level " & Index
Next
' do the validation, permit blank values
If IsEmpty(Target) Then
Valid = True
Else
Valid = False
For Index = 1 To 100
If Target.Value = ValidValues(Index) Then
' found match to valid value
Valid = True
Exit For
End If
Next
End If
If Not Valid Then
Target.Select
' tell user value isn't valid
Msg = _
"The value you entered is not valid" & vbCrLf & vbCrLf & _
"A user has restricted values that can be entered into this cell."
WhatToDo = MsgBox(Msg, vbRetryCancel + vbCritical, "Microsoft Excel")
Target.Value = ""
If WhatToDo = vbRetry Then
Application.SendKeys "{F2}"
End If
End If
End If
End Sub

Resources