对于步骤 0.001 的下一个循环,创建比预期更多的输出值

问题描述 投票:0回答:3

这段 VBA 代码正在生成看似无穷无尽的值。我不得不停下来,因为它持续了很长时间。

我预计它会在活动单元格列中产生 2626 个值 (2.626/0.001)。

Sub simp3()

    Dim i As Long
    Dim max1 As Long
    Dim max2 As Long
    Dim r1 As Range
    Dim r2 As Range
    Set r1 = Range("AP7:AP26500")
    Set r2 = Range("AS7:AS2633")
    
    Range("AS7").Select
    
    For i = 0 To 2.626 Step 0.001
        Range("C32") = i
        max1 = Application.WorksheetFunction.max(r1)
        ActiveCell.Value = max1
        ActiveCell.Offset(1, 0).Select
    Next i
    
    max2 = Application.WorksheetFunction.max(r2)
    Range("AS3").Value = max2

End Sub
excel vba loops
3个回答
2
投票

该行为的原因是正在发生隐式转换。

当您将

i
定义为数据类型为
long
的变量时,像
0 + 0.001
这样的操作将被转换为 long,因此
i = i + 0.001
将再次变为
0
。你已经创建了一个无限循环。

只需使用

Dim i as double

https://bettersolutions.com/vba/data-types/converting.htm

检查这个例子

   Sub implcitConversions()
    
    Dim i As Long
    i = 1
    i = i + 0.01
    ' Output will be 1 as 1 + 00.1 was converted to long by rounding
    Debug.Print i
    
    i = 1
    ' Output will be 1.01 as in this case
    ' a widening takes place due to the use of debug.print
    Debug.Print i + 0.01

End Sub

0
投票

您正在尝试使用浮点算术迭代声明为 Long 的变量。迭代最大到 2626 的整数,然后在循环中将该值除以 1000 会更干净。或者,将 i 声明为 double 而不是 long。虽然在 VBA 中可以使用浮点数进行迭代,但这并不被认为是干净的做法。在其他语言中,有时只允许整数步进行迭代。


0
投票

摆脱
Select
Active

  • 前面的答案和评论中讨论了代码失败的主要原因。
  • 下面展示了如何通过使用常量和变量来提高可读性和可维护性(请随意重命名它们,只要您认为合适)。
  • 不使用
    Select
    和各种风格的
    Active
    将提高代码的效率(速度)。它仍然可以通过引入一个数组来保存结果值并将它们一次性写入工作表来改进。
Sub simp3()
    
    ' Define constants.
    Const FIRST_NUMBER As Double = 0 ' maybe 0.001 !?
    Const LAST_NUMBER As Double = 2.626
    Const STEP_NUMBER As Double = 0.001
    
    ' Reference the worksheet.
    Dim ws As Worksheet: Set ws = ActiveSheet ' improve!

    ' Reference the source range.
    Dim srg As Range: Set srg = ws.Range("AP7:AP26500")
    ' Reference the source trigger cell, a cell the values in the source range
    ' depend on.
    Dim scell As Range: Set scell = ws.Range("C32")
    
    ' Reference the destination first cell.
    Dim dfcell As Range: Set dfcell = ws.Range("AS7")
    ' Reference the destination max cell.
    Dim dmcell As Range: Set dmcell = ws.Range("AS3")
    ' Reference the next destination cell.
    ' We need the first destination cell to build the destination range ('drg')
    ' to get the destination max.
    Dim dcell As Range: Set dcell = dfcell
     
    Dim i As Double
    
    For i = FIRST_NUMBER To LAST_NUMBER Step STEP_NUMBER
        ' Trigger a change in the source range.
        scell.Value = i
        ' Write the new source max to the current destination cell.
        dcell.Value = Application.WorksheetFunction.Max(srg)
        ' Reference the next destination cell (row).
        Set dcell = dcell.Offset(1)
    Next i
    
    ' Reference the destination range.
    Dim drg As Range: Set drg = ws.Range(dfcell, dcell.Offset(-1))
    
    ' Write the destination max to the destination max cell.
    dmcell.Value = Application.WorksheetFunction.Max(drg)

End Sub
© www.soinside.com 2019 - 2024. All rights reserved.