Copy data from one worksheet to other based on condition - vba

I am trying to copy data from one worksheet to another blank worksheet in a workbook. It has three columns where in I want to search a specific 'Unit' value and just copy all of the records with similar 'Unit' values into second worksheet with similar column structure.
**Doc_number** **Doc_version** **Unit**
43449 01 D013-LAG R
43450 02 D013-LAG R
43451 01 D013-DAMP
43452 02 D013-DAMP
Output should be like this if I provide D013-LAG R as input value ;
**Doc_number** **Doc_version** **Unit**
43449 01 D013-LAG R
43450 02 D013-LAG R
I want to paste the selected column to the DELIVERY sheet like if I pass 'Unit' value as 'D03-LAG R' then the output in the DELIVERY file should be just like as follows;
Doc_version Unit
01 D013-LAG R
02 D013-LAG R
It's more like I want to select entire row and then paste the data to another worksheet to the columns I want to. I don't want entire row to be pasted as it is.
I don't have much experience in VBA and have already tried doing the code which results in copying of the last record encountered in the loop. Need your advice.
Sub Row_Copy()
Dim sheet1 As Worksheet, sheet2 As Worksheet
Dim i As Integer, k As Integer
Dim Sheet1LR As Long, Sheet2LR As Long
Set sheet1 = Sheets("MASTER")
Set sheet2 = Sheets("DELIVERY")
Sheet1LR = Sheet1.Range("A" & Rows.Count).End(xlUp).Row + 1
Sheet2LR = Sheet2.Range("A" & Rows.Count).End(xlUp).Row + 1
i = 2
k = Sheet2LR
Do Until i = Sheet1LR
If Trim(sheet1.Cells(i, 26).Value) = "D013-LAG R" Then
With sheet1
.Range(.Cells(i, 1), .Cells(i, 26)).Copy
End With
With sheet2
.Cells(k, 1).PasteSpecial
.Cells(k, 1).Offset(1, 0).PasteSpecial
End With
End If
k = k + 1
i = i + 1
Loop
MsgBox (Complete)
ActiveWorkbook.Save
Application.ScreenUpdating = False
End Sub
This is the latest code I am using;
Sub CommandButton1_Click()
Dim LSearchRow As Long
Dim LCopyToRow As Long
Dim CopyFromSht As Worksheet
Dim CopyToSht As Worksheet
Dim LCnt As Long
On Error GoTo Err_Execute
Set CopyFromSht = Workbooks("TestRow.xlsm").Sheets("MASTER")
Set CopyToSht = Workbooks("TestRow.xlsm").Sheets("DELIVERY")
With CopyFromSht
'Start search in row 4
LSearchRow = .Range("A" & Rows.Count).End(xlUp).Row
'Start copying data to row 2 in Sheet2 (row counter variable)
LCopyToRow = 2
For LCnt = 2 To LSearchRow
'If value in column Z = "Unit as needed", copy entire row to Sheet2
If .Range("Z" & LCnt).Value = "D013-LAG R" Then
'Select row in Sheet1 to copy
.Rows(LCnt).Copy Destination:=CopyToSht.Rows(LCopyToRow)
'Move counter to next row
LCopyToRow = LCopyToRow + 1
End If
Next LCnt
End With

I wrote a macro that might give you an idea how to resolve your problem:
Sub CopyRows()
' Variables
Dim row_src As Integer
Dim row_dest As Integer
' Inizialize row within destination sheet
row_dest = 1
' Loop over all rows in source sheet
For row_src = 1 To 32767
' Go to correct cell within source sheet
Sheets("Source").Select
Range("B" & CStr(row_src)).Select
' Done if this row is empty
If (ActiveCell.Value = "") Then
Exit For
End If
' Copy row if it's the header or if match found
If (row_src = 1) Or (ActiveCell.Value = "D013-LAG R") Then
' Copy source row
Rows(CStr(row_src) & ":" & CStr(row_src)).Select
Selection.Copy
' Go to destination row
Sheets("Destination").Select
Rows(CStr(row_dest) & ":" & CStr(row_dest)).Select
' Copy row
ActiveSheet.Paste
' Make sure next row is copied on the right place
row_dest = row_dest + 1
End If
Next
End Sub
In case you want to copy only a few columns from the source to the destination sheet, try this:
' Copy columns B to E of source row
Range("B" & CStr(row_src) & ":E" & CStr(row_src)).Select
Selection.Copy
' Go to destination
Sheets("Destination").Select
Range("B" & CStr(row_dest)).Select
' Copy these columns
ActiveSheet.Paste
In case the columns to be copied are not consecutive (for instance B, D and F):
Range("B" & CStr(row_src) & ",D" & CStr(row_src) & ",F" & CStr(row_src)).Select
Range("F" & CStr(row_src)).Activate
Selection.Copy
By the way, I don't know this all by heart.
You can easily find out the details by executing within Excel:
- Menu View/Macro/Register Macro (or something similar; I got the Italian version)
- Do manually anything you want to automate
- Menu View/Macro/Interrput registration
- Menu View/Macro/View/Modify
I hope this helps you

Related

copying from one sheet to another

I am trying to copy my data depending on the column value. If column R has invalid, then it should copy all information from sheet1 to sheet2.
I have below code running. Due to some reason it does not copy the last two rows of my sheet1.
I have 551 rows in sheet1 , and I have the 551 row column R as invalid. 'It checks only till 548 rows and skips the last row without moving them.
Could someone help me to fix this issue
Sub Tab()
Dim cell As Range
Dim nextrow As Long
Dim a As Double
Application.ScreenUpdating = False
' get the count of rows in column r
a = Sheets("sheet1").Cells(Rows.count, "R").End(xlUp).Row
MsgBox (a)
For Each cell In Sheets("sheet1").Range("R5:R" & a)
' if the cell in column R has invalid, then copy the entire row to another sheet
If cell.Value = "Invalid" Then
nextrow = Application.WorksheetFunction.CountA(Sheets("sheet2").Range("R:R"))
Rows(cell.Row).Copy Destination:=Sheets("sheet2").Range("A" & nextrow + 1)
End If
Next
Application.ScreenUpdating = True
End Sub
Instead of
Rows(cell.Row).Copy Destination:=Sheets("sheet2").Range("A" & nextrow + 1)
try
Sheets("sheet1").Rows(cell.Row).Copy Destination:=Sheets("sheet2").Range("A" & nextrow + 1)
Your code can be written as
Sub Demo()
Dim cell As Range
Dim nextrow As Long, a as Long
Dim srcSht As Worksheet, destSht As Worksheet
Application.ScreenUpdating = False
Set srcSht = ThisWorkbook.Sheets("Sheet3")
Set destSht = ThisWorkbook.Sheets("Sheet6")
nextrow = Application.WorksheetFunction.CountA(destSht.Range("R:R"))
With srcSht
a = .Cells(.Rows.Count, "R").End(xlUp).Row
MsgBox a
For Each cell In .Range("R5:R" & a)
' if the cell in column R has invalid, then copy the entire row to another sheet
If cell.Value = "Invalid" Then
.Rows(cell.Row).Copy Destination:=destSht.Range("A" & nextrow + 1)
nextrow = nextrow + 1
End If
Next
End With
Application.ScreenUpdating = True
End Sub
Also instead of pasting data row by row you can also use UNION.
I will not go into the part on the variables and methodology (everyone has their way of scripting). I will respond based on your base code above, hopefully it is clear for your understanding.
Sub Tab()
Dim cell As Range
Dim nextrow As Long
Dim a As Double
Application.ScreenUpdating = False
' get the count of rows in column r
a = Sheets("sheet1").Cells(Rows.count, "R").End(xlUp).Row
MsgBox (a)
'This is assuming that you will always populate starting from the first row Range("A1") in Sheet2
nextrow = 1
For Each cell In Sheets("sheet1").Range("R5:R" & a)
' if the cell in column R has invalid, then copy the entire row to another sheet
If cell.Value = "Invalid" Then
'Use the EntireRow function to copy the whole row to the Sheet2.
'During the next iteration, it will +1 to nextrow, so the next record will be copied to Range("A2"), next Range("A3") and so forth.
cell.EntireRow.Copy Destination:=Sheets("Sheet2").Range("a" & nextrow)
nextrow = nextrow + 1
End If
Next
Application.ScreenUpdating = True
End Sub

Integer not storing correct LastRow value after many loops: VBA Run-Time error

In the code below, my LastRow variable is not storing the right row number on the 27th loop (i = 27) causing the code to malfunction
I have used the F8 step through multiple times and noticed that the issue is on the 27th loop. The LastRow variable is meant to be +1204 rows from the previous LastRow value on each iteration of the loop, so I was expecting LastRow = 32509 instead of LastRow = 31316. For reference, on the 26th loop, LastRow = 31305. I'm not sure why the it is finding the wrong LastRow when the code has worked for the first 26 loops.
I am trying to get from my Source Table to my Desired Table:
Source Table
to
Desired Table
Also , the final error that shows is:
Run-Time error '1004': Application -defined or object- defined error
Sub Populate_entity()
Dim i As Integer
i = 1
Dim LastRow As Long
Dim SearchText As String
Do While i < 122 ' go across entity (columns wise)
If i = 1 Then
Range("E1").Select
Selection.Copy
SearchText = ActiveCell.Value
ActiveCell.End(xlToLeft).Select 'snap to left (cell A1)
ActiveCell.Offset(0, 2).Select 'move to cell C1
ActiveCell.Offset(1, 0).Select ' move to cell C2
Else
ActiveCell.Offset(0, i + 1).Select
Selection.Copy
SearchText = ActiveCell.Value
ActiveCell.End(xlToLeft).Select
ActiveCell.Offset(0, 2).Select
ActiveCell.End(xlDown).Select
ActiveCell.Offset(1, 0).Select
End If
ActiveSheet.Paste
ActiveCell.Offset(1203, 0).Select
ActiveSheet.Paste
ActiveCell.End(xlUp).Select
' ======== Error here ========
LastRow = Cells.Find(What:=SearchText, After:=ActiveCell, LookIn:=xlValues, SearchOrder:=xlByRows).Row
Range("C" & ActiveCell.Row & ":C" & LastRow).FillDown
ActiveCell.End(xlUp).Select
i = i + 1
Loop
End Sub
A summary of what you want, as you described in the comments:
Copy the values from cells E1:DU1, paste each cell 1204 times in column C.
1st loop it will paste cell E1 in C2:C1205
2nd loop it will paste cell F1 to C1206:C2409
etc.
This code achieves that:
Sub Populate_entity()
' Declare 2 range variables (top row to copy from and paste destination)
Dim RowRange As Range
Dim PasteCells As Range
' Use the With block to specify the sheet. If you want the destination
' to be another sheet, then you can specify that instead:
' ThisWorkbook.Sheets("SheetName").Range("...")
With ThisWorkbook.ActiveSheet
Set RowRange = .Range("E1:DU1") ' Set range to copy from
Set PasteCells = .Range("C2:C1205") ' Set paste cells, blocks of 1204 cells in column C
End With
' Loop through RowRange, copy each cell's value into PasteCells
' Then offset the PasteCells range by 1024 rows, so next RowRange cell
' is inserted underneath previously copied cells.
Dim ofst As Long
For ofst = 1 To RowRange.Cells.Count
' Use .Value to avoid the (comparably slow) copy/paste operation
PasteCells.Offset((ofst - 1) * 1204, 0).Value = RowRange.Cells(ofst).Value
Next ofst
End Sub
In my opinion you don't need any search because your code always places the SearchString in row 1205. Since you know that it is there you don't need to look for it. This thought brings me to the code below.
Sub Populate_Entity()
Dim C As Long ' Column
Dim Target As Range
Dim FirstRow As Long
Dim LastRow As Long
FirstRow = 2
LastRow = 7 '1205
C = 3
Range("C2").value = Range("E1").value
' Cells(2, C).Value = Cells(1, 5).Value
Do
Set Target = Range(Cells(FirstRow, C), Cells(LastRow, C))
Target.FillDown
C = C + 1
Cells(2, C).value = "Can't figure"
Loop While C < 3 ' 122
End Sub
I have cut the loop short to only 7 rows (instead of 1205) and 3 columns (instead of 122). I just couldn't figure out where the text in the FirstRow should come from. For column C it comes from E1, but where does it come from in the subsequent columns? You can fill this in using the method I showed you above, like, Cells(2, C).Value = Cells(1, 5).Value. I believe that the 5 can be replaced by a value derived from the current C, perhaps C + 2.
Note the Cells(2, C).Value doesn't refer to the value in cell C2. Instead if refers to the cell in Row 2, Column C.

vlookup and if condition copy data vba

I have a code to copy data from one sheet to another as below but its lookup part is not working. if i do not use this lookup function then code is working good
Sub CopyRows()
Dim Rng As Range
Dim Rng2 As Range
Dim Cl As Range
Dim str As String
Dim RowUpdCrnt As Long
Set UsedRange = Sheets("Jan").Range("b5:bk81")
Set Rng = Sheets("Jan").UsedRange 'the range to search ie the used range
Set Rng2 = Sheets("Feb").Range("I5:AK5")
str = "WRK." 'string to look for
Sheets("Feb").Range("B5:B81").Value = ""
RowUpdCrnt = 5
' In my test data, the "WRK."s are in column AN. This For-Each only selects column AN.
' I assume all my "WRK."s are in a single column. Replace "B" by the appropriate
' column letter for your data.
For Each Cl In Rng.Columns("AN").Rows
If Cl.Text = str Then
'if the cell contains the correct value copy it to next empty row on sheet 2 & delete the row
VLookup(Cl.EntireRow.Range("b1"), Sheets("Master").Range("H7:H200"), 1, 0).Copy
Sheets("Feb").Cells(RowUpdCrnt, 2).PasteSpecial xlPasteValues
RowUpdCrnt = RowUpdCrnt + 1
End If
Next Cl
Application.CutCopyMode = False
End Sub
According to your post, the only thing you want to copy are the values, so you can just qualify the cells (without using Copy >> Paste), by using Sheets("Feb").Range("B" & RowUpdCrnt).Value = Application.VLookup(.Range("B" & Cl.Row).Value, Sheets("Master").Range("H7:H200"), 1, 0)
Try the code below:
With Sheets("Jan")
' loop until last row with data in Column AN (and not the entire column) to save time
For Each Cl In .Range("AN1:AN" & .Cells(.Rows.Count, "AN").End(xlUp).Row)
If Cl.Value Like str Then
'if the cell contains the correct value copy it to next empty row on sheet 2 & delete the row
If Not IsError(Application.VLookup(.Range("B" & Cl.Row).Value, Sheets("Master").Range("H7:H200"), 1, 0)) Then ' <-- verify the VLookup was successful
Sheets("Feb").Range("B" & RowUpdCrnt).Value = Application.VLookup(.Range("B" & Cl.Row).Value, Sheets("Master").Range("H7:H200"), 1, 0)
RowUpdCrnt = RowUpdCrnt + 1
End If
End If
Next Cl
End With

Excel VBA macro to copy specific rows from workbook sheets into new summary sheet....almost works

I need to be able to look at a specified range of cells in every worksheet of my workbook and if they meet criteria, copy that row to a summary sheet. The below code works for the most part except there are a few instances where it copies rows that do not meet the criteria and one instance where it skips a row it should have copied.
Is there a way to use a debug tool so that at any time while cycling through the code I can see: What is the active sheet? What is the active cell? What is the active row? etc.
Also, should I use a -For Each Cell in Range- instead of -While Len- to loop through the specified range on each sheet?
Sub LoopThroughSheets()
Dim LSearchRow As Integer
Dim LCopyToRow As Integer
Dim ws As Worksheet
'Start copying data to row 2 in HH (row counter variable)
LCopyToRow = 2
For Each ws In ActiveWorkbook.Worksheets
'Start search in row 7
LSearchRow = 7
While Len(ws.Range("M" & CStr(LSearchRow)).Value) > 0
'If value in column M > 0.8, copy entire row to HH
If ws.Range("M" & CStr(LSearchRow)).Value > 0.8 Then
'Select row in active Sheet to copy
Rows(CStr(LSearchRow) & ":" & CStr(LSearchRow)).Select
Selection.Copy
'Paste row into HH in next row
Sheets("HH").Select
Rows(CStr(LCopyToRow) & ":" & CStr(LCopyToRow)).Select
ActiveSheet.Paste
'Move counter to next row
LCopyToRow = LCopyToRow + 1
'Go back to active ws to continue searching
ws.Activate
End If
LSearchRow = LSearchRow + 1
Wend
Next ws
'Position on cell A1 in sheet HH
Sheets("HH").Select
Application.CutCopyMode = False
Range("A1").Select
MsgBox "All matching data has been copied."
End Sub
Very similar to the previous answer just worded differently.Same results though.
Sub Button1_Click()
Dim Rws As Long, Rng As Range, ws As Worksheet, sh As Worksheet, c As Range, x As Integer
Set ws = Worksheets("HH")
x = 2
Application.ScreenUpdating = 0
For Each sh In Sheets
If sh.Name <> ws.Name Then
With sh
Rws = .Cells(Rows.Count, "M").End(xlUp).Row
Set Rng = .Range(.Cells(7, "M"), .Cells(Rws, "M"))
For Each c In Rng.Cells
If c.Value > 0.8 Then
c.EntireRow.Copy Destination:=ws.Cells(x, "A")
x = x + 1
End If
Next c
End With
End If
Next sh
End Sub
For your first question about debugging, you can use:
Debug.Print "Worksheet: " & ActiveSheet.Name
at any time in your code to print out which sheet you are on into the "Immediate" window in the Visual Basic Editor. This is great for debugging in all scenarios.
Second, a For Each loop is the fastest way to loop through anything but it has disadvantages. Namely, if you are deleting/inserting anything it will return funny results (Copy/Paste will be ok). Any sort of While loop is better to use if you don't have a predetermined idea of how many rows you are going to need to work through.
As far as your code is concerned this is how I would do it (you would still need to include your code above and below the while loop):
Dim Items As Range
Dim Item As Range
'This will set the code to loop from M7 to the last row, if you
'didn't want to go to the end there is probably a better way to do it.
Set Items = ws.Range("M7:M26")
For Each Item In Items
'If value in column M > 0.8, copy entire row to HH
If Item.Value > 0.8 Then
'Select row in active Sheet to copy
Item.EntireRow.Copy
'Paste row into HH in next row
Sheets("HH").Rows(LCopyToRow & ":" & LCopyToRow).PasteSpecial
'Move counter to next row
LCopyToRow = LCopyToRow + 1
End If
Next Item

Find row value, copy row and all the range underneath for data reduction

I am trying to use a macro to clean up data files and only copy on Sheet2 what is most relevant.
I have written the code to find the row I want the data to be copied from. However I can only copy the row itself and not the range underneath. Please note I need the range to go from that row to the last column and last row as the size of the matriz always varies.
s N s N s N s N s rpm
Linear Real Linear Real Linear Real Linear Real Linear Amplitude
0.0000030 9853.66 0.0000030 5951.83 0.0000030 533.48 0.0000030 476.15 0.0000030 2150.16
0.0000226 9848.63 0.0000226 5948.19 0.0000226 557.02 0.0000226 488.60 0.0000226 2150.16
0.0000421 9826.05 0.0000421 5956.22 0.0000421 615.94 0.0000421 480.75 0.0000421 2150.15
0.0000616 9829.72 0.0000616 5989.72 0.0000616 642.59 0.0000616 476.77 0.0000616 2150.15
So basically the code below finds that first row and copies it in Sheet2. I need the macro to also select the range underneath and copy it onto Sheet2. Please can you help me finishing off the script?
Sub SearchForRawData()
Dim LSearchRow As Integer
Dim LCopyToRow As Integer
On Error GoTo Err_Execute
'Start search in row 1
LSearchRow = 1
'Start copying data to row 2 in Sheet2 (row counter variable)
LCopyToRow = 2
While Len(Range("A" & CStr(LSearchRow)).Value) >= 0
'If value in column A = "s", copy entire row to Sheet2
If Range("A" & CStr(LSearchRow)).Value = "s" Then
'Select row and range in Sheet1 to copy
Rows(CStr(LSearchRow) & ":" & CStr(LSearchRow)).Select
Selection.Copy
'Paste row into Sheet2 in next row
Sheets("Sheet2").Select
Rows(CStr(LCopyToRow) & ":" & CStr(LCopyToRow)).Select
ActiveSheet.Paste
'Select all Raw Data underneath found Row to Copy
'Paste all Raw Data into Sheet 2
'Move counter to next row
LCopyToRow = LCopyToRow + 1
'Go back to Sheet1 to continue searching
Sheets("Sheet1").Select
End If
LSearchRow = LSearchRow + 1
Wend
'Position on cell A1
Application.CutCopyMode = False
Range("A1").Select
MsgBox "All matching data has been copied."
Exit Sub
Err_Execute:
MsgBox "An error has occured"
End Sub
You don't need a loop for this if you want to copy the row that has the "s" and everything below it to the target sheet. The following sub finds the row with the "s" in column A and then copies that row and everything below it to the target sheet.
Note that you should always avoid selecting or activating anything in VBA code, and that the normal way to copy and paste relies on selecting. If you use the syntax I've included here, the clipboard is not used and the target sheet does not need to be selected.
Sub CopyRowAndBelowToTarget()
Dim wb As Workbook
Dim src As Worksheet
Dim tgt As Worksheet
Dim match As Range
Set wb = ThisWorkbook
Set src = wb.Sheets("Sheet1")
Set tgt = wb.Sheets("Sheet2")
Dim lastCopyRow As Long
Dim lastPasteRow As Long
Dim lastCol As Long
Dim matchRow As Long
Dim findMe As String
' specify what we're searching for
findMe = "s"
' find our search string in column A (1)
Set match = src.Columns(1).Find(What:=findMe, After:=src.Cells(1, 1), _
LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
' figure out what row our search string is on
matchRow = match.Row
' get the last row and column with data so we know how much to copy
lastCopyRow = src.Range("A" & src.Rows.Count).End(xlUp).Row
lastCol = src.Cells(1, src.Columns.Count).End(xlToLeft).Column
' find out where on our target sheet we should paste the results
lastPasteRow = tgt.Range("A" & src.Rows.Count).End(xlUp).Row
' use copy/paste syntax that doesn't use the clipboard
' and doesn't select or activate
src.Range(Cells(matchRow, 1), Cells(lastCopyRow, lastCol)).Copy _
tgt.Range("A" & lastPasteRow)
End Sub
Rows(CStr(LSearchRow) & ":" & CStr(LSearchRow)).Select
So firstly you don't acutally need the CStr, vba will cast numbers to strings by itself, i.e. Range(LSearchRow & ":" & LSearchRow) should work fine.
To find how many rows down to go use the end function of the range object:
bottomRow = Range("A" & LSearchRow).End(xldown).Row
Do the same for the column
lastCol = Range("A" & LSearchRow).End(xlleft).column
Now to copy:
Range("A" & LSearchRow & ":" & lastCol & bottomRow).Copy
However if you have empty cells inthe middleof the data then instead of using End(xldown), start at the bottom of the sheet and look up:
bottomRow = Range("A1000000").End(xlup).Row
etc