Count cells with values in a column up to two above the active cell, excluding the header - excel

I'm trying to count all the cells in a column that have values above the active cell excluding the header and excluding the cell immediately above the active cell.
For example if I have a column
1
5
4
N/A N/A
4
current cell
I want the current cell to equal 2. (Counting the 5 and 4, not the N/A N/A, not the cell above current cell, and not the first cell.)
The number of cells in the column will vary.
I want this for 260 consecutive columns.

Try this:
Sub counter()
Dim col As Integer
Dim lastrow As Integer
Dim cellcount As Integer
With ActiveCell
col = .Column
lastrow = .Row - 2
End With
cellcount = 0
For Each cell In ActiveSheet.Range(Cells(2, col), Cells(lastrow, col))
If IsError(cell) Then GoTo skipcell
If cell.Value > 0 And IsNumeric(cell) Then cellcount = cellcount + 1
skipcell:
Next cell
ActiveCell = cellcount
End Sub
It takes the active cell and finds the selected colum and find the cell two above the active cell.
It then loops though the range adding to a counter each time it finds a value higher than "0"
As requested by OP in comments added in checks to ensure date in the cell is Numeric and that there is not a error (#N/A) value in the cell
Also requested is for this to span 260 columns in the same row. For this, use of a for loop is employed:
Sub counter()
Dim firstCol as Integer
dim lastCol as Integer
firstCol = 1 'You can change this value depending on your first column
' for example you might use ActiveCell.Column
lastCol = firstCol + 260
Dim col As Integer
Dim lastrow As Integer
lastRow = 6 ' Make this the actual last row of the data to include
Dim cellcount As Integer
for col = firstCol to lastCol
cellcount = 0
For Each cell In ActiveSheet.Range(Cells(2, col), Cells(lastrow, col))
If IsError(cell) Then GoTo skipcell
If cell.Value > 0 And IsNumeric(cell) Then cellcount = cellcount + 1
skipcell:
Next cell
ActiveSheet.Cells(lastRow + 2, col) = cellcount
Next col
End Sub

Why does this have to be VBA code?
It is very simple to do in a cell formula:
=COUNTIF(A1:A5,"<>0")-2
This counts all the cells in the given range (A1:A5) which are not equal to zero. Since you know you want to remove the header row and one row above, subtract 2 from the answer. Of course, this the same as
=COUNTIF(A2:A4,"<>0")
If you want to use this in VBA then look into WorksheetFunction:
Dim myCount As Integer
myCount = WorksheetFunction.COUNTIF(ActiveSheet.Range("A2:A4"),"<>0")
Then insert myCount into the sheet
ActiveSheet.Range("A6").value = myCount

Related

Double for loop to iterate through columns B-M and then rows, to get row totals and change column heading

I am trying to change the font color of the cell row label to red if the row grand total is >130,000. The first part of the assignment entailed changing the color of the font in each cell with a value over 12000 - The code I have right now correctly colors the cells but does not turn the appropriate cell red (the cell in col A corresponding to the row it is iterating through to get a total). Any help would be appreciated, I am new to Excel VBA!
This is the code I have currently:
Option Explicit
Sub Question5()
Dim rng As Range
Dim cell As Range
Dim total As Integer
Dim i As Integer
Set rng = Range("B2", "M41")
For Each cell In rng
If cell.Value >= 12000 Then _
cell.Font.ColorIndex = 5
Next cell
Dim monthlysum As Integer
For Each Row In Range("B2", "M41")
Set monthlysum = 0
For Each cell In Row
monthlysum = cell.Value + monthlysum
Next cell
If monthlysum > 130000 Then _
Range("A" & rowNum).Select
Range("A" & rowNum).Font.Color = vbRed
Next Row
End Sub
Try this - fixes commented inline
Option Explicit
Sub Question5()
Dim rng As Range, Row As Range, cell as Range
Dim monthlySum as Long 'use Long not Integer
For Each Row In ActiveSheet.Range("B2:M41").Rows 'need to specify .Rows otherwise defaults to .Cells
monthlySum = 0
For Each cell in Row.Cells
with cell
if .Value >= 12000 Then cell.Font.ColorIndex = 5
monthlySum = monthlySum + .Value
End With
Next cell
if monthlySum > 130000 Then Row.Entirerow.cells(1).Font.color=vbRed
Next Row
End Sub

VBA loop until the last column and increase value in column by 1

I am working on a project where I need to populate the column headings with incremental values (increased by 1) until the Last Column.
The code is working OK but the value in the column headings is NOT increased by 1. It is just taking the original value and place it over all columns.
Could you help me?
My code so far:
Sub LastColumn_PopulateHeadings()
'Declare variable for Last row (Prior FY)
Dim LastColumn As Integer
Dim i As Integer
'Find the last Column used
LastColumn = Range("XFD4").End(xlToLeft).Column
'populate headings with column values UNTIL LAST COLUMN
' Loop to populate the heading until LAST column
i = 8
Do While i < LastColumn
'MsgBox (LastColumn)
Cells(4, i).Value = Cells(4, i).Value + 1
i = i + 1
Loop
End Sub
I find your code a little strange, but probably i am missing something. Anyway this one should work:
Sub LastColumn_PopulateHeadings()
'Declare variable for Last row (Prior FY)
Dim LastColumn As Integer
Dim i As Integer
Dim IntCounter01 As Integer '<<<<<<ADDED LINE (1 of 3)
'Find the last Column used
LastColumn = Range("XFD4").End(xlToLeft).Column
'populate headings with column values UNTIL LAST COLUMN
' Loop to populate the heading until LAST column
i = 8
IntCounter01 = 1 '<<<<<<ADDED LINE (2 of 3)
Do While i < LastColumn
'MsgBox (LastColumn)
Cells(4, i).Value = IntCounter01
i = i + 1
IntCounter01 = IntCounter01 + 1 '<<<<<<ADDED LINE (3 of 3)
Loop
End Sub
I took your code and added 3 lines. You could also use a For-Next cycle instead of using a Do-While-Loop cycle since you already know your maximal value. Something like:
For i = i To LastColumn - 1
Cells(4, i).Value = IntCounter01
IntCounter01 = IntCounter01 + 1
Next
You could also use a formula to cover your range instead of picking each cell one by one. Like this:
Sub LastColumn_PopulateHeadings()
'Declarations.
Dim IntFirstColumn As Integer
Dim IntLastColumn As Integer
Dim IntRow As Integer
Dim IntFirstValue
Dim RngRange01 As Range
'Setting variables.
IntFirstValue = 1
IntRow = 4
IntFirstColumn = 8
IntLastColumn = Range("XFD4").End(xlToLeft).Column
'Setting first value in the first cell.
Cells(IntRow, IntFirstColumn).Value = IntFirstValue
'Setting RngRange01.
Set RngRange01 = Range(Cells(IntRow, IntFirstColumn + 1), Cells(IntRow, IntLastColumn - 1))
'Setting formulas in RngRange01.
RngRange01.FormulaR1C1 = "=RC[-1]+1"
'Copy-pasting the values in RngRange01.
RngRange01.Value = RngRange01.Value
End Sub

VBA: Summing the rightmost cell per row?

I've a data set that looks similar to the below.
I'd like to average the data in the rightmost column only.
My range starts at C4 with no set end to either rows or columns.
**1**
1 **2**
1 2 **3**
1 **2**
**1**
I've put the following together which does what I need it to do for a single fixed column but I don't know how to expand that out to always use the value from the right most column.
Dim Sum, Count As Integer
Count = 0
Sum = 0
Application.ScreenUpdating = False
Range("C4").Select
Do While ActiveCell.Value <> ""
Sum = Sum + ActiveCell.Value
Count = Count + 1
ActiveCell.Offset(1, 0).Activate
Loop
Range("O1").Value = Sum / Count
Thank you.
This will cycle the rows.
The MATCH will return the column number of the last column with a number in it.
Then we get the number on that row in that column and add it to an array.
Then after the loop we average the array.
Sub aver()
With Worksheets("Sheet4") 'Change to your sheet
Dim lastrw As Long
lastrw = .Cells(.Rows.Count, 3).End(xlUp).Row
Dim num() As Variant
ReDim num(1 To lastrw) As Variant
Dim i As Long
For i = 4 To lastrw
Dim j As Long
j = Application.Match(1E+99, Rows(i), 1)
num(i) = .Cells(i, j).Value
Next i
.Range("O1").Value = Application.Average(num)
End With
End Sub

Excel VBA - Highlighting Duplicate Cell Values - Paragraphs (Long Strings)

I've searched the forums and found some great Excel VBA code to find and highlight duplicate cell values in a given dataset range.
However, the cell values in my dataset are paragraphs. This means some cell values in the dataset will be greater than 255 characters. When I run the code below, duplicate cells are highlighted until the code encounters a cell value greater than 255 charactions. This appears to cause the "countif" function to throw the error:
Run-time error '1004':
Unable to get CountIf property of the WorksheetFunction class
Any ideas on how to pass a Cell.Value greater than 255 characters to CountIf, or another idea to compare cell values greater than 255 characters to highlight duplicates?
Sub findDuplicates()
Const headRow As Integer = 7 'row that contains the table heading row for the dataset
Dim lastRow As Integer
Dim rng As Range
With ThisWorkbook.Worksheets(1)
lastRow = .Range("F" & Rows.Count).End(xlUp).Row 'finds last row in dataset
Set rng = .Range(Cells(headRow + 1, 6), Cells(lastRow, 6)) 'sets the range of the dataset between the headRow and lastRow
End With
For Each Cell In rng
If Application.WorksheetFunction.CountIf(rng, Cell.Value) > 1 Then 'tests if there is a duplicate
Cell.Interior.ColorIndex = 6 'highlight yellow
End If
Next Cell
End Sub
To compare cell values with lengths > 255, you can loop through the range doing a cell by cell comparison.
Please read the comments in the code below for further details, and post back with any questions.
Option Explicit 'require declaration of ALL variables
'go to Tools/Options/Editor and set "Require Variable Declaration"
Option Compare Text 'for case insensitive
Sub findDuplicates()
'Use Long instead of integer
' Plenty of articles as to why
Const headRow As Long = 7 'row that contains the table heading row for the dataset
Dim lastRow As Long
Dim rng As Range
Dim Counter As Long
Dim V As Variant, I As Long, J As Long
Dim COLL As Collection
With ThisWorkbook.Worksheets(1)
lastRow = .Range("F" & Rows.Count).End(xlUp).Row 'finds last row in dataset
Set rng = .Range(Cells(headRow + 1, 6), Cells(lastRow, 6)) 'sets the range of the dataset between the headRow and lastRow
End With
'Read range into vba array for faster processing
V = rng
'loop through the array to do the count
Set COLL = New Collection 'collect the duplicate cell addresses
For I = 1 To UBound(V, 1)
Counter = 0
For J = 2 To UBound(V, 1)
If V(J, 1) = V(I, 1) Then 'duplicate
Counter = Counter + 1
If Counter > 1 Then
On Error Resume Next 'avoid duplicate addresses in the collection
COLL.Add Item:=rng(I).Address, Key:=rng(I).Address
On Error GoTo 0
End If
End If
Next J
Next I
'highlight the relevant cells
rng.Interior.ColorIndex = xlNone
For Each V In COLL
Range(V).Interior.ColorIndex = 6
Next V
End Sub
I propose to convert long text into some numeric value. See my function:
Function UnicodeVal(str As String) As Double
Dim l As Long
Dim dblV As Double
dblV = 1
For l = 1 To Len(str)
If l Mod 2 Then
dblV = dblV * AscW(Mid(str, l, 1))
Else
dblV = dblV / AscW(Mid(str, l, 1))
End If
UnicodeVal = dblV
Next l
The function multiply and divides Unicode values of all character in the string and returns the score. Because it is multiplying for even numbers and dividing for odd, it is immuned from typos like "hoem" instead of "home". It is unlikely that the score will be the same in case of long strings, I think.
You can use this function in place of direct comparisons.

Counting upward in column until blank?

I have a column, which will contain a few rows of data, and then a blank cell.
I need a way to count the rows upwards in a column until a blank cell and sum the number using VBA. Any ideas?
I'm not 100% sure what you are asking. You say "sum the number" but do not specify if the number you want to sum is the number of rows counted or if you want to sum the value of the cells found.
-Edit-
Give this a try:
This will start at the bottom row and count upward until it finds a blank cell
Once a blank cell is found it will sum the cells between the last blank cell and the current blank cell.
-Edit2-
Added insert to the row under column headers so the first row also gets summed.
Sub CountUp()
Dim TotalRows As Long
Dim TotalCols As Long
Dim Col As Long
Dim i As Long
Dim n As Long
Rows(2).Insert Shift:=xlDown
TotalRows = ActiveSheet.UsedRange.Rows.Count
TotalCols = ActiveSheet.UsedRange.Columns.Count
'Assumes Data you want to sum is in the first column
Col = 1
Cells(TotalRows, Col).Select
For i = TotalRows To 1 Step -1
If Cells(i, Col).Value <> "" Then
n = n + 1
Else
Cells(i, Col).Formula = "=SUM(" & Cells(i + 1, Col).Address(False, False) & ":" & Cells(i + n, Col).Address(False, False) & ")"
n = 0
End If
Next
End Sub
Assuming Column F as the Column and it has number. Try the below code.
Sub sumAndcount()
Dim recCount As Long
Dim recSum As Long
Range("A65000").Value = "=COUNT(F:F)"
recCount = Range("A65000").Value
Range("A65000").Value = "=SUM(F:F)"
recCount = Range("A65000").Value
End Sub

Resources