VBA for if -then- else statement - excel

Below is code that I came up which copies values from cell Q13, and pastes them into column E until the list is complete (Q13 is updated with a new value each time). I have a condition which says if Q13 reads "45" copy that value and paste it into the p column. I know this an if -then- else statment, but I get a couple different compile errors (block if without end if, and if without block if) and realize it's most likely my syntax. If someone could review this that would be fantastic.
Sub Test()
Dim c As Range
Dim ws As Worksheet: Set ws = Sheet2
Dim range1 As Range: Set range1 = ws.Range("Q13")
Dim Cell As Range
For Each Cell In range1
If Cell.Value = "45" Then
NextRow = ws.Cells(ws.Rows.Count, "P").End(xlUp).Offset(1, 0).Row
Cell.Copy ws.Range("P" & NextRow)
Else
For Each c In Range("B2:B" & Range("B65536").End(xlUp).Row)
Dim R As Range
Set R = Worksheets("Sheet2").Cells(Rows.Count, "E").End(xlUp) 'last cell in Column E with data
If Len(R.Value) > 0 Then Set R = R.Offset(1)
R.Value = Worksheets("Sheet2").Range("Q13").Value
Exit For
End If
Next ws
End If

Don't put a loop variable after the Next keyword, it's useless. The only thing it can do, is make VBA throw a compiler error if you use the wrong loop variable - as is the case here. If there's so much code in the a loop body that you no longer know where you're at by the time you reach the bottom, then the loop body is doing too many things. The solution is to pull code from the loop body into smaller, more specialized procedures.
Use an indenter if you aren't sure how to properly indent your code: it makes this kind of syntax error blatantly obvious:
Dim c As Range
Dim ws As Worksheet: Set ws = Sheet2
Dim range1 As Range: Set range1 = ws.Range("Q13")
Dim Cell As Range
For Each Cell In range1
| If Cell.Value = "45" Then
| | NextRow = ws.Cells(ws.Rows.Count, "P").End(xlUp).Offset(1, 0).Row
| | Cell.Copy ws.Range("P" & NextRow)
| Else
| | For Each c In Range("B2:B" & Range("B65536").End(xlUp).Row)
| | | Dim R As Range
| \ | Set R = Worksheets("Sheet2").Cells(Rows.Count, "E").End(xlUp) 'last cell in Column E with data
\ |\ / If Len(R.Value) > 0 Then Set R = R.Offset(1)
\ | \/ R.Value = Worksheets("Sheet2").Range("Q13").Value
\ / /\ Exit For
/\/ End If
/ Next
End If
The If...Else...End If block is terminated with a Next; the inner For Each...Next loop is terminated with an End If, and the outer For Each...Next loop is terminated with End If - you need to de-tangle this.
Dim c As Range
Dim ws As Worksheet: Set ws = Sheet2
Dim range1 As Range: Set range1 = ws.Range("Q13")
Dim Cell As Range
For Each Cell In range1
If Cell.Value = "45" Then
NextRow = ws.Cells(ws.Rows.Count, "P").End(xlUp).Offset(1, 0).Row
Cell.Copy ws.Range("P" & NextRow)
Else
For Each c In Range("B2:B" & Range("B65536").End(xlUp).Row)
Dim R As Range
Set R = Worksheets("Sheet2").Cells(Rows.Count, "E").End(xlUp) 'last cell in Column E with data
If Len(R.Value) > 0 Then Set R = R.Offset(1)
R.Value = Worksheets("Sheet2").Range("Q13").Value
Exit For
Next
End If
Next

Related

How to copy specific rows to another sheet below black cell

I want to write a macro to copy rows from one worksheet to another below cell that is colored black (manually) - if it is detected, otherwise just copy rows from first sheet to Sheet1 at the top. After many trials and errors I came up with that code:
Sub copytherows(clf As Long, lastcell As Long) 'clf - cell that marks the start, lastcell - ending cell
Dim st As Long, cnext As Range
Dim wshet As Worksheet
Dim wshetend As Worksheet
'st - start of looking up, cnext - range of lines, wshet - worksheet
Dim coprange As String
Dim cnextcoprow, cnextrow As Long
'variables for copying macro part
Dim rangehelper As Range
Dim TargetColor As Long
Dim cell As Range
Dim sht As Worksheet
Dim x As Long
Dim Aend As Long
Set wshet = Worksheets(1)
Set wshetend = Sheets("Sheet1")
wshetend.Cells.Delete
For st = 1 To wshet.Cells(Rows.Count, "B").End(xlUp).Row
If wshet.Cells(st, "B").Interior.Color = clf Then 'has the color of interest
cnextcoprow = st
Set cnext = wshet.Cells(st, "B").Offset(1, 0) 'next cell down
Do While cnext.Interior.Color <> lastcell
Set cnext = cnext.Offset(1, 0) 'next row
Loop
st = st + 1
End If
Next st
cnextrow = cnext.Row - 1
coprange = cnextcoprow & ":" & cnextrow
Aend = Cells(Rows.Count, "A").End(xlUp).Row
'set color is black
TargetColor = RGB(255, 255, 255)
wshetend.Activate
For x = 1 To Rows.Count
If wshetend.Cells(x, "A").Interior.Color = TargetColor Then
x = x + 1
Set rangehelper = wshetend.Rows(x)
wshet.Range(coprange).Copy wshetend.Range(rangehelper).Offset(1)
Else
wshet.Range(coprange).Copy wshetend.Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
Next x
End Sub
When Macro is ran it displays an error(Run-time error '1004' Method 'Range' of object '_Worksheet' failed on line :
wshet.Range(coprange).Copy wshetend.Range(rangehelper).Offset(1)
Sheet1 is for sure present in Workbook.
Edit as suggested by #FaneDuru:
1 - in this image is my curret state of worksheet that is wshet in my macro and for example if I select (by checkboxes) section1 and section3, section3 should be in the place of black cell in section1 (the order of sections doesn't really matter to me) inside destination sheet ( I know I'm not good in explaining things like that).
2 - this should be end result of this macro
It's quite confusing how you use the for loops.
In the first one you use it to check for the start -which is fine- but then you put a while loop in there which will end up in an endless loop once your st gets past your lastcell row, instead use
ElseIf wshet.Cells(st, "B").Interior.Color = lastcell Then
cnextrow = st
Exit For
End If
In the second for loop you copy the rows if you find the black cell but you don't exit the for loop, speaking of which, you delete all the cells in your wshetend so you'll always start at row 1. So either you don't want to delete all the cells in your wshetend or the for loop is unnecessary.
This is my testSub and it copies from the first sheet to Sheet2 after the cell with black background (black = 0) (commented out the delete cells)
Sub TestBlackCellCopy()
Dim st As Long, cnext As Range
Dim wshet As Worksheet
Dim wshetend As Worksheet
'st - start of looking up, cnext - range of lines, wshet - worksheet
Dim coprange As String
Dim cnextcoprow, cnextrow As Long
'variables for copying macro part
Dim rangehelper As Range
Dim TargetColor As Long
Dim cell As Range
Dim sht As Worksheet
Dim x As Long
Dim Aend As Long
Dim clf As Long, lastcell As Long
clf = 5296274
lastcell = 65535
cnextcoprow = 0
Set wshet = Worksheets(1)
Set wshetend = Sheets("Sheet1")
' wshetend.Cells.Delete
For st = 1 To wshet.Cells(Rows.Count, "B").End(xlUp).Row
Debug.Print (wshet.Cells(st, "B").Interior.Color)
If wshet.Cells(st, "B").Interior.Color = clf And cnextcoprow = 0 Then 'has the color of interest
cnextcoprow = st
ElseIf wshet.Cells(st, "B").Interior.Color = lastcell Then
cnextrow = st - 1
Exit For
End If
Next st
coprange = cnextcoprow & ":" & cnextrow
Aend = Cells(Rows.Count, "A").End(xlUp).Row 'unused variable?
'set color is black
TargetColor = 0
wshetend.Activate
For x = 1 To Rows.Count
Debug.Print (wshetend.Cells(x, "A").Interior.Color)
If wshetend.Cells(x, "A").Interior.Color = TargetColor Then
wshet.Rows(coprange).EntireRow.Copy wshetend.Range("A" & x).Offset(1)
Exit For
' Else
' wshet.Range(coprange).Copy wshetend.Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
Next x
End Sub
So you'll have to figure out what exactly you want, to delete the cells? Then it starts at row 1, then put a skip after a copy you place after the second for loop.
Something like this:
wshetend.Activate
Aend = Cells(Rows.Count, "A").End(xlUp).Row
For x = 1 To Rows.Count
Debug.Print (wshetend.Cells(x, "A").Interior.Color)
If wshetend.Cells(x, "A").Interior.Color = TargetColor Then
wshet.Rows(coprange).EntireRow.Copy wshetend.Range("A" & x).Offset(1)
GoTo skipFor
End If
Next x
wshet.Rows(coprange).EntireRow.Copy wshetend.Range("A1")
skipFor:
Hope this helps.
Please, try the next way. It should work if you respected all what we set in the above discussion (check boxes in G:G, black cells in B:B for first sheet, and a black cell in any place of the second sheet:
Sub CopyRowsCheckBox_Black_limited()
Dim wshet As Worksheet, wshetend As Worksheet, blackCell As Range, redCell As Range, rngCopy As Range
Dim sh As Shape, chkB As MSForms.CheckBox, cellPaste As Range, pasteRow As Long
Set wshet = ActiveSheet 'use here the sheet where from you need copying
Set wshetend = wshet.Next 'use here the sheet where to copy
'settings to make Find function searching for Interior color:
With Application.FindFormat
.Clear: .Interior.Color = vbBlack
.Locked = True
End With
'find the black cell in the second sheet:
Set cellPaste = wshetend.cells.Find(What:=vbNullString, After:=wshetend.Range("A1"), SearchFormat:=True)
If Not cellPaste Is Nothing Then 'set the row where to copy first
pasteRow = cellPaste.Offset(1).row
Else
pasteRow = 1
End If
'iterate between all shapes, found the ones being checkBoxes and being on column G:G, set the rows range and copy it:
For Each sh In wshet.Shapes
If TypeName(sh.OLEFormat.Object.Object) = "CheckBox" And sh.TopLeftCell.Column = 7 Then
Set chkB = sh.OLEFormat.Object.Object 'set the checkBox ActiveX object
If chkB.Value = True Then 'if it is checked
Set blackCell = wshet.Range("B:B").Find(What:=vbNullString, After:=wshet.Range("B" & _
sh.TopLeftCell.row), SearchFormat:=True) 'find first black cell
Set rngCopy = wshet.Range(wshet.Range("B" & sh.TopLeftCell.row), blackCell).EntireRow 'set the rows to be copied
rngCopy.Copy wshetend.Range("A" & pasteRow): pasteRow = pasteRow + rngCopy.rows.count 'copy and update pasting row
End If
End If
Next sh
MsgBox "Ready..."
End Sub
The range to be copied is the one between the checked check box and the first black cell in B:B column.
Important Note: The top left corner of the check boxes must be inside of first series row!
Please, send some feedback after testing it.

How to Automate my Manual Selection Process in VBA

I have a manual selection process that I have tried but failed to automate, so I am reaching out for help. I have attached an image of my Excel sheet as a visual guide when reading my process. Excel Snapshot.
I select cell "L2" and run the code below. It finds the first instance of the value within "A2:J1501" and cuts the whole row. It pastes the row onto the sheet named Lineups. Then it highlights each of the values of the cut row in column "L:L" to let me know that value has been used. I then manually select the next non-highlighted value (in the image example it would be "L2") and run the code again, and again, and again, until every row of L:L is highlighted. This process can take some time depending on the number of rows in L:L so I was hoping I can get some help to automate.
Thank you very much.
Sub ManualSelect()
Dim rng As Range
Set rng = Range("A1:J1501")
Dim ac As Range
Set ac = Application.ActiveCell
rng.Find(what:=ac).Select
Range("A" & ActiveCell.Row).Resize(1, 10).Cut
ActiveWindow.ScrollRow = 1
Sheets("Lineups").Select
nextRow = Cells(Rows.Count, 1).End(xlUp).Row + 1
Cells(nextRow, 1).Select
ActiveSheet.Paste
Sheets("Data").Select
Dim wsData As Worksheet
Dim wsLineups As Worksheet
Dim rngToSearch As Range
Dim rngLineupSet As Range
Dim rngPlayerID As Range
Dim Column As Long
Dim Row As Long
Dim LastRow As Long
Set wsData = Sheets("Data")
Set wsLineups = Sheets("Lineups")
Set rngPlayerID = wsData.Range("L2:K200")
Set rngToSearch = rngPlayerID
LastRow = wsLineups.Cells(Rows.Count, 1).End(xlUp).Row
For Row = 2 To LastRow
For Column = 1 To 10
Set rngLineupSet = rngPlayerID.Find(what:=wsLineups.Cells(Row, Column), LookIn:=xlValues)
If Not rngLineupSet Is Nothing Then rngLineupSet.Interior.Color = 65535
Next Column
Next Row
End Sub
This should be pretty close:
Sub ManualSelect()
Dim wsData As Worksheet, c As Range, dict As Object, v, rw As Range
Dim wsLineups As Worksheet, c2 As Range, f As Range
Set dict = CreateObject("scripting.dictionary") 'for tracking already-seen values
Set wsLineups = ThisWorkbook.Worksheets("Lineups")
Set wsData = ThisWorkbook.Worksheets("Data")
For Each c In wsData.Range("L2", wsData.Cells(Rows.Count, "L").End(xlUp))
v = c.Value
If dict.exists(CStr(v)) Then
c.Interior.Color = vbYellow 'already seen this value in L or a data row
Else
'search for the value in
Set f = wsData.Range("A2:J1501").Find(v, lookat:=xlWhole, LookIn:=xlValues, searchorder:=xlByRows)
If Not f Is Nothing Then
Set rw = f.EntireRow.Columns("A").Resize(1, 10) 'A to J
For Each c2 In rw.Cells 'add all values from this row to the dictionary
dict(CStr(c2)) = True
Next c2
rw.Cut Destination:=wsLineups.Cells(Rows.Count, "A").End(xlUp).Offset(1)
c.Interior.Color = vbYellow
Else
'will there always be a match?
c.Interior.Color = vbRed 'flag no matching row
End If
End If 'haven't already seen this col L value
Next c 'next Col L value
End Sub
I believe this should do it (updated):
Sub AutoSelect()
Dim wsData As Worksheet, wsLineups As Worksheet
Dim rng As Range, listIDs As Range
Set wsData = ActiveWorkbook.Sheets("Data")
Set wsLineups = ActiveWorkbook.Sheets("Lineups")
Set rng = wsData.Range("A2:J1501")
'get last row col L to define list
LastRowL = wsData.Range("L" & Rows.Count).End(xlUp).Row
Set listIDs = wsData.Range("L2:L" & LastRowL)
'loop through all cells in list
For i = 1 To listIDs.Rows.Count
myCell = listIDs.Cells(i)
'retrieve first mach in listID
checkFirst = Application.Match(myCell, listIDs, 0)
'only check first duplicate in list
If checkFirst = i Then
'get new row for target sheet as well (if sheet empty, starting at two)
newrow = wsLineups.Range("A" & Rows.Count).End(xlUp).Row + 1
'check if it is already processed
Set processedAlready = wsLineups.Cells(2, 1).Resize(newrow - 1, rng.Columns.Count).Find(What:=myCell, lookat:=xlWhole, LookIn:=xlValues)
'if so, color yellow, and skip
If Not processedAlready Is Nothing Then
listIDs.Cells(i).Interior.Color = vbYellow
Else
'get fist match for value, if any (n.b. "xlWhole" ensures whole match)
Set foundMatch = rng.Find(What:=myCell, lookat:=xlWhole, LookIn:=xlValues)
'checking for a match
If Not foundMatch Is Nothing Then
'get the row
foundRow = foundMatch.Row - rng.Cells(1).Row + 1
'specify target range and set it equal to vals from correct row in rng
wsLineups.Cells(newrow, 1).Resize(1, rng.Columns.Count).Value2 = rng.Rows(foundRow).Value
'clear contents rng row
rng.Rows(foundRow).ClearContents
'give a color to cells that actually got a match
listIDs.Cells(i).Interior.Color = vbYellow
Else
'no match
listIDs.Cells(i).Interior.Color = vbRed
End If
End If
Else
'duplicate already handled, give same color as first
listIDs.Cells(i).Interior.Color = listIDs.Cells(checkFirst).Interior.Color
End If
Next i
End Sub
Also, I think, slightly faster than the other solution offered (because of the nested loop there?). Update: I got a bit confused about the nested loop in the answer by Tim Williams, but I missed that you also want to "accept" the values in the list that matched on a row that is already gone. I fixed this in the updated version by checking if a value that fails to match on the data range has already been transferred to Lineups. Provided that doing so is permissible, this method avoids the nested loop.
I checked both methods for speed (n = 50) on a list (n = 200) for the full data range, ended up with average of 1.70x faster... But maybe speed is not such a big deal, if you're coming from manual labor :)

How to match first 6 characters of a cell instead of the whole cell

Focusing on:
rows = w2.Columns("A:A").Find(What:=aCell, LookAt:=xlWhole).Row
Instead of looking at the whole cell to match (xlwhole), I'm trying to only match the first 6 characters of the cell. I've looked into xlpart and a few other options but have been unsuccessful.
Sub test()
Dim aCell
Dim A, B As Long, rows As Long
Dim w1, w2 As Worksheet
Dim cell As Range
Set w1 = Workbooks("Book1").Sheets("Sheet1")
Set w2 = Workbooks("Book2").Sheets("Sheet1")
A = w1.Cells(w1.Rows.Count, 1).End(xlUp).Row
B = w2.Cells(w2.Rows.Count, 1).End(xlUp).Row
For Each aCell In w1.Range("A2:A" & A)
On Error Resume Next
rows = w2.Columns("A:A").Find(What:=aCell, LookAt:=xlWhole).Row
On Error GoTo 0
If rows = 0 Then
Else
w2.Range("B" & rows).Value = aCell.Offset(0, 1).Value
End If
rows = 0
Next
End Sub
Find supports wildcards *. Use Left$ to get the first 6 characters of the cell value.
For Each aCell In w1.Range("A2:A" & A)
Dim rng As Range
Set rng = w2.Columns("A:A").Find(What:=Left$(aCell.Value, 6) & "*", LookAt:=xlWhole)
' First test if the find succeeded
If Not rng Is Nothing Then
rng.Offset(,1).Value = aCell.Offset(,1).Value
End If
Next

Remove Duplicates From A Row

I am facing problem with removing duplicate from a single row. I want to loop through all rows in a range and remove duplicate from a single row without effecting rest of data in sheet. Here is sample data:
+---------------+------+------+------+---------------+---------------+
| name | num1 | num2 | mun3 | emial1 | email2 |
+---------------+------+------+------+---------------+---------------+
| ali zubair | 1 | 2 | 1 | az#az.com | az#az.com |
+---------------+------+------+------+---------------+---------------+
| tosif | 1 | 2 | 2 | t#zb.com | t#gb.com |
+---------------+------+------+------+---------------+---------------+
| qadeer satter | 3 | 2 | 3 | qs#mtm.com | star#mtn.com |
+---------------+------+------+------+---------------+---------------+
| asif | 4 | 3 | 2 | | |
+---------------+------+------+------+---------------+---------------+
| hamid | 1 | 5 | 2 | hamid#beta.ds | hamid#beta.ds |
+---------------+------+------+------+---------------+---------------+
Below code removes duplicate rows based on column 2, it is not applicable in my case.
ActiveSheet.Range("A1:f100").RemoveDuplicates Columns:=Array(2), Header:=xlYes
I have no idea how I can remove duplicate from a selected row range. So far I have the code that will loop through all rows in my data.
Sub removeRowDubs()
Dim nextRang As Range
Dim sCellStr As String, eCellStr As String
Dim dRow As Long
dRow = Cells(Rows.Count, 1).End(xlUp).Row
For dRow = 2 To dRow
sCellStr = Range("A" & dRow).Offset(0, 1).Address
eCellStr = Cells(dRow, Columns.Count).End(xlToLeft).Address
Set nextRang = Range(sCellStr, eCellStr)
Debug.Print nextRang.Address
Next
End Sub
So what I need is some code to do what I need inserted after below code.
Set nextRang = Range(sCellStr, eCellStr)
If there is a simple solution to this like ".RemoveDuplicates" then please let me know. As of now I am thinking of doing this through looping but it seems complex as I think I will need at least 3 "for each" loops and 3 "if conditions", 2 more row ranges and probably something else when I start doing it like that.
I hope I made my question clear and I will really appreciate your help. I am new at Excel VBA coding, your patience is needed..
So I also worked on the code to remove duplicates for rows. Below is my code, its working for me. It is complex and people over stackoverflow provided better code.
Sub removeRowDublicates()
Dim nextRang As Range ' Variables for
Dim sCellStr As String, eCellStr As String ' Going through all rows
Dim dRow As Long ' And selecting row range
dRow = Cells(Rows.Count, 1).End(xlUp).Row ' This code selects the
For dRow = 2 To dRow ' next row in the data
sCellStr = Range("A" & dRow).Offset(0, 1).Address
eCellStr = Cells(dRow, Columns.Count).End(xlToLeft).Address
Set nextRang = Range(sCellStr, eCellStr)
Dim aRange As Range, aCell As Range ' Variables for
Dim dubCheckCell As Range, dubCheckRange As Range ' Loops to remove
Dim dubCheckCell1 As Range ' Dublicates from
Dim columnNum As Integer ' Current row
Set aRange = nextRang
columnNum = Range("b2:f2").Columns.Count + 1
aRange.Select
For Each aCell In aRange 'Loop for selecting 1 cell, if not blank from range to check its value against all other cell values
If aCell.Value <> "" Then
Set dubCheckCell = aCell
Else
GoTo nextaCell 'If current cell is blank then go to next cell in range
End If
If dubCheckCell.Offset(0, 2).Value <> "" Then 'Selects range by offsetting 1 cell to right from current cell being checked for dublicate value
Set dubCheckRange = Range(dubCheckCell.Offset(, 1), dubCheckCell.Offset(, 1).End(xlToRight))
Else
Set dubCheckRange = Range(dubCheckCell.Offset(0, 1).Address)
End If
For Each dubCheckCell1 In dubCheckRange 'Loop that goes through all cells in range selected by above if-statement
Do While dubCheckCell1.Column <= columnNum
If dubCheckCell = dubCheckCell1 Then
dubCheckCell1.ClearContents
Else
End If
GoTo nextdubCheckCell1
Loop 'For do while
nextdubCheckCell1:
Next dubCheckCell1 'Next for dubCheckRange
nextaCell:
Next aCell 'Next for aRange
Next 'For drow
End Sub
Try the next code, please:
Sub testRemoveRowDuplicates()
Dim sh As Worksheet, rng As Range, lastRow As Long, i As Long
Set sh = ActiveSheet 'use here your sheet
lastRow = sh.Range("A" & Rows.Count).End(xlUp).row
For i = 2 To lastRow
Set rng = sh.Range("C" & i & ":D" & i)
rng.Replace rng.Cells(1, 1).Offset(0, -1).Value, "", xlWhole
Set rng = sh.Range("D" & i)
rng.Replace rng.Cells(1, 1).Offset(0, -1).Value, "", xlWhole
Set rng = sh.Range("F" & i)
rng.Replace rng.Cells(1, 1).Offset(0, -1).Value, "", xlWhole
Next i
End Sub
The above code assumes that a name cannot be duplicate in the email columns. It removes duplicates on each category (names and emails).
If you really need to check each value of the row, please, use the next variant:
Sub testRemoveRowDuplicatesBis()
Dim sh As Worksheet, rng As Range, lastRow As Long
Dim i As Long, j As Long
Set sh = ActiveSheet
lastRow = sh.Range("A" & Rows.Count).End(xlUp).row
For i = 2 To lastRow
For j = 3 To 6 'last column
Set rng = sh.Range(sh.Cells(i, j), sh.Cells(i, 6))
rng.Replace rng.Cells(1, 1).Offset(0, -1).Value, "", xlWhole
Next j
Next i
End Sub
You can use some VBA nested loops to do this - loop the rows, and then have two column loops to check the values of the cells:
Sub sRemoveRowDubs()
On Error GoTo E_Handle
Dim ws As Worksheet
Dim lngLastRow As Long
Dim lngLastCol As Long
Dim lngRow1 As Long
Dim lngCol1 As Long
Dim lngCol2 As Long
Set ws = Worksheets("Sheet4")
lngLastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
lngLastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
For lngRow1 = 1 To lngLastRow
For lngCol1 = 1 To lngLastCol
For lngCol2 = lngCol1 + 1 To lngLastCol
If ws.Cells(lngRow1, lngCol1) = ws.Cells(lngRow1, lngCol2) Then
ws.Cells(lngRow1, lngCol2) = ""
End If
Next lngCol2
Next lngCol1
Next lngRow1
sExit:
On Error Resume Next
Set ws = Nothing
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "sRemoveRowDubs", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
Regards,
If you can use formula and create a new table.
Array (CSE) Formula for Num1 column, enter the formula in formula bar, press control+Shift+Enter and then select the cell copy to Num2 and Num3. Then select all three cells and copy down.
=IFERROR(INDEX($B2:$D2,1,MATCH(0,COUNTIF($H2:H2,$B2:$D2),0)),"")
Array (CSE) Formula for email1 column, enter the formula in formula bar, press control+Shift+Enter and then select the cell copy to email2. Then select those two cells and copy down.
=IFERROR(INDEX($E2:$F2,1,MATCH(0,COUNTIF($K2:K2,$E2:$F2),0)),"")
Or maybe something like this?
Sub test()
Set rngName = Range("A2", Range("A" & Rows.Count).End(xlUp))
For Each cell In rngName
For i = 1 To 4
Set Rng = Range(cell.Offset(0, i + 1), Cells(cell.Row, 6))
Set c = Rng.Find(cell.Offset(0, i).Value, lookat:=xlWhole)
If Not c Is Nothing Then c.ClearContents
Next i
Next cell
End Sub
What I am thinking is selecting 1 cell from row then check it against
all other cells in the same row
The code assumes that there will be no blank in between row with value under column NAME (column A), and all the name value is unique. This is for the first loop.
The second loop is the how many cell in the same row to check, in this case there are 4 cells to check (num1, num2, num3 and email1) then so does the checking are 4 times ---> in the same row : check num1 against num2, num3, email1 and email2 ... check num2 against num3, email1 and email2 .... check num3 against email1 and email2... then finally check email1 against email2. On each check, if the same value is found, then the code put blank to the found cell.
Clear Duplicate Entries By Row
Copy the complete code into a standard module (e.g. Module1).
Only run the first Sub, the other two are being called.
Adjust the constants in the first Sub, including the workbook.
The Code
Option Explicit
Sub clearDups()
Const wsName As String = "Sheet1"
Const FirstRowAddress As String = "A2:F2"
Const LastRowColumn As Long = 1
Const Replacement As Variant = Empty
Dim wb As Workbook: Set wb = ThisWorkbook
' Define Data First Row Range.
Dim rng As Range: Set rng = wb.Worksheets(wsName).Range(FirstRowAddress)
' Define Data Range and write its values to Data Array.
Dim Data As Variant: getRangeValuesFR Data, rng, LastRowColumn
If IsEmpty(Data) Then Exit Sub
' In data array, clear duplicate values by row
' (from the top and from the left).
replaceDupsByRow Data, Replacement
' Write modified values from Data Array to Data Range.
rng.Resize(UBound(Data)).Value = Data
End Sub
Sub getRangeValuesFR(ByRef Data As Variant, _
ByRef FirstRowRange As Range, _
Optional ByVal LastRowColumn As Long = 1)
Dim rng As Range
If LastRowColumn = 0 Then GoSub LastRow0 Else GoSub LastRowN
If rng Is Nothing Then Exit Sub
If rng.Row < FirstRowRange.Row Then Exit Sub
Set rng = FirstRowRange.Resize(rng.Row - FirstRowRange.Row + 1)
If rng.Row > 1 Then
Data = rng.Value
Else
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = rng.Value
End If
Exit Sub
LastRow0:
With FirstRowRange
Set rng = .Worksheet.Columns(.Column).Resize(, .Columns.Count) _
.Find("*", , xlValues, , xlByRows, xlPrevious)
End With
Return
LastRowN:
With FirstRowRange
Debug.Print .Columns(LastRowColumn).Address
Set rng = .Worksheet.Columns(.Columns(LastRowColumn).Column) _
.Find("*", , xlValues, , , xlPrevious)
End With
Return
End Sub
Sub replaceDupsByRow(ByRef Data As Variant, _
Optional ByVal Replacement As Variant = Empty)
Dim Curr As Variant, i As Long, j As Long, l As Long
For i = 1 To UBound(Data)
For j = 1 To UBound(Data, 2) - 1
Curr = Data(i, j + 1)
If Curr <> Replacement Then GoSub loopSubRows
Next j
Next i
Exit Sub
loopSubRows:
For l = 1 To j
If Curr = Data(i, l) Then
Data(i, j + 1) = Replacement: Exit For
End If
Next l
Return
End Sub

How to copy all rows from one column that contains two specific values to a different sheet on Excel

I am trying to copy all rows from an excel sheet (Sheet1) that have a specific value that is referenced from a different cell. and then paste them into a new sheet(Sheet2).
My specific example is I have figured out that I want to copy the rows that have a '0' and/or '35' in column A. these values can change however due to what ever is in "B6" and "B7".
The problem that I am having is it only copys rows that contain the value from "B6" which is 0 and ignoring my command that wants the "B7" value which is 35 in my instance. My code is below for reference
Sub Temp_copy()
set i = Sheets("Sheet1")
set e = Sheets("Sheet2")
Dim d
Dim j
d = 1
j = 2
Do Until IsEmpty(i.Range("A" & j))
If i.Range("A"&j) = Range("B6"&j) Then
d=d+1
e.Rows(d).Value=i.Rows(j).Value
End If
j = j+1
Loop
Do Until IsEmpty(i.Range("A" & j))
If i.Range("A"&j) = Range("B7"&j) Then
d=d+1
e.Rows(d).Value=i.Rows(j).Value
End If
j = j+1
Loop
End Sub
I am new to VBA so any help or guidance to achieve what I need would be muchly appreciated.
Instead of looping through cells, you may use Autofilter to copy the desired data like below...
Sub CopyRows()
Dim sws As Worksheet, dws As Worksheet
Dim lr As Long
Application.ScreenUpdating = False
Set sws = Sheets("Sheet1")
Set dws = Sheets("Sheet2")
lr = sws.Cells(Rows.Count, 1).End(xlUp).Row
dws.Cells.Clear
sws.AutoFilterMode = False
'Assuming Row1 is the Header Row on Sheet1
With sws.Range("A1:A" & lr)
.AutoFilter field:=1, Criteria1:=sws.Range("B6").Value, Operator:=xlOr, Criteria2:=sws.Range("B7").Value
.SpecialCells(xlCellTypeVisible).EntireRow.Copy
dws.Range("A1").PasteSpecial xlPasteValues
End With
sws.AutoFilterMode = False
Application.CutCopyMode = 0
Application.ScreenUpdating = True
End Sub
The simple or operator will help you get this done!
Sub Temp_copy()
Set i = Sheets("Sheet1")
Set e = Sheets("Sheet2")
Dim d
Dim j
d = 1
j = 2
Do Until IsEmpty(i.Range("A" & j))
If i.Range("A" & j) = Range("$B$6") Or i.Range("A" & j) = Range("$B$7") Then
d = d + 1
e.Rows(d).Value = i.Rows(j).Value
End If
j = j + 1
Loop
End Sub

Resources