【问题标题】:VBA For Loop Variables循环变量的 VBA
【发布时间】:2019-02-11 02:35:48
【问题描述】:

我对 VBA 比较陌生,我正试图在 Excel VBA 中模拟一个复杂的方程,因为我的数据记录器输出的是 CSV,而且由于方程很长而且很复杂,有 13 个变量和 17 个中间计算,我'正在尝试制作变量以帮助使代码在调试(现在和将来我做这样的事情时)和使我对模拟所做的修改更加可视化时更具可读性。

我的代码基本结构如下:

'Temperature = .Cells(i,1)
'WindSpeed = .Cells(i,2)
'SolarRadiation = .Cells(i,3)
'Humidity = .Cells(i,4)
'SimulatedValue = .Cells(i,5)

Sub Simulation()
With Worksheets("DataLoggerValues")
Dim i As Integer

For i = 2 To 184

.Cells(i,5) = (.Cells(i,1)+.Cells(i,3)/.Cells(i,2))^2 + .Cells(i,4)/37

Next i

End With
End Sub

我想清理一下,这样代码行看起来更像:

Simulated value = (Temperature+SolarRadiation/WindSpeed)^2 + Humidity/37

但每次我尝试使用 .Cells(i,j) 作为变量声明任何内容时(我尝试过字符串和数组),我都会收到许多不同的错误,最常见的是“运行时错误 1004”,但是有时将“语法错误”或“预期的新名称或类型名称”作为编译错误。

是否甚至可以将 .Cells(i,j) 转换为变量,还是我需要采取不同的方法?

提前致谢!

【问题讨论】:

  • CELLS() 是一个范围。有时没有它也可以工作,但我总是使用CELLS(i,j).VALUE 来明确我正在设置或获取单元格的值。而且我不确定你为什么有.Cells。试试不带.
  • 欢迎使用 Excel VBA 编程。我们都陷入了 Cell(row,column) 的陷阱,并认为“哦,这很容易”。你想要做的是使用范围,一个单元格就是一个范围。更重要的是,学习如何使用命名范围和 ListObjects 对您的成功至关重要。单击此处查看Microsoft's Named Range DocumentationChip Pearson 是我最喜欢的VBA。

标签: excel vba


【解决方案1】:

您的代码应如下所示。

Sub Simulation()

    Dim i As Long
    Dim Temperature As Long
    Dim WindSpeed As Long
    Dim SolarRadiation As Long
    Dim Humidity As Long
    Dim SimulatedValue As Long

    With Worksheets("DataLoggerValues")

        For i = 1 To 100

            Temperature = .Cells(i, 1).Value
            WindSpeed = .Cells(i, 2).Value
            SolarRadiation = .Cells(i, 3).Value
            Humidity = .Cells(i, 4).Value


            .Cells(i, 5).Value = (Temperature + SolarRadiation / WindSpeed) ^ 2 + Humidity / 37

        Next i

    End With

End Sub

你也可以使用这样的东西。只需将该函数用作普通的excel函数即可。然后,您可以使用自动填充来拖动它。您可以在将代码添加到模块后使用它。

Function Simulation(Temperature As Long, WindSpeed As Long, SolarRadiation As Long, Humidity As Long)

    Simulation = (Temperature + SolarRadiation / WindSpeed) ^ 2 + Humidity / 37

End Function

编辑:

对下面评论的回答。

Sub Simulation()

    Dim i As Long
    Dim Temperature As Long
    Dim WindSpeed As Long
    Dim SolarRadiation As Long
    Dim Humidity As Long
    Dim SimulatedValue As Double

    With Worksheets("DataLoggerValues")

        For i = 1 To 100

            Temperature = .Cells(i, 1).Value
            WindSpeed = .Cells(i, 2).Value
            SolarRadiation = .Cells(i, 3).Value
            Humidity = .Cells(i, 4).Value

            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

            SimulatedValue = (Temperature + SolarRadiation / WindSpeed) ^ 2 + Humidity / 37

            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''


            .Cells(i, 5).Value = SimulatedValue

        Next i

    End With

End Sub

我想你应该阅读一些关于什么是编程语言的对象。你可以从这个开始:

https://analysistabs.com/excel-vba/objects-properties-methods/

你的代码有什么问题:

Worksheets("DataLoggerValues") 是一个对象。它有一些特性。例如,它有一个名称:“DataLoggerValues”。

你可以检查一下

Sub Test()

    MsgBox Worksheets(1).Name

End Sub

如果它的索引是一。它可能会有所不同。您可以使用该对象的另一个属性来检查它。

Sub Test()

    MsgBox Worksheets("DataLoggerValues").Index

End Sub

现在我们要解决问题了。 Worksheets("DataLoggerValues").Cells(i, 5) 是另一个对象。它是一个子对象(子类对象)。

它不是一个单一的值!!!它是一个对象。它有不同的属性和方法。这就是为什么:.Cells(i,5) =... 没有意义。您是否将该值分配给 .Cells(i,5).Address.Cells(i,5).Value 或者可能是一些不同的属性?所有这些都“存储”值。您可以阅读或更改它们。

也许我应该弄清楚为什么你必须以不同的方式使用SimulatedValue。 好吧,使用前四个单元格很简单。您创建一个变量,例如Dim Temperature As Long。它可以将稍后分配的值存储在计算机内存中的某个位置!!!只需将一些单元格的值分配给它Temperature = .Cells(i, 1).Value

您对不同的变量执行相同的操作并执行一些计算。正如我在新代码中所做的那样,您可以将该数字(它必须是 Double,因为它必须“在逗号后存储一些数字”)存储在另一个变量中(如果您的温度、风速等不是整数,则更改 Long加倍)。

现在您可以将该值分配给单元格值.Cells(i, 5).Value = SimulatedValue。如果您要在计算之前的某处添加行 SimulatedValue = .Cells(i, 5).Value,您只需为变量 (SimulatedValue) 分配一个单元格的值(如果单元格为空或不存在,则为 0,我不是专家。如果您尝试打印该值,您什么也得不到,但是您可以将任何值乘以它的值,然后得到 0)。如果您随后编写 SimulatedValue = 5 之类的内容,则只需为变量分配新值。您不对那个单元格对象(单元格,单元格的值)做任何事情。

我希望它很清楚。我尽量简洁

我只是 vba 的初学者,我对编程了解不多,所以我可能用错了一些术语,请记住这一点。也许有人会纠正我。 :)


关于使用浮点变量(例如 Double)的重要内容。阅读:

Whats wrong with this simple 'double' calculation?

Compare double in VBA precision problem

我猜如果您将该值直接分配给某个单元格的值,问题仍然存在,尽管我还没有阅读或尝试过。

.Cells(i, 5).Value = (Temperature + SolarRadiation / WindSpeed) ^ 2 + Humidity / 37

如果您使用浮点数进行一些计算,将来可能会为您节省一些时间。

【讨论】:

  • 谢谢,这很有帮助,效果很好。我很好奇为什么 SimulatedValue 也不能设置为变量?我试过了,但它没有用。它不会产生任何实际距离,但会更干净一些。
  • 嗯,我一直在考虑它,我想到了一个简单的解决方案。我编辑了答案并解释了为什么你的代码是错误的,我希望我能清除一些东西。
【解决方案2】:

你实际上不需要循环这个,因为 Excel 足够聪明,可以增加它,然后你可以像这样复制和粘贴值:

Sub Simulation()
With Worksheets("DataLoggerValues").Range("E2:E184")
    .Formula = "=(A2+C2/B2)^2+D2/37" 'Excel will increment the row relative to the row the formula is in
    .Copy
    .PasteSpecial xlPasteValues
End With
End Sub

您应该将 Shelty 标记为正确,因为他的答案通过在循环内移动变量赋值来回答您的特定问题,我只是为您提供和替代想法,这将加快您的代码。

【讨论】:

    【解决方案3】:

    有 N 种方法可以标准化您的代码。为了简单起见,你可以这样做

         Sub Simulation()
    
        Dim i As Long
        Dim Temperature As Range
        Dim WindSpeed As Range
        Dim SolarRadiation As Range
        Dim Humidity As Range
        Dim SimulatedValue As Range
    
        With Worksheets("DataLoggerValues")
    
        'just initialize the header part
        Set Temperature = .Cells(1, 1)
        Set WindSpeed = .Cells(1, 2)
        Set SolarRadiation = .Cells(1, 3)
        Set Humidity = .Cells(1, 4)
        Set SimulatedValue = .Cells(1, 5)
    
    
        End With
        Dim i As Integer
    
        For i = 1 To 183
    
         SimulatedValue.Offset(i, 0) = (Temperature.Offset(i, 0) + SolarRadiation.Offset(i, 0) / WindSpeed.Offset(i, 0)) ^ 2 + Humidity.Offset(i, 0) / 37
    
         Next i
    
        ' and finally
          Set Temperature = Nothing
          Set WindSpeed = Nothing
          Set SolarRadiation = Nothing
          Set Humidity = Nothing
         Set SimulatedValue = Nothing
    
        End Sub
    

    一些提示:避免使用 With..End with,您可以使用命名范围或表或常量地址以获得更好的性能和可用性。

    【讨论】:

    • 似乎过度设计分配变量然后释放它们,我也不同意你的 cmets 关于不使用 With..End with,是什么让你认为与任何其他方法相比它会减慢代码速度?如果任何使用循环的东西都会减慢此代码的速度(请参阅我的答案以了解如何避免这种情况)。
    • 通常“With..End with”对小对象有利,但如果引用对象中包含更复杂的对象则有害..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    • 2021-07-27
    • 2019-04-30
    • 1970-01-01
    • 2014-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多