How to Dynamically Autofill Cells - excel

I would like to dynamically fill a column. However, with the VBA code I have now, the formula fills all the way to the max row count (1.04 million). I would like it to stop at the max rows found in the column to its left (same as manual auto fill)
Sub Vlookup()
Range("C2").Select
ActiveCell.FormulaR1C1 =
"=IFERROR(VLOOKUP(RC[-2],'C:\Test.xlsx'!R2C6:R1000C15,10,FALSE),"""")"
Selection.AutoFill Destination:=Range("C2", Range("C2").End(xlDown))
End Sub
I tried to use
Selection.Autofill Destination :=
Range("C2",Selection.Range("C2").End(xldown))
But that didnt seem to work either

You always want to use Long when finding the last row. Integers only go to 32,767 and there are over 1 million rows. You should also avoid using Select.
Dim lastRow as Long
lastRow=Cells(Rows.Count,2).End(xlup).Row
Range("C2").AutoFill Destination:=Range("C2:C" & lastRow)

first you can get the last row coming from column B and use that as reference for auto fill. see my example below.
Dim lastRow As Integer
Range("B1").Select
Selection.End(xlDown).Select
lastRow = Selection.Row
Range("C2").Select
Selection.AutoFill Destination:=Range("C2:C" & lastRow)

Related

How can I use VBA to create an =AVERAGE formula in a dynamic cell with a dynamic range?

I'm trying to write a Sub that will allow me to replace a formula for every time the macro is run.
I'm able to select the range I want using:
Range("A3").Select
Selection.End(xlDown).Select
Range("B5", ActiveCell.Offset(-1, 1)).Select
And I'm able to find the cell in which I want the formula using:
Range("A3").Select
Selection.End(xlDown).Select
ActiveCell.Offset(2, 1).Activate
Is there a way I can make a formula that says =AVERAGE([selected range])?
Note: I do not want to just have the value in the cell. I need to have it so there is an active formula showing the results.
It would seem you are trying to do something like this:
Dim lrows As Long
lrows = Range("A3").End(xlDown).Row - 1
Range("A" & lrows + 1).Formula = "=AVERAGE(B5:B" & lrows & ")"
You should avoid using SELECTing and ACTIVATEing cells in your code, it slows it down and makes it less reliable.
You can also use the formula. worksheetfunction.Average("Select range")

Recorded Excel macro with countIf function with lastrow

My problem is following. I am recording macro for for sheet that´s range is dynamic.
The formula is =CountIF(A:A;A2) and recorded it:
Range("M2").Select
ActiveCell.FormulaR1C1 = "=COUNTIF(C[-12],RC[-12])"
Range("M2").Select
Selection.AutoFill Destination:=Range("M2:M4333"), Type:=xlFillDefault
Range("M2:M4333").Select
Since the rows are dynamic, I want to end every formula to the lastrow. And I searched here for answer and copied this fuction to the beginning of the macro.
Function GetLastRow(sht As Worksheet, col As String) As Integer
GetLastRow = sht.Range(col & CStr(sht.Rows.Count)).End(xlUp).row
Now I am trying to call this to the orginal recorded macro
Range("M2").Select
Range(Selection, Selection.End(xlDown)).Select
Formula1 = "=COUNTIF(A:A" & GetLastRow(Sheets("Sheet1"), "A") & ",A2))"
I changed it looking like the formula that is copied in worksheet and not like it´s recorded. I would appreciate some help to this. It would be better if the lastrow function is used with recorded formula since I have lots other formulas to come with same problem.
You want to fill column M from row 2 down to the row in column M that meets the last populated cell in column A. Use the Range.Offset property and Range.Address property to get the correct address to use in the COUNTIF function.
With Worksheets("Sheet1") 'you should know what worksheet you are on!
With .Range("M2:M" & .Cells(.Rows.Count, "A").End(xlUp).Row)
.FormulaR1C1 = "=COUNTIF(" & .Offset(0, -12).Address(ReferenceStyle:=xlR1C1) & ", RC1)"
End With
End With
        

Trouble with an Excel VBScript, Referencing A Relational Cell Address

Okay, I'm learning scripting for Excel and I've come across something that I just don't know how to do.
I've been asked to help automate the import of a sheet into a sheet and then add some columns off to the side and do some calculations and autofill them to the last row of the imported info. That is no problem. I recently found out however that the sheet that I would import for my office has X number of columns and other offices have Y and Z number of columns in the sheets that they would import. So I'm trying to do this to where it builds the calculation columns at the end of the imported columns. With that bit of background here's where I need some assistance:
Script as written for my office and works:
Range("O1").Select
ActiveCell.FormulaR1C1 = "Remainder"
Range("O2").Select
ActiveCell.FormulaR1C1 = "=MOD(RC[-14],RC[-5])"
Range("O2").Select
Range("O2").AutoFill Destination:=Range("O2:O" & Cells(Rows.Count, "B").End(xlUp).Row)
So now I need to make this relational not Cell Address Specific So I came up with this.
Range("A1").select
Selection.End(xlToRight).Select
ActiveCell.Offset(0, 1).Select
ActiveCell.FormulaR1C1 = "Threshold"
ActiveCell.Offset(1, 0).Select
ActiveCell.FormulaR1C1 = "=IF(RC[-13]>(RC[-5]/3),""Over"",""Under"")"
Range(ActiveCell.Address).AutoFill Destination:=Range(*****How to return the Current Cell Address** : **How to Return the Current Column Letter***** & Cells(Rows.Count, "B").End(xlUp).Row)
I've Tried "ActiveCell.Address":"CHAR(COLUMN()+64))" but That doesn't work and I Just don't know how to get it to set that value to Be the equivalent ?2:? my office running this should autofill from O2:O. But would return P2:P in another.
I'm assuming you want the formula to go in the 1st unused column, no matter how many columns there are. (This will allow for future column use, as well.)
Dim LastCol as integer
LastCol = Cells(1, Columns.Count).End(xlToLeft).Column + 1
Cells(1, LastCol).FormulaR1C1 = "Remainder"
Cells(2, LastCol).FormulaR1C1 = "=MOD(RC[-14],RC[-5])"
Cells(2, LastCol).AutoFill Destination:=Range(Cells(2, LastCol), _
Cells(Cells(Rows.Count, "B").End(xlUp).Row, LastCol))
How's this:
Sub test()
Dim lastCol As Integer, lastRow As Integer, formulaCol As Integer
Dim ws As Worksheet
Set ws = ActiveSheet
' First, let's find the last column (#) and last row (#)
With ws.UsedRange
lastCol = .Columns.Count
lastRow = .Rows.Count
End With
' Now, create the "header, two columns offset from last column"
formulaCol = lastCol + 2
Cells(1, formulaCol).Value = "Remainder"
'Now, let's create a range, that we will fill with the MOD() formula. You can do this _
through resizing a range, instead of selecting and autofill
With ws
.Range(.Cells(2, formulaCol), .Cells(2, formulaCol)).Resize(lastRow - 1, 1).FormulaR1C1 = _
"=IF(RC[-" & formulaCol - 1 & "]>(RC[-2]/3),""Over"",""Under"")"
End With
End Sub
I am assuming a few things: Your raw sheets come with the data in one block. In other words, you don't have a gap of columns between data you need. This will get the last used column and row, and use those to enter your formula.
Also, I assume that you are checking that the first part of your mod() formula refers to the info in Col. A, and the second part is the right most column's data. I think I'm not understanding something, so any more info. about how the data is laid out would be helpful. But also, this avoids using "Select", which is good VBA practice from what I've gathered.

How do I AutoFill down in one column, using the row count of another column?

I am trying to produce some code that will use the AutoFill Down function. I would like to fill Column B with the typical 1,2,3,4, etc. as long as there is text/values in the respective rows of Column A. Right now, my code is hardwired to fill down to cell B50 no matter what, but I don't want it to paste that far down if Column A only has data through cell A7, for example. Ideally, I would like to use the following variable -- rownum = Range("A1").End(xlDown).Row -- to count the number of cells in Column A that have text/values, and use that to replace "B50" in the row designation below. Just not sure of the appropriate syntax to make that happen. Here is the code I have so far.
ActiveCell.FormulaR1C1 = "1"
Range("B2").Select
ActiveCell.FormulaR1C1 = "2"
Range("A1").Select
Range("B1:B2").Select
Selection.AutoFill Destination:=Range("B1:B50"), Type:=xlFillDefault
Thanks in advance to anyone who helps me out! I am a new user of both Macros and VBA Code, and the amount of knowledge that so many of you have amazes me!
Econ
You're much better off if you don't select anything in your code. If you just want to number the rows in column B based on the contents of column A, this will do the trick:
Sub NumberColumn()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
' get the last row from column A that has a value
lastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
' use the last row to determine how far down to extend the formula
ws.Range("B1:B" & lastRow).Formula = "=row()"
End Sub
Pretty simple option to use without the need for a string:
Selection.AutoFill Destination:=Range("A2:A" & Cells(Rows.Count, "B").End(xlUp).Row)
Same goes for copying the number of rows in a column:
Range("A2:A" & Cells(Rows.Count, "B").End(xlUp).Row).Select
Selection.Copy

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