Trying to select with .Range( .Cells( #,#) ) won't work in VBA - vba

I'm trying to select a range of cells and I need to use LastRow as the variable that defines the last row of the selection. Here is my code (well the necessary part anyway, it's part of a large loop..):
Dim LastRow As Long
LastRow = FlowWkbs(f).Sheets(w).Cells(7,sht.Columns.Count).End(xlToLeft).Column
With FlowWkbs(f).Sheets(w)
.Range("G1").FormulaR1C1 = "Normal_0to1"
.Range("G2").FormulaR1C1 = "0"
.Cells(LastRow, 7).FormulaR1C1 = "1"
.Range(.Cells(2, 7), .Cells(LastRow, 7)).Select
.Cells(LastRow, 7).Activate
End With
I am getting "Run-time error '1004': Application-defined or object-defined error" as an error on the line:
.Range(.Cells(2, 7), .Cells(LastRow, 7)).Select
It's funny because it does fine with assigning .Cells(LastRow,7) to a value of 1. But it can't handle the selection of G2:G65335 (that happens to be my last row) In the form that I want it to be in. I need to have the LastRow variable change for each iteration of FlowWkbs(f) and Sheets(w) so I need to use the Range(Cells(#%#%)) method as opposed to Range("G2:G324")
I've looked at a number of other questions/topics on here and they all suggest to add the Workbooks.Worksheets. prefix to the Range and Cells, but the With should take care of all that.
Any ideas?

You're finding the last column and putting the value in LastRow, then using that as the row argument to .Cells. If you need the last row, do something like this:
With FlowWkbs(f).Sheets(w)
LastRow = .Cells(.Rows.Count, 7).End(xlUp).Row
.Range("G1").FormulaR1C1 = "Normal_0to1"
.Range("G2").FormulaR1C1 = "0"
.Cells(LastRow, 7).FormulaR1C1 = "1"
.Range(.Cells(2, 7), .Cells(LastRow, 7)).Select
.Cells(LastRow, 7).Activate
End With
If you need to work with a range of columns, switch the argument order in your calls to .Cells (and rename the misleading variable).

I copy and pasted the wrong variable definition for LastRow, the actual LastRow in my code did find the last row and not column. So the issue wasn't that I was getting the last column. Also, that really wouldn't have answered my question because the variable LastRow would have still had a number value and the same error would've shown up..
The problem was that the Worksheet that I was trying to run the Range.select on wasn't selected first. This is the corrected code (without the row/column typo):
Dim LastRow As Long
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
With FlowWkbs(f).Sheets(w)
.Range("G1").FormulaR1C1 = "Normal_0to1"
.Range("G2").FormulaR1C1 = "0"
.Cells(LastRow, 7).FormulaR1C1 = "1"
.Select
.Range(.Cells(2, 7), .Cells(LastRow, 7)).Select
.Cells(LastRow, 7).Activate
End With
Voila!

Related

Range from first empty row to last filled row [duplicate]

I want to select the formatted range of an Excel sheet.
To define the last and first row I use the following functions:
lastColumn = ActiveSheet.UsedRange.Column - 1 + ActiveSheet.UsedRange.Columns.Count
lastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
In the next step I want to select this area:
Formula should look like this:
Range(cells(1, 1), cells(lastRow, lastColumn).Select
However, this is not working. Maybe somebody has an idea what is wrong with it. Thanks a lot!
I recorded a macro with 'Relative References' and this is what I got :
Range("F10").Select
ActiveCell.Offset(0, 3).Range("A1:D11").Select
Heres what I thought : If the range selection is in quotes, VBA really wants a STRING and interprets the cells out of it so tried the following:
Dim MyRange as String
MyRange = "A1:D11"
Range(MyRange).Select
And it worked :) ie.. just create a string using your variables, make sure to dimension it as a STRING variables and Excel will read right off of it ;)
Following tested and found working :
Sub Macro04()
Dim Copyrange As String
Startrow = 1
Lastrow = 11
Copyrange = "A" & Startrow & ":D" & Lastrow
Range(Copyrange).Select
End Sub
I ran into something similar - I wanted to create a range based on some variables. Using the Worksheet.Cells did not work directly since I think the cell's values were passed to Range.
This did work though:
Range(Cells(1, 1).Address(), Cells(lastRow, lastColumn).Address()).Select
That took care of converting the cell's numerical location to what Range expects, which is the A1 format.
If you just want to select the used range, use
ActiveSheet.UsedRange.Select
If you want to select from A1 to the end of the used range, you can use the SpecialCells method like this
With ActiveSheet
.Range(.Cells(1, 1), .Cells.SpecialCells(xlCellTypeLastCell)).Select
End With
Sometimes Excel gets confused on what is the last cell. It's never a smaller range than the actual used range, but it can be bigger if some cells were deleted. To avoid that, you can use Find and the asterisk wildcard to find the real last cell.
Dim rLastCell As Range
With Sheet1
Set rLastCell = .Cells.Find("*", .Cells(1, 1), xlValues, xlPart, , xlPrevious)
.Range(.Cells(1, 1), rLastCell).Select
End With
Finally, make sure you're only selecting if you really need to. Most of what you need to do in Excel VBA you can do directly to the Range rather than selecting it first. Instead of
.Range(.Cells(1, 1), rLastCell).Select
Selection.Font.Bold = True
You can
.Range(.Cells(1,1), rLastCells).Font.Bold = True
You're missing a close parenthesis, I.E. you aren't closing Range().
Try this Range(cells(1, 1), cells(lastRow, lastColumn)).Select
But you should really look at the other answer from Dick Kusleika for possible alternatives that may serve you better. Specifically, ActiveSheet.UsedRange.Select which has the same end result as your code.
you are turning them into an address but Cells(#,#) uses integer inputs not address inputs so just use lastRow = ActiveSheet.UsedRange.Rows.count and lastColumn = ActiveSheet.UsedRange.Columns.Count
I tried using:
Range(cells(1, 1), cells(lastRow, lastColumn)).Select
where lastRow and lastColumn are integers, but received run-time error 1004. I'm using an older VB (6.5).
What did work was to use the following:
Range(Chr(64 + firstColumn) & firstRow & ":" & Chr(64 + lastColumn) & firstColumn).Select.

copy paste filtered data not working as expected

First things first. I am very new to VBA.
Secondly, I googled my ass of and I honestly don't get to the bottom of it. Mostly because the code is adapted to my needs based on googleing i did (copy/paste of code).
To my problem. I have a sheet(Raw Data) with lots of columns(A:AN) and lots of rows(160000) that gets updated every now and then. I want to filter the dataset based on the criteria from a few columns(A & B), and the copy/paste the data in a different sheet(Scatter Raw) starting from column A. I also do not want to copy the header from "Raw Data" and start pasting in "Scatter Sheet" also below the header -> in this case 2 rows.
I have two issues for now:
Based on the filters I do, I will get 17267 rows in "Raw Data". If I simply do a select and copy then I copy only the filtered data. But the moment I paste the data somehow I suddenly get 18362 rows, even though they are empty. I can see this by the fact that the scroll bar goes down. I used this way of copying because sometimes I want to be able to append the copied data based on value set in a different cell. What am I doing here wrong, or what is happening?
I have more sheets inside the workbook. If I do not have the Raw Data worksheet selected I get an error like "Application-defined or object-defined error" on the "Set rng = " line which I don't get. In other test I also got a different error, but that was because the Range was based on the active sheet and not the one I needed. Why is this happening, since the filters are correctly set?
The values from column N should all be divided by 1000. I guess I have no other way then using a temporary copy column, divide it by 1000 in a new column and then copy/paste the new values to the location I need in, right?
Just one last mention, the code is running in a Module and will be later assigned to a button.
Sub Copy()
Dim destTrSheet As Worksheet
Dim sctrSheet As Worksheet
Set destTrSheet = ThisWorkbook.Worksheets("Data Raw")
Set sctrSheet = ThisWorkbook.Worksheets("Scatter Raw")
With destTrSheet
.Range("A:A").AutoFilter field:=1, Criteria1:="VF", Operator:=xlFilterValues
.Range("B:B").AutoFilter field:=2, Criteria1:="CITY", Operator:=xlFilterValues
Set Rng = .Range("N2").Resize(Cells(Rows.count, "N").End(xlUp).Row - 1)
Rng.Copy
sctrSheet.Range("A" & Rows.count).End(xlUp).Offset(1, 0).PasteSpecial (xlPasteValues)
Set Rng = .Range("X2").Resize(Cells(Rows.count, "N").End(xlUp).Row - 1)
Rng.Copy
sctrSheet.Range("B" & Rows.count).End(xlUp).Offset(2, 0).PasteSpecial (xlPasteValues)
End With
End Sub
The issues you mentioned
Discrepancy between manual copy and code copy could be caused by the offsets used:
Col A .Offset(1, 0).PasteSpecial - 1 row below last used row
Col B .Offset(2, 0).PasteSpecial - 2 rows below last used row
The error is caused by .Range("N2") vs (Cells(Rows.count, "N")
.Range("N2") is explicitly qualified because of the dot (.) - refers to "Data Raw"
Cells(Rows.count, "N") is implicitly referring to ActiveSheet (missing .)
If column N should be divided by 1000
Yes, a helper column can be used, as in the code bellow
Another way: copy the column to an array, divide each value, then paste it back
If column N contains strings, the division will generate cell errors:
Option Explicit
Public Sub CopyRawToScatter()
Dim wsR As Worksheet: Set wsR = ThisWorkbook.Worksheets("Data Raw")
Dim wsS As Worksheet: Set wsS = ThisWorkbook.Worksheets("Scatter Raw")
Dim lrR As Long: lrR = wsR.Cells(wsR.Rows.Count, "A").End(xlUp).Row
Dim lrS As Long: lrS = wsS.Cells(wsS.Rows.Count, "A").End(xlUp).Row + 1
With wsR
Dim fRng As Range: Set fRng = .Range(.Cells(1, "A"), .Cells(lrR, "B"))
Dim rngN As Range: Set rngN = .Range(.Cells(2, "N"), .Cells(lrR, "N"))
Dim rngX As Range: Set rngX = .Range(.Cells(2, "X"), .Cells(lrR, "X"))
Dim cRng As Range: Set cRng = Union(rngN, rngX)
End With
Application.ScreenUpdating = False
fRng.AutoFilter field:=1, Criteria1:="VF", Operator:=xlFilterValues
fRng.AutoFilter field:=2, Criteria1:="CITY", Operator:=xlFilterValues
If fRng.SpecialCells(xlCellTypeVisible).CountLarge > 2 Then
cRng.Copy
wsS.Cells(lrS, "A").PasteSpecial xlPasteValues
With wsS
Dim vis As Long: vis = .Cells(.Rows.Count, "A").End(xlUp).Row
Dim lcS As Long: lcS = .Cells(lrS, "A").End(xlToRight).Column + 1
Dim divA As Range: Set divA = .Range(.Cells(lrS, "A"), .Cells(vis, "A"))
Dim divX As Range: Set divX = .Range(.Cells(lrS, lcS), .Cells(vis, lcS))
divX.Formula = "=" & .Cells(lrS, 1).Address(RowAbsolute:=False) & " / 1000"
divA.Value2 = divX.Value2
divX.ClearContents
End With
End If
wsR.UsedRange.AutoFilter
Application.ScreenUpdating = False
End Sub
Other issues
Potential conflict between your Sub name (Copy()) with the built-in Range.Copy Method
The 2 AutoFilter lines are invalid
.Range("A:A").AutoFilter field:=1, Criteria1:="VF", Operator:=xlFilterValues
.Range("B:B").AutoFilter field:=2, Criteria1:="CITY", Operator:=xlFilterValues
If your code works you probably modified it when posting the question; they should be
.Range("A:B").AutoFilter field:=1, Criteria1:="VF", Operator:=xlFilterValues
.Range("A:B").AutoFilter field:=2, Criteria1:="CITY", Operator:=xlFilterValues
You don't need brackets for .PasteSpecial (xlPasteValues)

Copying and pasting info from one sheet to another using lastcol & lastrow

I understand copying and pasting is not a recommended way to go, however am proceeding with it. I currently have a amount of data on each sheet. I am avoiding the final row when I copy the data from the rows(Works perfect). And I am avoiding the final column when I copy the columns(Works perfect).
LastRow:
Lastrow = Cells(Rows.count, "A").End(xlUp).Row - 1
LastColumn:
With ActiveSheet
lastcol = .Cells(4, .Columns.count).End(xlToLeft).Column - 1
End With
I however need to now copy the data. I can copy the rows perfectly fine. However the columns is where I am getting caught up on. I'm quiet new to the Copy/Paste method, and am unsure how to go along of fixing this as I always used a range of cell names.
This will give me the rows needed, and all the columns needed as I am copying past the last column.
Sheets("Sheet2").Range("A4:AZ" & Lastrow).Copy Sheets(PlantArr(e)).Range("A1") 'Copy info to new sheet
How can I convert this so that AZ is actually the last column needed? Is there an easy way to go about this or will I need to set up a case to convert column number to cell value?
Answer:
gAddress = Split(Cells(1, lastcol).Address(True, False), "$") 'Converts Lastcol number into alphabet character
letter = gAddress(0)
Sheets("Sheet2").Range("A4:" & letter & Lastrow).Copy Sheets(PlantArr(e)).Range("A1") 'Copy info to new sheet
After a bit of digging around, I figured out that you can pull an address from a column value. I hope the code below helps anyone who would like to convert a column number to an alphabet column.
Dim gAddress
gAddress = Split(Cells(1, lastcol).Address(True, False), "$")
letter = gAddress(0)
It's possible to specify the copy Range by explicitly stating which cells compose that range. Using 'With', you can write something like this to accomplish what you need:
Sub copy_col_and_rows()
Dim Lastrow As Integer: Dim lastcol As Integer:
With ActiveSheet
Lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row - 1
lastcol = .Cells(4, Columns.Count).End(xlToLeft).Column - 1
End With
With Sheets("Sheet2")
.Range(.Cells(1, 4), .Cells(Lastrow, lastcol)).Copy Destination:=Sheets(PlantArr(e)).Range("A1")
'Where .Cells(1,4) corresponds to "A4"
End With
End Sub

Using Split function with Cells, Range, Rows.count, and xlup on excel-vba

Will this code work?
lr = RD.Cells(Rows.Count, 8).End(xlUp).Row
wArray() = Split(RD.Range(Cells(2, 8), Cells(Rows.Count, 8).End(xlUp).Row))
RD.Cells(2, 8).Value = wArray(0)
RD.Cells(2, 9).Value = wArray(1)
I want the code to go through each of the cells in the range and split the data in that range and put the 2nd string on the cell next to it. Like for example, I have a A1:A15 cell range that has the cell value of "01/01/2015 09:43 GMT", after I run the the code, I expect that "01/01/2015" will remain at range A1:A15 while "09:43" will be moved to cell range B1:B15. I have tried the same code by defining a single cell on the Split(RD.Cells) function and it worked beautifully. Now I need it to keep on going on the next row as long as that row has an input.
Are you looking to loop through all the rows rather than only 1 row? If so you can try this.
lr = RD.Cells(Rows.Count, 8).End(xlUp).Row
For i = 2 to lr
wArray() = Split(RD.Range(Cells(i, 8))
RD.Cells(i, 8).Value = wArray(0)
RD.Cells(i, 9).Value = wArray(1)
Next i
Without using a loop
With RD.UsedRange
.Columns(1).TextToColumns Destination:=.Cells(1), DataType:=xlFixedWidth, _
FieldInfo:=Array(Array(0, 1), Array(11, 1))
End With

VBA: Selecting range by variables

I want to select the formatted range of an Excel sheet.
To define the last and first row I use the following functions:
lastColumn = ActiveSheet.UsedRange.Column - 1 + ActiveSheet.UsedRange.Columns.Count
lastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
In the next step I want to select this area:
Formula should look like this:
Range(cells(1, 1), cells(lastRow, lastColumn).Select
However, this is not working. Maybe somebody has an idea what is wrong with it. Thanks a lot!
I recorded a macro with 'Relative References' and this is what I got :
Range("F10").Select
ActiveCell.Offset(0, 3).Range("A1:D11").Select
Heres what I thought : If the range selection is in quotes, VBA really wants a STRING and interprets the cells out of it so tried the following:
Dim MyRange as String
MyRange = "A1:D11"
Range(MyRange).Select
And it worked :) ie.. just create a string using your variables, make sure to dimension it as a STRING variables and Excel will read right off of it ;)
Following tested and found working :
Sub Macro04()
Dim Copyrange As String
Startrow = 1
Lastrow = 11
Copyrange = "A" & Startrow & ":D" & Lastrow
Range(Copyrange).Select
End Sub
I ran into something similar - I wanted to create a range based on some variables. Using the Worksheet.Cells did not work directly since I think the cell's values were passed to Range.
This did work though:
Range(Cells(1, 1).Address(), Cells(lastRow, lastColumn).Address()).Select
That took care of converting the cell's numerical location to what Range expects, which is the A1 format.
If you just want to select the used range, use
ActiveSheet.UsedRange.Select
If you want to select from A1 to the end of the used range, you can use the SpecialCells method like this
With ActiveSheet
.Range(.Cells(1, 1), .Cells.SpecialCells(xlCellTypeLastCell)).Select
End With
Sometimes Excel gets confused on what is the last cell. It's never a smaller range than the actual used range, but it can be bigger if some cells were deleted. To avoid that, you can use Find and the asterisk wildcard to find the real last cell.
Dim rLastCell As Range
With Sheet1
Set rLastCell = .Cells.Find("*", .Cells(1, 1), xlValues, xlPart, , xlPrevious)
.Range(.Cells(1, 1), rLastCell).Select
End With
Finally, make sure you're only selecting if you really need to. Most of what you need to do in Excel VBA you can do directly to the Range rather than selecting it first. Instead of
.Range(.Cells(1, 1), rLastCell).Select
Selection.Font.Bold = True
You can
.Range(.Cells(1,1), rLastCells).Font.Bold = True
You're missing a close parenthesis, I.E. you aren't closing Range().
Try this Range(cells(1, 1), cells(lastRow, lastColumn)).Select
But you should really look at the other answer from Dick Kusleika for possible alternatives that may serve you better. Specifically, ActiveSheet.UsedRange.Select which has the same end result as your code.
you are turning them into an address but Cells(#,#) uses integer inputs not address inputs so just use lastRow = ActiveSheet.UsedRange.Rows.count and lastColumn = ActiveSheet.UsedRange.Columns.Count
I tried using:
Range(cells(1, 1), cells(lastRow, lastColumn)).Select
where lastRow and lastColumn are integers, but received run-time error 1004. I'm using an older VB (6.5).
What did work was to use the following:
Range(Chr(64 + firstColumn) & firstRow & ":" & Chr(64 + lastColumn) & firstColumn).Select.