【问题标题】:First VBA Code: Run-time Error "1004"第一个 VBA 代码:运行时错误“1004”
【发布时间】:2016-03-14 02:32:48
【问题描述】:

我收到一个运行时错误,但这可能是我遇到的最小问题。这个逻辑在我脑海中是有道理的,但我可能没有使用正确的语法或函数。我的代码在下面带有 cmets 和“希望”:

Sub Random_Points()

    Dim i As Integer
    Dim j As Integer
    Dim Max As Integer
    Dim RandomNumber As Integer

    Max = 100 '(Max is being multiplied by the Rnd function to provide a random number between 0-100)

    For i = 2 To 100 Step 1

    RandomNumber = Int(Rnd * Max)
    ThisWorkbook.Sheets("VBA").Cells(i, 2).Value = RandomNumber

    '(The for loop above with start assigned cells values starting with Cells(2,2) to Cells(100,2))
    '(I DO NOT WANT DUPLICATE VALUES...therefore after the value is assigned above I want the code to compare the newly assigned cell to all the cells above it.)

        For j = 1 To 98 Step 1

        '(...and IF the cell values are the same...)
        If ThisWorkbook.Sheets("VBA").Cells(i, 2).Value = ThisWorkbook.Sheets("VBA").Cells(i - j, 2).Value Then

            '(...A new random number will be assigned...)
            RandomNumber = Int(Rnd * Max)
            ThisWorkbook.Sheets("VBA").Cells(i, 2).Value = RandomNumber
        End If

        '(...and then re-checked vs all the others)
        Next j

        '(Next cell is assigned...loop restarts)
    Next i
End Sub

【问题讨论】:

标签: vba excel runtime-error


【解决方案1】:

您的问题出在嵌套循环中。随着 j 的增加,它接近并最终等于 i。随后,当您使用.Cells(i - j, 2).Value 中的两个值时,没有行号小于1Range.Cells property

解决方案是更改嵌套的 For ... Next 语句,使 j 永远不会到达 i

'was ...
For j = 1 To 98 Step 1
'should be ...
For j = 1 To (i - 1) Step 1

在任何情况下,您只需要检查直到 i 的值。

fwiw,WorksheetFunction object 使用 MATCH function 和 VBA 的 IsError function 会更快。

Sub randomPoints_part_deux()
    Dim i As Long, mx As Long, randNum As Long

    mx = 100 '(mx is being multiplied by the Rnd function to provide a random number between 0-100)

    With ThisWorkbook.Sheets("VBA")
        'seed the column of numbers so you have something to check against
        randNum = Int(Rnd * mx)
        .Cells(2, 2) = randNum

        For i = 3 To 100 Step 1

            Do While Not IsError(Application.Match(randNum, .Range(.Cells(2, 2), .Cells(i - 1, 2)), 0))
                randNum = Int(Rnd * mx)
            Loop
            .Cells(i, 2) = randNum

        Next i
        'optional formula to count unique in C2
        .Cells(2, 3).Formula = "=SUMPRODUCT(1/COUNTIF(B2:B100, B2:B100))"
    End With
End Sub

【讨论】:

  • 非常感谢,非常感谢!
【解决方案2】:

由于您不希望重复,您可以生成随机数,然后反复检查它们是否已被使用,或者您可以先生成列表,然后随机从中提取。第二个选项更容易。

Sub Random100()

Dim i As Integer
Dim j As Integer
Dim Max As Integer
Dim RandomNumber As Integer
Dim cNum As New Collection

Max = 100 '(Max is being multiplied by the Rnd function to provide a random number between 0-100)

For i = 0 To Max 'fill collection with 0-100 in order
    cNum.Add i
Next i

k = cNum.Count - 1
For j = 0 To k
    RandomNumber = Int(Rnd * (k - j)) + 1
    ThisWorkbook.Sheets("VBA").Cells(j + 2, 2).Value = cNum(RandomNumber)
    cNum.Remove (RandomNumber)
Next j

End Sub

【讨论】:

  • 你能解释一下这个“RandomNumber = Int(Rnd * (k - j)) + 1”是否不断改变随机数的范围?谢谢。
  • 在引用您的收藏时,您希望从较大的数字向下计数。所以这让它从 0 中拉出一个随机数到集合中剩下的数量(K -J)。没有它,每次你在集合进行到一半时它都会中断,它会删除 50,然后尝试引用点 51。
【解决方案3】:

如果您的目的是获得一系列独特的价值,那么更好的方法是洗牌:

Const MIN = 1
Const MAX = 98

Dim values(MIN To MAX, 0 To 0) As Double, i&, irand&

' generate all the values
For i = MIN To MAX
  values(i, 0) = i
Next

' shuffle the values
For i = MIN To MAX
  irand = MIN + Math.Round(Rnd * (MAX - MIN))
  value = values(i, 0)
  values(i, 0) = values(irand, 0)
  values(irand, 0) = value
Next

' copy the values to the sheet
ThisWorkbook.Sheets("VBA").Range("A2").Resize(MAX - MIN + 1, 1) = values

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多