在我开始之前我是一个非常新的编程和excel vba所以请你好。 我正在尝试制作一个程序,根据我们的输赢比率的电子表格自动为星际争霸2的友方游戏创建平衡的团队。
以下是该电子表格的简化版
然后我尝试使用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” 下标超出范围
最后,我意识到我使用的算法是非常低效的,我应该使用递归算法来做这种事情,但我并不真正理解递归,所以这是下一个最好的事情
感谢您抽出宝贵时间阅读本文
答案 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)
Console.WriteLine
是VB.Net语法。对于VBA,Debug.Print
就像QHarr建议的那样。Integer
中可以保存带符号的32位(4字节)整数,其值范围从2,147,483,648
到2,147,483,647
。在VBA中Integer
可以保存从32,768
到32,767
的值。因此建议在VBA中使用Long
。无需声明数组并手动填充它。声明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))
要查找总和,再次不需要循环遍历数组,您可以使用Application.Evaluate
直接找到范围的总和。例如
TotalScore = Application.Evaluate("=SUM(Sheet1!D2:D9)")
希望这有帮助