VBA: Random selection from list, no duplicates

Noodle123

New Member
Joined
Sep 28, 2017
Messages
5
I am using the below code (provided by Tigeravitar) to randomly select statements to be audited and it is working perfectly with one exception:
There is nothing in the code to keep from selecting the same statement twice. I need to randomly select X number of statements without any duplicates.
I'm hoping there is a quick tweak that can solve this issue....but I've been searching through several forums and haven't had any luck yet.
Any ideas you may have would be greatly appreciated! Thank you!
Below is the code I am currently using which runs perfectly, but occasionally returns duplicates:

Sub EStmtAudit()

Dim wsEstmt As Worksheet
Dim wsEMas As Worksheet
Dim rngFound As Range
Dim arrResults() As Variant
Dim strNames As String
Dim lNumNames As Long
Dim i As Long, r As Long

Worksheets("Electronic Statements").Select 'Selects the "Electronic Statements" tab
TotRow = Range("D" & Rows.Count).End(xlUp).Row 'Finds bottom row of data
Range("D2:D" & TotRow).Copy 'Identifies range to copy & copies
Range("B2").PasteSpecial Paste:=xlPasteValues 'Identifies where to place first cell of data & pastes results as values




lNumNames = Int(Application.InputBox("How many statements will be audited?", "Number of Audits", 5, Type:=1))
If lNumNames <= 0 Then Exit Sub 'Invalid entry or pressed cancel

Set wsEstmt = Sheets("Electronic Statements")
Set wsEMas = Sheets("Electronic Stmt Audit Master")

With wsEstmt.Range("B2", wsEstmt.Cells(Rows.Count, "B").End(xlUp))
strNames = Join(Filter(Application.Transpose(Evaluate("If('" & .Parent.Name & "'!" & .Offset(, 1).Address & "<>""X"",'" & .Parent.Name & "'!" & .Address & ")")), False, False), "|")
End With

If Len(strNames) > 0 Then
If lNumNames <= (Len(strNames) - Len(Replace(strNames, "|", vbNullString)) + 1) Then
ReDim arrResults(1 To lNumNames, 1 To 3)
strNames = "|" & strNames & "|"
For i = 1 To lNumNames
r = Int(Rnd() * (Len(strNames) - Len(Replace(strNames, "|", vbNullString)) - 1)) + 1
Set rngFound = wsEstmt.Cells.Find(Trim(Mid(Replace(strNames, "|", String(255, " ")), 255 * r, 255)))
arrResults(i, 1) = i
arrResults(i, 2) = wsEstmt.Cells(rngFound.Row, "A").Text
arrResults(i, 3) = wsEstmt.Cells(rngFound.Row, "B").Text
strNames = Replace(strNames, "|" & rngFound.Text & "|", "|")
Next i
Intersect(wsEMas.Range("A2", wsEMas.Cells(Rows.Count, Columns.Count)), wsEMas.Columns("A").Resize(, UBound(arrResults, 2)).EntireColumn).ClearContents
wsEMas.Range("A2").Resize(UBound(arrResults, 1), UBound(arrResults, 2)).Value = arrResults
Else
MsgBox Title:="Entry Too High", _
Prompt:="There are not [" & lNumNames & "] statements that can be audited." & vbNewLine & _
"The maximum number that can be audited is: " & Len(strNames) - Len(Replace(strNames, "|", vbNullString)) + 1
End If
Else
MsgBox "No statements found that are available for auditing"
End If

Set wsEstmt = Nothing
Set wsEMas = Nothing
Set rngFound = Nothing
Erase arrResults

End Sub
 

Excel Facts

Can you sort left to right?
To sort left-to-right, use the Sort dialog box. Click Options. Choose "Sort left to right"
Hello NatalieBuck3,

This version of the macro will prevent duplicates.

Code:
Sub EStmtAudit()


    Dim Used        As New Collection
    Dim wsEstmt     As Worksheet
    Dim wsEMas      As Worksheet
    Dim rngFound    As Range
    Dim arrResults() As Variant
    Dim strNames    As String
    Dim lNumNames   As Long
    Dim i As Long, r As Long


        Worksheets("Electronic Statements").Select 'Selects the "Electronic Statements" tab
        TotRow = Range("D" & Rows.Count).End(xlUp).Row 'Finds bottom row of data
        
        Range("D2:D" & TotRow).Copy 'Identifies range to copy & copies
        Range("B2").PasteSpecial Paste:=xlPasteValues 'Identifies where to place first cell of data & pastes results as values


        lNumNames = Int(Application.InputBox("How many statements will be audited?", "Number of Audits", 5, Type:=1))
        If lNumNames <= 0 Then Exit Sub 'Invalid entry or pressed cancel


        Set wsEstmt = Sheets("Electronic Statements")
        Set wsEMas = Sheets("Electronic Stmt Audit Master")


            With wsEstmt.Range("B2", wsEstmt.Cells(Rows.Count, "B").End(xlUp))
                strNames = Join(Filter(Application.Transpose(Evaluate("If('" & .Parent.Name & "'!" & .Offset(, 1).Address & "<>""X"",'" & .Parent.Name & "'!" & .Address & ")")), False, False), "|")
            End With


            If Len(strNames) > 0 Then
                If lNumNames <= (Len(strNames) - Len(Replace(strNames, "|", vbNullString)) + 1) Then
                    ReDim arrResults(1 To lNumNames, 1 To 3)
                    strNames = "|" & strNames & "|"
                    For i = 1 To lNumNames
RandomNumber:
                        r = Int(Rnd() * (Len(strNames) - Len(Replace(strNames, "|", vbNullString)) - 1)) + 1
                        On Error Resume Next
                            Used.Add 1, Str(r)
                            If Err = 457 Then
                                On Error GoTo 0
                                GoTo RandomNumber
                            End If
                        On Error GoTo 0
                        
                        Set rngFound = wsEstmt.Cells.Find(Trim(Mid(Replace(strNames, "|", String(255, " ")), 255 * r, 255)))
                        arrResults(i, 1) = i
                        arrResults(i, 2) = wsEstmt.Cells(rngFound.Row, "A").Text
                        arrResults(i, 3) = wsEstmt.Cells(rngFound.Row, "B").Text
                        strNames = Replace(strNames, "|" & rngFound.Text & "|", "|")
                    Next i
                    Intersect(wsEMas.Range("A2", wsEMas.Cells(Rows.Count, Columns.Count)), wsEMas.Columns("A").Resize(, UBound(arrResults, 2)).EntireColumn).ClearContents
                    wsEMas.Range("A2").Resize(UBound(arrResults, 1), UBound(arrResults, 2)).Value = arrResults
                Else
                    MsgBox Title:="Entry Too High", _
                    Prompt:="There are not [" & lNumNames & "] statements that can be audited." & vbNewLine & _
                    "The maximum number that can be audited is: " & Len(strNames) - Len(Replace(strNames, "|", vbNullString)) + 1
                End If
            Else
                MsgBox "No statements found that are available for auditing"
            End If


        Set wsEstmt = Nothing
        Set wsEMas = Nothing
        Set rngFound = Nothing
        Erase arrResults


End Sub
 
Upvote 0
Wow, that was quick! Thank you so much! I will try running this code really quick and respond shortly with the results!
 
Upvote 0
Perhaps I spoke too soon, I am still getting a few duplicates. :(
I will continue to try and tweak this, thank you so much for pointing me in the right direction.
Once I find the code that works, I will definitely share it on this post!
 
Upvote 0

Forum statistics

Threads
1,223,888
Messages
6,175,206
Members
452,618
Latest member
Tam84

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top