【问题标题】:Using VBA to get a threshold value使用 VBA 获取阈值
【发布时间】:2015-06-18 18:07:30
【问题描述】:

我有一个 A 列和一个 B 列。在 A 列中,我的值(从 A2 开始)从 1 到 150(所以以 A151 结束)

在 B 列中,我有值。我想获得高于单元格 Z2 中的值的第一个值,并在单元格 B153 的 A 列中为 B 列写出相应的值。最后一部分很棘手。如果以下 4 个值也高于 Z2 中的值,我只想写这个值。这可能吗?

如果是这样,我在 C-Y 列中也有相同的内容

更好的解释:

我想遍历 B-Y 列 来自单元格 2-151 的内循环。

如果 B2>Z2 而且接下来的 4 个连续单元格 (B3-B6)>Z2,则将 A2 复制到 B153 并移动到下一列。 如果 B2 > Z2 但接下来的 4 不是全部 > Z2,则对 B3 重复该过程。 如果 B2

如果没有,则将 N/A 复制到 B153

这个可以吗?

我的第一次尝试:

=INDEX($A$2:$A$151,SUMPRODUCT(MATCH(1,--(B$2:B$151>$Z$2),0)),1)

这需要第一个值。我试图想出一个聪明的方法来取第一个值,只有当第二个值也符合标准时。从那里我确信我可以扩展到第 3、第 4、第 5 等。

【问题讨论】:

  • Have you tried anything? 请发布您尝试的解决方案
  • @Barranka 我发布了我尝试过的内容。工作表中另一个单元格中的简单代码
  • 用 VBA 考虑它的另一种方法是遍历每一列。从 B2 开始。如果 B2-B6 都大于 Z2,则返回 A2。如果没有,请转到 B3 并重复。找到值后,在 B153 中发布并移至下一列,在 Y 列停止。我能想到如何完成,只是努力写任何有效的东西。
  • @user1274820 好的,我发布了一个示例。突出显示的单元格用于视觉帮助。看看B列如何,有2个突出显示,但后面的没有突出显示?但是单元格的值 43 对应于 A 列中的第一个值,并且接下来的 4 个值也大于 Z2。这有意义吗?
  • 我添加了更好的解释。 @user1274820 有什么想法吗?

标签: vba excel


【解决方案1】:

有很多方法可以解决这个问题,但我认为您需要在用户定义的函数中使用嵌套循环。

我们可以...

function get_Energy_Row(cellSearch as Range, staticValue as Single)

  Dim cell1 as Single

  get_Energy_Row = "N/A"

  j = 1 
  col = cellSearch.Columns.Count

  Do
      cell1 = cellSearch(j, col) 

      If cell1 <= staticValue Then
          'do nothing, function already set to "N/A"
      Else

          For i = 1 to 4
              If cellSearch(i + j, col) > staticValue Then
                  get_Energy_Row = cellSearch(j,1)
              Else
                  'do nothing, function already set to "N/A"
              End If
          Next i
      End If

      j = j + 1

  Loop Until j >= cellSearch.Rows.Count - 3 Or get_Energy_Row <> "N/A"

End Function

然后像这样在单元格C153 中调用您的 UDF:

=get_Energy_Row($A2:B151,$Z$2),其中包含第一列。

注意美元符号,这将确保您的静态支票始终为 Z2

逻辑是我默认单元格为“N/A”,直到它找到覆盖“N/A”的条件,在这种情况下循环被打破。

【讨论】:

  • 是的,我刚刚运行它 - 我认为至少有一个错误。
  • 修好了,物有所值。
【解决方案2】:

您当前的公式可能适用于单值情况,但我认为尝试扩大规模会有点笨拙。通过公式实现此目的的几种快速方法是:

=MIN(IF(COUNTIF(INDIRECT("B"&ROW(2:147)&":B"&ROW(6:151)),">"&Z2)=5,$A2:$A147,1E9))

还有:

=MIN(IF((B2:B147>Z2)*(B3:B148>Z2)*(B4:B149>Z2)*(B5:B150>Z2)*(B6:B151>Z2),$A2:$A147,1E9))

我个人认为后者更容易阅读和拖动电子表格(尽管前者可以修改为同样容易拖动)。后者还避免了 volatile INDIRECT 函数。第一个函数一次获取 5 个单元格区域,并计算符合条件的单元格数量。如果我们的计数是 5,我们有一个匹配。如果您正在寻找更大的匹配集,则首选此方法。第二个公式只是逐步检查范围,基本上是 r 到 r+4,其中 r 是当前行。两者都是数组公式,应使用 CTRL + SHIFT + ENTER 输入,而不仅仅是 ENTER。

【讨论】:

    【解决方案3】:

    类似这样的:

    Sub OutputEnergy()    
    'y = Columns to check: 2-25
    'x = Rows to check: 2-152
    'z = check the next 4 cells
    Dim x, y, z, check
    'Clear the range where we store the #N/A or Energy Outputs
    Range("B153:Y153") = vbNullString
    For y = 2 To 25
        For x = 2 To 152
            If Cells(x, y) > Range("Z2") Then  'If value is greater than Z2
                check = True                   'Let's check the next 4
                For z = 1 To 4                 'If any of them fail
                    If Cells(x + z, y) < Range("Z2") Then
                        check = False          'The check fails
                        Exit For
                    End If
                Next z
                If check = True Then            'If the check doesn't fail
                    Cells(153, y) = Cells(x, 1) 'Set cell 153 to the energy level
                    Exit For
                End If
            End If
        Next x                                   'If no energy level was set - #N/A
        If Cells(153, y) = vbNullString Then Cells(153, y) = "#N/A"
    Next y
    End Sub
    

    编辑:作为函数:

    函数用法:

    =OutputEnergy(Range, Threshold, [Number of cells to check], [Using Headers?])

    基本上,给它检查的范围,给它一个阈值。

    之后要检查的单元格数默认为 4 个。

    要获得“能量”,它会获得行号(如果使用标题,则减去 1)

    Function OutputEnergy(TheRange As Range, Threshold As Variant, Optional NextCells As Integer = 4, Optional OffsetForHeader As Boolean = True) As Variant    
    Dim c, x, check
    For Each c In TheRange
        If c.Value > Threshold Then
            check = True
            For x = 1 To NextCells
                If c.Offset(x, 0) < Threshold Then
                    check = False
                    Exit For
                End If
            Next x
            If check = True Then
                OutputEnergy = IIf(OffsetForHeader, c.Row - 1, c.Row)
                Exit Function
            End If
        End If
    Next c
    OutputEnergy = CVErr(xlErrNA)
    End Function
    

    再次编辑 - 输出到所有工作表:

    OutputEnergyToSheet 接受工作表作为参数:

    Sub OutputEnergyToSheet(TheSheet As String)
    'y = Columns to check: 2-25
    'x = Rows to check: 2-152
    'z = check the next 4 cells
    Dim x, y, z, check
    'Clear the range where we store the #N/A or Energy Outputs
    With Sheets(TheSheet)
        .Range("B153:Y153") = vbNullString
        For y = 2 To 25
            For x = 2 To 152
                If .Cells(x, y) > .Range("Z2") Then  'If value is greater than Z2
                    check = True                   'Let's check the next 4
                    For z = 1 To 5                 'If any of them fail
                        If .Cells(x + z, y) < .Range("Z2") Then
                            check = False          'The check fails
                            Exit For
                        End If
                    Next z
                    If check = True Then                    'If the check doesn't fail
                        .Cells(153, y) = Int(.Cells(x, 1))  'Set cell 153 to the energy level
                        Exit For
                    End If
                End If
            Next x                                   'If no energy level was set - #N/A
            If .Cells(153, y) = vbNullString Then .Cells(153, y) = "#N/A"
        Next y
    End With
    End Sub
    

    OutputEnergyToAllSheets 循环遍历每个工作表并调用新的 sub:

    Sub OutputEnergyToAllSheets()
    Dim w
    For Each w In ThisWorkbook.Worksheets
        If Not InStr(w.Name, "Total") > 0 And Not InStr(w.Name, "eV") > 0 Then
            OutputEnergyToSheet w.Name
        End If
    Next w
    End Sub
    

    【讨论】:

    • 它应该通过更改该值来工作。该循环的唯一问题是当您到达底部并开始运行到空白单元格时。我不确定你想如何处理这些情况。我的猜测是它应该会失败,我相信它会失败。
    • 除了名称中带有“Total”或“eV”的工作表之外,有没有办法循环遍历所有工作表?
    • 我从未指定工作表,因此您应该能够选择每个工作表并再次运行宏 - 但是,如果需要修改范围,那就有点棘手了。可以重写它以使用最后一行和各种范围。如果布局相同,可以使用For Each w in ThisWorkbook.Worksheets If Not InStr(w.Name,"Total") &gt; 0 and Not InStr(w.Name, "eV") &gt; 0 Then n.Select Call OutputEnergy Next w
    • 我尝试复制但我认为格式可能混乱?
    • 原来他说需要对所有列返回值,所以我没有把它写成函数。是的,它可以写成一个函数来返回一个值,然后可以拖到他的数据底部。
    猜你喜欢
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 2013-04-27
    • 1970-01-01
    • 2017-08-14
    • 2014-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多