[RESOLVED] Delete Unchecked / Count checked Listview Records
Hi guys, i'm working on a project right now that requires deletion of unchecked items in Listview. I already have a working code but I guess this is not efficient if the number of items is 10,000+ or more. Here is my code:
Code:
recount:
For i = 1 To lvRecords.ListItems.Count
If Not lvRecords.ListItems(i).Checked Then
lvRecords.ListItems.Remove i
GoTo recount
End If
Next
I also have working code that counts/identify if the item is checked, however like my issue above this may take time if the records i'm processing is more than 10,000. Here is my code:
Code:
For i = 0 To lvRecords.ListItems.Count - 1
If lvRecords.ListItems(i + 1).Checked Then
countChecked = countChecked + 1
End If
Next
Is there any other efficient code than what i posted above that will provide the same functionality and results? Thanks in advance.
Re: Delete Unchecked / Count checked Listview Records
You could also increase/decrease the counter of checked items when a checkbox is checked/unchecked
Re: Delete Unchecked / Count checked Listview Records
Quote:
Originally Posted by
Arnoutdv
You could also increase/decrease the counter of checked items when a checkbox is checked/unchecked
How do I do that without selecting/highlighting the item?
Re: Delete Unchecked / Count checked Listview Records
The unchecked items need to be removed, correct?
Does this happen on a user action, like clicking a command button?
Re: Delete Unchecked / Count checked Listview Records
I created a small test, 1 ListView control, 4 command buttons.
Counting is very fast, deleting +7000 items from 10000 is also fast
You should not do a count for every delete, also delete the items backwards, starting with the last item.
Code:
Option Explicit
Private Sub Form_Load()
Randomize
End Sub
Private Sub cmdFill_Click()
Dim i As Long
With ListView1
.Checkboxes = True
.View = lvwReport
.ColumnHeaders.Clear
.ListItems.Clear
.ColumnHeaders.Add , , "Column 1"
For i = 1 To 10000
With .ListItems.Add(, , "Item: " & CStr(i))
.Checked = False
End With
Next i
End With
End Sub
Private Sub cmdCheck_Click()
Dim i As Long
Dim lIndex As Long
Dim lMax As Long
lMax = ListView1.ListItems.Count
For i = 1 To lMax
ListView1.ListItems(i).Checked = False
Next i
For i = 1 To lMax / 3
lIndex = Int(Rnd * lMax) + 1
ListView1.ListItems(lIndex).Checked = True
Next i
End Sub
Private Sub cmdCount_Click()
Dim i As Long
Dim lCnt
For i = 1 To ListView1.ListItems.Count
If ListView1.ListItems(i).Checked Then lCnt = lCnt + 1
Next i
Me.Caption = "Items checked: " & lCnt
End Sub
Private Sub cmdDelete_Click()
Dim i As Long
For i = ListView1.ListItems.Count To 1 Step -1
If Not ListView1.ListItems(i).Checked Then
ListView1.ListItems.Remove i
End If
Next i
End Sub
Re: Delete Unchecked / Count checked Listview Records
That first piece of code in the op is very inefficient. You need to forget that GoTo even exists and do not use it.
as is if you have 10,000 items and the last 100 are checked then it is going to check the first 9,900 items 100 times each. <eaning of course it would take 100 times longer than it should due to the use of GoTo and restarting the loop over and over again.
What it should be doing is a reverse loop like you have done in the second block. This way it only needs to process each item one time and items removed will not mess up the count on you.
Re: Delete Unchecked / Count checked Listview Records
An "For Each" is also faster on ListItems collections instead of an "For i =".
Re: Delete Unchecked / Count checked Listview Records
Quote:
Originally Posted by
Arnoutdv
The unchecked items need to be removed, correct?
Does this happen on a user action, like clicking a command button?
Yes, user initiated via clicking a button.
Quote:
Originally Posted by
Arnoutdv
I created a small test, 1 ListView control, 4 command buttons.
Counting is very fast, deleting +7000 items from 10000 is also fast
You should not do a count for every delete, also delete the items backwards, starting with the last item.
Code:
Option Explicit
Private Sub Form_Load()
Randomize
End Sub
Private Sub cmdFill_Click()
Dim i As Long
With ListView1
.Checkboxes = True
.View = lvwReport
.ColumnHeaders.Clear
.ListItems.Clear
.ColumnHeaders.Add , , "Column 1"
For i = 1 To 10000
With .ListItems.Add(, , "Item: " & CStr(i))
.Checked = False
End With
Next i
End With
End Sub
Private Sub cmdCheck_Click()
Dim i As Long
Dim lIndex As Long
Dim lMax As Long
lMax = ListView1.ListItems.Count
For i = 1 To lMax
ListView1.ListItems(i).Checked = False
Next i
For i = 1 To lMax / 3
lIndex = Int(Rnd * lMax) + 1
ListView1.ListItems(lIndex).Checked = True
Next i
End Sub
Private Sub cmdCount_Click()
Dim i As Long
Dim lCnt
For i = 1 To ListView1.ListItems.Count
If ListView1.ListItems(i).Checked Then lCnt = lCnt + 1
Next i
Me.Caption = "Items checked: " & lCnt
End Sub
Private Sub cmdDelete_Click()
Dim i As Long
For i = ListView1.ListItems.Count To 1 Step -1
If Not ListView1.ListItems(i).Checked Then
ListView1.ListItems.Remove i
End If
Next i
End Sub
This is perfect! I will just check if for each will make this code better. Thanks a lot! Cheers!
Quote:
Originally Posted by
DataMiser
That first piece of code in the op is very inefficient. You need to forget that GoTo even exists and do not use it.
as is if you have 10,000 items and the last 100 are checked then it is going to check the first 9,900 items 100 times each. <eaning of course it would take 100 times longer than it should due to the use of GoTo and restarting the loop over and over again.
What it should be doing is a reverse loop like you have done in the second block. This way it only needs to process each item one time and items removed will not mess up the count on you.
Yes, I knew that GoTo is not efficient that is why I asked a question here. Anyway, thanks for the info. I'm glad to hear your inputs and advice. Cheers!
Quote:
Originally Posted by
Krool
An "For Each" is also faster on ListItems collections instead of an "For i =".
I will try this one. Thanks!