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
Related
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.
I'm trying to write a code to solve this little issue that I have, but can't seem to get it. I have multiple columns in an excel spreadsheet and in one of those columns, there are duplicate values. What I want to do is to remove the second/duplicate value but also take the integer value in one of the other columns and add it to the row where the first value is and after that delete that "second" row. I tried with the .RemoveDuplicates command, but it just deleted the duplicate value and shifted the whole column up, so I can't add the values as I wanted.
Here's an example
I only need the duplicates removed from one of the columns, D, here we see that row 5 and 10 are similar in that column and what I want to do, is to add the numbers from column C in row 5 and delete row t´10, so I'll end up with this
I really hope any of you can help as I'm a bit lost. Thanks!
Without code, you could use the advanced copy to copy unique values into another range, sumif to get your total and index/match to bring in the other columns. Once you get that figured out, record it as a macro and clean it up.
Resume your data with Pivot Tables.
Your inputdata looks like this:
You could resume your data using Pivot Tables, and group the data by that 4th column and sum values in 3rd column. Something like this:
This way you could create a new datarange, where you have grouped your data as you wish, excluding innecesary rows. Try it!
Work from the bottom up if you are going to delete rows. See if there is a match to the value in column D above the row you are working on. If there is a match, sum the values in column C into the matched row and remove the row you're working on.
Sub words()
Dim i As Long, m As Variant
With Worksheets("sheet1")
For i = .Cells(.Rows.Count, "D").End(xlUp).Row To 2 Step -1
m = Application.Match(.Cells(i, "D").Value, .Range("D:D").Resize(i - 1, 1), 0)
If Not IsError(m) Then
.Cells(m, "C") = .Cells(m, "C").Value2 + .Cells(i, "C").Value2
.Cells(i, "D").EntireRow.Delete
End If
Next i
End With
End Sub
I am using the following code to find the last row number in a column of data:
Dim LR as Long
LR = Range("A4").End("xlDown").Row
There are no blank cells between data in the A column. I am getting a type mismatch error. When I try to select the last row, I get an object error.
I am using the previous code because this code:
Workbooks(JunxureFile).Sheets("Sheet1").Range("A4", "A" &
Range("A4").End(xlDown).Row).Copy
did not stop after the first blank cell, and instead copied the entire column (to the max rows Excel allows).
Every example I've seen of Range.End implies it should not be acting this way, so I'm not sure what the problem is. I'm going to try just using rows.count for now, but I'd like to know what the issue with this code is. How do I change my code for it to work?
EDIT2:
I just tried
ActiveSheet.Range("E1").Value = Rows.Count
to see that Rows.Count is getting me 1048576, so it's still selecting way too many rows. I'm going to try copy and pasting my data to a different workbook to see if that helps (EDIT3: it did not).
This
Workbooks(JunxureFile).Sheets("Sheet1").Range("A4", "A" & Range("A4").End(xlDown).Row).Copy
might fail because you did not specify the correct worksheet for the second range like
Workbooks(JunxureFile).Worksheets("Sheet1").Range("A4", "A" & Workbooks(JunxureFile).Worksheets("Sheet1").Range("A4").End(xlDown).Row).Copy
or in a shorter way
With Workbooks(JunxureFile).Worksheets("Sheet1")
.Range("A4", "A" & .Range("A4").End(xlDown).Row).Copy
End With
Explanation:
If you use Range("A4") without specifying in which worksheet this range is, VBA guesses which sheet you mean and in most cases it is the same like writing ActiveSheet.Range("A4") but this might be easily the wrong sheet. So always specify which worksheet you mean the range to be in like: Workbooks(JunxureFile).Worksheets("Sheet1").Range("A4")
I am attempting to select a dynamic range of filtered data that spans from col. A: col. J without selecting the header (in row 1). From there I need to copy and paste it into a new sheet where I will manipulate it further, but I cannot come up with an efficient or functional way to do this. Based on some code I found on another forum I was able to select all of the "visable cells" in a single column, but I am running into issues trying to select the whole range. I am still very new to vba so forgive my syntax, but my code posted below was an attempt to itterate through Rows.Count and i which was an integer 1-10. If you have any advice on how to do this better and more efficiently I would really appreciate it.
Sub SelectVisibleInColD()
Dim lRow As Long, i As Integer
Set i = 1
Do While i <= 10
With ActiveSheet
lRow = .Cells(.Rows.Count, i).End(xlUp).Row
If lRow < 3 Then Exit Sub
.Cells(1, 1).Offset(1, 0).Resize(lRow - 1).SpecialCells(xlCellTypeVisible).Select
End With
i = i + 1
Loop
End Sub
You can select a range by using Range property of ActiveSheet. You already have the last row and you know that the header is in the first row, so your range starts from position A2 and goes to the last row of column J
ActiveSheet.Range("A2:J"&lRow).SpecialCells(xlCellTypeVisible)
If you want to copy this range, use Copy function like
yourRangeAsAbove.Copy
This function only moves the selection to memory, to paste it, build your destination range and call PasteSpecial function.
I came across this answer googling my issue for: deleting of filtered selection in vba.
However trying your answer &lRow gives me an runtime error 1004, application-defineed or object-defined error
I got around it with this
ActiveSheet.Range("A2:G" & Range("A" & Rows.Count).End(xlUp).Row).SpecialCells(xlCellTypeVisible).Delete
For those that may also get the same issue.
Is it possible to use a function in Excel 2003 to delete an entire row if it's the same as the previous one? For example:
apple
apple
plum
vinegar
apple
banana
banana
banana
apple
I want to delete #2, 7# and #8, but I don't want #5 and #9 to be deleted. I want to delete a duplicated entry ONLY IF it's the next one. I hope I managed to keep it clear to you.
If there isn't a function, how can I do that in VBA? Thanks in advance!
If it is a one-off, you can do it without VBA fairly simple by adding a formula in the next column - let's say your column is A:
in B2 put the following:
=IF(A1=A2,"DELETE","")
drag the formula down
add an autofilter on both columns
filter on "DELETE" in column B
delete all visible rows
remove column B
Here's something that might fit, deleting all duplicate rows (physically, not only cell data!), so keep in mind that it can be used only if you use one-column sheets. Otherwise you will loose some other data.
Sub Unduplicate()
Dim prev As String
Dim sel As Range
Dim i As Integer
Set sel = Range(Selection, Selection)
prev = sel.Offset(0).Value ' set prev as the first value - never will be deleted
i = 1 ' start from 2nd row
Do While sel.Offset(i).Value <> "" And sel.Offset(i).Value <> ""
If sel.Offset(i).Value = prev Then ' if duplicate - delete row
sel.Offset(i).EntireRow.Delete
Else ' else set new prev, and go further
prev = sel.Offset(i).Value
i = i + 1
End If
Loop
End Sub
After running this macro for your example, I'm getting:
You can modify it, to store the values in an array, and than fill the column with remembered array instead of deleting the rows, but that should be easy now.
Just a quick note...Make sure you work your way from the bottom of the range if you are deleting entire rows. You may get some unexpected results if you work your way down from the top of the range. You may also want to consider clearing the cell value and then sorting, instead of deleting. I would write up an example for you but I am short on time. If you get stuck I can write it for you later.
Edit:
My original answer is not necessarily true as shown in makciook's solution below. In the past I have mistakenly approached the problem this way (DO NOT USE THIS AS A SOLUTION!!!):
Sub duplicates()
Dim c As Range, rng As Range
Set rng = Selection ''Select the entire list before running
For Each c In rng
If c.Value = c.Offset(-1, 0).Value Then c.EntireRow.Delete
Next
End Sub
With this script, the cell range does not reset once a row is deleted and shifted up. So running this would not catch the second duplicate of banana in your list. As an alternative I usually find the last row and work my way up to the first row to account for the rows shifting up when a deletion occurs. I am going to give myself a -1 if possible.