How to remove duplicate row but save the latest one (VBA)? - excel

I have an excel where I have 2 sheets and I want to import selected columns to another sheet and delete possible duplicate rows. The problem is, that when I run my code, it deletes my latest duplicate row, eventhough I want to save latest row and delete the other 'older' duplicate. I really appreciate any help! Thank you :) Here is my code what I have tried so far:
Private Sub CommandButton1_Click()
Cells.RemoveDuplicates Columns:=Array(1, 2, 3)
Dim lastrow As Long, erow As Long
lastrow = Worksheets("one").Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastrow
Worksheets("one").Cells(i, 1).Copy
erow = Worksheets("two").Cells(Rows.Count, 1).End(xlUp).Row
Worksheets("one").Paste Destination:=Worksheets("two").Cells(erow + 1, 1)
Worksheets("one").Cells(i, 3).Copy
Worksheets("one").Paste Destination:=Worksheets("two").Cells(erow + 1, 2)
Next i
End Sub
Another question is, I have tried this code for test excel, but where I want to use this macro has a lot larger data. It takes a very long time to go through all the data.. is the problem in my code or is the actual excel just so big? I hope I explain everything crearly.
Thank you!

"The problem is, that when I run my code, it deletes my latest duplicate row..."
The problem is the sort order of your data.
Remove Duplicates moves from first index to last and and keeps the first occurrence. So you either need to sort your data such that your "oldest" duplicate is the first occurrence at top or you have to use a different method to remove duplicates.
"is the problem in my code or is the actual excel just so big?"
It could be both, but one thing is certain, your code can definitely run faster.
The low hanging fruit is to put Application.EnableScreenUpdating = False in the beginning of you sub. That stops Excel from updating the screen when your runs. It will make a huge difference. Just remember to set it back to True again.
You're also looping through a range one row at a time but I don't see any particular reason why you need to. You can copy the while range in a single statement without looping. You don't even need to copy of you don't care about ordering the format, you could transfer the values just make the ranges equal each other.
An example of how you to transfer values without cutting or looping
Worksheets("two").Range("A2:A" & lastrow).Value = Worksheets("one").Range("E2:E" & lastrow).Value
You can use the same approach with copy and paste if you prefer.

Related

Find the last row/column in excel using access VBA

I am trying to run a for loop from start to end of all of the data in my excel sheet that is being processed by access vba. I have tried:
myWorksheet.Cells(Rows.Count, 4).End(xlUp).row
but it did not work. I am confused how I can get a one number output so that it is able to run in my loop successfully. Please help. Also, if you could break down the format of your answer that would really help me. Thanks
Access has not constant xlUp which has value -4162 in Excel. In Access xlUp is non-declared variable with Variant type and initial value Empty. To use proper End(xlUp) in Access VBA you can write .End(-4162):
myWorksheet.Cells(myWorksheet.Rows.Count, 4).End(-4162).row
I usually define my LastRow like so, with "N" that's just the column that has the data in it, you can adjust that as needed:
LastRow = ActiveSheet.Cells(Cells.Rows.Count, "N").End(xlUp).Row
I usually pair that with a Dim row_no As Long and use it in the loop like so, the hard number here being the first row of my dataset.
For row_no = 5 to LastRow
'Do the thing
Next
There's way to iterate through loops in reverse order, which makes more sense when you're deleting rows, because when you delete it row it messes with what row the macro thinks it's on. Ie: you delete row 2, so row 3 moves to row 2, but the macro moves to row 3 which has the 4th row of data. For those you'll approach it like so:
For x = LastRow To 5 Step -1
'Do the thing
Next x

VBA nonsense pointing at the wrong sheet?

Some strange things are happening to me in VBA. Somedays I am coding and everything works fine, then I go out of the code and the next day when I want to run the exact same code from the day before the code doesn't go into the loop, but jumps directly into end sub().
I tried to use the Activate sheet function, it seemed to work for 10 seconds and then afterwards suddenly it didn't work again which means my code didn't go into the loop again. The reason why I was using Activate sheet function was because I was afraid that my code was pointing at the wrong excel file / sheet. I have a lot of excel files and all of the sheets in those excel files are called Sheet1 could that create problems??
To give you a concrecte example, say I day one use the following code to loop through a column:
Sub stuff()
' Sheet1.Activate
lngLastRow = Worksheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
Set sheet1ArkRng = Worksheets("Sheet1").Range("A1:Z" & lngLastRow)
Set offsheetarkrng = Worksheets("Sheet1").Range("L5")
Dim i As Integer
For i = 3 To sheet1ArkRng.Rows.Count
sheet1VirkNavn = sheet1ArkRng.Cells(RowIndex:=i, ColumnIndex:="C").Value
Next i
End Sub
Then day 1 everything works fine and the variable sheet1VirkNavn shows me the value of the rows in column C. It can be seen when I debug.
Then day 2 once I debug the exact same code from the exact same file it goes to
"For i = 3 To sheet1ArkRng.Rows.Count"
and then jumps directly into
End sub
Problem solved:
I've learned what
lngLastRow = Worksheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
means. Now it all makes sense. If you're using the above code to loop through last row you should use the same letter for the column you want to loop through...
So the case was my code wasn't getting into the loop simply because my "A" column was empty.

Trying to Remove Duplicates based on first column

I am currently trying to remove rows from column A to column V based on duplicates found in column A.
my current formula is:
Workbooks(TgtWB).ActiveSheet.Range("A15:V500").RemoveDuplicates _
Columns:=Array(1), Header:=xlYes
My header is located on row 15.
the error i am getting is
Application-defined or object-defined error
I have tried switching ActiveSheet with worksheet("xxx") but still doesn't seem to work either. i'm not sure what i'm doing wrong here.
Try (note worksheetS, not worksheet),
Workbooks(TgtWB).worksheetS("xxx").Range("A15:V500").RemoveDuplicates Columns:=1, Header:=xlYes
'or,
ActiveSheet.Range("A15:V500").RemoveDuplicates Columns:=1, Header:=xlYes
If TgtWB is open, it may or may not contain the ActiveSheet. Each open workbook does not have an ActiveSheet. There is only one ActiveSheet for the application instance. ActiveSheet is not a property of the Workbooks collection.
Using built in functionality is great, unless you're a beginner like myself and the .Applications and .Worksheets get overwhelming and confusing. For a small data set, such as columns A through V (depending obviously on how many rows you have), a loop and if-statement not only can work well, but can be good practice as well! Something like this may work well:
Dim CurrentValue, LastValue As Variant
LastValue = ""
For I = 1 To 500
CurrentValue = Sheets("Sheet 1").Range("A" & i).Value
If CurrentValue = LastValue Then
Sheets("Sheet 1").Range("A" & i & ":V" & i).Clear Contents
Else
LastValue = CurrentValue
End If
Next i
This will loop through every row, ask if the current value in the cell is the same as the one previously observed (except the first one, the first one will automatically be saved by nature), and if it has been, it will clear the contents of the row. If it's not the same, it will assign it to the new variable and begin looking for new ones.
There are two drawbacks with this method that can be solved by simply adapting the code to your needs:
Non-Sequential Items: If the values that are duplicates are not sequential, the code won't kick them out. At that point I recommend using an application code or a dictionary. Dictionaries are infinitely useful for storing unique data entries and skipping duplicates.
Deleting Rows: When you delete rows in a loop it messes up your loop, throwing off the order of your incrementer. The best way to combat this is by first clearing the columns then having your code loop for empty rows and delete them outside of your loop.
This is very basic but something I've found greatly helpful as a beginner and hopefully other beginners and yourself can learn something from it.
Happy Coding!

Excel VBA .End(xlUp).Offset(1, 0).Row

Making a userform to add data to a database in VBA. What i'm wanting to do is pretty simple; to select the last filled row, and skip to the next empty cell in the row below.
Screenshot added with the problem highlighted.
Question is quite simple, what am I doing wrong, and how would it be fixed?
.End(... has nothing to reference to. If you wanted to add a linebreak, do so by writing:
Irow = ws.Cells(Rows.Count, 1) _
.End(xlUp).Offset(1,0).Row
Watch the _ with a space before it at the end of the first line.
This will connect the two lines, forming one valid statement.
Alternatively, just write the two lines as one:
Irow = ws.Cells(Rows.Count, 1).End(xlUp).Offset(1,0).Row

Copy several rows from excel sheet and paste into same row on new excel sheet

Could anyone provide some VBA code please that would facilitate the following request?
I would like to copy six rows and paste these into a new sheet on the same row. I have hundreds of rows, hence the request for code. It would need to copy the first six rows to one row, the next six to the second row etc. Each row to be copied has nine cells as in the example below.
ColA |ColB |ColC|ColD|ColE|ColF|ColG|ColH|ColI
Separatecombined|Smoothedremoved|1.00|1.00|99 |90 |95 |98 |accuracy
Many thanks.
Andy
This site exists to allow programmers to help other programmers develop their skills. Sometimes significant pieces of code are provided in answers but this is not a free coding site.
The macro to perform the actions you require is so small and simple, I do not believe you know any VBA at all. Normally I would respond to a question like this by telling you how to write the macro you seek. However, your requirement is so simple it was easier to code than to provide instructions. you must learn VBA if you want to use macros. It will not take long to learn the basics and the time spent will quickly repay itself. Search for "VBA Excel tutorial". There are many to choose from. Try a few and complete the one that matches your learning style. I prefer books. I visited a large library and reviewed all the Excel VBA primers. I then bought the one I preferred.
The first task is to find the last used row in the source worksheet. I have used the method that is normally the most convenient. However, there are several method of finding the last row or column and none work in every situation. The method I have chosen may not work with your data. This answer of mine includes a macro, FindFinal, which uses a variety of methods and shows when they fail. This will help you choose an alternative if necessary.
You then need nested for loops to move the data.
The macro below is the one you asked for but I am not sure it is the macro you want. If I had your requirement, I would want source row 1 (the column headings) duplicated six times and then rows 2 to last copied across. I leave you with the task of creating a copy of my inner loop to achieve this duplication. Come back with questions if necessary but I believe forcing you to make this amendment will help you understand my code and help you develop your own skills.
Good luck and welcome to the joys of programming.
Option Explicit
Sub MergeRows()
Dim ColDestCrnt As Long
Dim RowDestCrnt As Long
Dim RowSrcCrnt As Long
Dim RowSrcLast As Long
Dim RowWithinGroupNum As Long
Dim WshtDest As Worksheet
Application.ScreenUpdating = False
Set WshtDest = Worksheets("Destination")
With Worksheets("Source")
' Find last used row of worksheet. This assumes column "A"
' contains a value in every used row.
RowSrcLast = .Cells(Rows.Count, "A").End(xlUp).Row
RowDestCrnt = 1
' Loop for each set of six rows. Unless the source worksheet
' contains a multiple of six rows, the last set will involve the
' copying of empty rows. I decided it was less effort to copy
' these empty rows than to include code to not copy them
For RowSrcCrnt = 1 To RowSrcLast Step 6
' Loop for each row within a set
For RowWithinGroupNum = 0 To 5
' Calculate the start column in the destination worksheet
ColDestCrnt = (RowWithinGroupNum) * 6 + 1
' Copy all six cells from the current source row to the six cells
' starting at the appropriate column in the destination row
.Range(.Cells(RowSrcCrnt + RowWithinGroupNum, 1), _
.Cells(RowSrcCrnt + RowWithinGroupNum, 6)).Copy _
Destination:=WshtDest.Cells(RowDestCrnt, ColDestCrnt)
Next RowWithinGroupNum
' Step the destination row ready for the next set
RowDestCrnt = RowDestCrnt + 1
Next RowSrcCrnt
End With
End Sub

Resources