VBA help in selecting final row and choosing range - excel

The following code is doing the following:
Starting from A1, it searches for the last filled cell and selects
the cell right after it.
After selecting the first available blank cell it selects the entire row
The entire row is then colored with color index 16.
Here you go:
Sub Macro1()
Range("A1").End(xlDown).Offset(1, 0).Select
Range(Selection, Selection.End(xlToRight)).Select
With Selection.Interior
.ColorIndex = 16
End With
End Sub
This works great but I am having difficulty selecting only columns A to H within that row. I don't want to select the entire row.
Can someone please help me? I keep getting End With errors and not sure how to fix it :S
Thank you very much for your time and consideration!

That is too much selecting! How about
Sub Macro1()
currentRow = Range("A1").end(xldown).offset(1,0).row
Range(cells(currentRow, 1), cells(currentRow,8)).Interior.ColorIndex = 16
cells(currentRow,1)= " "
End Sub
Does that work?

you can set a range for your selection, also here is another method to find last row from the end of the column (version 1) - the (Rows.Count,1) represents column A (Rows.Count,2) would represents column B and so on...
this is version one: start looking for empty row from the end of column A:
Dim rowNum As Integer
rowNum = Cells(Rows.Count, 1).End(xlUp).Row + 1
Dim rng As Range
Set rng = Range(Cells(rowNum, 1), Cells(rowNum, 8))
rng.Interior.ColorIndex = 16
this is version two: start looking for empty row from the start (row 1) of column A:
Dim rowNum As Integer
rowNum = Range("A1").End(xlDown).Offset(1, 0).Row
Dim rng As Range
Set rng = Range(Cells(rowNum, 1), Cells(rowNum, 8))
rng.Interior.ColorIndex = 16

Try this:
'Declare Variables
Dim rowNum as integer
Dim YourRange as range
'Find last row by counting cells not empty and adding 1
'Assumes that all cells from A1 down are filled. Change the +1 accordingly if not
rowNum = worksheetfunction.counta(activesheet.columns(1))+1
'Set range object to column A through H of your row number
Set YourRange = Activesheet.Range("A" & rowNum & ":H" & rowNum)
'Set interior color of the rnage object instead of using Selection
YourRange.interior.colorindex=16

Related

Formula in first blank and filled down to end of data

I have the below code where in all other columns there is many populated rows, what I need this formula to do in column F is to find the first blank, then place the formula in it and fill it down to the last row.
What is currently happening is I have the range as F26 as this is usually first blank but this could change and I want the code to identify this and also have the formula dynamically know what row it is on, so for example if one month the first blank was in cell F30 the range would find it and the formula would start as E30*G30.
Any help would be greatly appreciated.
Private Sub calc()
Dim lastrow As Long
Dim rng As Range
lastrow = ThisWorkbook.Worksheets("Indiv").Cells(Rows.Count, 1).End(xlUp).Row
Set rng = Range("F26:F" & lastrow)
rng.Formula = "=Round((E26*G26),2)"
End Sub
You need to find the first free row in column F and then bulid your formula with this row:
Option Explicit
Private Sub calc()
Dim ws As Worksheet ' define worksheet
Set ws = ThisWorkbook.Worksheets("Indiv")
Dim LastRowA As Long ' find last used row in column A
LastRowA = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim FirstFreeRowF As Long ' find first free row in column F (if first 2 rows have data)
FirstFreeRowF = ws.Cells(1, "F").End(xlDown).Row + 1
' fix issue if first or second row is empty
If FirstFreeRowF = ws.Rows.Count + 1 Then
If ws.Cells(1, "F").Value = vbNullString Then
FirstFreeRowF = 1
ElseIf ws.Cells(2, "F").Value = vbNullString Then
FirstFreeRowF = 2
End If
End If
' define range to add formula
Dim Rng As Range
Set Rng = ws.Range("F" & FirstFreeRowF, "F" & LastRowA)
' add formula
Rng.Formula = "=Round((E" & FirstFreeRowF & "*G" & FirstFreeRowF & "),2)"
End Sub
So this will consider F5 the first free row and fill in the formula in the selected range as seen below:
I think you should find the last used row in column F, so that you could know the next row is blank
lastrowF=sheets(sheetname).range("F" & rows.count).end(xlup).row
So the next row would be like
range("F" & lastrowF+1).formula="Round((E" & lastrowF+1 & "*G" & lastrowF+1 & ",2)"

Loop through only filtered visible rows

I have a problem with below code. I would like to filter "OS" (filed 61) then if first cell in 1st column below filters is not empty macro should go to first cell below filters in column "57", check if value in that cell is > 365 if yes it should go to column 62 in the same row and put there "overdue" if no then put there "OK". After that it should go to next row and check the same till the end of the filtered rows.
The problem is with visible only cells. Macro is doing it on all rows even not visible.
It should work only for filtered visible rows. Any suggestions?
Sub Patch_Overdue()
Dim i As Long
Dim LastRow As Long
Sheets("Sheet1").Select
'filter AIX OS
Selection.Autofilter Field:=61, Criteria1:="AIX*"
ActiveSheet.Autofilter.Range.Offset(1).SpecialCells(xlCellTypeVisible).Cells(1, 61).Select
If IsEmpty(Selection) = False Then
LastRow = Range("a7").End(xlDown).Row
For i = 1 To LastRow
If ActiveSheet.Autofilter.Range.Offset(1).SpecialCells(xlCellTypeVisible).Cells(i, 57).Value > 365 Then
ActiveSheet.Autofilter.Range.Offset(1).SpecialCells(xlCellTypeVisible).Cells(i, 62).Select
ActiveCell.FormulaR1C1 = "Overdue"
Else
ActiveSheet.Autofilter.Range.Offset(1).SpecialCells(xlCellTypeVisible).Cells(i, 62).Select
ActiveCell.FormulaR1C1 = "OK"
End If
Next i
Else
ActiveSheet.ShowAllData
End If
End Sub
Please, try the next code. It is not tested, but it should work. Basically, it set the range to be processed based on the last cell in A:A and UserRange number of columns, extract the visible cells range, iterate between its areas and the between each area rows and check what you need:
Sub Patch_Overdue()
Dim sh As Worksheet, rngUR As Range, rngVis As Range, i As Long, LastRow As Long
Set sh = Sheets("Sheet1")
If sh.AutoFilterMode Then sh.AutoFilterMode = False 'eliminate a previous filter to correctly calculate last row
LastRow = sh.Range("A" & sh.rows.count).End(xlUp).row 'last row
'filter AIX OS
Set rngUR = sh.Range("A7", sh.cells(LastRow, sh.UsedRange.Columns.count)) 'set the range to be filtered
rngUR.AutoFilter field:=61, Criteria1:="AIX*" 'filter the range according to criteria
Set rngVis = rngUR.Offset(1).SpecialCells(xlCellTypeVisible) 'set the visible cells range
Dim arRng As Range, r As Range
For Each arRng In rngVis.Areas 'iterate between the range areas:
For Each r In arRng.rows 'iterate between the area rows:
If WorksheetFunction.CountA(r) > 0 Then 'for the case of the last row which is empty because of Offset
If r.cells(1, 57).value > 356 Then
r.cells(1, 62).value = "Overdue"
Else
r.cells(1, 62).value = "OK"
End If
End If
Next
Next
sh.ShowAllData
End Sub

Auto Fill Sequential Dates Until Next Row Down has Value

I am trying to pull down the date column to fill in the next sequential dates in the blank cells until the next cell down has a value in it. For example, the blank cells in the highlighted date range should read 3/23/2019 & 3/24/2019 (see screenshot, Column C):
Here is the code that I have crudely put together. But I am so new to this, I am not sure where I am going wrong. In my logic, I execute the code starting from Range C2:
Sub fillInDates()
Dim cellEndRange As Range
Dim cellStartRange As Range
Selection.End(xlDown).Select
ActiveCell.Offset(RowOffset:=-1, ColumnOffset:=0).Activate
cellEndRange = ActiveCell
Selection.End(xlUp).Select
cellStartRange = ActiveCell
cellStartRange.AutoFill Destination:=cellStartRange & cellEndRange
This can be done without VBA code.
select column C
hit F5 or Ctrl-G to open the Go To dialog
click Special
tick Blanks and hit OK
now all blank cells are selected. Without changing the selection, type a = character
hit the up arrow to reference the cell above the current cell
type +1 to add one day to the date from the cell above
hold down the Ctrl key and hit Enter.
Now that formula is in all the cells that were previously blank. You can use copy/Paste Values to replace the formula with the values it calculated.
Try, you can work with below.
Sub test()
Dim Ws As Worksheet
Dim vDB As Variant
Dim rngDB As Range
Dim myDate As Date
Dim i As Long
Set Ws = ActiveSheet
With Ws
Set rngDB = .Range("c2", .Range("c" & Rows.Count).End(xlUp))
End With
vDB = rngDB
For i = 1 To UBound(vDB, 1)
If vDB(i, 1) = "" Then
myDate = myDate + 1
vDB(i, 1) = myDate
Else
myDate = vDB(i, 1)
End If
Next i
rngDB = vDB
End Sub

How do I Cut a range from one worksheet to Paste to a second and make sure future lines go to the next blank row?

Two questions:
1) I have a spreadsheet (TC) that has data on one page that will be updated daily. There are 28 columns. Essentially I am looking to have the line (row) data cut and paste into a second spreadsheet (Archive) when Col. 28 has a value entered in it. I have the base coding but for some reason it causes Excel to be non-responsive.
I think it might be because the coding goes cell by cell rather than row by row. Can anyone point me in the right direction? (Again, keep in mind, this is a snippet of the coding - I have each Cut and Paste up to Column 28.)
2) The second part of my question is: Will what I have written make sure that when the Command Button is pressed next time, the data will cut and paste to the next blank line. Thank you!
Private Sub CommandButton1_Click()
a = Worksheets("TC").Cells(Rows.Count, 2).End(xlUp).Row
'Dim rng As Range
'Set rng = Worksheets("Archived").Range("A1")
b = 1
For i = 2 To a
If Worksheets(“TC”).Cells(i, 28).Value <> "" Then
'Change # to be the number column of Pt Name
Worksheets(“TC”).Cells(i, 1).Cut
'Change ,# to be the number column of where you want it pasted.
Worksheets(“TC”).Paste Destination:=Worksheets(“Archive”).Cells(b + 1, 1)
'Change ,# to be the number column of SOC
Worksheets(“TC”).Cells(i, 2).Cut
'Change ,# to be the number column of where you want it pasted.
Worksheets(“TC”).Paste Destination:=Worksheets(“Archive”).Cells(b + 1, 2)
b = b + 1
End If
Next
Application.CutCopyMode = False
ThisWorkbook.Worksheets(“TC”).Cells(1, 1).Select
End Sub
You can do something like this:
Private Sub CommandButton1_Click()
Dim i as long, b As Long, shtTC as worksheet, shtArch as worksheet
Set shtTC = Worksheets("TC")
Set shtArch = Worksheets("Archive")
'find the first empty row
b = shtArch.Cells(Rows.Count, 2).End(xlUp).Row + 1 'pick a column which will always be populated
For i = 2 To shtTC.Cells(Rows.Count, 2).End(xlUp).Row
If shtTC.Cells(i, 28).Value <> "" Then
'cut the row
shtTc.Cells(i, 1).Resize(1, 28).Cut shtArch.Cells(b, 1)
b = b + 1
End If
Next
Application.CutCopyMode = False
shtTC.Cells(1, 1).Select
End Sub
Here's an example of how to create the kind of copy results you're looking for. Notice that, unless you specifically want to copy/paste all of the formatting with the data, you don't need to use copy/paste. You can perform the copy by assigning the values of the ranges.
Option Explicit
Private Sub CommandButton1_Click()
CopyData ThisWorkbook.Sheets("TC"), ThisWorkbook.Sheets("Archived")
End Sub
Public Sub CopyData(ByRef source As Worksheet, _
ByRef dest As Worksheet, _
Optional ByVal deleteSource As Boolean = False)
'--- calculate and create the source data range
Const TOTAL_COLUMNS As Long = 1
Dim srcRange As Range
Dim lastRow As Long
With source
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
Set srcRange = .Range("A1").Resize(lastRow, TOTAL_COLUMNS)
End With
'--- determine where the data should go
Dim destRange As Range
With dest
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
If lastRow > 1 Then lastRow = lastRow + 1
Set destRange = .Cells(lastRow, 1)
Set destRange = destRange.Resize(srcRange.Rows.Count, TOTAL_COLUMNS)
End With
'--- now copy the data
destRange.Value = srcRange.Value
'--- optionally delete the source data
If deleteSource Then
srcRange.Clear
End If
End Sub

Copying a formula down through x number of rows

I'm at a loss on this and need some help. I've lurked around at answers and have Frankensteined together some code for a macro but it just isn't working.
Here is part of what I have so far:
With ActiveSheet
Firstrow = 1
Lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
For lrow = Lastrow To Firstrow Step -1
With .Cells(lrow, "G")
Range("G1").Select
ActiveCell.FormulaR1C1 = "=IF(ISNUMBER(RC[1]),RC[1],RC[-1])"
End With
Next lrow
End With
I have a very similar block of code before this that deletes crap from the text files I'm importing and it works perfectly through all the number of rows. When I run the same thing with this formula, it only puts the formula in G1 and doesn't cycle through the rest of the sheet. I've tried this and it works, but copies down through all million plus rows:
ActiveCell.FormulaR1C1 = "=IF(ISNUMBER(RC[1]),RC[1],RC[-1])"
Selection.AutoFill Destination:=Range("G:G")
I've tried this and then run the same code that gets rid of the text file crap but I get an error "End If without block If".
To fill the formula in one cell at a time you need to cycle through them; don't keep relying on the ActiveCell property.
With ActiveSheet
Firstrow = 1
Lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
For lrow = Lastrow To Firstrow Step -1
.Cells(lrow, "G").FormulaR1C1 = "=IF(ISNUMBER(RC[1]),RC[1],RC[-1])"
Next lrow
End With
But you can speed things up by putting the formula into all of the cells at once.
With ActiveSheet
Firstrow = 1
Lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
With .Range(.Cells(Firstrow, "G"), .Cells(Lastrow, "G"))
.FormulaR1C1 = "=IF(ISNUMBER(RC[1]),RC[1],RC[-1])"
End With
End With
See How to avoid using Select in Excel VBA macros for more methods on getting away from relying on select and activate to accomplish your goals.
Another version, to dynamically select the columns based on their titles. Comments included.
Dim row As Range
Dim cell As Range
Static value As Integer
'Set row numbers
'Find the starting row. Located using Title of column "Start" plus whatever number of rows.
Dim RowStart As Long
Set FindRow = Range("A:A").Find(What:="Start", LookIn:=xlValues)
RowStart = FindRow.row + 1
'End of the range. Located using a "finished" cell
Dim RowFinish As Long
Set FindRow = Range("A:A").Find(What:="Finished", LookIn:=xlValues)
RowFinish = FindRow.row - 1
'Set range - Goes Cells(Rownumber, Columnnumber)
'Simply ammend RowStart and RowFinish to change which rows you want.
' In your case you need to change the second column number to paste in horizontally.
Set rng = Range(Cells(RowStart, 1), Cells(RowFinish, 1))
'Start the counter from the starting row.
value = RowStart
For Each row In rng.Rows
For Each cell In row.Cells
'Insert relevant formula into each cell in range.
cell.Formula = _
"=IF(ISNUMBER(RC[1]),RC[1],RC[-1])"
'Increment row variable.
value = value + 1
Next cell
Next row

Resources