【问题标题】:Excel VBA nested for-loop outputs replicated/wrong resultsExcel VBA嵌套for循环输出复制/错误结果
【发布时间】:2019-04-24 22:49:40
【问题描述】:

我有一个嵌套的 for 循环,它遍历两个不同人的生日年份(1919 年到 2001 年)。

目的是找到两个人的每个年龄组合(基于出生日期)。

我遇到的问题是嵌套循环(带有变量 j 的循环)中的人的年龄似乎有时会随机重复,没有任何规律。

例如,当人 N 为 100-20 岁时,每个组合都可以正常工作,而人 J 没有重复的年龄值。然后突然之间,当人 N 为 19 岁时,人 J 将从 100-50 岁变为49岁两次,然后到47岁。

以下是我的代码:

Sub ChangeDOB()
Application.ScreenUpdating = False
Dim n As Long
Dim i As Long
Dim j As Long
i = 2

For n = 1919 To 2001
    Sheets("Inputs").Range("E6").FormulaR1C1 = "1/15/" & n
    'j = 1919

    For j = 1919 To 2001
        Sheets("FF Tool Rates").Range("B" & i).Value = Sheets("Inputs").Range("E7").Value
        Sheets("Inputs").Range("E10").FormulaR1C1 = "1/15/" & j

        Sheets("FF Tool Rates").Range("C" & i).Value = Sheets("Inputs").Range("E11").Value
        Sheets("FF Tool Rates").Range("D" & i).Value = Sheets("Inputs").Range("S8").Value
        i = i + 1
    Next j
Next n
Application.ScreenUpdating = True

End Sub

Inputs!E7 中的公式计算人 N 的年龄。 Inputs!E11 中的公式计算人 J 的年龄。 Inputs!S8 中的公式根据两人的年龄计算一个值。我希望这会增加清晰度。

以下是预期结果的示例:

Person N Age   Person J Age
90             90
90             89
90             88
90             87
90             86
90             85
90             84
90             83
90             82
90             81

以下是错误结果的示例(查看age 85如何出现两次):

Person N Age   Person J Age
33             90
33             89
33             88
33             87
33             85 <-should've been 86
33             85 
33             84
33             83
33             82
33             81

最初我认为这是我设置 Excel 的方式,它根据出生日期计算年龄。但如果我在单元格中手动输入年份,Excel 会产生不重复的结果。所以手动输入时85岁不会出现两次。

似乎没有关于何时出现此错误的模式,如果我重新运行代码,有时不会出现错误,有时错误会出现在其他地方。这就是为什么我很难调试它。

关于我可能遗漏了什么地方或者我是否搞砸了我的代码中的任何逻辑的任何建议或建议?

提前谢谢你!

【问题讨论】:

  • a) 您的"1/15/" &amp; n 样式日期结构应该是DateSerial(n, 1, 15)DateSerial(j, 1, 15) 在格式化为日期的单元格中。 b) 看来您在 Inputs!E7、Inputs!E11 和 Inputs!S8 中有公式。您应该包含这些,因为您的结果取决于它们。
  • (1/2) 你好!感谢您的评论,对于没有早点回复您,我深表歉意。 a.) 我更新了公式以使用 DateSerial 函数。应用此更改后,输出中仍然存在错误。 b.) 我使用 VBA 的电子表格部分是一个更大文件的一小部分。因此,Inputs!E7、11 和 S8 中的公式链接了电子表格的其他部分,因此除非您将电子表格视为一个整体,否则公式本身并无用处。
  • (2/2) 我通过使用给我错误错误的年份输入来手动测试错误。 Inputs!E7、Inputs!E11 和 Inputs!S8 在手动测试期间都产生了正确的结果,所以我不认为这些单元格中的公式是产生错误的原因。只看代码的逻辑,你能发现任何逻辑错误吗? Excel 的 VBA 是否有可能运行“太快”,以至于公式无法处理更改,这就是导致错误值的原因?
  • 澄清一下:Inputs!E7 中的公式计算人 N 的年龄。 Inputs!E11 中的公式计算人 J 的年龄。 Inputs!S8 中的公式根据两人的年龄计算一个值。我希望这会增加清晰度。

标签: excel vba loops for-loop


【解决方案1】:

我想我遇到了完全相同的问题,你的问题是我发现的唯一一个似乎它的答案可以帮助我的问题。太糟糕了,没有任何答案。

我最终修复了它,所以希望这对其他人有帮助:

我有一个根据 4 个变量计算产品价格的工作簿(这些变量本身被划分到不同的工作表和其他工作簿中)。变量 a 有 25 种可能性,b 有 52 种,c 有 3 种,d 有 6 种。这给了我 22,464 种不同的价格可能性。我的代码有 4 个嵌套循环,可以在不同的行中打印每种可能性,因此我可以将输出导入不同的系统。
我遇到的问题是,除了在高端计算机上运行将近 30 分钟外,我还会随机获取包含错误数据的行。

我的(未经证实的)诊断是,因为在 For 循环中,工作表的其他地方(实际上是 Excel 中的任何地方)都在进行大量计算,有时 VBA 会继续迭代并填写下一行在源有机会更新之前。
这就是为什么当我进行单步调试时错误不会出现,以及为什么即使在运行整个代码时它也是断断续续且看似随机的。

我首先使用With 来简化我的代码并避免VBA 在每一行代码中遍历整个WorkbooksWorksheets 数组。我还为我的许多引用创建了Excel.WorkbookExcel.WorksheetExcel.Range 变量。

不过,最终似乎解决了这个问题的是,将 Application.Calculation = xlCalculationManual 添加到 sub 的开头,并将 Application.Calculate 添加到嵌套循环中的适当点。我添加了对Application.CalculationState 的检查,然后添加了DoEvents,但我什至不确定如何测试它是否有效。

这是代码的相关部分:

Sub test()
    '
    ' (Variable declarations suppressed)
    '
    
    Application.ScreenUpdating = False
        
    'Set to manual
    Application.Calculation = xlCalculationManual
        
    For a = 0 To 22464
        rngTabCusto.Value = wksCalculos.Cells(a / 936 + 23, 28).Value
        For b = 0 To 918
            rngFrete.Value = wksFrete.Cells(b / 18 + 4, 1).Value
            For c = 0 To 12
                rngTipoFat.Value = wksCalculos.Cells(c / 6 + 3, 3).Value

                '
                ' Calculate sheets after changing variables
                '
                Application.Calculate
                
                '
                ' Waits until calculations are done
                '
                If Not Application.CalculationState = xlDone Then
                    DoEvents
                End If
                
                '
                ' Prints calculation results
                '
                With wksDescontos
                    For d = 0 To 5
                        .Cells(a + b + c + d + 2, 1).Value = rngEstab.Value
                        .Cells(a + b + c + d + 2, 2).Value = wksOrcamento.Cells(2, d + 2).Value
                        .Cells(a + b + c + d + 2, 3).Value = rngContrib.Value
                        .Cells(a + b + c + d + 2, 4).Value = wksRegiao.Cells(b / 18 + 2, 1).Value
                        .Cells(a + b + c + d + 2, 5).Value = wksRegiao.Cells(b / 18 + 2, 2).Value
                        .Cells(a + b + c + d + 2, 6).Value = wksOrcamento.Cells(4, d + 2).Value
                        .Cells(a + b + c + d + 2, 7).Value = rngTabOrc.Value
                        .Cells(a + b + c + d + 2, 8).Value = data
                        .Cells(a + b + c + d + 2, 11).Value = rngFat.Value
                    Next d
                End With
            c = c + 5
            Next c
        b = b + 17
        Next b
    a = a + 935
    Next a
    
    'Reset
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    
End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多