Excel VBA pass variable between functions - excel

I am trying to write excel VBA code that will parse column B (analyst login time), and if that column is 0 (as in they were out that day), it will update the adjacent columns to say NA. Currently, the below code errors out. If I change the rng variable in Cells(rng, i) to a number, then the code will take that number (let's say 4) and put NA in all of the fields (3 to 23, so, C to W). I believe that the issue is that the value of rng is not being passed into the inner function, but I do not know how to get arround this.
Dim rng As Range
For Each rng In Range("B4:B10")
If rng.Value = 0 Then
For i = 3 To 23
Cells(rng, i).Value = NA
Next i
End If
Next rng

rng on its own (without an explicit property name) defaults to returning .Value which when 0 tries to use row index 0 which is not valid, instead get the row number via .Row:
Cells(rng.Row, i).Value = "NA"
If NA is not a variable but a string, quote it.
Non-loop alternative:
If rng.Value = 0 Then Range(rng.Offset(0, 1), rng.Offset(0, 21)).Value = "NA"

Problem is here:
Cells(rng, i).Value = "NA"
why you give range to place where Number (row number) must go?
You need to use
Cells(rng.Row, i).Value = "NA"

Related

If value in one cell, then modify row which consists that cell

I am totally new to VBA and I am struggling a little bit with one thing. I want to make a macro, which checks values in "M" column. If value is higher than 5, then print "hello". If not then print "x". Unfortunately, I only gets "x" back in selected cells.
Private Sub costam()
Dim i As Integer
Dim a As Integer
a = 13
For i = 1 To Range("M" & Rows.Count).End(xlUp).Row
If Cells(a, i).Value > 5 Then
Range(Cells(1, i), Cells(10, i)).Value = "hello"
Else
Range(Cells(1, i), Cells(10, i)).Value = "x"
End If
Next i
End Sub
I know this problem is silly and takes like 1 minute to solve, but I am trying to apply some alike problems but without any progress.
You could create a custom function for this workbook.
Public Function CustomFunction(myVal As Integer)
Dim myResult As String
If myVal > 5 Then
myResult = "Hello"
Else
myResult = "X"
End If
CustomFunction = myResult
End Function
Then, you would write a formula in the cell where you want the value to be returned.
=CustomFunction(A2)
Your custom function will need to be placed into a module.
Excel VBA User-Defined Functions Tutorial

Compare all column values against individual cells in Excel

I'd like to find if any row in Column C matches any cells in Column A or B and print out 'yes' or 'no' in an adjacent cell if it does match. The match might not be exact, because an ID may be written as '12401' but the match in the column may be like 'cf[12401]', with the ID enclosed in brackets.
This is an example of what I might find in the table. The values in A and B columns originally came from another table but I'm trying to find all instances of where they might exist in the third column.
Excel Example:
If possible, I'd like to list the values themselves that matched in the column. But that part would be a nice extra while the other part is more important because there are around 6000 values in the middle column so it would take days by hand.
I've tried different things like this:
=IF(COUNTIF(C2,"*" & A6 & "*" ), "Yes", "No")
or
=IF(COUNTIF(C2,"*" & Length & "*" ), "Yes", "No")
these work for individual words or cells, but trying to check all the values in that column against the cell will return no. I've tried variations of SUMPRODUCT and others that I've found, but haven't been able to get something that works for multiple values.
Is there some function in Excel that will allow me to do this? Or maybe a way in VBA?
Here is some UDF you could use.
Dim MyArr As Variant, X As Double, LR As Double
Option Explicit
Public Function MatchID(RNG As Range) As String
With ActiveWorkbook.Sheets(RNG.Parent.Name)
LR = .Cells(Rows.Count, 1).End(xlUp).Row
MyArr = Application.Transpose(.Range(.Cells(2, 1), .Cells(LR, 1)))
For X = LBound(MyArr) To UBound(MyArr)
If InStr(1, RNG.Value, MyArr(X), vbTextCompare) > 0 Then
If MatchID = "" Then
MatchID = MyArr(X)
Else
MatchID = MatchID & ", " & MyArr(X)
End If
End If
Next X
End With
End Function
Public Function MatchCFNAME(RNG As Range) As String
With ActiveWorkbook.Sheets(RNG.Parent.Name)
LR = .Cells(Rows.Count, 1).End(xlUp).Row
MyArr = Application.Transpose(.Range(.Cells(2, 2), .Cells(LR, 2)))
For X = LBound(MyArr) To UBound(MyArr)
If InStr(1, RNG.Value, MyArr(X), vbTextCompare) > 0 Then
If MatchCFNAME = "" Then
MatchCFNAME = MyArr(X)
Else
MatchCFNAME = MatchCFNAME & ", " & MyArr(X)
End If
End If
Next X
End With
End Function
In D2 Ijust used =IF(F2<>"","YES","") and dragged it sideways and down.

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.

VLookup inequality error

I need to know whether a car in class A that has length B falls in its proper length range. I want to VLookup, via VBA, its class in a table that has maximum and minimum length values for each class. My code, where column 23=length, column 16=class, column 101=returns whether it's not in the right range.
Dim ClassCodeTable As Range
Set ClassCodeTable = Worksheets("Class Code Tables").Range("A:G")
Range("A1").Select
Lastrow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To Lastrow
If Cells(i, 23).Value > Application.WorksheetFunction.VLookup(Cells(i, 16), ClassCodeTable, 3, False) And Cells(i, 23).Value < Application.WorksheetFunction.VLookup(Cells(i, 16), ClassCodeTable, 4, False) Then
Cells(i, 101).Value = ""
Else
Cells(i, 101).Value = "Length Range Error"
End If
Next
This code returns a 1004 error, unable to get the VLookup property of the WorksheetFunction class. but this approach works when I VLookup whether car in Class A with characteristic C equals the expected categorical value for Class A in ClassCodeTable. It seems to me that the VLookup value returned is not being stored as number, even though all the values in the lookup table are numbers.
Is there a way to convert the VLookup value into a number that can be checked against an inequality?
Here is an alternate method to do the same thing, no loop required. I tested it given your described setup and it ran successfully for me:
Sub tgr()
With Range("CW2:CW" & Cells(Rows.Count, "P").End(xlUp).Row)
.Formula = "=IF(COUNTIF('Class Code Tables'!A:A,P2)=0,""Class not found""," & _
"IF(AND(W2>=VLOOKUP(P2,'Class Code Tables'!A:G,3,FALSE)," & _
"W2<=VLOOKUP(P2,'Class Code Tables'!A:G,4,FALSE))," & _
""""",""Length Range Error""))"
.Value = .Value
End With
End Sub
Or if you'd prefer to have the formula all on one line:
.Formula = "=IF(COUNTIF('Class Code Tables'!A:A,P2)=0,""Class not found"",IF(AND(W2>=VLOOKUP(P2,'Class Code Tables'!A:G,3,FALSE),W2<=VLOOKUP(P2,'Class Code Tables'!A:G,4,FALSE)),"""",""Length Range Error""))"

Ignore other cell value's when looping a column VBA EXCEL

I'm going to start my problem with an example, as otherwise it will be too difficult to explain.
A B C D E (ID)
1 word letter 1
test blabla
other
2 word letter 2
number
3 test true 3
4 other false 4
5 word letter Yes 5
6 word letter Yes 6
7 test letter 7
What's the goal?
If I'll try to explain the goal in words, it will be hard to understand; it's also hard to explain :) Anyway I also added my code, and if you are good with VBA you will understand the code better then the text.
IF a value (in this example: word) is also in other rows THEN we needs to check column C, AND IF there is a value in column C that we find more then once in column C (in this example: letter), we needs to recheck if in column A the value also appears more then once.
So I already made a SUB, AND IT WORKS ! :) BUT not if there are more values in a cell. So in the example when there is only 1 value in a cell, as in row 6 & 7, column D returns : YES
Here is my code so far.
Sub duplicates()
Dim source As Range
Dim source2 As Range
For Each source In Range("A1", Range("A" & Rows.Count).End(xlUp))
If source.Value <> "" Then
For Each source2 In Range("A1", Range("A" & Rows.Count).End(xlUp))
If source.Value = source2.Value And source.Offset(0, 4).Value <> source2.Offset (0, 4).Value Then
If source.Offset(0, 2).Value = source2.Offset(0, 2).Value Then
source.Offset(0, 3) = "Yes"
End If
End If
Next source2
End If
Next source
End Sub
So, we should return: YES in row 1 & 2 as well. Hope you understand my goal.
Hope someone can help.
My proposal is as follows:
A) additional function would check each element of each cell passed to the function as array:
Function AnyEqual(ColA, ColB) As Boolean
Dim itemA, itemB
For Each itemA In ColA
For Each itemB In ColB
If itemA = itemB Then
AnyEqual = True
Exit Function
End If
Next
Next
End Function
B) Some changes are made in your code- put it inside For Each source2 loop instead your inner code:
If AnyEqual(Split(source, Chr(10)), Split(source2, Chr(10))) And _
source.Offset(0, 4).Value <> source2.Offset(0, 4).Value Then
If AnyEqual(Split(source.Offset(0, 2), Chr(10)), _
Split(source2.Offset(0, 2), Chr(10))) Then
source.Offset(0, 3) = "Yes"
End If
End If
Based on data you provided it seems it works fine. I hope it is what you were looking for as it was a bit complicated to understand your needs.

Resources