VBA code executing very slowly
I'm new to VBA so the code I've written is very sloppy. My apologies.
The essence of my problem is that I need to delete duplicate rows from a worksheet with approx. 45,000 rows. Each iteration where the row is deleted takes approximately 30 seconds to complete, and I need to do this for thousands of rows. Any suggestions for how to improve my code so that this all goes faster?
Sub delete_duplicate_rows()
For i = 1 To 85000
If ActiveCell <> ActiveCell.Offset(1, 0) Or ActiveCell.Offset(0, -1) <> ActiveCell.Offset(1, -1) Or ActiveCell.Offset(0, 1) <> ActiveCell.Offset(1, 1) Or ActiveCell.Offset(0, 2) <> ActiveCell.Offset(1, 2) Or ActiveCell.Offset(0, 3) <> ActiveCell.Offset(1, 3) Or ActiveCell.Offset(0, 4) <> ActiveCell.Offset(1, 4) Or ActiveCell.Offset(0, 5) <> ActiveCell.Offset(1, 5) Or ActiveCell.Offset(0, 6) <> ActiveCell.Offset(1, 6) Or ActiveCell.Offset(0, 7) <> ActiveCell.Offset(1, 7) Or ActiveCell.Offset(0, 8) <> ActiveCell.Offset(1, 8) Or ActiveCell.Offset(0, 9) <> ActiveCell.Offset(1, 9) Or ActiveCell.Offset(0, 10) <> ActiveCell.Offset(1, 10) Or ActiveCell.Offset(0, 11) <> ActiveCell.Offset(1, 11) Or ActiveCell.Offset(0, 12) <> ActiveCell.Offset(1, 12) Or ActiveCell.Offset(0, 13) <> ActiveCell.Offset(1, 13) Then
ActiveCell.Offset(1, 0).Select
GoTo NextIteration
Else
End If
If ActiveCell.Value = "" Then Exit Sub
ActiveCell.Offset(0, -1).Range("A1:Q1").Select
Selection.Delete Shift:=xlUp
ActiveCell.Offset(0, 1).Range("A1").Select
NextIteration:
Next i
End Sub
Many thanks.
microsoft-excel vba microsoft-excel-2016
add a comment |
I'm new to VBA so the code I've written is very sloppy. My apologies.
The essence of my problem is that I need to delete duplicate rows from a worksheet with approx. 45,000 rows. Each iteration where the row is deleted takes approximately 30 seconds to complete, and I need to do this for thousands of rows. Any suggestions for how to improve my code so that this all goes faster?
Sub delete_duplicate_rows()
For i = 1 To 85000
If ActiveCell <> ActiveCell.Offset(1, 0) Or ActiveCell.Offset(0, -1) <> ActiveCell.Offset(1, -1) Or ActiveCell.Offset(0, 1) <> ActiveCell.Offset(1, 1) Or ActiveCell.Offset(0, 2) <> ActiveCell.Offset(1, 2) Or ActiveCell.Offset(0, 3) <> ActiveCell.Offset(1, 3) Or ActiveCell.Offset(0, 4) <> ActiveCell.Offset(1, 4) Or ActiveCell.Offset(0, 5) <> ActiveCell.Offset(1, 5) Or ActiveCell.Offset(0, 6) <> ActiveCell.Offset(1, 6) Or ActiveCell.Offset(0, 7) <> ActiveCell.Offset(1, 7) Or ActiveCell.Offset(0, 8) <> ActiveCell.Offset(1, 8) Or ActiveCell.Offset(0, 9) <> ActiveCell.Offset(1, 9) Or ActiveCell.Offset(0, 10) <> ActiveCell.Offset(1, 10) Or ActiveCell.Offset(0, 11) <> ActiveCell.Offset(1, 11) Or ActiveCell.Offset(0, 12) <> ActiveCell.Offset(1, 12) Or ActiveCell.Offset(0, 13) <> ActiveCell.Offset(1, 13) Then
ActiveCell.Offset(1, 0).Select
GoTo NextIteration
Else
End If
If ActiveCell.Value = "" Then Exit Sub
ActiveCell.Offset(0, -1).Range("A1:Q1").Select
Selection.Delete Shift:=xlUp
ActiveCell.Offset(0, 1).Range("A1").Select
NextIteration:
Next i
End Sub
Many thanks.
microsoft-excel vba microsoft-excel-2016
4
Avoid using.Select
/.Activate
– BruceWayne
Dec 17 '18 at 15:24
2
Curious why the "Remove Duplicates" built-in tool under the [Data] Ribbon tab can't be used for this?
– Mathieu Guindon
Dec 17 '18 at 15:35
1
@Comintern the answer below is still making way too many worksheet reads (and hints at nesting yet another loop, which wouln't improve performance). I'd work out the last row, dump the appropriate columns into a 2D array, iterate that array, andUnion
the rows that need to be deleted - then delete all union'd rows in a single.Delete
operation. I guess MT could be useful if there are millions of rows to go through, but then the MT overhead might just outweight its benefits.. not to mention out-of-process overhead for whatever non-VBA scripting tech is used for this.
– Mathieu Guindon
Dec 17 '18 at 16:29
Also see if that rather impressive matching criteria can be worked into aRange.RemoveDuplicates
call. If so, then you get Excel to do all the hard work.
– Mathieu Guindon
Dec 17 '18 at 16:36
A sample of data would be helpful. It appears you are satisfied with only looking a few rows ahead or behind for duplicates? There are many ways to speed this up but by necessity are more complex.
– Appleoddity
Dec 17 '18 at 20:15
add a comment |
I'm new to VBA so the code I've written is very sloppy. My apologies.
The essence of my problem is that I need to delete duplicate rows from a worksheet with approx. 45,000 rows. Each iteration where the row is deleted takes approximately 30 seconds to complete, and I need to do this for thousands of rows. Any suggestions for how to improve my code so that this all goes faster?
Sub delete_duplicate_rows()
For i = 1 To 85000
If ActiveCell <> ActiveCell.Offset(1, 0) Or ActiveCell.Offset(0, -1) <> ActiveCell.Offset(1, -1) Or ActiveCell.Offset(0, 1) <> ActiveCell.Offset(1, 1) Or ActiveCell.Offset(0, 2) <> ActiveCell.Offset(1, 2) Or ActiveCell.Offset(0, 3) <> ActiveCell.Offset(1, 3) Or ActiveCell.Offset(0, 4) <> ActiveCell.Offset(1, 4) Or ActiveCell.Offset(0, 5) <> ActiveCell.Offset(1, 5) Or ActiveCell.Offset(0, 6) <> ActiveCell.Offset(1, 6) Or ActiveCell.Offset(0, 7) <> ActiveCell.Offset(1, 7) Or ActiveCell.Offset(0, 8) <> ActiveCell.Offset(1, 8) Or ActiveCell.Offset(0, 9) <> ActiveCell.Offset(1, 9) Or ActiveCell.Offset(0, 10) <> ActiveCell.Offset(1, 10) Or ActiveCell.Offset(0, 11) <> ActiveCell.Offset(1, 11) Or ActiveCell.Offset(0, 12) <> ActiveCell.Offset(1, 12) Or ActiveCell.Offset(0, 13) <> ActiveCell.Offset(1, 13) Then
ActiveCell.Offset(1, 0).Select
GoTo NextIteration
Else
End If
If ActiveCell.Value = "" Then Exit Sub
ActiveCell.Offset(0, -1).Range("A1:Q1").Select
Selection.Delete Shift:=xlUp
ActiveCell.Offset(0, 1).Range("A1").Select
NextIteration:
Next i
End Sub
Many thanks.
microsoft-excel vba microsoft-excel-2016
I'm new to VBA so the code I've written is very sloppy. My apologies.
The essence of my problem is that I need to delete duplicate rows from a worksheet with approx. 45,000 rows. Each iteration where the row is deleted takes approximately 30 seconds to complete, and I need to do this for thousands of rows. Any suggestions for how to improve my code so that this all goes faster?
Sub delete_duplicate_rows()
For i = 1 To 85000
If ActiveCell <> ActiveCell.Offset(1, 0) Or ActiveCell.Offset(0, -1) <> ActiveCell.Offset(1, -1) Or ActiveCell.Offset(0, 1) <> ActiveCell.Offset(1, 1) Or ActiveCell.Offset(0, 2) <> ActiveCell.Offset(1, 2) Or ActiveCell.Offset(0, 3) <> ActiveCell.Offset(1, 3) Or ActiveCell.Offset(0, 4) <> ActiveCell.Offset(1, 4) Or ActiveCell.Offset(0, 5) <> ActiveCell.Offset(1, 5) Or ActiveCell.Offset(0, 6) <> ActiveCell.Offset(1, 6) Or ActiveCell.Offset(0, 7) <> ActiveCell.Offset(1, 7) Or ActiveCell.Offset(0, 8) <> ActiveCell.Offset(1, 8) Or ActiveCell.Offset(0, 9) <> ActiveCell.Offset(1, 9) Or ActiveCell.Offset(0, 10) <> ActiveCell.Offset(1, 10) Or ActiveCell.Offset(0, 11) <> ActiveCell.Offset(1, 11) Or ActiveCell.Offset(0, 12) <> ActiveCell.Offset(1, 12) Or ActiveCell.Offset(0, 13) <> ActiveCell.Offset(1, 13) Then
ActiveCell.Offset(1, 0).Select
GoTo NextIteration
Else
End If
If ActiveCell.Value = "" Then Exit Sub
ActiveCell.Offset(0, -1).Range("A1:Q1").Select
Selection.Delete Shift:=xlUp
ActiveCell.Offset(0, 1).Range("A1").Select
NextIteration:
Next i
End Sub
Many thanks.
microsoft-excel vba microsoft-excel-2016
microsoft-excel vba microsoft-excel-2016
asked Dec 17 '18 at 15:19
plshelpmewithexcel
132
132
4
Avoid using.Select
/.Activate
– BruceWayne
Dec 17 '18 at 15:24
2
Curious why the "Remove Duplicates" built-in tool under the [Data] Ribbon tab can't be used for this?
– Mathieu Guindon
Dec 17 '18 at 15:35
1
@Comintern the answer below is still making way too many worksheet reads (and hints at nesting yet another loop, which wouln't improve performance). I'd work out the last row, dump the appropriate columns into a 2D array, iterate that array, andUnion
the rows that need to be deleted - then delete all union'd rows in a single.Delete
operation. I guess MT could be useful if there are millions of rows to go through, but then the MT overhead might just outweight its benefits.. not to mention out-of-process overhead for whatever non-VBA scripting tech is used for this.
– Mathieu Guindon
Dec 17 '18 at 16:29
Also see if that rather impressive matching criteria can be worked into aRange.RemoveDuplicates
call. If so, then you get Excel to do all the hard work.
– Mathieu Guindon
Dec 17 '18 at 16:36
A sample of data would be helpful. It appears you are satisfied with only looking a few rows ahead or behind for duplicates? There are many ways to speed this up but by necessity are more complex.
– Appleoddity
Dec 17 '18 at 20:15
add a comment |
4
Avoid using.Select
/.Activate
– BruceWayne
Dec 17 '18 at 15:24
2
Curious why the "Remove Duplicates" built-in tool under the [Data] Ribbon tab can't be used for this?
– Mathieu Guindon
Dec 17 '18 at 15:35
1
@Comintern the answer below is still making way too many worksheet reads (and hints at nesting yet another loop, which wouln't improve performance). I'd work out the last row, dump the appropriate columns into a 2D array, iterate that array, andUnion
the rows that need to be deleted - then delete all union'd rows in a single.Delete
operation. I guess MT could be useful if there are millions of rows to go through, but then the MT overhead might just outweight its benefits.. not to mention out-of-process overhead for whatever non-VBA scripting tech is used for this.
– Mathieu Guindon
Dec 17 '18 at 16:29
Also see if that rather impressive matching criteria can be worked into aRange.RemoveDuplicates
call. If so, then you get Excel to do all the hard work.
– Mathieu Guindon
Dec 17 '18 at 16:36
A sample of data would be helpful. It appears you are satisfied with only looking a few rows ahead or behind for duplicates? There are many ways to speed this up but by necessity are more complex.
– Appleoddity
Dec 17 '18 at 20:15
4
4
Avoid using
.Select
/.Activate
– BruceWayne
Dec 17 '18 at 15:24
Avoid using
.Select
/.Activate
– BruceWayne
Dec 17 '18 at 15:24
2
2
Curious why the "Remove Duplicates" built-in tool under the [Data] Ribbon tab can't be used for this?
– Mathieu Guindon
Dec 17 '18 at 15:35
Curious why the "Remove Duplicates" built-in tool under the [Data] Ribbon tab can't be used for this?
– Mathieu Guindon
Dec 17 '18 at 15:35
1
1
@Comintern the answer below is still making way too many worksheet reads (and hints at nesting yet another loop, which wouln't improve performance). I'd work out the last row, dump the appropriate columns into a 2D array, iterate that array, and
Union
the rows that need to be deleted - then delete all union'd rows in a single .Delete
operation. I guess MT could be useful if there are millions of rows to go through, but then the MT overhead might just outweight its benefits.. not to mention out-of-process overhead for whatever non-VBA scripting tech is used for this.– Mathieu Guindon
Dec 17 '18 at 16:29
@Comintern the answer below is still making way too many worksheet reads (and hints at nesting yet another loop, which wouln't improve performance). I'd work out the last row, dump the appropriate columns into a 2D array, iterate that array, and
Union
the rows that need to be deleted - then delete all union'd rows in a single .Delete
operation. I guess MT could be useful if there are millions of rows to go through, but then the MT overhead might just outweight its benefits.. not to mention out-of-process overhead for whatever non-VBA scripting tech is used for this.– Mathieu Guindon
Dec 17 '18 at 16:29
Also see if that rather impressive matching criteria can be worked into a
Range.RemoveDuplicates
call. If so, then you get Excel to do all the hard work.– Mathieu Guindon
Dec 17 '18 at 16:36
Also see if that rather impressive matching criteria can be worked into a
Range.RemoveDuplicates
call. If so, then you get Excel to do all the hard work.– Mathieu Guindon
Dec 17 '18 at 16:36
A sample of data would be helpful. It appears you are satisfied with only looking a few rows ahead or behind for duplicates? There are many ways to speed this up but by necessity are more complex.
– Appleoddity
Dec 17 '18 at 20:15
A sample of data would be helpful. It appears you are satisfied with only looking a few rows ahead or behind for duplicates? There are many ways to speed this up but by necessity are more complex.
– Appleoddity
Dec 17 '18 at 20:15
add a comment |
1 Answer
1
active
oldest
votes
As others said, your code is slow do to a couple of things like using select
, activate
and goto
I believe the culprit of the slow performance is the multiple condition check at once, as you could check for changes on cells.
sub delete_duplicate_rows(byref ws as worksheet)
' Dim tbl_width as long, tbl_height as long
' Dim row_n, col_n as long
'
' This would be the correct form of one line var declarations, as it was stated in the comments
' I prefer this style, so I can group things like iters, table sizes, variants for `For each`
' and save some lines and see more code(I've a small screen)
dim tbl_width as long
dim tbl_height as long
dim row_n as long
dim col_n as long
with ws
for row_n=tbl_height to 2 step -1
for col_n=1 to tbl_width
if .range(.cells(row_n, col_n)) <> .range(.cells(row_n - 1, col_n)) then
.range(.cells(row_n , 1), .cells(row_n, tbl_width)).delete shift:=xlShiftUp
col_n = tbl_width
next col_n
next row_n
end with
end sub
This doesn't deppends on a fixed set of rows, don't activate or select anything, and the inner loop could be exited before when one of the conditions is not met. This way you will only check enough to make a decision on wheter to delete.
You could nest another loop, so it will check al the rows not just the one below to it.
1
note thatdim tbl_width, tbl_height as long
is declaringtbl_height
as a long integer, andtbl_weight
remains an implicitVariant
. Ditto withrow_n
.ws
has no reason to be passedByRef
, too. Lastly, this is still accessing the sheet directly in a tight, nested loop - that'll be faster than OP, but not half as efficient as it could be.
– Mathieu Guindon
Dec 17 '18 at 15:53
@MathieuGuindon is this true? Never had a problem with this style of declaration while usingoption explicit
you just poked my curiossity and I'm gonna check on that.
– dmb
Dec 17 '18 at 15:55
Yup. We even built an inspection for it in Rubberduck =)
– Mathieu Guindon
Dec 17 '18 at 15:58
@Comintern Given, forgot about this.
– dmb
Dec 17 '18 at 15:58
@MathieuGuindon You were right! I've been coding this whole time ignoring this implicitDIM
thing I think I've been trapped in thec
mentality. Thanks man, I love when stuff like this happens It makes improve your basics.
– dmb
Dec 21 '18 at 12:10
|
show 2 more comments
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "3"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1385274%2fvba-code-executing-very-slowly%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
As others said, your code is slow do to a couple of things like using select
, activate
and goto
I believe the culprit of the slow performance is the multiple condition check at once, as you could check for changes on cells.
sub delete_duplicate_rows(byref ws as worksheet)
' Dim tbl_width as long, tbl_height as long
' Dim row_n, col_n as long
'
' This would be the correct form of one line var declarations, as it was stated in the comments
' I prefer this style, so I can group things like iters, table sizes, variants for `For each`
' and save some lines and see more code(I've a small screen)
dim tbl_width as long
dim tbl_height as long
dim row_n as long
dim col_n as long
with ws
for row_n=tbl_height to 2 step -1
for col_n=1 to tbl_width
if .range(.cells(row_n, col_n)) <> .range(.cells(row_n - 1, col_n)) then
.range(.cells(row_n , 1), .cells(row_n, tbl_width)).delete shift:=xlShiftUp
col_n = tbl_width
next col_n
next row_n
end with
end sub
This doesn't deppends on a fixed set of rows, don't activate or select anything, and the inner loop could be exited before when one of the conditions is not met. This way you will only check enough to make a decision on wheter to delete.
You could nest another loop, so it will check al the rows not just the one below to it.
1
note thatdim tbl_width, tbl_height as long
is declaringtbl_height
as a long integer, andtbl_weight
remains an implicitVariant
. Ditto withrow_n
.ws
has no reason to be passedByRef
, too. Lastly, this is still accessing the sheet directly in a tight, nested loop - that'll be faster than OP, but not half as efficient as it could be.
– Mathieu Guindon
Dec 17 '18 at 15:53
@MathieuGuindon is this true? Never had a problem with this style of declaration while usingoption explicit
you just poked my curiossity and I'm gonna check on that.
– dmb
Dec 17 '18 at 15:55
Yup. We even built an inspection for it in Rubberduck =)
– Mathieu Guindon
Dec 17 '18 at 15:58
@Comintern Given, forgot about this.
– dmb
Dec 17 '18 at 15:58
@MathieuGuindon You were right! I've been coding this whole time ignoring this implicitDIM
thing I think I've been trapped in thec
mentality. Thanks man, I love when stuff like this happens It makes improve your basics.
– dmb
Dec 21 '18 at 12:10
|
show 2 more comments
As others said, your code is slow do to a couple of things like using select
, activate
and goto
I believe the culprit of the slow performance is the multiple condition check at once, as you could check for changes on cells.
sub delete_duplicate_rows(byref ws as worksheet)
' Dim tbl_width as long, tbl_height as long
' Dim row_n, col_n as long
'
' This would be the correct form of one line var declarations, as it was stated in the comments
' I prefer this style, so I can group things like iters, table sizes, variants for `For each`
' and save some lines and see more code(I've a small screen)
dim tbl_width as long
dim tbl_height as long
dim row_n as long
dim col_n as long
with ws
for row_n=tbl_height to 2 step -1
for col_n=1 to tbl_width
if .range(.cells(row_n, col_n)) <> .range(.cells(row_n - 1, col_n)) then
.range(.cells(row_n , 1), .cells(row_n, tbl_width)).delete shift:=xlShiftUp
col_n = tbl_width
next col_n
next row_n
end with
end sub
This doesn't deppends on a fixed set of rows, don't activate or select anything, and the inner loop could be exited before when one of the conditions is not met. This way you will only check enough to make a decision on wheter to delete.
You could nest another loop, so it will check al the rows not just the one below to it.
1
note thatdim tbl_width, tbl_height as long
is declaringtbl_height
as a long integer, andtbl_weight
remains an implicitVariant
. Ditto withrow_n
.ws
has no reason to be passedByRef
, too. Lastly, this is still accessing the sheet directly in a tight, nested loop - that'll be faster than OP, but not half as efficient as it could be.
– Mathieu Guindon
Dec 17 '18 at 15:53
@MathieuGuindon is this true? Never had a problem with this style of declaration while usingoption explicit
you just poked my curiossity and I'm gonna check on that.
– dmb
Dec 17 '18 at 15:55
Yup. We even built an inspection for it in Rubberduck =)
– Mathieu Guindon
Dec 17 '18 at 15:58
@Comintern Given, forgot about this.
– dmb
Dec 17 '18 at 15:58
@MathieuGuindon You were right! I've been coding this whole time ignoring this implicitDIM
thing I think I've been trapped in thec
mentality. Thanks man, I love when stuff like this happens It makes improve your basics.
– dmb
Dec 21 '18 at 12:10
|
show 2 more comments
As others said, your code is slow do to a couple of things like using select
, activate
and goto
I believe the culprit of the slow performance is the multiple condition check at once, as you could check for changes on cells.
sub delete_duplicate_rows(byref ws as worksheet)
' Dim tbl_width as long, tbl_height as long
' Dim row_n, col_n as long
'
' This would be the correct form of one line var declarations, as it was stated in the comments
' I prefer this style, so I can group things like iters, table sizes, variants for `For each`
' and save some lines and see more code(I've a small screen)
dim tbl_width as long
dim tbl_height as long
dim row_n as long
dim col_n as long
with ws
for row_n=tbl_height to 2 step -1
for col_n=1 to tbl_width
if .range(.cells(row_n, col_n)) <> .range(.cells(row_n - 1, col_n)) then
.range(.cells(row_n , 1), .cells(row_n, tbl_width)).delete shift:=xlShiftUp
col_n = tbl_width
next col_n
next row_n
end with
end sub
This doesn't deppends on a fixed set of rows, don't activate or select anything, and the inner loop could be exited before when one of the conditions is not met. This way you will only check enough to make a decision on wheter to delete.
You could nest another loop, so it will check al the rows not just the one below to it.
As others said, your code is slow do to a couple of things like using select
, activate
and goto
I believe the culprit of the slow performance is the multiple condition check at once, as you could check for changes on cells.
sub delete_duplicate_rows(byref ws as worksheet)
' Dim tbl_width as long, tbl_height as long
' Dim row_n, col_n as long
'
' This would be the correct form of one line var declarations, as it was stated in the comments
' I prefer this style, so I can group things like iters, table sizes, variants for `For each`
' and save some lines and see more code(I've a small screen)
dim tbl_width as long
dim tbl_height as long
dim row_n as long
dim col_n as long
with ws
for row_n=tbl_height to 2 step -1
for col_n=1 to tbl_width
if .range(.cells(row_n, col_n)) <> .range(.cells(row_n - 1, col_n)) then
.range(.cells(row_n , 1), .cells(row_n, tbl_width)).delete shift:=xlShiftUp
col_n = tbl_width
next col_n
next row_n
end with
end sub
This doesn't deppends on a fixed set of rows, don't activate or select anything, and the inner loop could be exited before when one of the conditions is not met. This way you will only check enough to make a decision on wheter to delete.
You could nest another loop, so it will check al the rows not just the one below to it.
edited Dec 21 '18 at 13:26
answered Dec 17 '18 at 15:51
dmb
654212
654212
1
note thatdim tbl_width, tbl_height as long
is declaringtbl_height
as a long integer, andtbl_weight
remains an implicitVariant
. Ditto withrow_n
.ws
has no reason to be passedByRef
, too. Lastly, this is still accessing the sheet directly in a tight, nested loop - that'll be faster than OP, but not half as efficient as it could be.
– Mathieu Guindon
Dec 17 '18 at 15:53
@MathieuGuindon is this true? Never had a problem with this style of declaration while usingoption explicit
you just poked my curiossity and I'm gonna check on that.
– dmb
Dec 17 '18 at 15:55
Yup. We even built an inspection for it in Rubberduck =)
– Mathieu Guindon
Dec 17 '18 at 15:58
@Comintern Given, forgot about this.
– dmb
Dec 17 '18 at 15:58
@MathieuGuindon You were right! I've been coding this whole time ignoring this implicitDIM
thing I think I've been trapped in thec
mentality. Thanks man, I love when stuff like this happens It makes improve your basics.
– dmb
Dec 21 '18 at 12:10
|
show 2 more comments
1
note thatdim tbl_width, tbl_height as long
is declaringtbl_height
as a long integer, andtbl_weight
remains an implicitVariant
. Ditto withrow_n
.ws
has no reason to be passedByRef
, too. Lastly, this is still accessing the sheet directly in a tight, nested loop - that'll be faster than OP, but not half as efficient as it could be.
– Mathieu Guindon
Dec 17 '18 at 15:53
@MathieuGuindon is this true? Never had a problem with this style of declaration while usingoption explicit
you just poked my curiossity and I'm gonna check on that.
– dmb
Dec 17 '18 at 15:55
Yup. We even built an inspection for it in Rubberduck =)
– Mathieu Guindon
Dec 17 '18 at 15:58
@Comintern Given, forgot about this.
– dmb
Dec 17 '18 at 15:58
@MathieuGuindon You were right! I've been coding this whole time ignoring this implicitDIM
thing I think I've been trapped in thec
mentality. Thanks man, I love when stuff like this happens It makes improve your basics.
– dmb
Dec 21 '18 at 12:10
1
1
note that
dim tbl_width, tbl_height as long
is declaring tbl_height
as a long integer, and tbl_weight
remains an implicit Variant
. Ditto with row_n
. ws
has no reason to be passed ByRef
, too. Lastly, this is still accessing the sheet directly in a tight, nested loop - that'll be faster than OP, but not half as efficient as it could be.– Mathieu Guindon
Dec 17 '18 at 15:53
note that
dim tbl_width, tbl_height as long
is declaring tbl_height
as a long integer, and tbl_weight
remains an implicit Variant
. Ditto with row_n
. ws
has no reason to be passed ByRef
, too. Lastly, this is still accessing the sheet directly in a tight, nested loop - that'll be faster than OP, but not half as efficient as it could be.– Mathieu Guindon
Dec 17 '18 at 15:53
@MathieuGuindon is this true? Never had a problem with this style of declaration while using
option explicit
you just poked my curiossity and I'm gonna check on that.– dmb
Dec 17 '18 at 15:55
@MathieuGuindon is this true? Never had a problem with this style of declaration while using
option explicit
you just poked my curiossity and I'm gonna check on that.– dmb
Dec 17 '18 at 15:55
Yup. We even built an inspection for it in Rubberduck =)
– Mathieu Guindon
Dec 17 '18 at 15:58
Yup. We even built an inspection for it in Rubberduck =)
– Mathieu Guindon
Dec 17 '18 at 15:58
@Comintern Given, forgot about this.
– dmb
Dec 17 '18 at 15:58
@Comintern Given, forgot about this.
– dmb
Dec 17 '18 at 15:58
@MathieuGuindon You were right! I've been coding this whole time ignoring this implicit
DIM
thing I think I've been trapped in the c
mentality. Thanks man, I love when stuff like this happens It makes improve your basics.– dmb
Dec 21 '18 at 12:10
@MathieuGuindon You were right! I've been coding this whole time ignoring this implicit
DIM
thing I think I've been trapped in the c
mentality. Thanks man, I love when stuff like this happens It makes improve your basics.– dmb
Dec 21 '18 at 12:10
|
show 2 more comments
Thanks for contributing an answer to Super User!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1385274%2fvba-code-executing-very-slowly%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
Avoid using
.Select
/.Activate
– BruceWayne
Dec 17 '18 at 15:24
2
Curious why the "Remove Duplicates" built-in tool under the [Data] Ribbon tab can't be used for this?
– Mathieu Guindon
Dec 17 '18 at 15:35
1
@Comintern the answer below is still making way too many worksheet reads (and hints at nesting yet another loop, which wouln't improve performance). I'd work out the last row, dump the appropriate columns into a 2D array, iterate that array, and
Union
the rows that need to be deleted - then delete all union'd rows in a single.Delete
operation. I guess MT could be useful if there are millions of rows to go through, but then the MT overhead might just outweight its benefits.. not to mention out-of-process overhead for whatever non-VBA scripting tech is used for this.– Mathieu Guindon
Dec 17 '18 at 16:29
Also see if that rather impressive matching criteria can be worked into a
Range.RemoveDuplicates
call. If so, then you get Excel to do all the hard work.– Mathieu Guindon
Dec 17 '18 at 16:36
A sample of data would be helpful. It appears you are satisfied with only looking a few rows ahead or behind for duplicates? There are many ways to speed this up but by necessity are more complex.
– Appleoddity
Dec 17 '18 at 20:15