I want to remove duplicated values in my Table. It is ListObject Table with 1000s of lines.
I cannot get to work my code and I am using function RemoveDuplicates for ranges with the condition to delete the lines in the table if there are duplicates in 2 relative columns.
This is how it looks before running the code:
In my code, based on column C:C and E:E only, I need to check if each line has any duplicates within these 2 columns and delete them, leaving only one.
And this is my desired outcome:
This is my code that does not work. I am not sure if it is because my table is the List Object or because I assign Array wrong?
Sub test_Duplicate()
Dim endrow As Long
Dim rng As Range
Dim ws As Worksheet
Set ws = Sheets("Sheet4")
With ws
endrow = .Cells(.Rows.Count, 3).End(xlUp).Row
Set rng = .Range(.Cells(2, 3), .Cells(endrow, 6))
rng.RemoveDuplicates Columns:=Array(1, 3), Header:=xlNo
End With
End Sub
I will appreciate any help.
I noticed that whether my data is in the table as List Object or whether is it without it, I am getting the error nr 9 anyway.
This will work:
Just change the TableName ..Mine is Table1
Sub test_Duplicate()
Dim ws As Worksheet
Set ws = Sheets("Sheet4")
With ws
.Range("Table1[#All]").RemoveDuplicates Columns:=Array(1, 3), Header:=xlYes
End With
End Sub
Table Name is found on the Design Tab when you select the table.
Here is the best solution I managed to find by looking through web.
Sub RemoveDuplicates()
Const TEST_COLUMN As String = "A"
Dim i As Long
Dim iLastRow As Long
Dim rng As Range
Dim ws As Worksheet
Set ws = Worksheets("Sheet4")
With ws
iLastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
For i = 1 To iLastRow
If .Evaluate("SUMPRODUCT(--(A" & i & ":A" & iLastRow & "=A" & i & ")," & _
"--(I" & i & ":I" & iLastRow & "=I" & i & "))") > 1 Then
If rng Is Nothing Then
Set rng = .Cells(i, "A").Resize(, 9)
Else
Set rng = Union(rng, .Cells(i, "A").Resize(, 9))
End If
End If
Next i
If Not rng Is Nothing Then rng.Delete
End With
End Sub
Related
I am new to coding and need help with a code that won't complete. I suspect it is due to the size of the data set. I tested the code using a reduced data set and it processes fine. However, my actual data set is over 210,000 rows and is expected to grow.
Is there a way to speed this up? Thank you for your assistance
Sub DupValidation()
Dim wb As Workbook
Dim ws1 As Worksheet
Dim i As Long
Dim lastrow As Long
Dim lastrow2 As Long
Set wb = ActiveWorkbook
Set ws1 = wb.Worksheets("Tickets")
lastrow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
ws1.Range("g2:g" & lastrow).ClearContents
i = 2
Do While i <= lastrow
If Application.CountIf(ws1.Range(ws1.Cells(2, 2), ws1.Cells(lastrow, 2)), ws1.Cells(i, 2)) > 1 Then
ws1.Cells(i, 7).Value = True
End If
i = i + 1
Loop
End Sub
May be better
Sub Check_Duplicates_Using_Evaluate()
With Range("B2", Range("B" & Rows.Count).End(xlUp))
.Offset(, 5).Value = .Parent.Evaluate("IF(COUNTIF(" & .Address & "," & .Address & ")>1,""True"","""")")
End With
End Sub
I want to find empty cells and copy there values:
Values: "10/11/2017" and "Yes" should be copied to row 7 (colB & colC).
What I have:
Sub add_value()
Dim wbA As Workbook
Dim wsA As Worksheet
Set wbA = ActiveWorkbook
Set wsA = wbA.Worksheets("Sheet1")
Dim nrow As Long
nrow = 6
Do Until wsA.Range("B" & nrow).Value = ""
wsA.Range("B" & nrow).Value = wsA.Range("B3").Value
wsA.Range("C" & nrow).Value = wsA.Range("C3").Value
Exit Sub
nrow = nrow + 1
Loop
End Sub
Something is wrong with my loop and I don't know how to fix it.
No need to loop through your rows until you find an empty one. You can replace the entire sub with this:
Sub add_value()
With ThisWorkbook.Worksheets("Sheet1")
.Cells(.Rows.Count, "B").End(xlUp).Offset(1, 0).Resize(1, 2).Value = .Range("B3:C3").Value
End With
End Sub
As per your comments, to also add borders you can reorganise the code a bit like this:
Sub add_value()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
With ws.Cells(ws.Rows.Count, "B").End(xlUp).Offset(1, 0).Resize(1, 2)
.Value = ws.Range("B3:C3").Value
.Borders(xlEdgeLeft).LineStyle = xlContinuous
End With
End Sub
I would have done something like this:
Sub FindFirstEmptyValue()
Dim lastRow As Long
With Worksheets("Sheet1")
lastRow = .Cells(.Rows.Count, 2).End(xlUp).Row + 1
.Cells(lastRow, 2) = .Range("B3").value
.Cells(lastRow, 3) = .Range("C3").value
End With
End Sub
It gives you the last row, you increment it with 1 and on this row you write the B3 and C3 values.
I have a code that's intended to:
1) Find a name from a table using a searchbox
2) Copy cells in the row with the name on to another sheet
3) This should work for all entries in the table associated with this name.
Code sample:
Sub Printout()
Dim LR2 As Long
Dim c As Variant
Dim txt As Variant
c = InputBox("Enter Last Name")
txt = CStr(c)
Sheets("B").Select
Sheets("B").Range("K3").Value = txt
Sheets("A").Select
Sheets("A").Columns(2).Find(What:=txt, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True).Activate
LR2 = Sheets("A").Cells(Rows.Count, "a").End(xlUp).Row
Sheets("A").Range(Cells(ActiveCell.Row, 2), Cells(LR2, 10)).Select
Selection.Copy Destination:=Sheets("B").Range("A2:J2")
End Sub
Problem:
Currently, the code doesn't just copy the specific name from the searchbox input, but all entries under the name as well. Ie if "Johnson" is entry 3, 6, and 11, I want columns 2 to 10 for those three rows. Currently it finds the first entry and seem to copy everything in columns 2 to 10 underneath it. Can someone please help me troubleshoot this code so that I can make it do what I want?
Thanks in advance!
this should be what youre after. Season to taste but itll do what you want
Private Sub derp()
Dim this As String
this = InputBox("Enter Last Name")
Dim rng As Range
Dim rcell As Range
Dim lastrow As Long
Dim that As Variant
lastrow = ThisWorkbook.Sheets("Sheet3").UsedRange.Rows.Count
Set rng = ThisWorkbook.Sheets("Sheet2").Range("A1:a40")
For Each rcell In rng.Cells
If rcell.Value <> vbNullString Then
If rcell.Value = this Then
that = ThisWorkbook.Sheets("Sheet2").Range("A" & rcell.Row & ":H" & rcell.Row)
ThisWorkbook.Sheets("Sheet3").Range("A" & lastrow & ":H" & lastrow).Value2 = that
lastrow = lastrow + 1
End If
End If
Next rcell
End Sub
This is my best guess
Sub Printout()
Dim LR2 As Long
Dim c As Variant
Dim txt As Variant
Dim r As Range
Dim s As String
c = InputBox("Enter Last Name")
txt = CStr(c)
Sheets("B").Range("K3").Value = txt
With Sheets("A")
Set r = .Columns(2).Find(What:=txt, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True)
If Not r Is Nothing Then
s = r.Address
Do
LR2 = Sheets("B").Cells(Rows.Count, "a").End(xlUp).Row
.Range(.Cells(r.Row, 2), .Cells(r.Row, 10)).Copy Destination:=Sheets("B").Range("A" & LR2)
Set r = .Columns(2).FindNext(r)
Loop While r.Address <> s
End If
End With
End Sub
It is sometimes problematic to work with code, that is not created by you. In your case, you want to select and copy the cells, which you have found in column 2.
If you take a look at this code and edit it a bit, you would be able to do it.
Option Explicit
Option Private Module
Sub Printout()
Dim txt As Variant
Dim rngUnion As Range
Dim rngCell As Range
txt = "vi"
With ActiveSheet
For Each rngCell In .Range(.Cells(1, 1), .Cells(9, 1))
If InStr(1, rngCell, txt) Then
If rngUnion Is Nothing Then
Set rngUnion = .Range(.Cells(rngCell.Row, 2), .Cells(rngCell.Row, 5))
Else
Set rngUnion = Union(rngUnion, .Range(.Cells(rngCell.Row, 2), .Cells(rngCell.Row, 5)))
End If
End If
Next rngCell
End With
rngUnion.Select
End Sub
Your ActiveSheet should like this:
What the code does:
It loops through the Cells from A1 to A9.
If it finds vi in one of those cells, it adds 4 cells of the same row to a union - rngUnion
At the end it selects a union, just to show you which one is it. You can copy the selection or copy the range, without selecting it.
Good luck, have fun!
I have simple problem using a sort macro. When I import data from my other Workbook, the workbook run the macro below in SheetChange and receive the run-time error.
HOWEVER, it is working completely fine if I just run the macro when the Workbook is open.
I donĀ“t know if I have to replace Range with ActiveWorkbook or something, but I think I have tried a lot of different stuff, still without luck :(
I want it to sort from column B, starting in row 13 and until the last row/column. It is dynamic, so it will change every time I import stuff.
Sub TESTSORT()
Dim startCol, myCol As String
Dim startRow, lastRow, lastCol As Long
Dim ws As Worksheet
Dim Rng, cell As Range
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
startCol = "A"
startRow = 13
lastRow = ws.Range(startCol & ws.Rows.Count).End(xlUp).Row
'lastCol = ws.Cells(2, ws.Columns.Count).End(xlToLeft).Column
lastCol = ActiveSheet.UsedRange.Columns(ActiveSheet.UsedRange.Columns.Count).Column
myCol = GetColumnLetter(lastCol)
Set Rng = ws.Range(startCol & startRow & ":" & myCol & lastRow)
' I GET THE ERROR HERE
Range(.Cells(13, 1), .Cells(lastRow, lastCol)).Sort key1:=Range("B13:B" & lastRow),
order1:=xlAscending, Header:=xlNo
End With
Application.ScreenUpdating = True
End Sub
Function GetColumnLetter(colNum As Long) As String
Dim vArr
vArr = Split(Cells(1, colNum).Address(True, False), "$")
GetColumnLetter = vArr(0)
End Function
It looks like you've got some issues inside your With statement... using Range instead of .Range in several places. I've tried to clean it up a bit below...
Sub TESTSORT()
Dim startCol, myCol As String
Dim startRow, lastRow, lastCol As Long
Dim ws, ws2 As Worksheet
Dim Rng, cell As Range
Set ws2 = ActiveSheet 'Preserves a reference to the active sheet as ws2
ThisWorkbook.Activate 'Makes this workbook the one that is displayed
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
startCol = "A"
startRow = 13
lastRow = .Range(startCol & .Rows.Count).End(xlUp).Row
'lastCol = .Cells(2, .Columns.Count).End(xlToLeft).Column
lastCol = ws2.UsedRange.Columns(ws2.UsedRange.Columns.Count).Column
myCol = GetColumnLetter(lastCol)
Set Rng = .Range(startCol & startRow & ":" & myCol & lastRow)
' I GET THE ERROR HERE
.Range(.Cells(13, 1), .Cells(lastRow, lastCol)).Sort key1:=.Range("B13:B" & lastRow),
order1:=xlAscending, Header:=xlNo
End With
Application.ScreenUpdating = True
End Sub
Function GetColumnLetter(colNum As Long) As String
Dim vArr
vArr = Split(Cells(1, colNum).Address(True, False), "$")
GetColumnLetter = vArr(0)
End Function
I am trying to write a macro in vba for excel. I want to delete every row that does not have at least one of three keywords in column D (keywords being "INVOICE", "PAYMENT", or "P.O."). I need to keep every row that contains these keywords. All other rows need to be deleted and the rows remaining need to be pushed to the top of the document. There are also two header rows that can not be deleted.
I found the code below but it deletes every row that does not contain "INVOICE" only. I can not manipulate the code to do what I need it to do.
Sub Test()
Dim ws As Worksheet
Dim rng1 As Range
Dim lastRow As Long
Set ws = ActiveWorkbook.Sheets("*Name of Worksheet")
lastRow = ws.Range("D" & ws.Rows.Count).End(xlUp).Row
Set rng = ws.Range("D1:D" & lastRow)
' filter and delete all but header row
With rng
.AutoFilter Field:=1, Criteria1:="<>*INVOICE*"
.Offset(2, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
' turn off the filters
ws.AutoFilterMode = False
End Sub
I would approach this loop slightly different. To me this is a bit easier to read.
Sub Test()
Dim ws As Worksheet
Dim lastRow As Long, i As Long
Dim value As String
Set ws = ActiveWorkbook.Sheets("*Name of Worksheet")
lastRow = ws.Range("D" & ws.Rows.Count).End(xlUp).Row
' Evaluate each row for deletion.
' Go in reverse order so indexes don't get messed up.
For i = lastRow To 2 Step -1
value = ws.Cells(i, 4).Value ' Column D value.
' Check if it contains one of the keywords.
If Instr(value, "INVOICE") = 0 _
And Instr(value, "PAYMENT") = 0 _
And Instr(value, "P.O.") = 0 _
Then
' Protected values not found. Delete the row.
ws.Rows(i).Delete
End If
Next
End Sub
The key here is the Instr function which checks for your protected keywords within the cell value. If none of the keywords are found then the If condition is satisfied and the row is deleted.
You can easily add additional protected keywords by just appending to the If conditions.
'similar with previous post, but using "like" operator
Sub test()
Dim ws As Worksheet, i&, lastRow&, value$
Set ws = ActiveWorkbook.ActiveSheet
lastRow = ws.Range("D" & ws.Rows.Count).End(xlUp).Row
For i = lastRow To 2 Step -1
value = ws.Cells(i, 4).value
' Check if it contains one of the keywords.
If Not (value Like "*INVOICE*" _
Or value Like "*PAYMENT*" _
Or value Like "*P.O.*") _
Then
' Protected values not found. Delete the row.
ws.Rows(i).Delete
End If
Next
End Sub
'
Sub test()
Dim i&
Application.ScreenUpdating = False
i = Range("D" & Rows.Count).End(xlUp).Row
While i <> 1
With Cells(i, 4)
If Not (.value Like "*INVOICE*" _
Or .value Like "*PAYMENT*" _
Or .value Like "*P.O.*") _
Then
Rows(i).Delete
End If
End With
i = i - 1
Wend
Application.ScreenUpdating = True
End Sub
The othe way is to insert an IF test in a working column, and then AutoFilter that.
This is the VBA equivalent of entering
=SUM(COUNTIF(D1,{"*INVOICE*","*PAYMENT*","*P.O.*"}))=0
and then deleting any row where none of these values are found in the corrresponing D cell
Sub QuickKill()
Dim rng1 As Range, rng2 As Range, rng3 As Range
Set rng1 = Cells.Find("*", , xlValues, , xlByColumns, xlPrevious)
Set rng2 = Cells.Find("*", , xlValues, , xlByRows, xlPrevious)
Set rng3 = Range(Cells(rng2.Row, rng1.Column), Cells(1, rng1.Column))
Application.ScreenUpdating = False
Rows(1).Insert
With rng3.Offset(-1, 1).Resize(rng3.Rows.Count + 1, 1)
.FormulaR1C1 = "=SUM(COUNTIF(RC[-1],{""*INVOICE*"",""*PAYMENT*"",""*P.O.*""}))=0"
.AutoFilter Field:=1, Criteria1:="TRUE"
.EntireRow.Delete
On Error Resume Next
'in case all rows have been deleted
.EntireColumn.Delete
On Error GoTo 0
End With
Application.ScreenUpdating = True
End Sub