I'm looking to create a COUNTIF which takes into account the text value and font color of a criteria string. This is what I've come up with so far. It's currently returning a #VALUE! error.
Function test(range As range, criteria As range) As Double
Dim cell As range
Dim criteriaLength As Integer
Dim counter As Integer
counter = 0
For Each cell In range
If InStr(cell.value, criteria.value) > 0 And
cell.Characters(InStr(cell.value, criteria.value),
criteriaLength).Font.Color = criteria.Font.Color Then
counter = counter + 1
End If
Next cell
test = counter
End Function
The cells in the search range each contain characters of different font colors--that's why I'm using InStr and Characters. Any ideas what the issue might be?
You never assign a value to criteriaLength
You need to add:
criteriaLength = Len(criteria)
before the loop.
And the If will try both sides of the And in the if and if the criteria is not in the string the second part will error. You need to nest the if so the second only fires if the first returns True.
Function test(range As range, criteria As range) As Double
Dim cell As range
Dim criteriaLength As Integer
Dim counter As Integer
counter = 0
criteriaLength = Len(criteria)
For Each cell In range
If InStr(cell.Value, criteria.Value) > 0 Then
If cell.Characters(InStr(cell.Value, criteria.Value), criteriaLength).Font.color = criteria.Font.color Then
counter = counter + 1
End If
End If
Next cell
test = counter
End Function
Related
I have this Excel VBA function:
Function Positives(Rng As Range) As Range
Dim cell As Range, out As Range
For Each cell In Rng
If cell > 0 Then
If Not out Is Nothing Then
Set out = Union(out, cell)
Else
Set out = cell
End If
End If
Next cell
Set Positives = out
End Function
Why doesn't it work well when there are non-sequential positive numbers in Rng range? for example with values 5, 6, 7, -3, 4, 5 but values 5, 6, 7, -3, -4, -5 it works.
Thank you for your cooperation.
There is a limit for excel to display not consecutive range value using array function, see the comparison below
With consecutive range:
When it is not consecutive range
In your VBA code, when the result is in consecutive range, you will have no issue to display in array formula
When the result is not consecutive range, it return #Value as you mention, to solve this problem, one of the method is to change the result to display in string, hope you find it useful :)
Function Positives1(Rng As Range) As String
Dim cell As Range, out As Range, outCell As Range
Dim result As String
For Each cell In Rng.Cells
If cell.Value > 0 Then
If Not out Is Nothing Then
Set out = Union(out, cell)
Else
Set out = cell
End If
End If
Next cell
result = ""
For Each outCell In out.Cells
If result <> "" Then
result = result & "," & outCell.Value
Else
result = outCell.Value
End If
Next
Positives1 = result
End Function
if you want to return multiple values to multiple cells from a UDF to a sheet, you can do this using an array. Note that the best result will be when the dimensions of the call area and the return array match.
Option Explicit
Function Positives(Rng As Range) As Variant
Dim cell As Range, out As Variant, i As Long
ReDim out(1 To Rng.Cells.Count, 1 To 1) ' form the vertical array
For i = 1 To UBound(out, 1)
out(i, 1) = "no value" ' initial fill of the array
Next
i = 0
For Each cell In Rng
If cell > 0 Then
i = i + 1
out(i, 1) = cell
End If
Next cell
Positives = out
End Function
I am trying to get VBA code to count cells in a range that match by cell fill color and by the text within.
I can get one criteria at a time easy enough, but every time I try to combine the conditions I get VALUE error. Please help!
This is what I have:
G23-100 is the range
F19 is the color and text to match
.
Function CountColorValue()
Dim text As String
Dim cell As Range
For Each cell In Range("G23:G210")
If cell.Interior.ColorIndex = Range("F19").Interior.ColorIndex Then
If cell.text Like Range("F19").text Then
text = text + 1
End If
End If
Next cell
Cells(1, 2).Value = numbers
End Function
It doesn't work, hence I am here..
Thanks in advance for any help.
Your function is not a function in fact, but a routine because you have no out put. You have multiple mistakes that I fixed without trying, it should work, if it did, please mark it as the correct answer on the upper left
Function CountColorValue() as integer
Dim iColor as long, cnt as long
Dim text As String, str as string
Dim cell As Range
iColor=Range("F19").Interior.ColorIndex
str=Range("F19").value
For Each cell In Range("G23:G210")
If cell.Interior.ColorIndex = iColor and cell.text Like str Then
cnt=cnt+1
End If
Next cell
CountColorValue=cnt
End Function
Base on my test, please try the VBA code as below:
Option Explicit
Sub CountColorValue()
Dim text As Long
Dim cell As Range
For Each cell In Range("G23:G210")
If cell.Interior.ColorIndex = Range("F19").Interior.ColorIndex And cell.text Like Range("F19").text Then
text = text + 1
End If
Next cell
Range("A1").FormulaR1C1 = text
End Sub
Hopefully it helps you.
Copy and paste the code in a module.
Select the cell you want to have the results
Use this Function as the usally functions
The first Argument is the range you want to count, the second Argument is the cell with the interior.color you want to compare and the third Argument is the value or the cell you want to count the function in the range of first Argument. e.g =CountColorValue(G23:G210,$F$19,$F$19) or =CountColorValue(G23:G210,$F$19,"a")
Option Explicit
Function CountColorValue(Rng_dt As Range, criteria As Range, Val As Variant) As Double
Application.Volatile
Dim datar As Range
Dim xcolor As Long
xcolor = criteria.Interior.Color
For Each datar In Rng_dt
If datar.Interior.Color = xcolor And WorksheetFunction.CountIf(datar, Val) = 1 Then
CountColorValue = CountColorValue + 1
End If
Next datar
End Function
function i wrote below is taking one range which i have some conditional formatting on (for font color), and another one cell range for comparing color. Function is counting how many cells in the big range having the same font color as the one cell range.
Function CountColor(rng As Range, clr As Range) As Integer
Dim c As Range
Dim a As Integer
a = 0
For Each c In rng
If c.DisplayFormat.Font.Color = clr.Font.Color Then
a = a + 1
End If
Next
CountColor = a
End Function
Now, problem is - in the function window, the actual result is coming correctly, while in the cell itself, i'm getting #VALUE! error.
The following code worked for me but not with conditional formatting:
Option Explicit
Function CountColor(rng As Range, clr As Variant) As Variant
Dim c As Range
Dim a As Integer
a = 0
For Each c In rng
If c.Font.color = clr.Font.color Then
a = a + 1
End If
Next c
CountColor = a
End Function
If I simply change the font color apart from conditional formatting it works. But for some reason it won't work, otherwise.
As multiple people have mentioned in the comments - The DisplayFormat property doesn't work in user defined functions. Therefore, if you remove .DisplayFormat. from your function it should work as expected.
Function CountColor(rng As Range, clr As Range) As Integer
Dim c As Range
Dim a As Integer
a = 0
For Each c In rng
If c.Font.Color = clr.Font.Color Then
a = a + 1
End If
Next
CountColor = a
End Function
I have come across a situation which required me to average the result of an array of Vlookups. I had no idea how to achieve this with formulas and it seemed like nobody else on StackOverflow had any idea either.
So I decided to write a function to do the job for me. Unfortunately it returns the "#VALUE!" error and I have no idea why! The function works fine when tested with a msgbox. I have annotated my code below:
Option Explicit
Public Function AvgVlookup(Target_Array As String, Lookup_Array As String, Column_Index As Long) As Double
Dim Result As Double
Dim Total As Double
Dim Counter As Long
Dim TargetRange As Range
Dim LookupRange As Range
Dim Cell As Range
' Remove Absolute Indicator
Target_Array = Replace(Target_Array, "$", "")
Lookup_Array = Replace(Lookup_Array, "$", "")
' Convert String to Range
Set TargetRange = Range(Left(Target_Array, InStr(1, Target_Array, ":") - 1), Mid(Target_Array, InStr(1, Target_Array, ":") + 1))
Set LookupRange = Range(Left(Lookup_Array, InStr(1, Lookup_Array, ":") - 1), Mid(Lookup_Array, InStr(1, Lookup_Array, ":") + 1))
' Set Variables to 0
Counter = 0
Total = 0
' For each cell in defined array
For Each Cell In TargetRange
' Vlookup the cell and save lookup value to Result variable
Result = Application.WorksheetFunction.vlookup(Cell, LookupRange, Column_Index, "False")
' Update variables used to calculate average
Total = Total + Result
Counter = Counter + 1
Next Cell
' Perform calculation
AvgVlookup = Total / Counter
End Function
Sub test()
MsgBox AvgVlookup("A5:A8", "G5:H8", 2)
End Sub
Any ideas?
Thanks!
Two things:
First, the way you are setting your ranges are a little long, it can be truncated to simply:
Set TargetRange = Range(Target_Array)
No need to parse the strings after removing the $.
Second, you need to put in an error check in case one of the values in the target range is not in the lookup range.
The whole code:
Public Function AvgVlookup(Target_Array As String, Lookup_Array As String, Column_Index As Long) As Double
Dim Total As Double
Dim Counter As Long
Dim TargetRange As Range
Dim LookupRange As Range
Dim Cell As Range
' Remove Absolute Indicator
Target_Array = Replace(Target_Array, "$", "")
Lookup_Array = Replace(Lookup_Array, "$", "")
' Convert String to Range
Set TargetRange = Range(Target_Array)
Set LookupRange = Range(Lookup_Array)
' Set Variables to 0
Counter = 0
Total = 0
' For each cell in defined array
For Each Cell In TargetRange
' Vlookup the cell and save lookup value to Result variable
Dim Result
Result = Application.VLookup(Cell, LookupRange, Column_Index, "False")
If IsNumeric(Result) Then
Total = Total + Result
Counter = Counter + 1
End If
Next Cell
' Perform calculation
AvgVlookup = Total / Counter
End Function
With the above function to call from the worksheet you would need to call it like this: =AvgVlookup("A5:A8", "G5:H8", 2)
But that is not very helpful. If you change your inputs to ranges:
Public Function AvgVlookup(TargetRange As Range, LookupRange As Range, Column_Index As Long) As Double
Dim Result As Double
Dim Total As Double
Dim Counter As Long
Dim Cell As Range
' Set Variables to 0
Counter = 0
Total = 0
' For each cell in defined array
For Each Cell In TargetRange
' Vlookup the cell and save lookup value to Result variable
Dim t
t = Application.VLookup(Cell, LookupRange, Column_Index, "False")
If IsNumeric(t) Then
Total = Total + t
Counter = Counter + 1
End If
Next Cell
' Perform calculation
AvgVlookup = Total / Counter
End Function
Then you would call it simply, =AvgVlookup($A$5:$A$8,$G$5:$H$8,2). This way you can just highlight the correct ranges and it will work. Also less typing trying to convert a string to a range when what you want to enter is a range.
I need help on this. I'm doing a report and inserting comments on cells. How do I count cells with in a range in excel with specific value that has a comment using vba or formula?
Here is one way. It loops through each cell you pass in the range and checks if there is a comment. If so, it adds it to a counter. This is probably going to be pretty expensive if used on large range, but it should at least get you started:
Add to a regular module:
Function CommentCounter(rng As Range) As Integer
Dim cell As Range
Dim counter As Integer
Dim currentComment As String
For Each cell In rng
On Error Resume Next
currentComment = cell.Comment.Text
If Len(currentComment) > 0 Then counter = counter + 1
currentComment = ""
Next cell
CommentCounter = counter
End Function
Just saw the part about having a specific value AND a comment. This should get you going:
Function CommentCounter(rng As Range) As Integer
Dim cell As Range
Dim counter As Integer
Dim currentComment As String
Dim specificValue As String
specificValue = "Something Specific"
For Each cell In rng
On Error Resume Next
currentComment = cell.Comment.Text
If cell.Value = specificValue And Len(currentComment) > 0 Then counter = counter + 1
currentComment = ""
Next cell
CommentCounter = counter
End Function
=COUNTIF(A:A;"comment")
Where A:A specifies that you want to examine the whole column of A. Instead of A:A, you could also use A1:A3, which means examine A1, A2 and A3.
EDIT:
If you want to count the cells with comments (not with the word "comment"), I would suggest to do the following:
=COUNT(A1:A3) - COUNTBLANK(A1:A3)