I'm trying to get a dynamic range in a recorded macro.
The data in column "O" is variable.
When I used the macro, VBA set it at the range of the specific worksheet.
Is there a way to make the autofill option variable to the amount of rows?
I used this code:
Range("O2").Select
Selection.AutoFill Destination:=Range("O2:O188")
Range("O2:O188").Select
I want the range to be dynamic.
Try the next code, please. It uses column N:N as reference for the number of rows to be filled. No need to select anything:
Sub testAutoFill()
Dim sh As Worksheet, lastRow As Long
Set sh = ActiveSheet
lastRow = sh.Range("N" & Rows.Count).End(xlUp).row
sh.Range("O2").AutoFill Destination:=sh.Range("O2:O" & lastRow)
End Sub
The code can use the maximum rows of the used range, but in such a case, if the value to be filled down is a formula, the referenced column is good to be used. Otherwise, one of the neighbor column.
Related
I'm currently exporting a document (wsCopy) from a software and paste special valuing the data to another excel workbook I'm creating (wsDest). Within (wsDest), I also have two vlookups, columns AI:AJ, which reference the newly created exported data, a "SupportReference" tab, and a "RegionLookup" tab. My issue is that the values in the exported data is formatted weirdly. Even though the exported data format says "General", the vlookups in column AJ are returning #N/A errors. The only ways to fix this problem is if I click on the referenced cells (column AH), which includes the exported data, hit F2, then Enter, or create a vba that will multiply all of the vlookups in column AI by 1. However, I don't want to do the first option since I'll have to do it for ~14000 rows. The issue with the second option is that, multiplying the entire AI column by 1 won't work if the vlookup in column AI returns with any letter; also, it gets rid of the vlookup in column AI. Below is what I came up with:
Sub CopyOver()
Dim wsCopy As Worksheet
Dim wsDest As Worksheet
Dim lCopyLastRow As Long
Dim lDestLastRow As Long
Set wsCopy = Workbooks("Export").Worksheets("Sheet1")
Set wsDest = ThisWorkbook.Worksheets("Data")
'1. Find last used row in the copy range based on data in column A
lCopyLastRow = wsCopy.Cells(wsCopy.Rows.Count, "A").End(xlUp).Row
'2. Find first blank row in the destination range based on data in column A
'Offset property moves down 1 row
lDestLastRow = wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Offset(1).Row
'3. Clear contents of existing data range
wsDest.Range("A9:AH" & lDestLastRow).ClearContents
'4. Copy & Paste Data
wsCopy.Range("A2:AH" & lCopyLastRow).SpecialCells(xlCellTypeVisible).Copy
wsDest.Range("A9").PasteSpecial Paste:=xlPasteValues
'Start copy down formulas
Dim DestLastPopulatedRow As Long
'Find last populated row
DestLastPopulatedRow = wsDest.Range("A" & Rows.Count).End(xlUp).Row
'Select the rows where formula is to be populated
wsDest.Range("AI9: " & "AJ" & DestLastPopulatedRow).FillDown
End Sub
The very last part of the code (wsDest.Range("AI9: " & "AJ" & DestLastPopulatedRow).FillDown) is where I start having issues because the vlookup formula starts in cell AI9. The vlookup formula is as follows:
Column AI Vlookup:
=VLOOKUP(AH9,'SupportReference'!E:E,1,FALSE)
Column AJ Vlookup:
=VLOOKUP(AI9,'RegionLookup'!M:M,1,FALSE)
Attempted VBA code multiplying column AI:
With wsDest.Range("AI9: " & "AI" & DestLastPopulatedRow)
.Value = Evaluate(.Address & "*1")
End With
Let me know if you need more clarification or further data.
Thank you.
If you don't need the VLOOKUP functions to be active, which I expect to be the case because you are copying a large block of data in, you can use VBA to set the value of the lookup cells instead of a function. Here's a sub-procedure where you pass it a destination cell and other lookup parameters, and the VBA finds the value and puts it in the destination cell:
Sub exact_lookup(destination As Range, lookup_value As Variant, lookup_table As Range, column As Integer)
Dim foundCell As Range
Set foundCell = lookup_table.Columns(1).Find(lookup_value, , , xlWhole)
If foundCell Is Nothing Then
destination.Value = CVErr(xlErrNA)
Else
destination.Value = foundCell.Offset(0, column - 1).Value
End If
End Sub
Then write a loop to fill the value of each cell where your current approach uses lookup formulas. An example call is:
exact_lookup wsDest.range("AI9"), wsDest.range("AH9").value, worksheets("RegionLookup").range("E:E"), 1
Note: I'm not entirely sure I understand just what you doing, but hopefully this approach will work this is enough to get headed in the right direction.
I want to stop a vlookup from working after it has filled the appropriate cell with data.
Column B will contain stock figures from a material that is typed into column A.
The stock will be constantly changing.
Once a cell has been filled with data from a vlookup I want it to stay that way.
I do not want it to refresh as the stock figures refresh as they were the figures relevant at that time.
Within VBA, as #Steven Pomponio mentioned, you may set the value equal to what the value already is. That means that if a formula has been calculated and returned a result (or error for that matter), the result replaces the formula in the given cell.
Sub SetValues()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
With ws
fRow = .Cells(.Rows.Count, 2).End(xlUp).Row
End With
ws.Range("B1:B" & fRow).Value = ws.Range("B1:B" & fRow).Value
End Sub
I would assign this to a Private Sub Worksheet_Activate()-event or a Private Sub Workbook_Open()-event.
Above code will also take into account the amount of rows you have in your B-column.
So first of all, I wanna write a VBA Code, which allows me to pick a certain range of an Excel sheet, to then copy SOME of the needed values to another worksheet. The issue with this is, that in the Excel sheet of which i take Information from, has some filters applied.
So i found the solution with the method (?) .SpecialCells(xlCellTypeVisible) but the Problem again is, that it works for 1 column, but not for Ranges with more than one column. For Ranges with more than one column, it only picks the first row
Dim rng As Range
Set rng = src.Worksheets("l04").Range(src.Worksheets("l04").Range("Z7:AK7"), src.Worksheets("l04").Range("Z7:AK7").End(xlDown)).SpecialCells(xlCellTypeVisible)
My expected result from this Line of Code should be, that the Range rng is set from Z7 to AK7 all the way down to the maximum number of rows, but only those which are visible.
Edit1: Changed SpecialCell --> SpecialCells
Dim cell As Range
Dim lastRow As Long
With src.Worksheets("104")
lastRow = .Cells(.Rows.Count, "Z").End(xlUp).row
With .Range("Z7:AK" & lastRow)
For Each cell In .Columns(1).SpecialCells(xlCellTypeVisible)
Debug.Print Intersect(.Cells, cell.EntireRow).Address ' change this to what you actually need to grab from each visible cell
Next
End With
End With
Based on some clues in your question, you may find that using the Intersect Method is advantageous.
Dim rng as Range
With src.Worksheets("l04")
'gets all visible cells within the used range on your sheet
set rng = .UsedRange.SpecialCells(xlCellTypeVisible)
'Use the Intersect method to select specific columns
set rng = Intersect(rng, .range("AB:AB, AD:AD"))
End With
Note: This will not select down to last row (i.e. row 1,048,576), only to the last row with data in the specified range.
What's the neatest way of applying Autofill if the ROW count is more than 1?
I use the below line and it's working. However, if there's an instance where there is only 1 count ROW in column "I", there will be an error.
Sheets(1).Range("J2").AutoFill Destination:=Range("J2:J" & Cells(Rows.Count, "I").End(xlUp).Row)
You need to explicitly reference the Range.Parent worksheet property for all Range object and Range.Cells properties. You cannot rely on the implicit reference to the ActiveSheet property.
with Sheets(1)
.Range("J2").AutoFill Destination:=.Range("J2:J" & .Cells(Rows.Count, "I").End(xlUp).Row)
end with
You might find the Range.FillDown method easier to code.
with Sheets(1)
.Range("J2:J" & .Cells(Rows.Count, "I").End(xlUp).Row).FillDown
end with
The With ... End With statement passes the parent worksheet reference to all .Range and .Cells that have the prefix period (aka full stop or .).
I have used copy and paste method to do autofill function.
You can use paste special as values or formula as per yourrequirement. It is another way of doing auto fill
Sub test11()
Dim L As Long
L = Sheets(1).Range("J1:J" & Sheets(1).Cells(Sheets(1).Rows.Count, "J").End(xlUp).Row).Count
With Sheets("Sheet1")
.Range("J1").Copy
' Change Range as per your requirement and paste function as per your requirement
.Range("J2:J" & L).PasteSpecial xlValues
End With
End Sub
In Excel 2013, having sheet named "Tags", I am trying to set a printing area from A2 till end of page, ending with column L.
Worksheets("Tags").PageSetup.PrintArea = Worksheets("Tags").Range( _
Cells(2, 1), Cells(Worksheets("Tags").Range("A65536").End(xlUp).Row, 12))
My code compiles okay, but it does not seems to work - no printing area has been set.
What should be a correct macro to set printing area?
It's easier to see what is happening if you declare a few variables and decompose your statement.
Try this:
Sub SetPrintArea()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ThisWorkbook.Sheets("Tags")
' find the last row with formatting, to be included in print range
lastRow = ws.UsedRange.SpecialCells(xlCellTypeLastCell).Row
ws.PageSetup.PrintArea = ws.Range("A2:L" & lastRow).Address
End Sub
Alternatively, if you want to find the lastRow with data, you can find the lastrow like this:
lastRow = ws.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Note that the 65536 value you're using as the starting point to find the last row is obsolete (although it will frequently still work) as of Excel 2007, which has over a million rows per sheet.
A few things to note about your approach:
Cells(2,1) is A2. The syntax is Cells([row], [column])
You want the last populated row in column L, but are looking in column A instead. Range("A65536").End(xlUp).Row
This results in a print area (once you've added the .Address to your range) of A1:L2. Why A1? Because the column A is empty, and the lastrow is therefore row 1. You have set the range to be A2:L1, which becomes A1:L2.
You need to add .Address at the end of your code.
Worksheets("Tags").PageSetup.PrintArea = Worksheets("Tags").Range( _
Cells(2, 1), Cells(Worksheets("Tags").Range("A65536").End(xlUp).Row, 12)).Address
PageSetup.PrintArea Property
Returns or sets the range to be printed, as a string using A1-style references in the language of the macro. Read/write String.