WorksheetFunction.Match为具有可变范围的数组

时间:2018-11-23 16:38:01

标签: excel vba excel-vba worksheet-function

我正在尝试将.Match函数实现为VBA中具有可变范围的数组,以查找特定范围内的第一个非零单元格。

但是,当前我仅收到运行时错误1004。

非常感谢您的帮助!谢谢

Set myRange = Worksheets("Portf_Mod").Range("AB368:CY368") 
With Application.WorksheetFunction
    Date_col = .Match(True, [myRange <> 0], 0)
End With

4 个答案:

答案 0 :(得分:2)

在使用 VBA 时,您可以使用API​​编写更明确和可维护的代码,而不用使用Match

Function FirstNonZeroCell(rng As Range) As Range
    Dim cell As Range
    For Each cell In rng.Cells
        If cell.Value <> 0 Then
            Set FirstNonZeroCell = cell
            Exit Function
        End If
    Next
End Function

或者如果您想要更紧凑的版本(但我认为可读性较差):

Function FirstNonZeroCell(rng As Range) As Range
    For Each FirstNonZeroCell In rng.Cells
        If FirstNonZeroCell.Value <> 0 Then Exit Function
    Next
    Set FirstNonZeroCell = Nothing
End Function

以下是使用示例:

Sub test()
    Dim res As Range
    Set res = FirstNonZeroCell(Range("A1:Z100"))
    If Not res Is Nothing Then
        MsgBox "Found value " & res.Value & " in cell " & res.Address & "."
    Else
        MsgBox "No match has been found!"
    End If
End Sub

答案 1 :(得分:1)

认为数组元素会淘汰您的方法,因此这里是另一种选择。

尚不清楚您是否想要第一个非零值或其位置,因此可以同时覆盖这两个值。

Date_col = Evaluate("MATCH(TRUE," & myRange.Address & "<>0,0)") 'returns position
Date_col = Evaluate("INDEX(" & myRange.Address & ",MATCH(TRUE," & myRange.Address & "<>0,0))") 'returns value

答案 2 :(得分:0)

我不会为此使用Match函数...

Set myRange = Worksheets("Portf_Mod").Range("AB368:CY368") 
On Error Resume Next
Date_col = myRange.Find("*", LookIn:=xlValues, SearchOrder:=xlByColumns).Column
On Error GoTo 0

答案 3 :(得分:0)

这是我第一次在VBA中遇到“数组公式”。这没错,但是了解/排除故障不是很明显。在我的机器上[该区域的所有单元格都为空,它给出了错误[myRange <> 0] = Error 2092,然后在Match函数中给出了另一个错误...

仅在公式工作表中,数组公式才有用,但是我认为您应该在VBA中避免使用它们。您可以在VBA中使用循环,因此,请不要犹豫使用它们!编写软件时,关键是要尽可能地使内容透彻,这是很关键的(因此您以后会理解!)。

我的建议是:

Option Explicit

Function FindDateColumnInRange(ByVal RangeToLookIn As Range) As Long

If RangeToLookIn.Rows.Count <> 1 Then
    'The range you're looking in has more than one row
    'what should you do in this case? Look only in the first row?

Else

    Dim i As Long
    'The range has only one row
    For i = 0 To RangeToLookIn.Columns.Count - 1
        If RangeToLookIn.Item(1, i).Value <> 0 Then
            'should you verifiy that the value is a date value?
            FindDateColumnInRange = RangeToLookIn.Item(1, i).Column
            Exit Function
        End If
    Next
End If

'the range didn't have a value different from 0
FindDateColumnInRange = 0

End Function

实际上,您会得到:

Sub Test()

Dim MyRange As Range
Set MyRange = Worksheets("Portf_Mod").Range("AB368:CY368")
Dim date_col As Integer

date_col = FindDateColumnInRange(MyRange)

If date_col = 0 Then
    'There was no date in your range
End If

End Sub

是的,它比SJR建议要长得多,但是,它涵盖了所有异常,并且您可以控制如何传递多维数组(首先遍历行,然后遍历列,或者反过来遍历)。