【问题标题】:VBA: If - ElseIf with multiple Or conditionsVBA:如果 - 具有多个或条件的 ElseIf
【发布时间】:2018-10-01 20:15:25
【问题描述】:

我在工作表摘要报告中的第 2 列循环,寻找一个值 0。

我正在使用嵌套的If 语句来确定第 1 列中的工具是债券还是商品或股票或外汇。 如果第 1 列中第 2 列中值 0 的符号对应于其中一个资产类别,并且该资产类别没有工作表,那么它应该为该资产类别创建一个新工作表。

On Error Resume Next

For i = 3 To SR.Cells(SR.Rows.Count, 2).End(xlUp).Row

If (SR.Cells(i, 2).Value <> 0) And _
        ((SR.Cells(i, 1).Value Like "*GER10YBond*") Or _
        (SR.Cells(i, 1).Value Like "*Gilt10Y*") Or _
        (SR.Cells(i, 1).Value Like "*JPN10yBond*") Or _
        (SR.Cells(i, 1).Value Like "*US30YBond*")) Then

        'Create new Worksheet named "Bonds"


ElseIf (SR.Cells(i, 2).Value <> 0) And ((SR.Cells(i, 2).Value Like "*#Corn*") Or _
        (SR.Cells(i, 2).Value Like "*#NaturalGas*") Or _
        (SR.Cells(i, 2).Value Like "*#Oil*") Or (SR.Cells(i, 2).Value Like "*#Wheat*") Or _
        (SR.Cells(i, 2).Value Like "*#XAGUSD*") Or (SR.Cells(i, 2).Value Like "*#XAUUSD*") Or _
        (SR.Cells(i, 2).Value Like "*Aluminium*") Or (SR.Cells(i, 2).Value Like "*BrentOil*") Or _
        (SR.Cells(i, 2).Value Like "*Cocoa*") Or (SR.Cells(i, 2).Value Like "*Cocoa!*") Or _
        (SR.Cells(i, 2).Value Like "*Cocoa!*") Or (SR.Cells(i, 2).Value Like "*Coffee*") Or _
        (SR.Cells(i, 2).Value Like "*Coffee!*") Or (SR.Cells(i, 2).Value Like "*Coffee!*") Or _
        (SR.Cells(i, 2).Value Like "*Copper*") Or (SR.Cells(i, 2).Value Like "*Corn*") Or _
        (SR.Cells(i, 2).Value Like "*Corn!*") Or (SR.Cells(i, 2).Value Like "*Corn!*") Or _
        (SR.Cells(i, 2).Value Like "*Cotton*") Or (SR.Cells(i, 2).Value Like "*Cotton!*") Or _
        (SR.Cells(i, 2).Value Like "*NaturalGas*") Or (SR.Cells(i, 2).Value Like "*Oil*") Or _
        (SR.Cells(i, 2).Value Like "*Palladium*") Or (SR.Cells(i, 2).Value Like "*Platinum*") Or _
        (SR.Cells(i, 2).Value Like "*Rice*") Or (SR.Cells(i, 2).Value Like "*soybeans*") Or _
        (SR.Cells(i, 2).Value Like "*Soybeans!*") Or (SR.Cells(i, 2).Value Like "*Soybeans!*") Or _
        (SR.Cells(i, 2).Value Like "*Soybeans!*") Or (SR.Cells(i, 2).Value Like "*Wheat*") Or _
        (SR.Cells(i, 2).Value Like "*Wheat!*") Or (SR.Cells(i, 2).Value Like "*Wheat!*") Or _
        (SR.Cells(i, 2).Value Like "*XAGUSD*") Or (SR.Cells(i, 2).Value Like "*XAGUSD.*") Or _
        (SR.Cells(i, 2).Value Like "*XAUUSD*") Or (SR.Cells(i, 2).Value Like "*XAUUSD.*")) Then

       ' Create new Worksheet named "Commodities"

End If

Next i

当循环从ElseIf 语句中找到一个资产,在第 2 列 0 中有一个值,它只是跳到 End If 并转到 Next Iteration

为什么?

【问题讨论】:

  • 你必须在某个地方有On Error Resume Next,因为VBA中的条件表达式永远不会短路,所以整个表达式需要每次进行评估。考虑编写和使用short-circuiting function,一旦一个表达式为真,它就会退出。这些单元格是否包含错误值(例如#DIV/0!#N/A#VALUE! 等)?
  • "#" 用于与 Like 运算符进行模式匹配。您需要将其括在括号内。
  • 您确实需要为SR.Cells(i, 2).Value 提取一个局部变量,然后比较该变量,而不是点击工作表并每次迭代重新读取同一个单元格 40 次..
  • 像这样嵌入在代码中的大检查列表很难维护 - 如果您将单词列表放入工作表中,您可以在单个操作中直接检查列表。
  • Dim foo As Variant; foo = SR.Cells(i, 2).Value ??? ...你还在尝试吗?

标签: vba excel for-loop if-statement


【解决方案1】:

我建议你使用 Collection/Dictionary 对象来保存列表。此示例使用字典(=hashmap,关联数组)作为示例。使用 VBA 编辑器中的Tools/Referennces 菜单启用脚本运行时。这是大多数体面大小的 VBA 应用程序需要的东西。

您可以在参数表中维护列表并在 VBA 函数中填充字典。我试图以合理的格式构建循环,以便更容易理解正在发生的事情。

大多数编程指南也有充分的理由避免使用 GOTO 命令。但是,VBA 缺少 continue 语句,如果您问我,这是 goto 语句的罕见用途。

Option Explicit
' Tools/References: [x]Microsoft Scripting Runtime

Public Sub doIt()
    Dim ws As Worksheet
    Dim iRow As Long
    Dim idx As Long
    Dim val As String
    Dim key As String
    Dim bonds As New Scripting.Dictionary
    Dim commodities As New Scripting.Dictionary

    Call bonds.Add("*GER10YBond*", "")
    Call bonds.Add("*Gilt10Y*", "")
    Call bonds.Add("*JPN10yBond*", "")
    Call bonds.Add("*US30YBond*", "")

    Call commodities.Add("*[#]Corn*", "")
    Call commodities.Add("*[#]NaturalGas*", "")
    Call commodities.Add("*[#]Oil*", "")
    Call commodities.Add("*[#]Wheat*", "")

    Set ws = Application.Sheets("Sheet1")
    For iRow = 3 To ws.UsedRange.Rows.Count
        val = ws.Cells(iRow, 2).Value
        If val = "0" Or val = "" Then GoTo ContinueLoop
        val = LCase(ws.Cells(iRow, 1).Value)

        For idx = 0 To bonds.Count - 1
            key = bonds.Keys(idx)
            If val Like LCase(key) Then
                ws.Cells(iRow, 3) = "bonds " & key
                GoTo ContinueLoop
            End If
        Next

        For idx = 0 To commodities.Count - 1
            key = commodities.Keys(idx)
            If val Like LCase(key) Then
                ws.Cells(iRow, 3) = "commodities " & key
                GoTo ContinueLoop
            End If
        Next

        ws.Cells(iRow, 3) = "Unknown"

ContinueLoop:
        ' next step
    Next iRow
End Sub

【讨论】:

  • 非常感谢您的努力。让我明天看看。现在我需要承担起首先提出这个问题的耻辱。
  • 抱歉回复晚了。我测试了上面的代码,它工作正常。但是,我正在尝试在我的代码中实现它,但我遇到了一些麻烦。见[(stackoverflow.com/questions/52707448/…
  • 另外,避免使用Continue 的方法是:For iRow = 3 To ws.UsedRange.Rows.Count: Do ` '\\something, something...` If val = "0" Or val = "" Then Exit Do ` '\\ more something, something`Loop While False: Next iRow
【解决方案2】:

您正在检查同一单元格中的 0 和文本。您需要检查第一列的文本

SR.Cells(i, 2).Value <> 0) And ((SR.Cells(i, 1).Value Like "*#Corn*")  –

【讨论】:

    【解决方案3】:

    @谁家,

    根据您的建议,我设法将这个循环放在一起。

    Option Explicit
    Public Sub PopulateHistoricalData(ByVal BondsDict As Dictionary, ByVal CryptoDict As Dictionary, ByVal CommoditiesDict As Dictionary, ByVal IndexesDict As Dictionary, ByVal FXDict As Dictionary, ByVal StocksDict As Dictionary)
    
              Dim CTF As Workbook
              Dim SR As Worksheet
    
              Dim SRRow As Long
              Dim ItemIndex As Long
    
              Dim Deal As String
              Dim SheetName As String
              Dim DealVal As String
              Dim Key1 As String
              Dim Key2 As String
              Dim Key3 As String
              Dim Key4 As String
              Dim Key5 As String
              Dim Key6 As String
    
              Dim FSO As Object
              Dim Folder As Object
    
    1         Set CTF = Workbooks("CodeTestFile_V2")
    2         Set SR = Worksheets("Summary Report")
    
    3         Set FSO = CreateObject("Scripting.FileSystemObject")
    4         Set Folder = FSO.GetFolder("C:\Users\Betty\AppData\Roaming\MetaQuotes\Terminal\B4D9BCD10BE9B5248AFCB2BE2411BA10\MQL4\Files")
    
    5         On Error Resume Next
    
    6         For SRRow = 3 To SR.Cells(SR.Rows.Count, 2).End(xlUp).Row: Do
    
    7             Deal = SR.Cells(SRRow, 2)
    
    8             If Deal = 0 Or Deal = "" Then Exit Do
    
    9             DealVal = SR.Cells(SRRow, 2).Offset(, -1).Value
    
    10            For ItemIndex = 0 To BondsDict.Count - 1
    
    11                Key1 = BondsDict.Keys(ItemIndex)
    
    12                If DealVal = Key1 Then
    
    13                    SheetName = "Bonds"
    
    14                        If FilepathExists(ByVal DealVal, ByVal SheetName, ByVal Folder) Then
    
    15                            If SheetExists(ByVal SheetName, ByVal DealVal, ByVal Folder, ByVal Key1, ByVal Key2, ByVal Key3, ByVal Key4, ByVal Key5, ByVal Key6) Then
    
    16                                With Worksheets(SheetName)
    17                                    Call PopulateHeadersAndClosePrices(ByVal DealVal, ByVal SheetName, ByVal Folder)
    18                                End With
    
    19                            End If
    
    20                        End If
    
    21                        Exit Do
    
    22                End If
    
    23            Next ItemIndex
    
    24            For ItemIndex = 0 To CryptoDict.Count - 1
    
    25                Key2 = CryptoDict.Keys(ItemIndex)
    
    26                If DealVal = Key2 Then
    
    27                    SheetName = "Crypto"
    
    28                    If FilepathExists(ByVal DealVal, ByVal SheetName, ByVal Folder) Then
    
    29                        If SheetExists(ByVal SheetName, ByVal DealVal, ByVal Folder, ByVal Key1, ByVal Key2, ByVal Key3, ByVal Key4, ByVal Key5, ByVal Key6) Then
    
    30                            With Worksheets(SheetName)
    31                                Call PopulateHeadersAndClosePrices(ByVal DealVal, ByVal SheetName, ByVal Folder)
    32                            End With
    
    33                        End If
    
    34                    End If
    
    35                    Exit Do
    
    36                End If
    
    37            Next ItemIndex
    
    38            For ItemIndex = 0 To CommoditiesDict.Count - 1
    
    39                Key3 = CommoditiesDict.Keys(ItemIndex)
    
    40                If DealVal = Key3 Then
    
    41                    SheetName = "Commodities"
    
    42                    If FilepathExists(ByVal DealVal, ByVal SheetName, ByVal Folder) Then
    
    43                        If SheetExists(ByVal SheetName, ByVal DealVal, ByVal Folder, ByVal Key1, ByVal Key2, ByVal Key3, ByVal Key4, ByVal Key5, ByVal Key6) Then
    
    44                            With Worksheets(SheetName)
    45                                Call PopulateHeadersAndClosePrices(ByVal DealVal, ByVal SheetName, ByVal Folder)
    46                            End With
    
    47                        End If
    
    48                    End If
    
    49                    Exit Do
    
    50                End If
    
    51            Next ItemIndex
    
    52            For ItemIndex = 0 To IndexesDict.Count - 1
    
    53                Key4 = IndexesDict.Keys(ItemIndex)
    
    54                If DealVal = Key4 Then
    
    55                    SheetName = "Indexes"
    
    56                    If FilepathExists(ByVal DealVal, ByVal SheetName, ByVal Folder) Then
    
    57                        If SheetExists(ByVal SheetName, ByVal DealVal, ByVal Folder, ByVal Key1, ByVal Key2, ByVal Key3, ByVal Key4, ByVal Key5, ByVal Key6) Then
    
    58                            With Worksheets(SheetName)
    59                                Call PopulateHeadersAndClosePrices(ByVal DealVal, ByVal SheetName, ByVal Folder)
    60                            End With
    
    61                        End If
    
    62                    End If
    
    63                    Exit Do
    
    64                End If
    
    65            Next ItemIndex
    
    66            For ItemIndex = 0 To FXDict.Count - 1
    
    67                Key5 = FXDict.Keys(ItemIndex)
    
    68                If DealVal = Key5 Then
    
    69                    SheetName = "FX"
    
    70                    If FilepathExists(ByVal DealVal, ByVal SheetName, ByVal Folder) Then
    
    71                        If SheetExists(ByVal SheetName, ByVal DealVal, ByVal Folder, ByVal Key1, ByVal Key2, ByVal Key3, ByVal Key4, ByVal Key5, ByVal Key6) Then
    
    72                            With Worksheets(SheetName)
    73                                Call PopulateHeadersAndClosePrices(ByVal DealVal, ByVal SheetName, ByVal Folder)
    74                            End With
    
    75                        End If
    
    76                    End If
    
    77                    Exit Do
    
    78                End If
    
    79            Next ItemIndex
    
    80            SheetName = vbNullString
    
    81            For ItemIndex = 0 To StocksDict.Count - 1
    
    82                Key6 = StocksDict.Keys(ItemIndex)
    
    83                If DealVal = Key6 Then
    
    84                    SheetName = "Stocks"
    
    85                    If FilepathExists(ByVal DealVal, ByVal SheetName, ByVal Folder) Then
    
    86                        If SheetExists(ByVal SheetName, ByVal DealVal, ByVal Folder, ByVal Key1, ByVal Key2, ByVal Key3, ByVal Key4, ByVal Key5, ByVal Key6) Then
    
    87                            With Worksheets(SheetName)
    88                                Call PopulateHeadersAndClosePrices(ByVal DealVal, ByVal SheetName, ByVal Folder)
    89                            End With
    
    90                        End If
    
    91                    End If
    
    92                    Exit Do
    
    93                End If
    
    94            Next ItemIndex
    
    95        Loop While False: Next SRRow
    
    End Sub
    

    请注意我用来避免使用Continue 命令的方法。

    【讨论】:

      猜你喜欢
      • 2017-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2015-12-23
      • 1970-01-01
      相关资源
      最近更新 更多