创建随机数而不重复

时间:2015-04-29 17:31:58

标签: ms-access random access-vba

我正在尝试对现有的Access数据库应用程序进行故障排除,该应用程序应该生成介于1和表中记录数之间的随机数。这是针对具有不同记录数量的2个不同表格完成的。记录较少的表显示了应该显示的10个重复数字,并写入单独的表。我假设较大的表会发生同样的情况,但有更多数字可供选择,我只是无法复制问题。

以下是删除错误处理的代码示例:

    Dim db As DAO.Database
Dim rstRecords As DAO.Recordset
Dim rs As DAO.Recordset
Dim tdfNew As TableDef
Dim fldNew As Field
Dim i As Integer
Dim K As Integer
Dim Check As String

Set db = CurrentDb
Set rstRecords = db.OpenRecordset("customer_table")

     rstRecords.MoveLast
     FindRecordCount = rstRecords.RecordCount
     i = rstRecords.RecordCount
DoCmd.DeleteObject acTable, "Unique_numbers"

'--- create the table
Set tdfNew = db.CreateTableDef("Unique_numbers")
'--- add text field (length 20)
Set fldNew = tdfNew.CreateField("customer_table", dbLong)
'--- save the new field
tdfNew.Fields.Append fldNew

'--- save the new table design
db.TableDefs.Append tdfNew

'---Initialize your recordset
Set rs = CurrentDb.OpenRecordset("Unique_numbers", dbOpenDynaset)


'Dim i As Integer
'Dim K As Integer
'Dim Check As String

'i = TxtInput
  TxtInput = i
  K = 0
  Check = T

Do
  Do While K < 11
    'K = K + 1
        Randomize
          If K = 0 Then
            TxtOutput = Fix(i * Rnd) + 1
            rs.AddNew
            rs.Fields(0).Value = TxtOutput
            rs.Update
            K = K + 1
          ElseIf K = 1 Then
            TxtOutput2 = Fix(i * Rnd) + 1
            rs.AddNew
            rs.Fields(0).Value = TxtOutput2
            rs.Update
            K = K + 1
          ElseIf K = 2 Then
             TxtOutput3 = Fix(i * Rnd) + 1
             rs.AddNew
             rs.Fields(0).Value = TxtOutput3
             rs.Update
             K = K + 1
          ElseIf K = 3 Then
             TxtOutput4 = Fix(i * Rnd) + 1
             rs.AddNew
             rs.Fields(0).Value = TxtOutput4
             rs.Update
             K = K + 1
          ElseIf K = 4 Then
             TxtOutput5 = Fix(i * Rnd) + 1
             rs.AddNew
             rs.Fields(0).Value = TxtOutput5
             rs.Update
             K = K + 1
          ElseIf K = 5 Then
             TxtOutput6 = Fix(i * Rnd) + 1
             rs.AddNew
             rs.Fields(0).Value = TxtOutput6
             rs.Update
             K = K + 1
          ElseIf K = 6 Then
             TxtOutput7 = Fix(i * Rnd) + 1
             rs.AddNew
             rs.Fields(0).Value = TxtOutput7
             rs.Update
             K = K + 1
          ElseIf K = 7 Then
             TxtOutput8 = Fix(i * Rnd) + 1
             rs.AddNew
             rs.Fields(0).Value = TxtOutput8
             rs.Update
             K = K + 1
           ElseIf K = 8 Then
             TxtOutput9 = Fix(i * Rnd) + 1
             rs.AddNew
             rs.Fields(0).Value = TxtOutput9
             rs.Update
             K = K + 1
           ElseIf K = 9 Then
             TxtOutput10 = Fix(i * Rnd) + 1
             rs.AddNew
             rs.Fields(0).Value = TxtOutput10
             rs.Update
             K = K + 1
             Check = f
            Exit Do
          End If
    Loop
Loop Until Check = f

2 个答案:

答案 0 :(得分:1)

请注意,Randomize VBA函数会重新初始化随机数生成器种子。没有arugments,它使用系统计时器作为种子。

在每次调用Rnd之前,每次循环迭代都会重新初始化它。鉴于调用Randomize之间可能没有太多时间,您可能会在同一点重复重新启动随机数生成器,从而导致重复的数字。

尝试在代码顶部调用一次Randomize。

答案 1 :(得分:0)

生成随机数不是问题。生成随机唯一编号也不是问题。但是,从一个范围中选择一个尚未选择的随机数需要跟踪使用过的数字。问题在于性能,特别是如果您想从表中读取/更新值并检查ID是否已被使用。

您有两种选择。 (也许更多,我现在无法想到)

  • 如果您使用VBA更新表格。您可以使用包含已使用和未使用的数字列表的公共数组创建公共函数。
  • 如果您使用SQL查询再次更新表,则可以使用公共函数来获取随机数,但是您将使用新表中尚未使用的条件ID执行随机选择而不是数组。

第一种方法看起来像这样: 您可以从范围中发送最小值和最大值,并获取尚未使用的值。阵列或持有人将用于跟踪您使用和未使用的号码。我使用字典但你可以使用数组或数组与字典。

SELECT wp_posts. * , 
       SUM( wp_wti_like_post.value ) -4 AS total_sum,
       wp_wti_like_post.post_id
FROM wp_posts
INNER JOIN wp_term_relationships ON ( wp_posts.ID =  
                                        wp_term_relationships.object_id ) 
INNER JOIN wp_term_taxonomy ON ( wp_term_relationships.term_taxonomy_id =  
                                   wp_term_taxonomy.term_taxonomy_id ) 
JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) 
LEFT JOIN wp_wti_like_post ON ( wp_posts.ID = wp_wti_like_post.post_id    ) 
WHERE wp_term_taxonomy.taxonomy = 'category'
AND wp_term_taxonomy.term_id IN ('$c_cid')
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish')
GROUP BY wp_posts.ID
HAVING SUM( wp_wti_like_post.value )  > $min_like
ORDER BY wp_posts.post_date DESC

只需通过以下方式从您的范围中获取随机唯一ID:

    Option Compare Database
Option Explicit

Private mNumbers As Object
Private mSession_ID As Long

Public Function FN_GET_RANDOM_NO(iMin As Long, iMax As Long) As Long
    FN_GET_RANDOM_NO = Int((iMax - iMin + 1) * Rnd + iMin)
End Function

Public Function FN_RANDOM_INIT_COLLECTION(iSession_id As Long, iMin As Long, iMax As Long) As Object
    Set mNumbers = CreateObject("Scripting.Dictionary")
    Dim i, J As Long
    mSession_ID = iSession_id
    J = 0
    For i = iMin To iMax
        J = J + 1
        mNumbers.Add J, i
    Next i
End Function

Public Function FN_RANDOM_READ_UNUSED_NO() As Long
    Dim ID As Long
    ID = FN_GET_RANDOM_NO(1, mNumbers.count)
    FN_RANDOM_READ_UNUSED_NO = mNumbers(ID)
    If mNumbers.exists(ID) Then mNumbers.Remove ID

    Dim tmpDic As Object
    Set tmpDic = CreateObject("Scripting.Dictionary")

    Dim item As Variant
    Dim i As Long
    i = 0
    For Each item In mNumbers
        i = i + 1
        tmpDic.Add i, mNumbers(item)
    Next item

    Set mNumbers = tmpDic

End Function
Public Function FN_GET_UNUSED_NO(iSession_id As Long, iMin As Long, iMax As Long) As Long
    If mSession_ID = iSession_id Then
        If Not mNumbers Is Nothing Then
READ_AFTER:
            FN_GET_UNUSED_NO = FN_RANDOM_READ_UNUSED_NO
        Else
INIT:
            'initialize the table
            FN_RANDOM_INIT_COLLECTION iSession_id, iMin, iMax
            GoTo READ_AFTER:
        End If
    Else
        'new session reload the used number collection
        Set mNumbers = Nothing
        GoTo INIT
    End If
End Function

session_id用于标识您在一个会话中访问该集合。不同的id会重新初始化未使用的表。如果要管理多个集合,请展开代码。也许有阵列。

如果还没有要返回的数字,它将返回0。

结果将如下所示:

FN_GET_UNUSED_NO(1,10, 50)

第二种方法非常简单,您只需检索一个随机值,检查该值是否已在新表中分配。