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

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

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 and Paste row by index number in Excel Macro

I'm trying to copy an entire row by index number and paste it to another row with a different index number when a certain condition is met (I know the issue is not with the conditional logic). I'm thinking of something like this:
Sub Makro1()
Dim i As Integer
With ActiveSheet
'for looping
totalRows = .Cells(.Rows.Count, "A").End(xlUp).Row
'index of last row even after rows have been added
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
'data starts at row #3
For i = 3 To totalRows
If .Cells(i, 19).Value > 0 Then
Number = .Cells(i, 19).Value
Do While Number > 0
lastRow = lasRow + 1
'Next line doesnt do anything
.Rows(lastRow) = .Rows(i).Value
Number = Number - 1
Loop
End If
Next i
End With
End Sub
The logic works like its supposed to but no lines are pasted. I've gone step by step and am certain the problem is not with the logic.
I assume that you want to copy Rows(i) and paste it as value in Rows(lastRow). So, you need to replace this line
.Rows(lastRow) = .Rows(i).Value
with these two lines:
.Rows(i).Copy
.Rows(lastRow).PasteSpecial xlPasteValues
Or
.Rows(lastRow).Copy
.Rows(i).PasteSpecial xlPasteValues
if you want to copy Rows(lastRow) and paste it as value in Rows(i).
Edit:
To paste everything (formulas + values + formats), use paste type as xlPasteAll.
Reference: msdn
Range Copy and Paste
Syntax
Range().Copy [Destination]
The square brackets indicate that Destination is an optional parameter. If you don't designate a Destination range it copies the selection to the clipboard. Otherwise it copies the first range directly to the new location.
Change this line:
.Rows(lastRow) = .Rows(i).Value
To:
.Rows(lastRow).copy .Rows(i)
It's worth noting that
.Rows(lastRow).copy .Cells(i, 1)
Will also work. Excel will resize the Destination range to fit the new data.
your code works for me
so just add a breakpoint at .Rows(lastRow) = .Rows(i).Value statement and then query all relevant variables value in the Immediate Window, like:
?lastRow
?.Rows(lastRow).Address
?i
?.Rows(i).Address
in the meanwhile you could
add Option Explicit statement at the very top of your code module
this will force you to declare all variables and thus lead to some extra work, but you'll get repaid with much more control over your variables usage and misspelling, thus saving debugging time
dim variables to hold rows index as of Long type, to handle rows index higher then 32767
avoid inner loop using the Resize() method of range object
much like follows:
Option Explicit
Sub Makro1()
Dim i As Long, totalRows As Long, lastRow As Long, Number As Long
With ActiveSheet
'for looping
totalRows = .Cells(.Rows.Count, "A").End(xlUp).Row
'index of row to add from
lastRow = totalRows + 1 '<--| start pasting values one row below the last non empty one in column "A"
'data starts at row #3
For i = 3 To totalRows
If .Cells(i, 19).Value > 0 Then
Number = .Cells(i, 19).Value
.Rows(lastRow).Resize(Number).Value = .Rows(i).Value
lastRow = lastRow + Number
End If
Next i
End With
End Sub

Matching and inserting records in excel

I have two sheets of data. One sheet has Primary Id with 4 fields and other has primary Id with 2 fields.
Sheet A Sheet B
ID Name Price Type Category ID Name Price
1 S Normal 2 Aus 500
2 N Default 1 Ind 400
Basically I need to match the ID of both sheets and copy the corresponding Name and Price in sheet A form Sheet B. I have tried the following code,
Sub Copy()
lastrowA = Worksheets("SheetA").Cells(Rows.Count, "A").End(xlUp).Row + 1
Set rngA = Range("A2" & lastrowA)
lastrowB = Worksheets("SheetB").Cells(Rows.Count, "A").End(xlUp).Row + 1
Set rngB = Range("A2" & lastrowB)
For Each x In rngB
For Each y In rngA
If x.Value() = y.Value Then
' Copy paste name and price form B to A
End If
Next
Next
End Sub
It's never a good idea to use a reserved word as the name of your macro. Particularly so if you plan to use a .Copy operation within the macro.
Sub MyCopy()
Dim lastrowA As Long
With Worksheets("SheetA")
lastrowA = .Cells(Rows.Count, "A").End(xlUp).Row
With .Range("B2:C" & lastrowA)
.Formula = "=IFERROR(VLOOKUP($A2, 'SheetB'!$A:$C, COLUMN(B:B), FALSE), """")"
.Value = .Value
End With
End With
End Sub
That bulk populates the entire region with the appropriate formula without looping then converts the returned values to raw values. Any non-matches will be blank rather than #N/A errors.
Does it have to be done without using formulas? I'm not sure if I'm missing something, but surely you can just use either a Vlookup or an Index Match?
If entering the formula from VBA:
Cells(2,2).FormulaR1C1 = "=INDEX(Sheet2!R2C2:R3C3,MATCH(RC[-1],Sheet2!RC[-1]:R[1]C[-1],0),1)"
Cells(2,3).FormulaR1C1 = "=INDEX(Sheet2!R2C2:R3C3,MATCH(RC[-2],Sheet2!R2C1:R3C1,0),2)"
Then you can find the last row in the ID column on sheet 1, and fill the formula down both of the columns. Once the formula has been filled down, just copy and paste as values.
Dim lstRow As Long
lstRow = Sheets("Sheet 1").Cells(Rows.Count, 1).End(xlUp).Row '' find last row
Range(Cells(2, 2), Cells(lstRow, 3)).FillDown
Range(Cells(2, 2), Cells(lstRow, 3)).Copy
Cells(2, 2).PasteSpecial Paste:=xlPasteValues
Edit: You can use the lstRow variable within the VBA formula to make sure the formula is covering the whole range everytime the automation is run. You can use the 'Record Macro' button within excel to get the code for a formula, if you are not comfortable creating them yourself.
The Problem with your code is that
Set rngA = Range("A2" & lastrowA)
evaluates to Range("A25") for lastRowA=5.
If you want to address multiple cells, use
Set rngA = Range("A2:A" & lastrowA)
to get Range("A2:A5") for lastRowA = 5.
Besides that, formulas as already mentioned are an elegant solution as well.

VBA: Placing a forumula down a column using a vlookup formula

Below I am attempting to place the formula just to the right of the last column, beginning at row 2. I know the For statement works, as well as the searching for last column/ row as i've used this in a previous macro when placing a formula down a column. The only question I have is how do I make the VLookup formula work properly?
End goal:
1) Forumla on column to the right of last one
2) Vlookup looksup the value in the last column on the given row within the For statement on a tab called "Lookup"
3) On this Lookup tab, column A is where the value will be found, but I need to return the second column value.
Please zero in on the forumula beginning with the "=iferror(...". I currently receive the error, "Application Defined or Object-Defined" error.
EThree = Cells(Rows.Count, 4).End(xlUp).Row
NumThree = Evaluate("=COUNTA(9:9)")
For r = 2 To EThree
Cells(r, NumThree + 2).Formula = "=IFERROR(((Vlookup(" & Cells(r, 14).Value & ",Lookup!$A:$B,2,0)""))))"
Next
You can place your formula in one go; no need to loop.
Try this:
With Sheets("NameOfWorksheet") '~~> change to suit
'~~> first get the last row and column
Dim lrow As Long, lcol As Long
lrow = .Range("D" & .Rows.Count).End(xlUp).Row
lcol = .Cells(9, .Columns.Count).End(xlToLeft).Column
Dim rngToFillFormula As Range, mylookup As String
'~~> get the lookup value address
mylookup = .Cells(2, lcol).Address(False, False, xlA1)
'~~> set the range you need to fill your formula
Set rngToFillFormula = .Range(.Cells(2, lcol), Cells(lrow, lcol)).Offset(0, 1)
rngToFillFormula.Formula = "=IFERROR(VLOOKUP(" & mylookup & _
",Lookup!A:B,2,0),"""")"
End With
What we did is explained in the comments. HTH.

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.