使用VBA在Range中搜索Value,并让它将值的列作为Variable返回

时间:2017-03-13 20:21:46

标签: excel vba excel-vba

我是VBA的新手,我开始做一些基本的编码。

我目前的最终目标是根据两个经过数据验证的单元格的输入,将表格中的单元格清零。

我目前有一张表,我已成功实现了我想要做的事情,但代码很长,我相信它可以通过使用Find函数来简化。在实施此变通方法之前,我尝试实施Find几个小时。

用户通过单元格B4中的验证列表选择当前的预测月份。然后,他们可以通过在单元格B5中选择是/否来选择将所需单元“清零”。几个月从B7:M7开始。我最初的目标是让VBA从B4中选择一个月,在B7中找到那个月:M7,返回该列,然后使用列数据转到第15行并将该单元归零。但是,我找不到合适的方法将其编码到find函数中而不会导致编译错误。

以下是我认为可以简化的当前代码:

Private Sub Worksheet_Change_B(ByVal Target As Range)
If Target.Address(False, False) = "B5" Then
    If Range("B5").Value = "Yes" Then
        If Range("B4").Value = "Oct" Then
            Range("B15").Value = "0"
        ElseIf Range("B4").Value = "Nov" Then
            Range("C15").Value = "0"
        ElseIf Range("B4").Value = "Dec" Then
            Range("D15").Value = "0"
        ElseIf Range("B4").Value = "Jan" Then
            Range("E15").Value = "0"
        ElseIf Range("B4").Value = "Feb" Then
            Range("F15").Value = "0"
        ElseIf Range("B4").Value = "Mar" Then
            Range("G15").Value = "0"
        ElseIf Range("B4").Value = "Apr" Then
            Range("H15").Value = "0"
        ElseIf Range("B4").Value = "May" Then
            Range("I15").Value = "0"
        ElseIf Range("B4").Value = "Jun" Then
            Range("J15").Value = "0"
        ElseIf Range("B4").Value = "Jul" Then
            Range("K15").Value = "0"
        ElseIf Range("B4").Value = "Aug" Then
            Range("L15").Value = "0"
        ElseIf Range("B4").Value = "Sep" Then
            Range("M15").Value = "0"
        End If
    ElseIf Range("B5").Value = "No" Then
        If Range("B4").Value = "Oct" Then
            Range("B15").Value = Range("B35").Value
        ElseIf Range("B4").Value = "Nov" Then
            Range("C15").Value = Range("C35").Value
        ElseIf Range("B4").Value = "Dec" Then
            Range("D15").Value = Range("D35").Value
        ElseIf Range("B4").Value = "Jan" Then
            Range("E15").Value = Range("E35").Value
        ElseIf Range("B4").Value = "Feb" Then
            Range("F15").Value = Range("F35").Value
        ElseIf Range("B4").Value = "Mar" Then
            Range("G15").Value = Range("G35").Value
        ElseIf Range("B4").Value = "Apr" Then
            Range("H15").Value = Range("H35").Value
        ElseIf Range("B4").Value = "May" Then
            Range("I15").Value = Range("I35").Value
        ElseIf Range("B4").Value = "Jun" Then
            Range("J15").Value = Range("J35").Value
        ElseIf Range("B4").Value = "Jul" Then
            Range("K15").Value = Range("K35").Value
        ElseIf Range("B4").Value = "Aug" Then
            Range("L15").Value = Range("L35").Value
        ElseIf Range("B4").Value = "Sep" Then
            Range("M15").Value = Range("M35").Value
        End If
    End If
End If

End Sub

我最初用Find函数思考的是这样的,但我无法正确编译。

Sub Test()

Dim rFind As Range

If Target.Address(False, False) = "B5" Then
    If Range("B5").Value = "Yes" Then 'If the user wants to zero out the cell on row 15
        With Range("B7:M7") 'Range of Months
            Set rFind = .Find(What:=("B4"), LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
                Range("rFind.Column,15").Value = "0" 'Set Value of cell in row 15 of referenced column to zero
        End With
    If Range("B5").Value = "No" Then 'If the user doesn't want to zero out cell on row 15
        With Range("B7:M7") 'Range of Months
            Set rFind = .Find(What:=("B4"), LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
                Range("rFind.Column,15").Value = Range("rFind.Column,35").Value 'Pulls in Previous Value
        End With
    End If
End Sub

我正在走上正轨吗?如何在我想要更改的单元格地址中引用月份列?

3 个答案:

答案 0 :(得分:3)

这些语句中的语法错误:

  

Range("rFind.Column,15").Value = 0

     

Range("rFind.Column,15").Value = Range("rFind.Column,35").Value

应该是:

Cells(15, rFind.Column).Value = 0

Cells(15, rFind.Column).Value = Cells(35, rFind.Column).Value

此处出现另一种语法错误:

  

What:=("B4"), ...

应该是

What:=Range("B4").Value, ...

为了完整起见,您可以通过以下方式简化第一个版本:

Private Sub Worksheet_Change_B(ByVal Target As Range)

    ' we're only interested when cell B5 changes
    If Target.address <> "$B$5" Then Exit Sub

    ' First we will get the month's number from its name. We use the Month
    ' method of VBA but it needs a date. so we append a 1 to the month (i.e. Sep 1)
    Dim col As Long
    col = Month(Range("B4").value & " 1")

    ' Getting the column. Since First cell is in column 2 (B) we start at column 2
    ' Month 10 (Oct) comes first so we count from that using modulo 
    col = 2 + ((col + 2) Mod 12) ' since you start with Oct. at column B

    ' Finally we set the value at row 15 according to cell B5 (Target)
    ' We can shorten the If statement using IIF(condition, trueValue, falseValue)
    Cells(15, col).value = IIf(Target.value = "Yes", 0, Cells(35, col).value)

End Sub

答案 1 :(得分:2)

一些Select Case语句和一些基本数学可以快速完成所有条件。找到模式后,某些日期函数会达到顺序月份,并根据您的偏移量进行调整。

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)

    If Target.Address(False, False) = "B5" Then
        On Error GoTo Safe_exit
        Application.EnableEvents = False
        If LCase(Range("B5").Value2) = "yes" Then
            Select Case LCase(Range("B4").Value2)
                Case "jan", "feb", "mar", "apr", "jun ", "jul", "aug", "sep", "oct", "nov", "dec"
                    Cells(15, Month(DateSerial(2017, Month(DateValue("1-" & Range("B4").Value2)) + 3, 1)) + 1) = 0
                Case Else
                    'do nothing
            End Select
        ElseIf LCase(Range("B5").Value2) = "no" Then
            Select Case LCase(Range("B4").Value2)
                Case "jan", "feb", "mar", "apr", "jun ", "jul", "aug", "sep", "oct", "nov", "dec"
                    Cells(15, Month(DateSerial(2017, Month(DateValue("1-" & Range("B4").Value2)) + 3, 1)) + 1) = _
                      Cells(35, Month(DateSerial(2017, Month(DateValue("1-" & Range("B4").Value2)) + 3, 1)) + 1).Value
                Case Else
                    'do nothing
            End Select
        End If
    End If
Safe_exit:
    Application.EnableEvents = True
End Sub

不要担心限定父工作表。您位于工作表代码表的私有子目录中。假定任何不合格的范围或单元格引用属于代码表的工作表(有关详细信息,请参阅Is the . in .Range necessary when defined by .Cells?)。

答案 2 :(得分:0)

我对你的月份序列不太确定。 你可以尝试:

Private Sub Worksheet_Change_B(ByVal Target As Range)
    If Target.address <> "$B$5" Then Exit Sub
    With Range("B7:M7").Find(What:=Range("B4").Value, lookin:=xlValues, lookAt:=xlWhole)
        Cells(15, .Column).value = IIf(Target.value = "Yes", 0, Cells(35, .Column).value)
    End With
End Sub