I'm automating an Excel sheet for my work and I'm stuck in a problem.
I'm trying to copy a specific range (A3:D3) and paste it to the ending row of another workbook. I'm trying to use an if statement to filter ranges that have the number 0 in cell B3.
Please help. I'm a complete rookie and I'm just starting out. Sorry if there's a lot of questions.
I've tried to change the range to a cell (i, 2) but it only copies B3 and not the rest (A3:D3).
Edit: forgot to add the s in cells
Edit2: I just need to copy four cells (A3:D3) and increment it on my next iteration so that the copied cell would be (A4:D4)
Sub CopyData()
Dim wsCopy As Worksheet, wsDest As Worksheet
Dim iCopyLastRow As Long, iDestLastRow As Long
Set wsCopy = Workbooks("file1.xlsx").Worksheets("trend")
Set wsDest = Workbooks("file2.xlsx").Worksheets("raw data")
iCopyLastRow = wsCopy.Cells(wsCopy.Rows.Count, "A").End(xlUp).Row
For i = 3 To iCopyLastRow
If wsCopy.Cells(i, 2).Value = 0 Then
Else
wsCopy.range(Cell(i,2), Cell(i,4)).Copy
'wsCopy.Cells(i, 2). Copy ##this copies just one cell
iDestLastRow = wsDest.Cells(wsDest.Rows.Count, "B").End(xlUp).Offset(1).Row
wsDest.range("A" & iDestLastRow).PasteSpecial xlPasteValues
End If
Next i
Error messages:
Run-time error '1004':
Method 'Range' of object '_Worksheet' failed
and the debug highlights wsCopy.range(Cell(i,2), Cell(i,4)).Copy, the statement after else
Try using this code:
Sub CopyData()
Dim wsCopy As Worksheet, wsDest As Worksheet
Dim iCopyLastRow As Long, iDestLastRow As Long
Set wsCopy = Workbooks("file1.xlsx").Worksheets("trend")
Set wsDest = Workbooks("file2.xlsx").Worksheets("raw data")
iCopyLastRow = wsCopy.Cells(wsCopy.Rows.Count, "A").End(xlUp).Row
For i = 3 To iCopyLastRow
If wsCopy.Cells(i, 1).Value <> 0 Then
'A = 1, D = 4
wsCopy.Range(wsCopy.Cells(i, 1), wsCopy.Cells(i, 4)).Copy
iDestLastRow = wsDest.Cells(wsDest.Rows.Count, "B").End(xlUp).Offset(1).Row
wsDest.Range("A" & iDestLastRow).PasteSpecial xlPasteValues
End If
Next i
End Sub
Just make sure that iCopyLastRow and iDestLastRow are the values that you expect.
I hope this helps.
Try below code, it's ready to use in a loop:
Sub CopyAndAppend()
Dim destSheet As Worksheet, srcSheet As Worksheet, lastRow As Long
Set destSheet = Worksheets("Sheet2")
Set srcSheet = Worksheets("Sheet1")
' determine last row in Sheet2
lastRow = destSheet.Cells(destSheet.Rows.Count, 1).End(xlUp).Row
Dim i As Long
i = 3
' copy range A3:D3 and paste it right after last row in Sheet2
srcSheet.Range(srcSheet.Cells(i, 1), srcSheet.Cells(i, 4)).Copy destSheet.Cells(lastRow + 1, 1)
' increment row index
i = i + 1
' do something else
End Sub
Related
I'm working with two sheets. One sheet has the full raw data while the other has a select few headers from sheet 1. If it finds a match on the header, i need it to copy the full column from sheet one to sheet 2
and it copies it to sheet 2
Here is my code so far but i can't figure out how to break the loop so that it goes through every column on sheet 1 until it finds a match:
Private Sub CommandButton1_Click()
Dim ShtOne As Worksheet, ShtTwo As Worksheet
Dim shtOneHead As Range, shtTwoHead As Range`enter code here`
Dim headerOne As Range, headerTwo As Range
Set ShtOne = Sheets("Sheet1")
Set ShtTwo = Sheets("Sheet2")
'row count
Dim b As Long
b = ShtOne.Cells(Rows.Count, 1).End(xlUp).Row
'column count in sheet 1
Dim a As Long
a = ShtOne.Cells(1, Columns.Count).End(xlToLeft).Column
'column count in sheet 2
Dim c As Long
c = ShtTwo.Cells(1, Columns.Count).End(xlToLeft).Column
Dim lastCol As Long
'get all of the headers in the first sheet, assuming in row 1
lastCol = ShtOne.Cells(1, Columns.Count).End(xlToLeft).Column
Set shtOneHead = ShtOne.Range("A1", ShtOne.Cells(1, lastCol))
'get all of the headers in second sheet, assuming in row 1
lastCol = ShtTwo.Cells(1, Columns.Count).End(xlToLeft).Column
Set shtTwoHead = ShtTwo.Range("A1", ShtTwo.Cells(1, lastCol))
'stops the visual flickering of files opening and closing - run at the background
Application.ScreenUpdating = False
'start loop from first row to last row
'For i = 1 To a
i = 1
j = 0
'actually loop through and find values
For Each headerOne In shtOneHead
j = j + 1
For Each headerTwo In shtTwoHead
'copy and paste each value
If headerTwo.Value = headerOne.Value Then
'copies one row at a time (a bit slow)
' headerOne.Offset(i, 0).Copy
' headerTwo.Offset(i, 0).PasteSpecial xlPasteAll
'copies whole rows at a time
ShtOne.Columns(i).Copy ShtTwo.Columns(j)
i = i + 1
Application.CutCopyMode = False
Exit For
End If
Next headerTwo
Next headerOne
'Next
End Sub
Assuming your headers are on row 1 for both sheets and that you will always be pasting on the second row on Sheet2.
Only loop through your column headers on the second sheet. Use Range.Find to search for each header on Sheet1. If the header is found, copy and paste accordingly
Sub Headerz()
Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Sheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Sheets("Sheet2")
Dim LC As Long, i As Long, LR As Long
Dim Found As Range
LC = ws2.Cells(1, ws2.Columns.Count).End(xlToLeft).Column
For i = 1 To LC
Set Found = ws1.Rows(1).Find(ws2.Cells(1, i).Value)
If Not Found Is Nothing Then
LR = ws1.Cells(ws1.Rows.Count, Found.Column).End(xlUp).Row
ws1.Range(ws1.Cells(2, Found.Column), ws1.Cells(LR, Found.Column)).Copy
ws2.Cells(2, i).PasteSpecial xlPasteValues
End If
Set Found = Nothing
Next i
End Sub
Would you know what is the following code adjustment needed. Range I have set up (A1:B20) changes over time. The first block of data stays be between A1:B20 and the second block of data always will be between A25:B60. Ranges will change over time. First block of data could reach 200 rows going down. After my code reaches the second block of data and my range falls between that block of data it picks up the range only if I have adjusted manually the range. Please note, Second block of data normally provides duplicates from the first block.
How could I have my code automatically select the first block of data past my range output without having to adjust the "range" manually?
Sub CopyPaste()
Dim lastRow As Long
Dim Sheet2 As Worksheet
Dim Results As Worksheet
Dim LookupLastrow As Long
'code line will set values from sheet
("Sheet1") into ("Sheet2") starting 5 rows down.
Set Results = Sheets("Sheet2")
lastRow = ThisWorkbook.Sheets("Sheet2").Cells(Rows.Count, 1).End (xlUp).row
Range("A1:B20" & lastRowcount).Copy
Results.Range("A" & lastRow + 5).PasteSpecial xlPasteValuesAndNumberFormats
Application.GoTo ActiveSheet.Range("A1"), True
Application.CutCopyMode = False
End Sub
Think simple. No need to build strings for range addresses, and no need for using the clipboard with .Copy and .Paste. Use a direct assignment to the .Value property in a table of cells.
Public Sub CopyValues()
Dim r_src As Range, r_dst As Range
' Source starts at row 20
Set r_src = Sheets("Sheet 2").Cells(20, 1)
' Destination starts at row 5
Set r_dst = Sheets("Sheet 1").Cells(5, 1)
Dim n As Long
' Count the non-empty cells
n = r_src.Range(r_src, r_src.End(xlDown)).Rows.Count
' Copy n rows and 2 columns with one command
r_dst.Resize(n, 2).Value = r_src.Resize(n, 2).Value
End Sub
Based on the picture you showed, the following code will capture the entire top and bottom sections, regardless of how many lines or columns exists. This assumes your top section will start in "A8" as shown. You can edit the code to reflect your actual sheet names.
Sub CopyPaste()
Dim OrigLastRow As Long
Dim OrigLastCol As Long
Dim DestLastRow As Long
Dim OrigRng As Range
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Origin")
Set ws2 = ThisWorkbook.Worksheets("Destination")
OrigLastRow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
OrigLastCol = ws1.Cells(10, Columns.Count).End(xlToLeft).Column
DestLastRow = ws2.Cells(Rows.Count, 1).End(xlUp).Row + 5
Set OrigRng = ws1.Range(ws1.Cells(8, 1), ws1.Cells(OrigLastRow, OrigLastCol))
OrigRng.Copy
ws2.Cells(DestLastRow, 1).PasteSpecial xlPasteValuesAndNumberFormats
Application.CutCopyMode = False
End Sub
The version below creates a top and bottom section like your picture and copies both sections separately with a 5 row gap in the destination.
Sub CopyPaste2()
Dim OrigLastRow As Long
Dim OrigLastCol As Long
Dim TopLastRow As Long
Dim BotLastRow As Long
Dim DestLastRow As Long
Dim OrigTopRng As Range
Dim OrigBotRng As Range
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Origin")
Set ws2 = ThisWorkbook.Worksheets("Destination")
'Assumes contiguous data from row 8 down
TopLastRow = ws1.Cells(8, 1).End(xlDown).Row
BotLastRow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
OrigLastCol = ws1.Cells(10, Columns.Count).End(xlToLeft).Column
DestLastRow = ws2.Cells(Rows.Count, 1).End(xlUp).Row + 5
'Assumes we are starting the top range in row 8
Set OrigTopRng = ws1.Range(ws1.Cells(8, 1), ws1.Cells(TopLastRow, OrigLastCol))
'Columns I & J as shown in the picture
Set OrigBotRng = ws1.Range(ws1.Cells(TopLastRow + 5, 9), ws1.Cells(BotLastRow, 10))
OrigTopRng.Copy
ws2.Cells(DestLastRow, 1).PasteSpecial xlPasteValuesAndNumberFormats
'Recalculate destination last row
DestLastRow = ws2.Cells(Rows.Count, 1).End(xlUp).Row + 5
OrigBotRng.Copy
ws2.Cells(DestLastRow, 1).PasteSpecial xlPasteValuesAndNumberFormats
Application.CutCopyMode = False
End Sub
I have the following code which I am using to loop through a worksheet. Each row needs to be copied a certain number of times and the new rows pasted at the bottom, after the last row that currently has any text. The number of rows to copy for each present row is in the cell for column BU of that row.
Hence, in order to do this, I have created the following loop to move through each row and use the cell value in column BU to copy cells in columns A through BT, then paste after the last active visible row.
However, it's not working well.
Any thought?
Sub Transfer()
Application.ScreenUpdating = False
Dim lastrow As Long, lngRows
lastrow = sht.Cells(sht.Rows.Count, 1).End(xlUp).Row + 1
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim rowCount As Long
Set wsSource = Worksheets("Forecasted Movement")
With wsSource
rowCount = .Cells(.Rows.Count, "A").End(xlUp).Row ' <-- modifed this line
On Error Resume Next
For i = 2 To rowCount
If .Cells(i, "BU").Value > 0 Then
lngRows = .Cells(i, "BU").Value
Range(Cells(i, 1), Cells(i, 72)).specialcells(xlCellTypeVisible).Copy
wsSource.Cells(lastrow, 1).Resize(lngRows).PasteSpecial Paste:=xlPasteValues
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
If this is all in the same worksheet ( as the code suggests) the your lastrow is your problem. You need to recalculate it everytime you paste a new row.
Sub Transfer()
Application.ScreenUpdating = False
Dim lastrow As Long, lngRows
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim rowCount As Long
Set wsSource = Worksheets("Forecasted Movement")
With wsSource
rowCount = .Cells(.Rows.Count, "A").End(xlUp).Row ' <-- modifed this line
On Error Resume Next
For i = 2 To rowCount
If .Cells(i, "BU").Value > 0 Then
lngRows = .Cells(i, "BU").Value
Range(Cells(i, 1), Cells(i, 72)).specialcells(xlCellTypeVisible).Copy
lastrow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1 ' recalculate this for the next blank row
wsSource.Cells(lastrow, 1).Resize(lngRows).PasteSpecial Paste:=xlPasteValues
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
I want to copy a range of cells, say F10:F59, of the Form sheet, then transpose and paste them to another range on another sheet named Stock Manual Senin, say B11:BA25.
This is what I currently have:
Sub InputPAGS_Senin()
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
Dim vntRange As Variant
Dim lastRow As Long
Set copySheet = Sheets("Form")
Set pasteSheet = Sheets("Stock Manual Senin")
' Calculate last row of data.
lastRow = pasteSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1).Row
' Copy 2 cells.
pasteSheet.Cells(lastRow + 1, 1).Offset(0, 1) = copySheet.Range("N2").Value
' Paste column range into array.
vntRange = copySheet.Range("F10:F59").Value
' Paste transpose array into row range.
Sheets("Stock Manual Senin").Select
Range("B11:BA25").Select
pasteSheet.Cells(lastRow + 1, 1).Offset(0, 3).Resize(, copySheet _
.Range("F10:F59").Rows.Count).Value = Application.Transpose(vntRange)
End Sub
the paste target should be in row 11, but it'd paste in row 285 cause target range is located between the others table's row.
Can anyone advise me on how I should continue please? Thank you.
xlUp Becomes xlDown
You have to calculate the last row from NAMA TOKO down (xlDown). Do not delete NAMA TOKO and PAGS / MIGO, then you can use the following
lastRow = pasteSheet.Cells(9, 2).End(xlDown).Offset(1).Row
or even better
lastRow = pasteSheet.Cells(9, 2).End(xlDown).Row + 1
Does something like this work? I just did a manual pivot as I wrote out the values.
Sub SOTest()
Dim copySheet As Worksheet
Dim CopyRange As Range
Dim Cell As Range
Dim pasteSheet As Worksheet
Dim lastRow As Long
Dim ColIndex As Long
Set copySheet = ThisWorkbook.Worksheets("Form")
Set pasteSheet = ThisWorkbook.Worksheets("Stock Manual Senin")
Set CopyRange = copySheet.Range("F10:F59")
ColIndex = 2 'Column B
With pasteSheet
lastRow = .Cells(.Rows.Count, 2).End(xlUp).Row + 1
End With
Application.ScreenUpdating = False
For Each Cell In CopyRange
pasteSheet.Cells(lastRow, ColIndex).Value = Cell.Value
ColIndex = ColIndex + 1
Next
Application.ScreenUpdating = True
End Sub
I am trying to copy rows from Sheet1 which meet a crieteria and post the whole row at the end of the current data. I am able to copy the row but it is not pasting it. Help will be appreciated. Here is my code I have written:
Sub Button1_Click()
Dim i As Integer
'Range("H2:O65536").ClearContents
Sheets("Sheet1").Select
LastRowColA = Range("A65536").End(xlUp).Row
For i = 2 To LastRowColA
If Cells(i, 6) = "No" Then
Rows(i).Select
Rows(i).Copy
Sheets("Sheet2").Select
Dim LastRow As Long
Dim StartRow As Long
Dim Col As Long
Dim Row As Long
StartRow = 2
Col = 1
LastRow = findLastRow(1)
For Row = StartRow To LastRow
Rows(LastRow).Select
ActiveSheet.Paste
Next Row
Else
'do nothing
End If
Next i
End Sub
Function findLastRow(ByVal Col As Integer) As Long
'Find the last row with data in a given column
findLastRow = Cells(Rows.Count, Col).End(xlUp).Row
End Function
here we go: a tad shorter, but should do the job...
Sub Button1_Click()
Dim i As Integer
Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Sheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Sheets("Sheet2")
For i = 2 To ws1.Range("A65536").End(xlUp).Row
If ws1.Cells(i, 6) = "No" Then ws1.Rows(i).Copy ws2.Rows(ws2.Cells(ws2.Rows.Count, 6).End(xlUp).Row + 1)
Next i
End Sub
To add a bit more help, why spend all that (processing) time looping through a potentially large row set when you can just filter and copy all your data at once?
See code below. You may need to tweak it a bit to match your data set.
Sub Button1_Click()
Dim ws1 as Worksheet: Set ws1 = ThisWorkbook.Sheets("Sheet1")
Dim ws2 as Worksheet: Set ws2 = ThisWorkbook.Sheets("Sheet2")
With ws1
.UsedRange.AutoFilter 6, "No"
'-> assumes data starts in column A, if not adjust the 6
Intersect(.UsedRange,.UsedRange(Offset(1)).SpecialCells(xlCellTypeVisible).Copy
' -> assumes No's are there, if they may not exist, will need to error trap.
End With
With ws2
.Rows(.Cells(ws2.Rows.Count, 6).End(xlUp).Row + 1).PasteSpecial xlPasteValues
End With
ws1.AutoFilterMode = False
End Sub
// Just use it.
Sheet2.Select (Sheet1.Rows(index).Copy)
Sheet2.Paste (Rows(index))
If you want to copy, paste two or more rows then use the for loop.