将具有命名范围的Excel函数转换为VBA时键入不匹配错误

时间:2018-04-02 16:06:29

标签: excel vba excel-vba

我试图将一个简单的excel函数复制到VBA中,但是我遇到了Type mismatch错误。基本上,我有两个命名范围rDate和rYear以及以下Excel函数,它完美地提供以下输出:

= IF(YEAR(RDATE)= rYear,rYear,"&#34)

https://www.screencast.com/t/rPpsVjudqrI

但是,正如我所提到的,尝试将其转换为VBA时出现类型不匹配错误。这是我的代码:

Public ws As Worksheet
Sub Test()
Dim rDate, rYear, rResult, cell As Range

Set ws = Worksheets("Sheet1")
Set rDate = ws.Range("rDate")
Set rYear = ws.Range("rYear")
Set rResult = ws.Range("rResult")

For Each cell In rResult
    If Year(rDate) = rYear Then 'Problematic line
        cell = rYear
    Else
        cell = ""
    End If
Next
End Sub

请让我知道我做错了什么。谢谢

1 个答案:

答案 0 :(得分:1)

vba对范围的反应与工作表不同。在vba中,需要将一个单元的值与多个单元范围内的一个值进行比较,再到多单元范围。

而不是试图将整个范围等同于根据单元格的位置选择每个范围中的一个单元格。

要获得垂直范围的正确参考,我们要找到相对的行:

rDate.Cells(cell.Row - rResult.Row + 1, 1)

和相关栏目:

rYear.Cells(1, cell.Column - rResult.Column + 1)

然后:

  

Dim rDate, rYear, rResult, cell As Range

仅将cell声明为范围,其他声明为Variant

所以使用:

Dim rDate As Range, rYear As Range, rResult As Range, cell As Range

工作表函数根据公式的相对位置对行和列进行假设,而vba则没有。

Public ws As Worksheet
Sub Test()
Dim rDate As Range, rYear As Range, rResult As Range, cell As Range

Set ws = Worksheets("Sheet1")
Set rDate = ws.Range("rDate")
Set rYear = ws.Range("rYear")
Set rResult = ws.Range("rResult")

For Each cell In rResult
    If Year(rDate.Cells(cell.Row - rResult.Row + 1, 1)) = rYear.Cells(1, cell.Column - rResult.Column + 1) Then 'Problematic line
        cell = rYear.Cells(1, cell.Column - rResult.Column + 1)
    Else
        cell = ""
    End If
Next
End Sub

更快的方法是将数据加载到内存数组中并循环遍历这些数据。

Public ws As Worksheet
Sub Test()
Dim rDate, rYear, rResult
Dim i As Long, j As Long

Set ws = Worksheets("Sheet1")
rDate = ws.Range("rDate").Value
rYear = ws.Range("rYear").Value
ReDim rResult(1 To UBound(rDate, 1), 1 To UBound(rYear, 2))

For i = LBound(rDate, 1) To UBound(rDate, 1)
    For j = LBound(rYear, 2) To UBound(rYear, 2)
        If rYear(1, j) = Year(rDate(i, 1)) Then
            rResult(i, j) = rYear(1, j)
            Exit For
        End If
    Next j
Next i
ws.Range("rResult").Value = rResult

End Sub

每次从vba访问工作表时,都会降低代码的速度。使用此方法,我们只能访问工作表3次,无论范围有多大。