Count number of cells in a column that contain data - variables

I have this code:
Dim first As Integer
Dim Last As Integer
Dim i As Integer
For i = 1 To 17
first = (ActiveCell.Row + 1)
Selection.End(xlDown).Select
Last = (ActiveCell.Row - 1)
Range("J" & first & ":J" & Last).Select
Selection.Value = "=J$" & (first - 1)
Range("A" & Last + 1).Select
Next i
and would like to be able to replace the 17 with a variable because some of the workbooks have an extra group. I can't just count the number of rows as there is information between first and last but in different columns.
Is there a way to count the number of cells that have data in a set column where the data may not be contiguous (then I can replace the 17 with a variable that is equal to variable -1)?

Found it online: Thanks.
n = Worksheets("Sheet1").Range("A:A").Cells.SpecialCells(xlCellTypeConstants).Count

Related

Summing across columns with fixed start cell to last column VBA

I have a table which changes in size each time it is run. I want the last column to return the sum of all values of each row. The last row of the table returns the sum of each column which I've tried to edit so that it would return the sum of the rows in the last column
'Sums everything starting from "L16" to the last row in column L and drags formula across the last row until the last column
Range(Cells(LR, "L"), Cells(LR, lastcol)).Formula = "=sum(L16:L" & LR - 1 & ")"
'Doesn't work but I want it to sum everything starting from "L16" to the last column in row 16 and drag the formula to the last row
Range(Cells(16, lastcol), Cells(LR, lastcol)).Formula = "=sum(L16:16" & lastcol-1 & ")"
There's a syntax error here =sum(L16:16" & lastcol-1 & "), you need column letter before the row number.
If your lastcol isn't greater than 27 you can use the following statement:
Range(Cells(16, lastcol), Cells(LR, lastcol)).Formula = "=sum(L16:" & Chr(lastcol - 1 + 64) & "16)"
Alternatively, add this function to your project:
Function ColLetter(Col As Long) As String
Dim vArr
vArr = Split(Cells(1, Col).Address(True, False), "$")
ColLetter = vArr(0)
End Function
It returns a letter of any column number you supply.
Then in your code you can use it like this:
Range(Cells(16, lastcol), Cells(LR, lastcol)).Formula = "=sum(L16:" & ColLetter(lastcol - 1) & "16)
Not sure where your data starts but that can be set with iStartCol & iStartRow. It will put a sum formula at the end of each row & column, and also a grand total.
Sub Test()
Dim iStartCol As Long
Dim iStartRow As Long
iStartCol = 2 ' Starting Column of your Data
iStartRow = 11 ' Starting Row of your Data
Dim iTotalCol As Long ' Find where the Total Column will be
iTotalCol = Sheet1.UsedRange.Columns.Count + 1
Dim iTotalRow As Long ' Find where the Total Row will be
iTotalRow = Sheet1.UsedRange.Rows.Count + 1
' Total Row
Sheet1.Range(Cells(iTotalRow, iStartCol), Cells(iTotalRow, iTotalCol - 1)).Formula = "=Sum(R[-" & iTotalRow - iStartRow & "]C:R[-1]C)"
' Total Cols
' Note: no -1 in Range so we will also sum the Total Row, for grand total
Sheet1.Range(Cells(iStartRow, iTotalCol), Cells(iTotalRow, iTotalCol)).Formula = "=Sum(RC[-" & iTotalCol - iStartCol & "]:RC[-1])"
End Sub

VBA copy row from sheet1 to sheet2 based on keyword

My code does what I want, but it copies it to column A in sheet 2. I would like it to put the data in starting at Column B if possible.
Sub EFP()
Dim keyword As String: keyword = Sheets("Results").Range("B3").Value
Dim countRows1 As Long, countRows2 As Long
countRows1 = 3 'the first row of my dataset in the Data tab
endRows1 = 500 'the last row of my dataset in the Data tab
countRows2 = 6 'the first row where I want to start writing the found rows
For j = countRows1 To endRows1
If Sheets("Data").Range("B" & j).Value = keyword Then
Sheets("Results").Rows(countRows2).Value = Sheets("Data").Rows(j).Value
countRows2 = countRows2 + 1
End If
Next j
End Sub
If you copy and paste whole rows, they will always start in column A. If you want the result to start in column B, you need a different approach, for example
Sheets("Results").Range("B" & countRows2 & ":Z" & countRows2).Value = Sheets("Data").Range("A" & j & ":Y" & j).Value

VBA - Add new Column then COPY cells and then SUM cells

I am attempting to create a new column that consolidates multiple values into a single Column. The code below has no problems creating a new column exactly where I need it.
Within each newly created column however, I would like my code to Sum the previous 5 cells within the same row. It works currently, but is static(The new column is G in the below example, and it sums B:F). I think I need some sort of Offset function built into it to allow the Range it sums to be dynamic (Previous 5 columns), as it loops through the entire sheet.
Additionally, I would love it to copy the Header information from rows 1-9 from the column to the left of the new column, into the new column, and place the word "Combo" into Row 10 of the new column.
Office 2013
Any help with this endeavor would be great.
Thanks
Dim currentColumn As Integer
Dim columnHeading As String
For currentColumn = Sheets("SLTData").UsedRange.Columns.Count To 2 Step -1
columnHeading = Sheets("SLTData").UsedRange.Cells(10, currentColumn).Value
'CHECK WHETHER TO KEEP THE COLUMN
Select Case columnHeading
Case "PD.G0100", "PD.G0500", "PD.G0800", "PD.G0900", "PD.G1000", "PD.G0300", "PD.G0400", "PD.G0150", "PD.G0600"
'Do nothing
Case Else
If InStr(1, _
Sheets("SLTData").UsedRange.Cells(10, currentColumn).Value, _
"Homer", vbBinaryCompare) = 0 Then
Sheets("SLTData").Columns(currentColumn).Insert
For i = 11 To Cells(Rows.Count, "B").End(xlUp).Row
Range("G" & i) = WorksheetFunction.Sum(Range("B" & i), Range("C" & i), Range("D" & i), Range("E" & i), Range("F" & i))
Next i
End If
End Select
Next
Instead of Range("G" & i) use Cells(row, column) (both row and column are integer). To sum up the 5 cells left of it: Cells(row, column) = WorksheetFunction.Sum(Range(Cells(row, column-5), Cells(row, column-1)))

Select blank cells after a used cell and copy data

I have a problem regarding this:
I need to make the blank cells' value equal to the value of the used cell before them. My desired outcome is this:
You can observe that the blank cells' value depends on the value of the used cell before them. Is there any way to achieve this using macro? Thanks.
You can also use this one:
Public Sub fillBlank()
Dim row, lastRow As Integer
With Sheets("sheetname")
'Getting the last use row.
lastRow = .Range("B1").SpecialCells(xlCellTypeLastCell).row
'looping from row 2 to last used row (let row 1 is not blank)
For row = 2 To lastRow Step 1
If .Range("C" & row) = "" Then
.Range("C" & row) = .Range("C" & row - 1)
End If
Next row
End With
End Sub
I found the answer myself after some time.
For i = 2 To last
If log.Sheets("Entry").Cells(i, 3) <> "" Then
If log.Sheets("Entry").Cells(i + 1, 3) = "" Then
log.Sheets("Entry").Cells(i + 1, 3) = log.Sheets("Entry").Cells(i, 3)
End If
End If
Next i

Am I using the isnumeric function correctly?

This program is to convert a column of data from cumulative to non-cumulative. On my sheet I have A1, B1, and C1 with the text Non-Cumulative, Cumulative, and Converted, respectively. I have numbers 1 to 10 beneath A1, then them summed cumulatively beneath B1. C1 is where I want to convert column B back to non-cumulative.
The IsNumeric is used to make the first row of data in C equal to the first row of data in B. It should detect that the title is above the number it is evaluating, thus knowing that no calculations have to be performed. For the rest of them, it'll see that the number above the one it is evaluating is a number, and thus the calculation has to be done.
My problem is that it isn't working. I think the reason is because IsNumeric() keeps coming back as false. Is there a different function I should be using? Do cell references not work in IsNumeric?
Here's the program!
Option Explicit
Dim i As Variant
Sub Conversion()
Sheets("Test Sheet").Select
For i = 1 To 10
If IsNumeric("B" & i) = False Then
Range("C" & i + 1) = Range("B" & i + 1)
Else: Range("C" & i + 1) = Range("B" & i + 1) - Range("B" & i - 1)
End If
Next
End Sub
The way you wrote your code is logical, just a minor syntax changes you need initially. However,
It's also best to check if the range is empty first...
Then check on if the value is numeric.
Better even, if you set the Range into a Range object and use offset
Code:
Option Explicit '-- great that you use explicit declaration :)
Sub Conversion()
Dim i As Integer '-- integer is good enough
Dim rngRange as Range
'-- try not to select anything. And for a cleaner code
Set rngRange = Sheets("Test Sheet").Range("B1")
For i = 1 To 10
If (rangeRange.Offset(i,0).value) <> "" then '-- check for non-empty
If IsNumeric(rangeRange.Offset(i,0).value) = False Then
rangeRange.Offset(i+1,1) = rangeRange.Offset(i+1,0)
Else
rangeRange.Offset(i+1,1) = rangeRange.Offset(i+1,0) - rangeRange.Offset(i-1,0)
End If
End if
Next i '-- loop
End Sub
To make your code more dynamic:
Another suggestion, you may simply Application.WorkSheetFunction.Transpose() the entire B column range that you need to validate into a variant array
Process the array and Transpose back to the Range with column B and C.
By doing so, you may omit setting for loop size manually but setting it using Lower and Upper bound of the array ;)
You need to check if the range of B i is numeric, not the string "B" & i
and rather than selecting the sheet, simply using a parent identifier like:
sheets("sheet1").range("B" & i)
This will help you avoid errors in your code
For i = 1 To 10
If IsNumeric(sheets("test sheet").range("B" & i).value) = False Then
Range("C" & i + 1) = Range("B" & i + 1)
Else: Range("C" & i + 1) = Range("B" & i + 1) - Range("B" & i - 1)
End If
Next