I had figured out this formula to count all those values that weren't blank, but the system updated the template and now besides blank it has also "N/A" values.
How can I transform this
=COUNTIF('R Plan'!XT2:XT3658,"<>")
To test if besides NOT blank also test for NOT N/A
Because I tried this
=COUNTIF('R Plan'!XT2:XT3658,"<>" OR "<>N/A")
and I'm getting a message that we found an error on your formula
If you're using >=XL2007 then you can use COUNTIFS:
=COUNTIFS('R Plan'!XT2:XT3658,"<>",'R Plan'!XT2:XT3658,"<>N/A")
If you're using <=XL2003 then you can use:
=SUM(COUNTIF('R Plan'!XT2:XT3658,"<>"),-COUNTIF('R Plan'!XT2:XT3658,"N/A"))
Count the number that are not empty and minus those that have N/A.
or
=SUMPRODUCT(('R Plan'!XT2:XT3658<>"")*('R Plan'!XT2:XT3658<>"N/A"))
If you want to use VBA, then this will work for you,
Put this in a cell and choose your range =COUNTBLANKS(B1,A1:A21) , B1 being the value you want to count and the second range is the range you want to count how many times that value occurs.
Add a module and paste this function in it.
Function COUNTBLANKS(r As Range, rng As Range) As Long
Dim x
Dim c
x = rng
For Each c In x
If c = r Then
COUNTBLANKS = COUNTBLANKS + 1
End If
Next c
End Function
Related
I have a spreadsheet on one sheet with the values in column C being generated using the results of a vlookup statement, from a value which I enter in column A.
I need to be able to count the number of cells in column C up to a maximum of 51 rows (from row 1 to row 51) which have a value in them, not including errors, after I have entered all my values in column A.
Oh - by the way, each time I do the count there will be a different number of rows used.
I've tried using:
ccc = Range("C:C").Cells.SpecialCells(xlCellTypeConstants).Count
but this only counts the first line which is my header row.
Sorry if there is already an answer out there, but I've been looking for quite a while and can't find anything.
Thanks.
You can easily do this without VBA, but you could try:
sub testy()
dim myRange as range
dim numRows as long
Set myRange = Range("C:C")
numRows = Application.WorksheetFunction.CountA(myRange) - _
myRange.SpecialCells(xlCellTypeFormulas, xlErrors).Count
end sub
Your code is not working because xlCellTypeConstants is specifically telling it to count only constant values, ignoring formulas calculated values.
The worksheet function CountA counts only cells with values:
=CountA(C1:C51)
We can call any worksheet function from VBA with the WorksheetFunction function:
dim c as integer
c = WorksheetFunction.CountA([C1:C51])
CountIf can be used to skip errors:
Skip errors with: `=COUNTIF(D5:D9,">0")`
You are looking to count cells that have no errors.
Replace your vlookup by the below formula. So all errors will be replaced by "NOT FOUND" Text
=IFERROR(VLOOKUP(C1,A1:B3,2,FALSE), "NOT FOUND")
Then add this to find the number of cells that are non blank and non erroneous
=COUNTA(D:D) - COUNTIF(D:D,"NOT FOUND")
Assumptions:-
A:B Source Range
C Lookup Column
D the vlookup function is in this coulmn
For VBA
cnt = Application.WorksheetFunction.CountA(D:D) - Application.WorksheetFunction.Countif(D:D, "NOT FOUND")
I am trying to create a dynamic range using both the count and offset function within count.
Here is the current formula
=OFFSET(BATLYearlyPnLListHeader,1,0,COUNT(OFFSET(BATLYearlyPnLListHeader,1,0,0,0), BATLYearlyPnLListRangeEnd))
In English, the range is offset 1 down from the header, and encompasses as many used cells as counted from 1 row down from header to the range end cell. But it doesnt work, so I tested using this.
Sub Test_YearlyPnLListFormulas()
Dim rangeCount As Integer
rangeCount = WorksheetFunction.Count(Range(Range("BATLYearlyPnLListHeader").Offset(1, 0), Range("BATLYearlyPnLListRangeEnd")))
Debug.Print rangeCount
End Sub
The formula only selects the cell below the header, but when I run the test sub the count is right, 12. What am I missing in the excel formula?
I have some sample data in a sheet, I want to get headers of each column in used range, Here is the sample
I never know the exact number of columns used, I need to get all headers (Customers, Managers, Managers-2....)from this sheet to show it to user.
I can loop through each cell in a used range like
For Each cell In ActiveWorkbook.Worksheets(SheetName).UsedRange
Next
but how can I loop though each column, and only read values from their 1st cell? as number of these lists can be one or more than one.
Replace your code by this one iterate over the first row of used range:
For Each cell In ActiveWorkbook.Worksheets(SheetName).UsedRange.Rows(1).Cells
...
Next
'Get a 2D array of header values
Dim aHeaders() As Variant
aHeaders = Sheet1.UsedRange.Rows(1).Value
It all depends on your data quality. Come across this numerous times.
If your headers are consistent, then you just need to resize to the first row. Something like:
Dim r as range, r1 as range
Set r = Range("A1").CurrentRegion.Resize(1)
Then do a for each for the r range.
For Each r1 in r
Next
You could also use an integer variable....
Dim i as integer
For I = 1 to r.Count
Next
32bit Excel 2013 / Win 7 64 bit
UDF asks user for two range inputs from the same table and a lookup value ie:
Public Function FindBfromA(A as Range,B as Range, IDValue as Integer)
For IDCheck = 1 to A.Count
IF A(IDCheck) = IDValue then
IDNum = IDCheck
Exit For
End if
Next IDCheck
FindBfromA = B(IDNum)
End Function
Formula is added into another column of the table, for example
=FindBfromA([A],[B],[#C])
'Where C is calculated via something
My issues is Ranges A & B become disjointed. Where A(IDCheck) and B(IDCheck) should belong to corresponding columns in the same table row, based on where my cursor is when calculating begins Range [B] will re-key
This then causes the formula to return the wrong value from the FindBfromA=B(IDNum) as A(IDNum){Row} <> B(IDNum){Row}
I couldn't reproduce the error in the workbook I created with the false data - in my company (private) workbook the function operates essentially the same way, but captures two 'B' values given two IDs and passes them to another function.
It's difficult to be sure without seeing your range selections, but the unreliable element of your code is the cell references. By using a single integer index, you are basically selecting the nth cell in the range rather than cell on row n. My suspicion is that range B is offset from range A by a number of rows. Let's say your two selections were A = "A1:A10" and B = "B2:B11" then A(3), for example, would be on row 3 but B(3) would be on row 4. The same would apply if Range A had more than one column.
To eliminate that risk, refer to the ranges by the row and column indexes, as in the code below. You'll note I've also change the data type of the IDValue to a variant as this prevent an error being thrown in your IDValue should ever be something like a String or Long. I've also looped through range A with a For Each loop on each cell to cater for the case that range A has more than one column.
Public Function FindBfromA(A As Range, B As Range, IDValue As Variant) As Variant
Dim cell As Range
For Each cell In A.Cells
If cell.Value2 = IDValue Then
FindBfromA = B.Cells(cell.Row, 1).Value2
Exit Function
End If
Next
End Function
I need to run the function AddColumnofData on each cell from c27 and every contiguous non empty cell to the right, but I get a "Run-time error 424 object required", any help woul dbe greatly appreciated.
Set col = Range("$C$27", Range("$C$27").End(xlToRight))
For Each c In col
AddColumnofData (c)
Next c
On the assumption you have defined AddColumnofData as
Sub AddColumnofData(c As Range)
...
End Sub
your call to it needs to be
AddColumnofData c
(that is, remove the brackets)
Jesse's advice to DIM your variables, while not not manditory is good advice. Applies to col as well. To make it manditory add Option Explicit to the top of your module.
You can declare or set your range objects before passing them to your function. To prove that you are passing the correct values to your function, try this.
Dim r As Range '-- if you don't declare it as a range type you get a variant type as default
Dim c As Range '-- this is used to store the single cell in the For Each loop
Set r = Range("A1:D1") '-- substitute your range as per your example
For Each c In r '-- you could also use r.cells
MsgBox c.Value '-- pass to your function instead of a call to the Message Box
Next
This produces a series of 4 Message Boxes containing the values in cells A1 to D1 of the active worksheet, if your Range "r" is seriously large then pass it to Debug.Print instead.
If you declare c:
Dim c as Range
Then what you have should work.