I have this code which cuts and pastes an entire row to another sheet. When i set values as = it works, but when i set to like or contains, the loop doesnt happen. The value of the filter i'm looking for would keep changing including with a unique phrase. Eg: 1. Overlap error: 1234, 1. Overlap error:1235 etc.
Sub loopMe()
Dim sh As Worksheet, ws As Worksheet
Dim LstR As Long, rng As Range, c As Range
Set sh = Sheets("Sheet1") 'set the sheet to loop
Set ws = Sheets("Sheet2") 'set the sheet to paste
With sh 'do something with the sheet
LstR = .Cells(.Rows.Count, "BE").End(xlUp).Row 'find last row
Set rng = .Range("BE5:BE" & LstR) 'set range to loop
End With
'start the loop
For Each c In rng.Cells
'If c = "1. Overlap error:" Then
If c.Value Like "*1. Overlap error:*" Then
'If Left(c.Value, 17) = "1. Overlap error:" Then
'If InStr(1, c, "1. Overlap error:") > 0 Then
c.EntireRow.Copy ws.Cells(ws.Rows.Count, "A").End(xlUp).Offset(1) 'copy row to first empty row in sheet2
c.EntireRow.Delete Shift:=xlUp
End If
Next c
End Sub
You can use a filter to find the data, move it and delete the rows.
Sub ed()
Dim sh As Worksheet, ws As Worksheet
Dim rng As Range
Set sh = Sheets("Sheet1")
Set ws = Sheets("Sheet2")
With sh
.Range("BE4").AutoFilter Field:=1, Criteria1:= _
"=*1. Overlap error:*", Operator:=xlAnd
Set rng = .Range("BE5:BE" & .Cells(.Rows.Count, "BE").End(xlUp).Row)
With ws
rng.SpecialCells(xlCellTypeVisible).EntireRow.Copy ws.Cells(ws.Rows.Count, "A").End(xlUp).Offset(1)
End With
rng.EntireRow.Delete
.AutoFilterMode = False
End With
End Sub
So if you prefer your original approach,
Sub loopMe()
Dim sh As Worksheet, ws As Worksheet
Dim LstR As Long, c As Range
Set sh = Sheets("Sheet1")
Set ws = Sheets("Sheet2")
'find last row
LstR = sh.Range("BE65000").End(xlUp).Row
Dim irow
For irow = LstR To 5 Step -1
Set c = sh.Range("BE" & irow)
If c.Value Like "*1. Overlap error:*" Then
'copy row to first empty row in sheet2
c.EntireRow.Copy ws.Cells(65000, 1).End(xlUp).Offset(1, 0)
c.EntireRow.Delete Shift:=xlUp
End If
Next irow
End Sub
Related
Completely new to VBA. I basically copied the code below and I am repurposing it.. the code essentially selects a row based on whether a certain cell has a certain value. eg. if K5 is "yes" then select the row "K5" copy and paste into a new worksheet.
I am trying to do something slightly different. I want to select certain cells as opposed to the whole entire row - How do I do this
For example, If K5 is "yes", then select A5:D5 & K5 & I5??
Currently the below code below copys the whole "k5" row and pastes it in sheet 2 if there a "y" that appears in the cell "k5"..
Private Sub CommandButton1_Click()
'Declare variables
Dim sht1 As Worksheet
Dim sht2 As Worksheet
Dim sht3 As Worksheet
Dim lastRow1 As Long, lastRow2 As Long, lastRow3 As Long
Dim Cell As Range
Dim RngToDelete As Range
Application.ScreenUpdating = False
'Set variables
Set sht1 = Sheets("To DO")
Set sht2 = Sheets("Ongoing")
Set sht3 = Sheets("Done")
'Select Entire Row
'Selection.EntireRow.Select
'Move row to destination sheet & Delete source row
lastRow1 = sht1.Range("A" & sht1.Rows.Count).End(xlUp).Row
lastRow2 = sht2.Range("A" & sht2.Rows.Count).End(xlUp).Row
lastRow3 = sht3.Range("A" & sht3.Rows.Count).End(xlUp).Row
With sht2
' loop column H untill last cell with value (not entire column)
For Each Cell In .Range("H2:H" & .Cells(.Rows.Count, "H").End(xlUp).Row)
If Cell.Value = "Not started" Then
If RngToDelete Is Nothing Then
Set RngToDelete = Cell
Else
Set RngToDelete = Union(RngToDelete, Cell)
End If
lastRow1 = sht1.Range("A" & sht1.Rows.Count).End(xlUp).Row
' Copy>>Paste in 1-line (no need to use Select)
.Rows(Cell.Row).Copy Destination:=sht1.Rows(lastRow1 + 1)
'.Rows(Cell.Row).Delete
ElseIf Cell.Value = "Closed" Then
If RngToDelete Is Nothing Then
Set RngToDelete = Cell
Else
Set RngToDelete = Union(RngToDelete, Cell)
End If
lastRow3 = sht3.Range("A" & sht3.Rows.Count).End(xlUp).Row
' Copy>>Paste in 1-line (no need to use Select)
.Rows(Cell.Row).Copy Destination:=sht3.Rows(lastRow3 + 1)
'.Rows(Cell.Row).Delete
End If
Next Cell
End With
If Not RngToDelete Is Nothing Then RngToDelete.EntireRow.Delete
Application.CutCopyMode = 0
Application.ScreenUpdating = True
MsgBox "Update Done!"
End Sub
I tried to implement the below (ignore the actual cells being copied, the concept of multiple cells instead of the entire row is what im after - sourced from Select multiple ranges with VBA), which seems to work if I use it on its own, but im not able or sure where to implement it in the code above to do what I want it to do.
set rng = Union(.Range("A84:B" & LastRow),.Range("D84:E" & LastRow),.Range("H84:J" & LastRow))
Thanks for your time
Here's one way to do it:
Private Sub CommandButton1_Click()
Dim sht1 As Worksheet, sht2 As Worksheet, sht3 As Worksheet
Dim Cell As Range, e, rngDest As Range
Dim RngToDelete As Range, wsDest As Worksheet
Application.ScreenUpdating = False
Set sht1 = Sheets("To DO")
Set sht2 = Sheets("Ongoing")
Set sht3 = Sheets("Done")
For Each Cell In sht2.Range("H2:H" & _
sht2.Cells(sht2.Rows.Count, "H").End(xlUp).Row).Cells
Select Case Cell.Value 'check the row...
Case "Not started": Set wsDest = sht1
Case "Closed": Set wsDest = sht3
Case Else: Set wsDest = Nothing
End Select
If Not wsDest Is Nothing Then 'any row to copy?
BuildRange RngToDelete, Cell 'build up the delete range
Set rngDest = wsDest.Cells(Rows.Count, "A").End(xlUp).Offset(1)
For Each e In Array("A1:D1", "K1", "I1") 'array of cells/ranges to copy, in order
With Cell.EntireRow.Range(e) '#note Range() is *relative* to EntireRow
.Copy rngDest 'copy this cell/area
Set rngDest = rngDest.Offset(0, .Columns.Count) 'next paste destination
End With
Next e
End If
Next Cell
If Not RngToDelete Is Nothing Then RngToDelete.EntireRow.Delete
Application.CutCopyMode = 0
Application.ScreenUpdating = True
MsgBox "Update Done!"
End Sub
'utility sub for building up a range
Sub BuildRange(ByRef rngTot As Range, rngAdd As Range)
If rngTot Is Nothing Then
Set rngTot = rngAdd
Else
Set rngTot = Application.Union(rngTot, rngAdd)
End If
End Sub
I need to find certain names on a worksheet, copy the entire row once it finds said name and paste it on another worksheet.
I wrote code that finds one of the names, then copies the row and pastes it to another sheet.
Sub Macro2()
Dim StatusCol As Range
Dim Status As Range
Dim PasteCell As Range
Set StatusCol = Sheet10.Range("A1:AV1569")
For Each Status In StatusCol
If Sheet11.Range("A2") = "" Then
Set PasteCell = Sheet11.Range("A2")
Else
Set PasteCell = Sheet11.Range("A1").End(xlDown).Offset(1, 0)
End If
If Status = "Jane Thompson" Then Status.Offset(0, -4).Resize(1, 5).Copy PasteCell
Next Status
End Sub
Instead of finding only one string, the "Jane Thompson" name, I want to loop through a list of names, find each, copy the entire row where they are located and paste the row into another sheet. I have all the names on another worksheet (about 80 different names)
I managed to find code that gives me the desired output:
Sub FruitBasket()
Dim rngCell As Range
Dim lngLstRow As Long
Dim strFruit() As String
Dim intFruitMax As Integer
intFruitMax = 3
ReDim strFruit(1 To intFruitMax)
strFruit(1) = "Fruit 2"
strFruit(2) = "Fruit 5"
strFruit(3) = "Fruit 18"
lngLstRow = ActiveSheet.UsedRange.Rows.Count
For Each rngCell In Range("A2:A" & lngLstRow)
For i = 1 To intFruitMax
If strFruit(i) = rngCell.Value Then
rngCell.EntireRow.Copy
Sheets("Inventory").Select
Range("A65536").End(xlUp).Offset(1, 0).Select
Selection.PasteSpecial xlPasteValues
Sheets("Fruit").Select
End If
Next i
Next
End Sub
But instead of 3 items in the array, I had to hard code 81 names. Is there any way to pull the items of an array from another sheet?
With the names in an array you can use Match rather than looping through them.
Option Explicit
Sub FruitBasket()
Dim ws As Worksheet, wsInv As Worksheet
Dim rngCell As Range, v As Variant, arNames
Dim lngLastRow As Long, lngInvRow As Long
With Sheets("Names")
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
arNames = .Range("A2:A" & lngLastRow)
End With
Set wsInv = Sheets("Inventory")
With wsInv
lngInvRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Application.ScreenUpdating = False
Set ws = ActiveSheet
With ws
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For Each rngCell In .Range("A2:A" & lngLastRow)
' check if value is in array
v = Application.Match(rngCell, arNames, 0)
If IsError(v) Then
' no match
Else
' match
rngCell.EntireRow.Copy
lngInvRow = lngInvRow + 1
wsInv.Cells(lngInvRow, "A").PasteSpecial xlPasteValues
End If
Next
End With
Application.CutCopyMode = False
Application.ScreenUpdating = True
MsgBox "Done"
End Sub
I have been trying to create a function which checks that if Col"B" <> Empty then copy the third cell which is under the same row.
I have this Data:
Where from i want to copy the Col"D" highlighted cells and paste them into same row where Col"B" <> empty.
Here is the final result. Your help will be appreciated in this regards.
Option Explicit
Sub CopyPasting()
Dim ws As Worksheet
Dim r As Long
Dim LastRow As Long
Dim n As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
LastRow = .Range("D" & .Rows.Count).End(xlUp).Row
For r = LastRow To 2 Step -2
If .Cells(r, "B") <> "" Then
.Rows(r + "D").Copy
.Rows(r + "D").PasteSpecial
n = n + 1
End If
Next
End With
End Sub
Please, try the next code:
Sub testRetOffset3()
Dim sh As Worksheet, lastR As Long, rngV As Range, rngFin As Range, c As Range
Set sh = ActiveSheet 'use here the sheet you need
lastR = sh.Range("B" & sh.rows.count).End(xlUp).row 'last sheet row
On Error Resume Next 'if not empty cells in column, it will not return the range and raise an error
Set rngV = sh.Range("B2:B" & lastR).SpecialCells(xlCellTypeConstants)
On Error GoTo 0
If rngV Is Nothing Then Exit Sub 'stop the code if run on a wrong sheet, without empty cells in column B:B
For Each c In rngV.cells 'iterate between the discontinuous range cells
If rngFin Is Nothing Then 'if the final range is not set (first time)
Set rngFin = c.Offset(3, 2) 'set the range = the Offset necessary cell
Else
Set rngFin = Union(rngFin, c.Offset(3, 2)) 'make a Union between existing range and the Offset necessary cell
End If
Next
If Not rngFin Is Nothing Then 'copy both ranges in consecutive columns
rngV.Copy sh.Range("F2")
rngFin.Copy sh.Range("G2")
End If
End Sub
It will return in columns F:G, starting from the second row. It is easy to modify the range where to return...
You can even clear the existing processed columns and return in B:C, or in another sheet.
Edited:
In order to solve the last request, please use the next code:
Sub testRetOffsetMoreRows()
Dim sh As Worksheet, lastR As Long, rngV As Range, rngFin As Range, A As Range
Set sh = ActiveSheet
lastR = sh.Range("B" & sh.rows.count).End(xlUp).row
On Error Resume Next
Set rngV = sh.Range("A2:D" & lastR).SpecialCells(xlCellTypeConstants)
On Error GoTo 0
If rngV Is Nothing Then Exit Sub
For Each A In rngV.Areas 'iterate between the range areas
If rngFin Is Nothing Then
Set rngFin = A.cells(1,2).Offset(3, 3) 'use the second cell of the area
Else
Set rngFin = Union(rngFin, A.cells(1,2).Offset(3, 3))
End If
Next
If Not rngFin Is Nothing Then
rngV.Copy sh.Range("H2")
rngFin.Copy sh.Range("L2")
End If
End Sub
But take care to have continuous ranges when have a value in column B:B. Otherwise, the code may fail... The areas property will return differently.
I wasn't sure where you wanted the output, this will put it into a sheet called "Sheet2". (You'll have to make that before running the code it won't create it for you.)
Dim i As Long
Dim j As Long
Dim lr As Long
Dim srcWS As Worksheet
Dim destWS As Worksheet
Set srcWS = ThisWorkbook.Sheets("Sheet1")
Set destWS = ThisWorkbook.Sheets("Sheet2")
With srcWS
lr = .Cells(.Rows.Count, 4).End(xlUp).Row
j = 2
For i = 2 To lr
If .Cells(i, 2).Value <> "" Then
destWS.Cells(j, 1).Value = .Cells(i, 2).Value
destWS.Cells(j, 2).Value = .Cells(i, 4).Offset(2, 0).Value
j = j + 1
End If
Next i
End With
If you need the colors copied over as well then use this:
.Cells(i, 4).Offset(2, 0).Copy
destWS.Cells(j, 2).PasteSpecial xlPasteAll
instead of:
destWS.Cells(j, 2).Value = .Cells(i, 4).Offset(2, 0).Value
For each value in Sheet("Scrap2") Column A.
find all matching instances of this value in column A of Sheet("VA_Data"). copy entire row and paste to first empty Row on sheet("List")
My code right now basically only copys the first instance it comes to of the match and then moves to the next value in Sheet("Scrap2").
If there are 10 cells in col A of sheet "VA_Data" that match the first value of Scrap2, then those 10 rows need to copy entire row and paste to first empty rows on sheet "List".
any help is appreciated.
Option Explicit
Public Sub Loop_VA_Data()
Dim wsa As Worksheet
Dim wsb As Worksheet
Dim wsc As Worksheet
Dim a As Integer
Dim b As Integer
Dim c As Integer
Dim stra As String
Dim rng As Range
On Error GoTo errLoop_VA_Data
Application.ScreenUpdating = False
Set wsa = ThisWorkbook.Worksheets("Scrap2")
Set wsb = ThisWorkbook.Worksheets("VA_Data")
Set wsc = ThisWorkbook.Worksheets("List")
wsa.Range("B:B").Clear
wsc.Rows("2:" & wsc.Range("A1").CurrentRegion.Rows.Count + 1).Clear
a = 2
Do
If Trim(wsa.Cells(a, 1).Value) = "" Then
Exit Do
End If
stra = Trim(wsa.Cells(a, 1).Value)
Set rng = wsb.Range("A:A").Find(What:=stra, LookIn:=xlValues, LookAt:=xlWhole)
If Not (rng Is Nothing) Then
b = rng.Row
c = wsc.Range("A1").CurrentRegion.Rows.Count + 1
wsb.Rows(b).Copy wsc.Rows(c)
wsa.Cells(a, 2).Value = "Found on row " & b
Else
wsa.Cells(a, 2).Value = "Not Found"
End If
If Not (rng Is Nothing) Then
Set rng = Nothing
End If
a = a + 1
Loop
MsgBox "Complete!", vbInformation
GoTo closeout
Exit Sub
errLoop_VA_Data:
MsgBox "Err Number is: " & Err.Number & " / Err Desc is: " & Err.Description & " in sub Loop_VA_Data!", vbCritical
closeout:
If Not (wsa Is Nothing) Then
Set wsa = Nothing
End If
If Not (wsb Is Nothing) Then
Set wsb = Nothing
End If
If Not (wsc Is Nothing) Then
Set wsc = Nothing
End If
If Not (rng Is Nothing) Then
Set rng = Nothing
End If
Exit Sub
End Sub
I think #urdearboy has the right idea - using a filter & copying en masse. The following code assumes the data on your VA_Data sheet is contiguous. Let me know how you go with it.
Option Explicit
Sub Filter_Copy()
Application.ScreenUpdating = False
Dim c As Range
Dim LastRow As Long, PasteRow As Long
Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet
Set ws1 = Sheets("Scrap2")
Set ws2 = Sheets("VA_Data")
Set ws3 = Sheets("List")
LastRow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
For Each c In ws1.Range(ws1.Cells(1, 1), ws1.Cells(LastRow, 1))
With ws2.Cells(1, 1).CurrentRegion
.AutoFilter 1, c.Value
PasteRow = ws3.Cells(Rows.Count, 1).End(xlUp).Row + 1
.Offset(1).Resize(.Rows.Count - 1).Copy ws3.Range("A" & PasteRow)
.AutoFilter
End With
Next c
End Sub
I have data in a table, where I compare two columns J and T. The values which J and T can take include A2B, APL, BGF, CMA, among others (see code).
If these values are equal, copy row i into the sheet which has the name of the cells just checked.
If these values are not equal, copy row i into the sheets which have the name of the cells just checked.
Example: Compare J2 and T2,
Suppose J2=T2=BGF then copy row 2 and paste into sheet("BGF")
Next, compare J3 and T3
Suppose J3=BGF and T3=CMA, copy row 3 and paste into sheet(BGF) and sheet(CMA)
Next, compare J4 and T4
Suppose J4=Nothing and T4=CMA, copy row 4 and paste into sheet CMA
the only other combination is where Ji has a value and Ti is empty.
Problem: When running this code, If J3=BGF and T3= nothing (its empty), then the line is not copied to any sheet.
Here's the code
Sub Sortdata()
'step 1 clear all data
Sheets("A2B").Cells.ClearContents
Sheets("APL").Cells.ClearContents
Sheets("BGF").Cells.ClearContents
Sheets("CMA").Cells.ClearContents
Sheets("K Line").Cells.ClearContents
Sheets("MacAndrews").Cells.ClearContents
Sheets("Maersk").Cells.ClearContents
Sheets("OOCL").Cells.ClearContents
Sheets("OPDR").Cells.ClearContents
Sheets("Samskip").Cells.ClearContents
Sheets("Unifeeder").Cells.ClearContents
Dim i As Long
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim LastRow As Long
With Worksheets("All Data")
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
For i = 2 To LastRow
If IsEmpty(.Range("J" & i)) Then
Set ws1 = Nothing
Else
Set ws1 = Worksheets(.Range("J" & i).Value)
End If
If IsEmpty(.Range("T" & i)) Then
Set ws2 = Nothing
Else
Set ws2 = Worksheets(.Range("T" & i).Value)
End If
If ws1 Is Nothing Then
If Not ws2 Is Nothing Then
CopyToWs ws2, .Rows(i)
End If
ElseIf ws2 Is Nothing Then
If Not ws1 Is Nothing Then
CopyToWs ws1, .Rows(i)
End If
Else
CopyToWs ws1, Rows(i)
If ws1.Name <> ws2.Name Then
CopyToWs ws2, .Rows(i)
End If
End If
Next
End With
End Sub
Sub CopyToWs(ws As Worksheet, rng As Range)
rng.Copy
ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(1, 0).EntireRow.PasteSpecial xlPasteValuesAndNumberFormats
End Sub
Please try this code. It takes a slightly different approach to what you tried but it gets the job done, I think.
Option Explicit
Sub Sortdata()
' Variatus #STO 20 Jan 2020
Const WsNames As String = "A2B,APL,BGF,CMA,K Line,MacAndrews," & _
"Maersk,OOCL,OPDR,Samskip,Unifeeder"
Dim WsS As Worksheet ' Source
Dim Ws As Worksheet
Dim Rng As Range
Dim Rt As Long ' target row
Dim LastRow As Long
Dim J As Long, T As Long
Dim Tmp As Variant, PrevTmp As Variant
Dim R As Long, C As Long
'step 1 clear all data
Tmp = Split(WsNames, ",")
For R = LBound(Tmp) To UBound(Tmp)
On Error Resume Next
Worksheets(Tmp(R)).Cells.ClearContents
Next R
Application.ScreenUpdating = False
Set WsS = Worksheets("All Data")
With WsS
J = .Columns("J").Column
T = .Columns("T").Column
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For R = 2 To LastRow
PrevTmp = ""
For C = J To T Step T - J
Tmp = .Cells(R, C).Value
If Len(Tmp) And Tmp <> PrevTmp Then
On Error Resume Next
Set Ws = Worksheets(Tmp)
If Err = 0 Then
Set Rng = .Range(.Cells(R, 1), .Cells(R, .Columns.Count).End(xlToLeft))
With Ws
Rt = Application.Max(.Cells(.Rows.Count, "A").End(xlUp).Row + 1, 2)
Rng.Copy Destination:=Ws.Cells(Rt, 1)
End With
End If
End If
PrevTmp = Tmp
Next C
If R Mod 25 = 0 Then Application.StatusBar = "Currently processing row " & R
Next R
End With
With Application
.ScreenUpdating = True
.StatusBar = "Done"
End With
End Sub
I think you will be able to find your way through it and make any required modifications. Let me know if you require any assistance.