How to autofill formula for known number of columns but variable number of rows in excel macro - vba

I writing a macro within which I need to autofill some rows with formulas, across multiple columns.
The number of columns is fixed, but each time the macro runs, the number of rows is variable. I use the "record macro" function and the current macro only ever fills my rows to row 16. Below is the code:
Range("D3:P3").Select
Selection.AutoFill Destination:=Range("D3:P16")
I obviously need to change the "P16" to something dynamic.
I have tried to use the following:
Dim LR As Long
LR = Range("D3:P3" & Rows.Count).End(xlUp).Row
Range("B3:P3").AutoFill Destination:=Range("B3:P" & LR)
I am unsure whether the "Dim LR as Long" has to be placed at the very beginning of my macro - or can it just be placed anywhere?
I am getting an error anyway with what i attempted above giving me an "autofill selectio error" (sorry i cant remember the exact error message.
Would someone be able to point me in the right direction?

LR can be declared anywhere before where you first use it, but it's best to do it at the beginning. Your range for LR is incorrect.
LR = Range("D3:P3" & Rows.Count).End(xlUp).Row
Should be
LR = Range("D3:P3").End(xlUp).Row
You should use xlDown if you are trying to find the end of a range BELOW D3:P3
LR = Range("D3:P3").End(xlDown).Row
Would give you the last row with data in all columns D:P in it below D3:P3

I think you're looking for this:
LR = Range("D3:P" & Rows.Count).End(xlUp).Row
but note that this finds the last row with any content in Column D - if there are later rows with content in Cols E-P but not in Col D then those rows will be ignored.

So I used the information provided to me and managed to get the following:
Dim LR As Long
LR = Range("C3:P" & Rows.Count).End(xlDown).Row
Range("D3:P3").AutoFill Destination:=Range("D3:P" & LR)
ActiveSheet.ListObjects.Add(xlSrcRange, Range("$D$2:P" & LR), , xlYes).Name = _
"Table10"
This allowed me to count the number of rows that had already been populated in column "C", and then take the formulas that already existed in cells D3:P3 and autofill them down through the range until the last populated row of column C.
I then used that structure to make the whole range a table, in this case named "Table10".
Great stuff guys - your help allowed me to get exactly what I wanted. Thanks

Related

Excel VBA: Formula Syntax to refer to Worksheet Index Number (Relative Instead of Name)

I am working on a macro that will filter a database (updated daily) and compute specific formulas. Each time the macro is ran, a new sheet (uniquely named) will be created with the filtered information, and the calculations will be performed on an additional sheet.
I am having trouble creating a macro with the correct syntax. Each time the macro is run, the filtered data I need to reference is located on worksheet #3 (uniquely named). I'm new to VBA and don't understand the syntax I need to reference the worksheet(index) as the worksheet in an R1C1 formula. Right now, my code looks like this:
Dim LR As Long
LR = Worksheets(3).Cells(Rows.Count, 1).End(x1Up).Row
Range("G6").Select
ActiveCell.FormulaR1C1 = _
"=COUNTIF(='Worksheets(3)'!R6C5:R" & LR &"C5,R[-1]C"
The code is counting if a column of Years (of a variable length) is equal to R[-1]C, which is a cell that contains a certain year, and will display the count in cell G6.
Is it possible to use a worksheet(index) reference in this context? How else could I accomplish the task of referencing a worksheet without name? Would I need to reference a "name" variable?
You had an extra = sign in there and you seem to be missing a closing bracket but .Address external:=true produces a nice range reference.
Dim LR As Long, str as string
with Worksheets(3)
LR = .Cells(Rows.Count, 1).End(xlUp).Row
str = .range(.cells(6, 5), .cells(lr, 5)).address(external:=true, ReferenceStyle:=xlR1C1)
end with
Range("G6").FormulaR1C1 = _
"=COUNTIF(" & str & ", R[-1]C)"

Simplifying complex excel formula with VBA

I have a macro that is generally slow due to overuse of LOOKUP formulas. I want to insert some VBA variables to speed these up. I am currently working on speeding up the formula below:in Excel:
=IF(ISNA(MATCH(A2,Summary!B:B,0)),"n",I2-((I2/LOOKUP(2,1/(I:I<>""),I:I))*VLOOKUP(A2,Summary!$G$10:$H$902,2,FALSE)))
in VBA:
"=IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-((RC[-1]/LOOKUP(2,1/(C[-1]<>""""),C[-1]))*VLOOKUP(RC[-9],Summary!R10C7:R902C8,2,FALSE)))"
The portion I need to replace is LOOKUP(2,1/(C[-1]<>""""),C[-1]). All this does is reference the last non empty cell in column I. Right now I have the following code to return the address of the last cell in VBA
Sub FormulaTest()
Set lRow = Range("I1").SpecialCells(xlCellTypeLastCell).Address
End Sub
I am trying to figure out how to implement this "lRow" into the VBA code for the formula. Can anyone steer me in the right direction?
**EDIT 1
Please see Fernando's comment below. He has the right idea however the solution is still off a bit. Ill try to explain it better in a few comments: First off, The first row is always a title row, the last row is always a sum row, the current tab is the "Sales" tab, and the amount of rows in any given Sales tab will vary (could be I1:I59, could be I:1:I323).
In this example I1 is a row title and I59 is the sum of I2:I58. Rows I2:I58 are dollar amounts. My macro places this formula in J2:J58. This formula takes each row's dollar amount (I2:I58) as a percentage of the total (I59) and multiplies it by an input amount on the Summary tab (the VLOOKUP). This amount is then subtracted proportionately from the dollar value in column I with the J cell showing the result.
I am looking to eliminate the need for the LOOKUP function (selects last non empty cell) within my formula above: LOOKUP(2,1/(C[-1]<>""""),C[-1]).
**EDIT 2
Fernando's solution worked. Thank you all for your input
This would return the last non-empty row in column I
with Worksheets("Summary")
lRow = .Cells(.Rows.Count, "I").End(xlUp).Row
end with
So your code would be
sub testy
dim lRow as long
with Worksheets("Summary")
lRow = .Cells(.Rows.Count, "I").End(xlUp).Row
end with
"=IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-_
((RC[-1]/R"&lRow&"C[-1])*VLOOKUP(RC[-9],Summary!R10C7:R902C8,2,FALSE)))"
In your solution you're using xlCellTypeLastCell. This is very useful, but it calculates based on UsedRange, which may not be what you want. with this, if you have data up to row n and then you update the data and now you have less records, the last row with xlCellTypeLastCell will still be n, so be careful with that.
Assuming that you are doing all your work on the active sheet, looking up to a "Summary" sheet:
Sub fillCol()
Dim aRow As Long, bRow As Long
aRow = Cells(Rows.Count, "I").End(xlUp).Row
bRow = Sheets("Summary").Cells(Rows.Count, "I").End(xlUp).Row
Range("J2:J" & aRow).FormulaR1C1 = "=IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-" _
& "((RC[-1]/" & aRow & ")*VLOOKUP(RC[-9],Summary!R10C7:R" & bRow & "C8,2,FALSE)))"
End Sub
You made need to change the columns which contain the contiguous range (in order to determine the last row)

How to get VLOOKUP to select down to the lowest row in VBA?

Looking to automate the insertion of a VLOOKUP formula in a cell.
When recording the macro I instruct it to populate the columns below with the same formula. Works great, however, there is an issue when the table that the VLOOKUP searches through changes (more or less rows).
As it's recorded, the VLOOKUP drops down to the final row in the table (273). However, I want to set it up so that it will go down to the very last row. Meaning that I can run the script on tables of varying numbers of rows.
Selected columns will remain the same.
Range("AJ2").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[-20], Previous!R2C2:R273C22,17,FALSE)"
try this:
With Worksheets("Previous")
Range("AJ2").FormulaR1C1 = _
"=VLOOKUP(RC[-20], Previous!R2C2:R" & .Cells(.Rows.Count, 2).End(xlUp).Row & "C22,17,FALSE)"
End With
where:
Range("AJ2")
will implicitly reference the ActiveSheet
.Cells(.Rows.Count, 2).End(xlUp).Row
will reference "Previous" worksheet, being inside a With Worksheets("Previous")- End With block
#nbayly said it, plenty of posts on this. Infact i have provided an answer to this before here:
How to Replace RC Formula Value with Variable
below is slightly modified for a dynamic range, which is what i believe you are looking for
For j = n To 10 Step -1
If Cells(j, 1).Value = "" Then
Cells(j, 1).Formula = "=VLookup(RC20,Previous!R2C2:R273C22,17,FALSE)"
End If
Next j
remember to define j as long and n=sheets("sheetname)".cells(rows.count,1).end(xlup).row
replace 10 in j = n to 10 with the starting row number

Macro to create dynamic range with variable rows and columns

Very simple scenario: One spreadsheet where the columns and rows will change every time I update it; the spreadsheet will always begin on A1.
Here is the code I have now that is not working:
Dim LR As Long
LR = Range("A" & Rows.Count).End(xlUp).Row
Range("A1l:BM" & LR).Select
Can you please let me know what needs to be changed so that it will always capture the current region of columns x rows?
Thanks!
If you want to select the entire used range in you sheet, you can simply do it by using:
ActiveSheet.UsedRange.Select

I need a VBA code to count the number rows, which varies from ss to ss, return that number and copy and paste that row and all other columns

I have vba question I have been trying to find the answer for for a long time. I have numerous spreadsheets from numerous clients that I run macro's on, I'm new to coding and have been able to mostly figure out what I need to do. My clients send us data monthly and every month the number of rows change. The columns don't change but the amount of data does. My previous macro's I have just chosen the entire column to copy and paste onto our companies template. This worked fine for must things but has created some really long code and macros take a long time. I would like to write a code that counts how many rows are in a certain column and then from there copies and pastes that however many rows it counted in each column. Only a few columns contain data in every row, so I need it to count the rows in one specific column and apply to that every column. Any help would be appreciated.
Thanks
Tony
Hi Guys,
Still having issues with this, below I pasted the code I'm using if anyone can see why it won't run please help.
Windows("mmuworking2.xlsx").Activate
Workbooks.Open Filename:= _
"C:\Users\I53014\Desktop\QC DOCS\Sample_Data_Import_Template.xlsx"
Windows("mmuworking2.xlsx").Activate
Dim COL As Integer
COL = Range("A:DB").Columns.Select
**Range(Cells(2, COL), Cells(Range("E" & Rows.Count).End(xlUp).Row, COL)).Copy Destination:=Windows("Sample_Data_Import_Template.xlsx").Range("A2")**
Range("A2").Paste
Range("A5000").Formula = "='C:\Users\I53014\Desktop\[Import_Creator.xlsm]sheet1'!$B$2"
ActiveWorkbook.SaveAs Filename:="Range (A5000)", _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
I bolded where it keeps stopping.
This should give you the last row containing data:
ActiveSheet.UsedRange.Rows.Count
This will give you the last row in a specific column:
Range("B" & Rows.Count).End(xlUp).Row
here is an example of how I can copy every row in the first three columns of a worksheet
Sub Example()
Dim LastRow As Long
LastRow = ActiveSheet.UsedRange.Rows.Count
Range(Cells(1, 1), Cells(LastRow, 3)).Copy Destination:=Sheet2.Range("A1")
End Sub
You have to be careful as there are some caveats to both methods.
ActiveSheet.UsedRange may include cells that do not have any data if the cells were not cleaned up properly.
Range("A" & Rows.Count).End(xlUp).Row will only return the number of rows in the specified column.
Rows(Rows.Count).End(xlUp).Row will only return the number of rows in the first column.
Edit Added an example
Edit2 Changed the example to be a bit more clear
For this example lets say we have this data
You could copy any other column down to the number of rows in column A using this method:
Sub Example()
Dim Col as Integer
Col = Columns("C:C").Column
'This would copy all data from C1 to C5
'Cells(1, Col) = Cell C1, because C1 is row 1 column 3
Range(Cells(1, Col), Cells(Range("A" & Rows.Count).End(xlUp).Row, Col)).Copy Destination:=Sheet2.Range("A1")
End Sub
The end result would be this: