if statement compare inputbox to cell.value - excel

Sub Botão34_Clique()
Dim x As String
Dim z As Integer
InputBox "FIND PRODUCT", "TYPE" = x
For z = 2 To 143
If Range("B" & z).Value = x Then
MsgBox Range("B" & z)
End If
Next z
End Sub
Hi guys,
I don't understand why the above code is not working.
The user's input will be compared with an existing product list.
When the input is equal to an existing product, the msgbox should indicate the cell in which it is present.
Unfortunately, I don't understand why the statement Range("B" & z).Value = x doesn't work...
Any ideas?

You don't write the result of the InputBox into the variable x.
What you do is to call the InputBox with 2 parameters.
The first parameter ("FIND PRODUCT") is the text that is shown in the input box as label.
The second parameter is used as form caption. You pass the expression "TYPE" = x as second parameter, and VBA will happily compare the string "TYPE" with the content of the variable x, resulting in either True or (most likely) False. So if you carefully look at the input box window, you will see the string "False" as caption.
Now the user enters something into the box and presses the "OK"-button. The entered value is returned, but you don't assign it to anything and the value is send to the big Computer Nirvana.
What you want is to assign the value to x. The correct syntax for this is
x = InputBox("FIND PRODUCT", "TYPE")
Note that in VBA, you have to put parenthesis around the list of parameters when you are calling a function and use the return value.

Related

How to identify and remove a single letter from a string in a cell?

I have a dataset of names in a column in Excel.
However, only some but not all of the names have a letter attached to the end of it (e.g. John Doe A, Kai Jin, Johnny Desplat Lang B, etc).
Can anyone think of a method to remove the letter from the end of the name from each row, if it is there? Such that, using the example above, I will be left with: John Doe, Kai Jin, Johnny Desplat Lang, etc.
I am fairly familiar with VBA and Excel and would be open to trying anything at all.
Thank you for your help with this question! Apologies beforehand if this seems like an elementary question but I have no idea how to begin to solve it.
"I am fairly familiar with VBA and Excel and would be open to trying anything at all."
If so, then this can be done with a simple formula if you wish to avoid VBA. With your value in A1:
=IF(MID(A1,LEN(A1)-1,1)=" ",LEFT(A1,LEN(A1)-2),A1)
If you must use VBA, I think the Like operator comes in handy:
Sub Test()
Dim arr As Variant: arr = Array("John Doe A", "Kai Jin", "Johnny Desplat Lang B")
For Each el In arr
If el Like "* ?" Then 'Or "* [A-Z]" if you must check for uppercase alpha.
Debug.Print Left(el, Len(el) - 2)
Else
Debug.Print el
End If
Next
End Sub
Just for fun and in order to demonstrate another approach via the Filter() function:
Function ShortenName(ByVal FullName As Variant) As String
'Purpose: remove a single last letter
Dim n: n = Split(FullName, " "): n = Len(n(UBound(n)))
ShortenName = Left(FullName, Len(FullName) + 2 * (n = 1))
End Function
Explanation
Applying the Split() function upon the full name and isolating the last name token (via UBound()) allows to check for a single letter length (variable n).
The function result returns the entire string length minus 2 (last letter plus preceding space) in case of a single letter (the the condition n = 1 then results in True equalling -1). - Alternatively you could have coded: ShortenName = Left(FullName, Len(FullName) - IIf(n = 1, 2, 0))

How to exit IIf() statement when no value is present

Is there any way to terminate an IIf() statement if it doesn't return a value?
This is what my code looks like:
Do While Sheets("testsheet").Cells(1, Z) <> ""
text1 = Sheets("testsheet").Cells(1, Z).Value
vLook = Application.HLookup(text1, lookupRange, u, False)
Sheets("Kilepok").Cells(i, Z).Value = IIf(IsError(vLook), ????, vLook)
Z = Z + 1
Loop
The code runs through the header (z), and looks for a value. If it finds a value, I would like to paste this in those cases (when there is no error in vlook). In other cases, I don't want to modify the value of the current cell.
Either
Sheets("Kilepok").Cells(i, Z).Value = IIf(IsError(vLook), Sheets("Kilepok").Cells(i, Z).Value, vLook)
or
If Not IsError(vLook) Then Sheets("Kilepok").Cells(i, Z).Value = vLook
will do the job.
But note that the first will re-write the cell's value (which makes it slow) and if there is a forumla in it, it will be converted into a value. So the second one would be the preferred solution.

User defined column letter in a Range call

Asking to user the letter referencing a column ; then using the answer to get the range of this a cell with in this column at some row.
But the "Range" refuses to recognize the letter input.
What am I missing in the following simple two lines ?
UserCol = Application.InputBox(" Please enter the column...", Type:=0)
Set Z = Range(UserCol & 5)
You need to use Type:=2.
Using Type:=0 will return ="<input string>", rather than just <input string>.
So, after:
Dim UserCol As String
UserCol = Application.InputBox(" Please enter the column...", Type:=2)
You can either do:
Set Z = Cells(5, UserCol)
OR:
Set Z = Range(UserCol & "5")
I would also suggest that use Option Explicit and also fully qualify range references. e.g. instead of Set Z = Range(UserCol & "5"), use Set Z = Thisworkbook.sheets("MySheetName").Range(UserCol & "5")
Try this:
UserCol = Application.InputBox(" Please enter the column...", Type:=2)
Set Z = Range((UserCol & 5))
I set Type to 2 to return a string from your user's input (see her for more)
Additionally, I added a parenthesis to the Range, because (UserCol & 5) becomes e.g. A5, and you need Range(A5).
This way is easier:
Dim UserCol As String
UserCol = Application.InputBox(" Please enter the column...")
Set Z = Cells(5, UserCol)
I don't know how did you declare your UserCol or if you even declared it. If you didn't and to avoid problems always use Option Explicit on the top of your module.
This is a really simple bug to fix: Set Z = Range(UserCol & "5")
Why? Because when you use implicit conversion, by typing UserCol & 5, VBA includes a space between UserCol and the 5 (and also after the 5).
Here is a test:
MsgBox "A" & 5 'Outputs "A 5 "
MsgBox "A" & "5" 'Outputs "A5"
(As Gravitate points out, Application.InputBox(" Please enter the column...", Type:=0) is a Formula, so an input of "A" would give you "=""A"", and not "A" -since "=""A""5" is not a valid cell reference either, use Type:=2 for Text or InputBox(" Please enter the column...") without the Application. or the type filtering)

Excel if function

I've made this large excel sheet and at the time i didn't know i'd need to sort this table through categories.
I have in a column (J here ) the description of the line and the category joint. (example: "Shipment of tires for usin'ss")
The only way i was able to sort the table the way i wanted was to build a category column using this :
=IF(COUNTIF(J3;"*usi*");"Usins";IF(COUNTIF(J3;"*remis*");"Remise";IF(COUNTIF(J3;"*oe*");"Oenols";IF(COUNTIF(J3;"*KDB*");"KDB";IF(COUNTIF(J3;"*vis*");"cvis";IF(COUNTIF(J3;"*amc*");"AMC";0))))))
usi for instance is a segment of a category name, that i sometimes wrote as
usin'ss
usin
usin's
usins
'cause you know smart.
Anyway, how do i translate =If(If(If...))) into something readable in VBA like:
If...then
If... then
Example of "IF ... ELSE" in EVBA
IF condition_1 THEN
'Instructions inside First IF Block
ELSEIF condition_2 Then
'Instructions inside ELSEIF Block
...
ELSEIF condition_n Then
'Instructions inside nth ELSEIF Block
ELSE
'Instructions inside Else Block
END IF
Example of Case Switch in EVBA
Select Case score
Case Is >= 90
result = "A"
Case Is >= 80
result = "B"
Case Is >= 70
result = "C"
Case Else
result = "Fail"
End Select
Both cases work off a waterfall type logic where if the first condition is met, then it does not continue, but if condition 1 is not met then it checks the next, etc.
Example usage:
Function makeASelectAction(vI_Score As Integer) As String
Select Case vI_Score
Case Is >= 90
makeASelectAction = "A, fantastic!"
Case Is >= 80
makeASelectAction = "B, not to shabby."
Case Is >= 70
makeASelectAction = "C... least your average"
Case Else
makeASelectAction = "Fail, nuff said."
End Select
End Function
Function makeAnIfAction(vS_Destination As String, vS_WhatToSay As String, Optional ovR_WhereToStick As Range, Optional ovI_TheScore As Integer)
If vS_Destination = "popup" Then
MsgBox (vS_WhatToSay)
ElseIf vS_Destination = "cell" Then
ovR_WhereToStick.value = vS_WhatToSay
ElseIf vS_Destination = "select" Then
MsgBox makeASelectAction(ovI_TheScore)
End If
End Function
Sub PopMeUp()
Call makeAnIfAction("popup", "Heyo!")
End Sub
Sub PopMeIn()
Call makeAnIfAction("cell", "Heyo!", Range("A4"))
End Sub
Sub MakeADescision()
Call makeAnIfAction(vS_Destination:="select" _
, vS_WhatToSay:="Heyo!" _
, ovI_TheScore:=80 _
)
End Sub
It will show you how to send variables to functions and how to call said function, it will show you how use optional parameters, how a function and interact with another function or sub, how do write a value to a sheet or spit out a messagebox. The possabilities are endless. Let me know if you need anything else cleared up or coded out.
You seem to be using CountIf just to see if the contents of the cell matches a certain pattern and, if so, give a replacement string. In VBA you can use the Like operator for pattern matching. In any event -- here is a function I wrote which, when passed a string and a series of pattern/substitution strings, loops through the patterns until it finds a match and then returns the corresponding substitution. If no match is found, it returns an optional default value (the last argument supplied). If no default is supplied, it returns #N/A.
The code illustrates that sometimes complicated nested ifs can be replaced by a loop which iterates through the various cases. This is helpful when you don't know the number of cases before hand.
Function ReplacePattern(s As String, ParamArray patterns()) As Variant
Dim i As Long, n As Long
n = UBound(patterns)
If n Mod 2 = 0 Then n = n - 1
For i = 0 To n Step 2
If s Like patterns(i) Then
ReplacePattern = patterns(i + 1)
Exit Function
End If
Next i
If UBound(patterns) Mod 2 = 0 Then
ReplacePattern = patterns(n + 1)
Else
ReplacePattern = CVErr(xlErrNA)
End If
End Function
Your spreadsheet formula is equivalent to
=ReplacePattern(J3,"*usi*","Usins","*remis*","Remise","*oe*","Oenols","*KDB*","KDB","*vis*","cvis","*amc*","AMC",0)

Comparing Strings in VBA

I have a basic programming background and have been self sufficient for many years but this problem I can't seem to solve. I have a program in VBA and I need to compare two strings. I have tried using the following methods to compare my strings below but to no avail:
//Assume Cells(1, 1).Value = "Cat"
Dim A As String, B As String
A="Cat"
B=Cell(1, 1).Value
If A=B Then...
If A Like B Then...
If StrCmp(A=B, 1)=0 Then...
I've even tried inputting the Strings straight into the code to see if it would work:
If "Cat" = "Cat" Then...
If "Cat" Like "Cat" Then...
If StrCmp("Cat" = "Cat", 1) Then...
VBA for some reason does not recognize these strings as equals. When going through Debugger it shows that StrComp returns 1. Do my strings have different Char lengths? Thanks for any help.
Posting as answer because it doesn't fit in the comments:
I find it hard to believe that something like:
MsgBox "Cat" = "Cat"
Would not display True on your machine. Please verify.
However, I do observe that you are most certainly using StrComp function incorrectly.
The proper use is StrComp(string, anotherstring, [comparison type optional])
When you do StrComp(A=B, 1) you are essentially asking it to compare whether a boolean (A=B will either evaluate to True or False) is equivalent to the integer 1. It is not, nor will it ever be.
When I run the following code, all four message boxes confirm that each statement evaluates to True.
Sub CompareStrings()
Dim A As String, B As String
A = "Cat"
B = Cells(1, 1).Value
MsgBox A = B
MsgBox A Like B
MsgBox StrComp(A, B) = 0
MsgBox "Cat" = "Cat"
End Sub
Update from comments
I don't see anything odd happening if I use an array, just FYI. Example data used in the array:
Modified routine to use an array:
Sub CompareStrings()
Dim A As String, B() As Variant
A = "Cat"
B = Application.Transpose(Range("A1:A8").Value)
For i = 1 To 8
MsgBox A = B(i)
MsgBox A Like B(i)
MsgBox StrComp(A, B(i)) = 0
MsgBox "Cat" = B(i)
Next
End Sub
What I would check is how you're instantiating the array. Range arrays (as per my example) are base 1. If it assigned some other way, it is most likely base 0, so check to make sure that you're comparing the correct array index.

Resources