Formula Auto Fill VBA - excel

I managed to get this to work, but the problem is I have to specify the range (in this case I just hard coded C2:c25 and the file will have different row counts every time.
Is there a way to make this run only for the rows that have data?
Sub addFormulas()
ThisWorkbook.Worksheets("Sheet2").Range("C2").Formula = "=(B2/12)*100"
Range("C2").Select
Selection.AutoFill Destination:=Range("C2:C25")
End Sub

You could use xlDown to find your last row number based on column B, so you won't have to change your code next time.
Sub addFormulas()
ThisWorkbook.Worksheets("Sheet2").Range("C2").Formula = "=(B2/12)*100"
Range("C2").Select
'find last row with value
last_row = Range("B2").End(xlDown).Row
Selection.AutoFill Destination:=Range("C2:C" & last_row)
End Sub
But I'm assuming that column B doesn't have blank cells between values. In case column B may have blank cells, you could run a FOR loop to find the last row. It's a lot less efficient, but it works well as long as you don't have a very large number of rows:
Sub addFormulas2()
ThisWorkbook.Worksheets("Sheet2").Range("C2").Formula = "=(B2/12)*100"
Range("C2").Select
For i = 1 To 20
If Range("B" & i) & "" > "" Then last_row = i
Next i
Selection.AutoFill Destination:=Range("C2:C" & last_row)
End Sub
EDIT: Just learned here that using xlUp ir more efficient than FOR and more reliable than xlDown, since it won't have any problems if there's some blank cell in column B:
Sub addFormulas_()
ThisWorkbook.Worksheets("Sheet2").Range("C2").Formula = "=(B2/12)*100"
Range("C2").Select
With Sheets("Sheet2")
last_row = .Range("B" & .Rows.Count).End(xlUp).Row
End With
Selection.AutoFill Destination:=Range("C2:C" & last_row)
End Sub

You can accomplish your task without using AutoFill or Select. It is better to use a With … End With statement. Comments are provide in the code below.
Sub addFormulas()
With ThisWorkbook.Worksheets("Sheet2") 'used to set the focus on the worksheet object
.Cells(2, 3).Resize(.Cells(.Rows.Count, 2).End(xlUp).Row - 1).Formula = "=(B2/12)*100"
'writes the formula in the variable range in column C
'Breakdown...
'the "." (dot) e.g. (.Cells and .Rows) is used to refer to the worksheet object in the With statement
'".Cells(2, 3)" is the start of the range you want to write the formula
'".Resize(.Cells(.Rows.Count, 2).End(xlUp).Row")expands the range to the last use row in column B
'the "- 1" adjusts your range because you started on row 2
End With
End Sub

Related

Excel VBA Moving Row Values [Only] from one Sheet to another - Current code is working, just needs tweaking

This is currently the setup that I have found helpful and have modified to work well... However, I'm struggling with one small further and final modification. I would like to just - Paste Values as opposed to the Formulas.
Sub move_rows_to_another_sheet()
'
Sheets("User").Select
Columns("A:Y").Select
Range("A:Y").Activate
'
For Each myCell In Selection.Columns(25).Cells
If myCell.Value = "Closed" Then
myCell.EntireRow.Copy Worksheets("Archive").Range("A" & Rows.Count).End(3)(2)
myCell.EntireRow.Delete
End If
Next
'
Range("A2").Select
End Sub
''Updated Version - Move Single Rows
'
Sub move_rows_to_another_sheet()
'
Sheets("Users").Select
Columns("A:Y").Select
Range("A:Y").Activate
'
For Each mycell In Selection.Columns(25).Cells
'
If mycell.Value = "Closed" Then
mycell.EntireRow.Copy
Worksheets("Archive").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValuesAndNumberFormats
mycell.EntireRow.Delete
End If
Next
'
Range("A2").Select
End Sub
The idea is simple... The current code is successful, however, I would like to just copy and paste the [values] of the rows cell content and [not] the formulas etc. The formatting is fine and everything, I just need the result of the functioning formulas recorded.
I have tried various options such as [myCell.EntireRow.CopyValues] even [& Rows.Count & Rows.PasteSpecial]... Any thoughts?
Thanks in advance
I tried your code. It looks like when there are several cells with "closed" it will not work for all. because when one deletes, one should delete from below upwards.
But then the data in Archive is not in right order.
In your original code you can make the range smaller, so it will run faster.
or take what you want from this code:
Sub move_rows_to_another_sheet2()
Dim mycell As Range
Dim checkClosed
Dim Lastrow As Long
Dim i As Long
Set checkClosed = ThisWorkbook.Worksheets("User").Range("Y1:Y10000")
Lastrow = Worksheets("Archive").Cells(Rows.Count, 1).End(xlUp).Row + 1 'one cell below last used cell in column A
For i = 10000 To 1 Step -1 'from row 10000 to row 1
Set mycell = ThisWorkbook.Worksheets("User").Cells(i, "Y")
If LCase(mycell.Value) = "closed" Then 'checks for Closed and closed
mycell.EntireRow.Copy
Worksheets("Archive").Range("A" & Lastrow).PasteSpecial Paste:=xlPasteValues
mycell.EntireRow.Delete
Lastrow = Lastrow + 1
End If
Next i
'
Range("A2").Select
End Sub

Insert rows by AutoFill using VBA

I want to create a macro which can insert a new row below the last row, containing the same formulas and formatting (not the values) as the rows above. If I do it by hand I would select an entire row and use the AutoFill feature, but this didn't work out when I try to implement it in my macro.
What I basically did is this:
Sub CommandButton1_Click()
Dim lRow As Long
Dim lRsp As Long
On Error Resume Next
Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Select
lRow = Selection.Row() - 1
lRsp = MsgBox("Insert New row above " & lRow & "?", _
vbQuestion + vbYesNo)
If lRsp <> vbYes Then Exit Sub
Rows(lRow).Select
Selection.AutoFill Destination:=Range(lRow, lRow + 1)
End Sub
Thanks in advance!
Insert rows by AutoFill using VBA
why not try to copy the last cell with formula and paste in the range of the new rows.
'Callback for btnRellenarFormulas onAction
Sub btnRellenarFormulas_OnClick()
Sheets("YourSheet").Select ' the sheet you will add rows
'Here add your rows, you current code just to add below will solve the column D problem
Dim nRows As Double, nRowLastFormula As Double
'chose one and remove or comment the other one
nRows = Range("CONFIG_NROWS_DATOS") 'This is a named range with formula counta, which counts the number of rows after add the new rows, in your case the column A
'or you can use the formula in code:
nRows = Application.WorksheetFunction.CountA(Sheets(1).Range("A:A"))
'Remove one or comment
nRowLastFormula = Range("CONFIG_NROWS_FORMULA")'this is a named range with formula counta, which will count the number of rows wiht fomula
'or you can use the formula in code:
'The counta in column D will be less than the countA column A, maybe you will need plus 1 to the nRowLastFormula value: nRowLastFormula=nRowLastFormula +1
nRowLastFormula = Application.WorksheetFunction.CountA(Sheets(1).Range("D:D"))
'Column A
Range("A" & nRowLastFormula).Select
Selection.Copy
Range("A" & nRowLastFormula + 1 & ":A" & nRows).Select
Application.CutCopyMode = False
End Sub
Good Luck

VBA - How to Autofill all the way to the bottom until the last B cell with data

I recorded a macro and I tried to autofill column C with the COUNTIF function all the way down until B column has their last cell value. It doesn't work with new data so I tried to edit the macro and replace it with Range("D2:D") but that doesn't work.
Sub COUNTIF()
'
' COUNTIF Macro
'
'
Range("D2").Select
ActiveCell.FormulaR1C1 = "=COUNTIF(C[-3],RC[-3])>1"
Range("D2").Select
Selection.AutoFill Destination:=Range("D2:D")
End Sub
Better to find the last cell. Also avoid using select as it slows down your code.
Sub COUNTIF()
Dim LastRowB As Long
LastRowB = Range("B" & Rows.Count).End(xlUp).Row
Range("D2").FormulaR1C1 = "=COUNTIF(C[-3],RC[-3])>1"
Range("D2: " & "D" & LastRowB).FillDown
End Sub
Now change your "=COUNTIF(C[-3],RC[-3])>1" formula to whatever it is you really want to fill down.

Column selection to lastrow then resize

I have a code that finds the last row of data in column E and selects the column to that last row. I want to be able to select associated data in columns B through D that goes with column E and then sort based on column B. So I thought I would just find the last row in column E then resize by 3 columns and sort from that selection but I keep getting a run-time error 1004 application-defined or object-defined error. I have provided the code I'm using below. Columns B through D contain data past the end of column E. Thanks!
ws.Range("E1:E" & finalrow).Resize(0, 3).Select
You may not always be starting in the first row (e.g. E1) so lastRow may not be applicable without some maths. In that case, use With ... End With statements to shorten the code while explicitly referencing the correct cell and cell ranges.
dim lastRow as long
with ws
lastRow = .cells(.rows.count, "E").end(xlup).row
'option 1
.range("B5:D" & lastRow).select
'option 2
with .range("E5:E" & lastRow)
.offset(0, -3).resize(.rows.count, 3).select
end with
'option 3
.range("E5", .cells(lastRow, "G")).offset(0, -3).select
end with
See How to avoid using Select in Excel VBA macros for more methods on getting away from relying on Range.Select and Range.Activate to accomplish your goals.
Something like:
Sub SelectLast3Cols()
Dim ws As Worksheet, lrow As Long
Set ws = Sheets("Sheet3")
lrow = ws.Range("E" & ws.Rows.Count).End(xlUp).Row
ws.Range("B1", ws.Range("D" & lrow)).Select
End Sub

Vlookup in Visual Basic: Trying to Set for the reference column that has a variable range

I had a question regarding the code below. If anyone could provide some insight, I would be greatly appreciative. Essentially this is part of a report I'm building to be run on a weekly basis. The issue I'm having is that the reference column K is variable in size of inputs and I hate putting in a constant that results in a bunch of N/A#s (K rows should never exceed 300). I'm sure it's something simple I'm overlooking, but I tried to write something to count K2:Kn and then input it in the Ranges (q2:r2:s2:t2:qrstn). Please share your wisdom =)
Sub Vlookup()
Sheets(2).Select
Range("q2").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC[-6],table,15,FALSE)"
Range("q2").Select
Selection.AutoFill Destination:=Range("q2:q300"), Type:=xlFillDefault
Range("r2").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC[-7],table,16,FALSE)"
Range("r2").Select
Selection.AutoFill Destination:=Range("r2:r300"), Type:=xlFillDefault
Range("s2").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC[-8],table,17,FALSE)"
Range("s2").Select
Selection.AutoFill Destination:=Range("s2:s300"), Type:=xlFillDefault
Range("t2").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC[-9],table,18,FALSE)"
Range("t2").Select
Selection.AutoFill Destination:=Range("t2:t300"), Type:=xlFillDefault
Hope I've understood your question properly
The following will autofill range Q2:QN where N is the last used cell in column Q
Selection.AutoFill Destination:=Range(Range("K2"),Range("K2").End(xlDown)).Offset(ColumnOffset:=6), Type:=xlFillDefault
You could also do it the other way round as you have a fixed maximum.
Selection.AutoFill Destination:=Range(Range("K2"),Range("K301").End(xlUp)).Offset(ColumnOffset:=6), Type:=xlFillDefault
The first looks down the sheet for the last row, and the 2nd looks up the sheet from the maximum to the last row.
You can replace Q with whatever column you need, as you appear do do the same for lots of columns!
Update
I've updated the example, it now finds the used range in the K column and offsets it to your desired column. The value of ColumnOffset will be the same (although positive) as the value used in your R1C1 formulas.
Also, as the K Range should remain constant, and your formulas are fairly predictable you could shorten it a little. like the following (i've not testing it, just playing around)
Sub Vlookup() ' might want to re-name, to avoid confusion with the worksheet function
Dim R As Range
Dim A As Range
Dim I As Integer
Set R = Range(Range("K2"), Range("K301").End(xlUp))
Set A = Range("K2")
For I = 6 To 9
A.Offset(ColumnOffset:=I).FormulaR1C1 = "=VLOOKUP(RC[-" & CStr(I) & "], table, " & CStr(I+9) & ", FALSE)"
A.Offset(ColumnOffset:=I).AutoFill Destination:=R.Offset(I), Type:=xlFillDefault
Next I
End Sub
You don't need to fill down when you use FormulaR1C1. You can apply the formula to the whole range. Here's an example.
Sub MakeVlookup()
Dim lRows As Long, lCols As Long
Dim rCell As Range
Dim rRef As Range
'Set the first cell of the reference column
Set rRef = Sheet1.Range("K2")
'Count the rows of the reference column
lRows = Sheet1.Range(rRef, rRef.End(xlDown)).Rows.Count
'Loop through the row 2 cells where you want the formula
For Each rCell In Sheet1.Range("Q2:T2").Cells
'Compute the offset back to the reference column
lCols = rCell.Column - rRef.Column
'Write the formula to the whole range
rCell.Resize(lRows, 1).FormulaR1C1 = _
"=VLOOKUP(RC[-" & lCols & "],Table1," & rCell.Column - 2 & ",FALSE)"
Next rCell
End Sub
No need to loop or address each column with a different formula!
Instead of these formulas:
Column Q: =VLOOKUP(K2,table,15,FALSE)
Column R: =VLOOKUP(K2,table,16,FALSE)
...
you can simply use =VLOOKUP($K2,table,COLUMN()-2,0) as one formula across all columns! $K2 (in R1C1: RC11) instead of K2 (in R1C1 RC[-6], RC[-7], ...) will keep column K. And COLUMN() will return you the column number of the actual cell, i.e. column Q = 17, R = 18, etc.. (I also replaced FALSE with 0 as this reduces typing for lazy blokes like me but results in the same. :-) ).
Therefore, you can reduce your macro to
Sub MakeVLOOKUP
Sheets(2).Range("Q2:T300").FormulaR1C1 = "=VLOOKUP(RC11,table,COLUMN()-2,0)"
End Sub
and achieve the same result.
If you want to flexibilize the range as in Dick's solution, you can do it like this:
Sub MakeVLOOKUP
Sheets(2).Range("Q2").Resize(Sheet1.Range("K2").End(xlDown)).Rows.Count-1,4).FormulaR1C1 = _
"=VLOOKUP(RC11,table,COLUMN()-2,0)"
End Sub

Resources