为什么我在Excel VBA上遇到运行时错误

时间:2018-04-13 03:43:58

标签: excel vba excel-vba

在我开始之前我是一个非常新的编程和excel vba所以请你好。 我正在尝试制作一个程序,根据我们的输赢比率的电子表格自动为星际争霸2的友方游戏创建平衡的团队。

以下是该电子表格的简化版

the simplified spreadsheet

然后我尝试使用vba代码来运行每个可能的团队配置,并找到两个团队,其中赢/输比之和之间的差异是最小的。

这是我的代码,我希望你能理解所有的变量名称

        Public Sub Main()
    Dim TotalScore As Integer
    TotalScore = 0
   Dim TargetScore As Integer
    TargetScore = 0
    Dim CurrentScore As Integer
    CurrentScore = 0
    Dim InitialScoreDifference As Integer
    InitialScoreDifference = 0
    Dim ScoreDifference As Integer
    ScoreDifference = 0
   Dim Scores(0 To 7) As Long
    Scores(0) = Worksheets("Sheet1").Cells(2, "D").Value
    Scores(1) = Worksheets("Sheet1").Cells(3, "D").Value
    Scores(2) = Worksheets("Sheet1").Cells(4, "D").Value
    Scores(3) = Worksheets("Sheet1").Cells(5, "D").Value
    Scores(4) = Worksheets("Sheet1").Cells(6, "D").Value
    Scores(5) = Worksheets("Sheet1").Cells(7, "D").Value
    Scores(6) = Worksheets("Sheet1").Cells(8, "D").Value
    Scores(7) = Worksheets("Sheet1").Cells(9, "D").Value
        For x = 0 To Scores(7)
            TotalScore = TotalScore + Scores(x)
        Next x
        TargetScore = Int(TotalScore / 2)
        InitialScoreDifference = (TotalScore)
        Console.WriteLine (TotalScore)
        Console.WriteLine (TargetScore)
        Console.WriteLine (InitialScoreDifference)
        For a = 0 To Scores(7)
            For b = 0 To Scores(7)
                For c = 0 To Scores(7)
                    For d = 0 To Scores(7)
                        CurrentScore = (Scores(a) + Scores(b) + Scores(c) + Scores(d))
                        ScoreDifference = ((TargetScore - CurrentScore) * (TargetScore - CurrentScore))
                        If ScoreDifference <= InitialScoreDifference Then

                            If ((Scores(a) <> Scores(b)) And (Scores(a) <> Scores(c)) And (Scores(a) <> Scores(d)) And (Scores(b) <> Scores(c)) And (Scores(b) <> Scores(d)) And (Scores(c) <> Scores(d))) Then
                                InitialScoreDifference = ScoreDifference
                                Console.WriteLine (Scores(a) & " " & Scores(b) & " " & Scores(c) & " " & Scores(d) & " " & ScoreDifference)
                            End If
                        End If
                    Next d
                Next c
            Next b
        Next a
  End Sub

当我在视觉工作室运行代码时,它工作正常,并给我4个赢/输分数的组合,将平衡团队。但是,当我在excel vba上运行它时,我会继续: 运行时错误“9” 下标超出范围

最后,我意识到我使用的算法是非常低效的,我应该使用递归算法来做这种事情,但我并不真正理解递归,所以这是下一个最好的事情

感谢您抽出宝贵时间阅读本文

2 个答案:

答案 0 :(得分:2)

在vba中你不能写

Console.WriteLine (TotalScore)

改为写

Debug.Print TotalScore

您还应该声明Long而不是Integer以避免溢出,将Option Explicit放在模块的顶部并声明所有变量,例如。

由于我认为你循环整个数组,最好避免硬编码边界,​​因为你可能会在未来增加数组的大小,所以假设你在当前的ActiveWorkbook中有一个名为“Sheet1”的工作表:

Option Explicit

Public Sub Main()
    Dim TotalScore As Long
    Dim TargetScore As Long
    Dim CurrentScore As Long
    Dim InitialScoreDifference As Long
    Dim ScoreDifference As Long

    TotalScore = 0
    TargetScore = 0
    CurrentScore = 0
    InitialScoreDifference = 0
    ScoreDifference = 0

    Dim Scores(0 To 7) As Long
    Scores(0) = Worksheets("Sheet1").Cells(2, "D").Value
    Scores(1) = Worksheets("Sheet1").Cells(3, "D").Value
    Scores(2) = Worksheets("Sheet1").Cells(4, "D").Value
    Scores(3) = Worksheets("Sheet1").Cells(5, "D").Value
    Scores(4) = Worksheets("Sheet1").Cells(6, "D").Value
    Scores(5) = Worksheets("Sheet1").Cells(7, "D").Value
    Scores(6) = Worksheets("Sheet1").Cells(8, "D").Value
    Scores(7) = Worksheets("Sheet1").Cells(9, "D").Value

    Dim x As Long

    For x = LBound(Scores) To UBound(Scores)
        TotalScore = TotalScore + Scores(x)
    Next x

    TargetScore = CLng(TotalScore / 2)
    InitialScoreDifference = (TotalScore)

    Debug.Print "TotalScore: " & TotalScore
    Debug.Print "TargetScore: " & TargetScore
    Debug.Print "InitialScoreDifference: " & InitialScoreDifference

    Dim a As Long, b As Long, c As Long, d As Long

    For a = LBound(Scores) To UBound(Scores)
        For b = LBound(Scores) To UBound(Scores)
            For c = LBound(Scores) To UBound(Scores)
                For d = LBound(Scores) To UBound(Scores)
                    CurrentScore = (Scores(a) + Scores(b) + Scores(c) + Scores(d))
                    ScoreDifference = (TargetScore - CurrentScore) * (TargetScore - CurrentScore)
                    If ScoreDifference <= InitialScoreDifference Then
                        If ((Scores(a) <> Scores(b)) And (Scores(a) <> Scores(c)) And (Scores(a) <> Scores(d)) And (Scores(b) <> Scores(c)) And (Scores(b) <> Scores(d)) And (Scores(c) <> Scores(d))) Then
                            InitialScoreDifference = ScoreDifference
                            Debug.Print (Scores(a) & " " & Scores(b) & " " & Scores(c) & " " & Scores(d) & " " & ScoreDifference)
                        End If
                    End If
                Next d
            Next c
        Next b
    Next a
End Sub

答案 1 :(得分:0)

  1. Console.WriteLine是VB.Net语法。对于VBA,Debug.Print就像QHarr建议的那样。
  2. 在VB.Net Integer中可以保存带符号的32位(4字节)整数,其值范围从2,147,483,6482,147,483,647。在VBA中Integer可以保存从32,76832,767的值。因此建议在VBA中使用Long
  3. 无需声明数组并手动填充它。声明Variant并在运行时填充数组。例如

    Dim Scores(0 To 7) As Long
    Scores(0) = Worksheets("Sheet1").Cells(2, "D").Value
    Scores(1) = Worksheets("Sheet1").Cells(3, "D").Value
    Scores(2) = Worksheets("Sheet1").Cells(4, "D").Value
    Scores(3) = Worksheets("Sheet1").Cells(5, "D").Value
    Scores(4) = Worksheets("Sheet1").Cells(6, "D").Value
    Scores(5) = Worksheets("Sheet1").Cells(7, "D").Value
    Scores(6) = Worksheets("Sheet1").Cells(8, "D").Value
    Scores(7) = Worksheets("Sheet1").Cells(9, "D").Value
    

    可以写成

    Dim Scores As Variant
    Scores = Worksheets("Sheet1").Range("D2:D9").Value
    

    然后你可以将它们用作

    CurrentScore = (Scores(a, 1) + Scores(b, 1) + Scores(c, 1) + Scores(d, 1))
    
  4. 要查找总和,再次不需要循环遍历数组,您可以使用Application.Evaluate直接找到范围的总和。例如

    TotalScore = Application.Evaluate("=SUM(Sheet1!D2:D9)")
    
  5. 希望这有帮助