How to use AND in IF Statement - excel

I want to check:
IF cells (i,"A") contains the text 'Miami' AND (i,"D") contains the text 'Florida' THEN change value of cell (i,"C") to BA.
Sub ABC()
Dim wsh As Worksheet, i As Long, lngEndRowInv As Long
Set wsh = ActiveSheet
i = 2
lngEndRowInv = wsh.Range("A" & wsh.Rows.Count).End(xlUp).Row
While i <= lngEndRowInv
If Cells(i, "A") like "*Miami*" And Cells(i, "D") like "*Florida*" Then
Cells(i, "C").Value = "BA"
End If
i = i + 1
Wend
End Sub

Brief syntax lesson
Cells(Row, Column) identifies a cell. Row must be an integer between 1 and the maximum for version of Excel you are using. Column must be a identifier (for example: "A", "IV", "XFD") or a number (for example: 1, 256, 16384)
.Cells(Row, Column) identifies a cell within a sheet identified in a earlier With statement:
With ActiveSheet
:
.Cells(Row,Column)
:
End With
If you omit the dot, Cells(Row,Column) is within the active worksheet. So wsh = ActiveWorkbook wsh.Range is not strictly necessary. However, I always use a With statement so I do not wonder which sheet I meant when I return to my code in six months time. So, I would write:
With ActiveSheet
:
.Range.
:
End With
Actually, I would not write the above unless I really did want the code to work on the active sheet. What if the user has the wrong sheet active when they started the macro. I would write:
With Sheets("xxxx")
:
.Range.
:
End With
because my code only works on sheet xxxx.
Cells(Row,Column) identifies a cell. Cells(Row,Column).xxxx identifies a property of the cell. Value is a property. Value is the default property so you can usually omit it and the compiler will know what you mean. But in certain situations the compiler can be confused so the advice to include the .Value is good.
Cells(Row,Column) like "*Miami*" will give True if the cell is "Miami", "South Miami", "Miami, North" or anything similar.
Cells(Row,Column).Value = "Miami" will give True if the cell is exactly equal to "Miami". "MIAMI" for example will give False. If you want to accept MIAMI, use the lower case function:
Lcase(Cells(Row,Column).Value) = "miami"
My suggestions
Your sample code keeps changing as you try different suggestions which I find confusing. You were using Cells(Row,Column) <> "Miami" when I started typing this.
Use
If Cells(i, "A").Value like "*Miami*" And Cells(i, "D").Value like "*Florida*" Then
Cells(i, "C").Value = "BA"
if you want to accept, for example, "South Miami" and "Miami, North".
Use
If Cells(i, "A").Value = "Miami" And Cells(i, "D").Value like "Florida" Then
Cells(i, "C").Value = "BA"
if you want to accept, exactly, "Miami" and "Florida".
Use
If Lcase(Cells(i, "A").Value) = "miami" And _
Lcase(Cells(i, "D").Value) = "florida" Then
Cells(i, "C").Value = "BA"
if you don't care about case.

If there are no typos in the question, you got the conditions wrong:
You said this:
IF cells (i,"A") contains the text 'Miami'
...but your code says:
If Cells(i, "A") <> "Miami"
--> <> means that the value of the cell is not equal to "Miami", so you're not checking what you think you are checking.
I guess you want this instead:
If Cells(i, "A") like "*Miami*"
EDIT:
Sorry, but I can't really help you more. As I already said in a comment, I'm no Excel VBA expert.
Normally I would open Excel now and try your code myself, but I don't even have Excel on any of my machines at home (I use OpenOffice).
Just one general thing: can you identify the row that does not work?
Maybe this helps someone else to answer the question.
Does it ever execute (or at least try to execute) the Cells(i, "C").Value = "BA" line?
Or is the If Cells(i, "A") like "*Miami*" stuff already False?
If yes, try checking just one cell and see if that works.

If you are simply looking for the occurrence of "Miami" or "Florida" inside a string (since you put * at both ends), it's probably better to use the InStr function instead of Like. Not only are the results more predictable, but I believe you'll get better performance.
Also, VBA is not short-circuited so when you use the AND keyword, it will test both sides of the AND, regardless if the first test failed or not. In VBA, it is more optimal to use 2 if-statements in these cases, that way you aren't checking for "Florida" if you don't find "Miami".
The other advice I have is that a for-each loop is faster than a for-loop. Using .offset, you can achieve the same thing, but with better effeciency. Of course there are even better ways (like variant arrays), but those will add a layer of complexity not needed in this example.
Here is some sample code:
Sub test()
Application.ScreenUpdating = False
Dim lastRow As Long
Dim cell As Range
lastRow = Range("A" & Rows.Count).End(xlUp).Row
For Each cell In Range("A1:A" & lastRow)
If InStr(1, cell.Value, "Miami") <> 0 Then
If InStr(1, cell.Offset(, 3).Value, "Florida") <> 0 Then
cell.Offset(, 2).Value = "BA"
End If
End If
Next
Application.ScreenUpdating = True
End Sub
I hope you find some of this helpful, and keep at it with VBA! ^^

I think you should append .value in IF statement:
If Cells(i, "A").Value <> "Miami" And Cells(i, "D").Value <> "Florida" Then
Cells(i, "C").Value = "BA"
End IF

Related

How to delete rows that have a cell that has a special symbol?

I need to delete rows that have cells containing ®.
Cells(iCntr, 6).Value = "*®*"
Cells(iCntr, 6).Value = "®"
I have also tried setting condition_ranges and conditions instead - I have not been able to get anything to work in regard to the special character.
Sub Remove()
Dim lRow As Long
Dim iCntr As Long
lRow = 1000
For iCntr = lRow To 1 Step -1
If Cells(iCntr, 6).Value = "BLK" Then
Rows(iCntr).Delete
ElseIf Cells(iCntr, 6).Value = "WHI" Then
Rows(iCntr).Delete
ElseIf Cells(iCntr, 7).Value = "*®*" Then
Rows(iCntr).Delete
End If
Next
End Sub
The code works just fine for the "BLK" and "WHI" but nothing is taken out using the "®". There are no error messages it just does not modify the worksheet.
You can use Like:
ElseIf Cells(iCntr, 7).Value Like "*®*" Then
The question could be translated to "How to check whether a string contains a specific substring", because once this part is resolved, then the corresponding cell could be deleted.
InStr is a function, that compares two strings, returning the position of the second one within the first one. If the second one is not found in the first one, then 0 is returned. With some fantasy, this could be used to see whether the (R) is present:
Sub TestMe()
Debug.Print ThePresenceOfR("kt®b")
Debug.Print ThePresenceOfR("tzv")
End Sub
Function ThePresenceOfR(str As String) As Boolean
ThePresenceOfR = InStr(1, str, "®")
End Function
Or as mentioned in the other answer, kt®b Like "*®*" would deliver the same results.

Data Validation List Clear

Currently I have three fields of data. Two are data validation lists and another is just a normal cell where I input a number value. Once I've selected the data I want, I press an ActiveX button which copies the data into another spreadsheet. What it currently looks like:
The issue I have is I want on the button press for the fields to clear but retain their information. I've tried both .Clear and .ClearContents but they completely remove my data validation lists. I just want them to go back to a blank state for the next time.
What I want it to reset to:
Is there any way of doing this or do I need to rethink the entire spreadsheet and use VBA?
VBA : If myCell is the cell which you want to clear, use
myCell.FormulaR1C1 = ""
Edit: after comments below and assuming that the 3 fields from the screenshots above are c4, c7 and c10 I would recommend to change your sub like this:
Private Sub Command5Button21_Click()
Dim s1, s2
Set s1 = Worksheets("Master")
Set s2 = Worksheets("Sheet1")
With s1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).EntireRow
.Cells(, "a").Value = s2.Range("p20").Value
.Cells(, "b").Value = s2.Range("p21").Value
.Cells(, "c").Value = s2.Range("c4").Value
.Cells(, "d").Value = s2.Range("c7").Value
.Cells(, "e").Value = s2.Range("c10").Value
s2.Range("c4").FormulaR1C1 = ""
s2.Range("c7").FormulaR1C1 = ""
s2.Range("c10").FormulaR1C1 = ""
End With
End Sub

pasting in vba data

image worksheetI am setting up sheet with hotels details and column "D" has hospitals that are close by eg PMH,SCGH,FSH. What i am trying to do is search column "D" based on a cell value on same sheet. I have code below but it will only do what i want if the cells in column"D" are single entry eg pmh. I need to be able to search all the cells in Column "D" for any instance of the text.
Many Thanks for any assistance
`Option Explicit
Sub finddata()
Dim hospitalname As String
Dim finalrow As Integer
Dim i As Integer
Sheets("Results").Range("A4:D100").ClearContents
Sheets("Main").Select
hospitalname = Sheets("Main").Range("g3").Value
finalrow = Sheets("Main").Range("A1000").End(xlUp).Row
For i = 2 To finalrow
If Cells(i, 4) = hospitalname Then
Range(Cells(i, 1), Cells(i, 4)).Copy
Sheets("Results").Range("A4").End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats
End If
Next i
Sheets("Main").Range("g3").Select
End Sub
`
The two simplest ways to do this would be
Using the Like operator:
If Cells(i, 4).Value Like "*" & hospitalname & "*" Then
This method has the drawback that a hospital name of, for instance, PMH might be matched against another one such as SPMH.
Using the InStr function:
If Instr("," & Cells(i, 4).Value & ",", "," & hospitalname & ",") > 0 Then
In this line, I "wrap" both the cell being looked at, and the value being searched for, within commas so it ends up searching for the string (for instance) ",PMH," within the string ",PMH,SCGH,FSH,". InStr will return the character position at which a match occurs, or zero if no match is found. So testing for > 0 is testing whether a match occurred.

EXCEL VBA - Similar function to excel formula Value

I'm new to VBA so I got a problem trying to convert some string number to a value number for a IF validation.
The problem is. I have Column "A" filled with something like this:
E/B: Houses 01
E/B: Houses 02
E/B: Building/New Villa
E/B: Building/Bella Casa
E/B: Houses 03
So, in my code, I want it to fill the "B" Column with the last 2 numbers if there's numbers or the name if there isn't.
Set Rng = Range("A8:A" & Range("I" & Rows.Count).End(xlUp).Row)
For Each celula In Rng.SpecialCells(xlCellTypeVisible)
Select Case True
Case IsNumeric(Right(celula, 2)) = True
celula.Offset(0, 1).Value = Right((celula), 3)
Case Else
celula.Offset(0, 1).Value = Mid(celula, InStr(4, celula, "/") + 1, Len(celula))
End Select
Next celula
But the Case IsNumeric(Right(celula, 2)) = True is never True. It do not capture the 2 last numbers. But it works alright with the names and returns "New Villa" and "Bella Casa". And I think the problem is that Right(celula, 2) is never a number, even if theres a number.
I want to know if theres a way to convert "Right(celula, 2)" in a Value, just like the =Value formula in excel, to do the validation.
OBS: Before trying this way, I had a excel formula applied to those cells and it worked, but I want to try this way for learning purposes.
Thanks
I think the for each loop itself works as expected.
However, this
Set Rng = Range("A8:A" & Range("I" & Rows.Count).End(xlUp).Row)
is probably where the problem lies. You have to make sure you've got the correct Range. You can verify by debugging: Debug.print Rng.Address.
Sub t()
Dim rng As Range
With ActiveSheet
Set rng = .Range("a1:a" & .Range("a" & .Rows.Count).End(xlUp).Row)
For Each cell In rng.Cells
If Val(Right(cell.Value, 2)) = 0 Then
cell.Offset(0, 1) = Mid(cell.Value, InStrRev(cell.Value, "/") + 1, Len(cell))
Else
cell.Offset(0, 1) = Val(Right(cell.Value, 2))
End If
Next cell
End With
End Sub

Use a cell value in VBA function with a variable

I'm new to VBA and I can't manage to do what I want although it's very simple.
I need to automatically modify cells of a big (333x333) empty (full of zeros) spreadsheet.
In a separate spreadsheet I have the row and column of all the cells to modify. (5000 of them)
A for loop seems to be suited for this purpose.
Here is the code of my macro. The problem appears on the line before the last one.
Dim val1 As String, val2 As String, i As Integer
For i = 1 To 333
Sheets("Feuil2").Activate
ActiveSheet.Cells(i, 1).Select
val1 = Cells(i, 1).Value
val2 = Cells(i, 2).Value
Sheets("Classeur2.csv").Select
Cells(val1, val2).Select
ActiveCell.FormulaR1C1 = "1"
Next i
The line that causes a problem is this one : Cells(val1, val2).Select
I believe my error is a syntax error. But I can't find out what I should add before, after or around my two variables "val1" and "val2"
What do you think ?
Thanks a lot for your help.
Nicolas.
Edit
My problem is now solved :
The first answer is exactly what I needed to male my macro work.
The second answer is the proper and faster way to do it.
No need to activate or selection sheets or cells if you're using VBA. You can access it all directly.
The code:
Dim rng As Range
For Each rng In Sheets("Feuil2").Range("A1:A333")
Sheets("Classeur2.csv").Cells(rng.Value, rng.Offset(, 1).Value) = "1"
Next rng
is producing the same result as Joe's code.
If you need to switch sheets for some reasons, use Application.ScreenUpdating = False at the beginning of your macro (and Application.ScreenUpdating=True at the end). This will remove the screenflickering - and speed up the execution.
VAL1 and VAL2 need to be dimmed as integer, not as string, to be used as an argument for Cells, which takes integers, not strings, as arguments.
Dim val1 As Integer, val2 As Integer, i As Integer
For i = 1 To 333
Sheets("Feuil2").Activate
ActiveSheet.Cells(i, 1).Select
val1 = Cells(i, 1).Value
val2 = Cells(i, 2).Value
Sheets("Classeur2.csv").Select
Cells(val1, val2).Select
ActiveCell.FormulaR1C1 = "1"
Next i

Resources