excel formula for named range using both offset and count - vba

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?

Related

Counting cells using Excel VBA which are a result of a vlookup statement

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")

Count values that aren't blank or N/A - VBA

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

Highlight unique values based on another range

Column 1 is in Sheet1 and column 2 is in Sheet2. If the value is not found , then highlight that cell. I am trying to do a vlookup comparing two columns. I think the Syntax is incorrect. Please see my code I was trying below:
Option Explicit
Sub VlookupColoums()
' declarations
Dim lookFor As Range
Dim srchRange As Range
Dim I As Long
Dim vtest As Variant
' start
Set lookFor = Sheets("Sheet1").Range("A13").End(xlUp)
Set srchRange = Sheets("Sheet2").Range("A2").End(xlUp)
vtest = Application.VLookup(lookFor.Rows.Count, srchRange.Rows.Count, 2, False)
' process
For I = 1 To lookFor.Rows.Count
If IsError(vtest) Then
srchRange.Interior.Color = 4
Else
Exit Sub
End If
Next I
End Sub
Assuming you have data on Sheet1!A1:A15 and Sheet2!A1:A10.
Also assuming you want to highlight unique cells (ones withouth at least one identical in the other list) on Sheet2.
Basically you want to format all the cells that if counted on the other list comes up with 0. The steps:
Select all the cells to be evaluated on Sheet2
Go to Home/Styles/Conditional Formatting
Select New Rule, then Use a formula to determine...
Enter this formula: =COUNTIF(Sheet1!$A$1:$A$5,A1)=0
Click on the Format button, and set up a formatting for the unique cells
OK
Profit. :)

passing a range object to a sub in VBA

Trying to create a subroutine that takes a range cell and calculates the average of the cells in that column. But I get the error: Object Required
How can I correct this?
Sub test()
Dim rg As Range
Set rg = ThisWorkbook.Worksheets(1).Range("B1")
ColumnAverageToTop (rg)
End Sub
Sub ColumnAverageToTop(rg As Range)
'calculates the average of the data in column and puts it above the data
Cells(1, rg.Column).End(xlDown).Offset(1, 0).Value = Application.WorksheetFunction.Average(rg.Columns(rg.Column))
End Sub
Good that there's a comment that is telling what this sub should do: I read it as: If I run "Test()", the following happens: in the passed range's column in row one, the average of that column's values should appear.
There are three problems in your code.
The first is mentioned in previous comments: Use either call ColumnAverageToTop(rg) or ColumnAverageToTop rg in your test-routine. Solution:
Sub test()
Dim rg As Range
Set rg = ThisWorkbook.Worksheets(1).Range("B1")
ColumnAverageToTop rg
End Sub
Now that we will succesfully enter the ColumnAverageToTop routine, there's an issue with passing the parameter to the WorkSheetFunction.Average
It takes arguments as documented here: https://msdn.microsoft.com/en-us/library/office/ff836809.aspx so to keep it simple just make sure to pass a Range-object to it on which the calculation is performed.
Lastly, when using End and Offset, make sure you use them in the right order. Each of these functions will provide a new range object. I see you attempt to get the cell below the passed argument and then go down and get all the other values to calculate the average of that range.
If you truely always need the average of the entire column, I would advise:
Sub ColumnAverageToTop(rg As Range)
'calculates the average of the data in column and puts it in row 1 of column
'We declare where we put the value: Cells(1,1) of the column of the Range passed
'E.g. "B1" passed means that the average will be in "B1".
'Same fore passing "B323"
rg.EntireColumn.Cells(1, 1).Value = WorksheetFunction.Average(rg.EntireColumn)
End Sub
This will include any numerical value in row 1 of the same column of the passed range, even though it will be overwritten with the result. Running the same test multiple times will therefore change the result.
If you really need the average of everything below the 1st row until the first blank row, it should be:
.rg.EntireColumn.Cells(1,1).value = WorksheetFunction.Average(rg.EntireColumn.Range(Cells(2, 1), Cells(2,1).End(xlDown)))
If your need the average of the filled cells below the referenced cell:
.rg.EntireColumn.Cells(1, 1).Value = WorksheetFunction.Average(rg.Offset(1, 0).Resize(rg.Offset(1, 0).End(xlDown).Row - rg.Offset(1, 0), 1))
Hope this helps you out.

Loop Through 1st cell of each column in used range Excel VBA

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