将不连续的单元格视为单个范围,用作UDF的参数

时间:2019-05-06 00:23:43

标签: excel vba range user-defined-functions contiguous

我正在尝试通过使用两个数据集进行插值来构建收益曲线:一系列到期日,以及另一个利率范围。

我在VBA上有一个UDF,可以对利率进行插值。它使用用户在excel工作表上选择的两个单元格区域作为参数。

我知道Excel要求这些范围必须由连续的单元格组成。 我想做的是在工作表中选择不连续的单元格,并将其值用作UDF参数的范围。

更具体地说,我有两列数据用作范围。但是有时候我需要在每列上跳过一个值,然后将剩余的值用作UDF的范围。

我尝试在UDF中再包含两个范围参数,并使用union方法将两个范围合并为一个,以便在代码中使用结果范围。没用。

****编辑

克里斯, 感谢您指出手表和即时Windows。经过多次尝试,该代码最终按我的预期工作,但是仅对DC_1和taxas_1范围使用单独的循环。 奇怪的是,如果我从循环内部删除“ If k> 1 Then”语句,它将无法正常工作。所以我需要保留它并使它什么也不做。

我注意到间接函数无法与(A1:A3,C2:C5)之类的参数一起使用,因此我不能将indirect((A1:A3,C2:C5))用作UDF的参数。但是,这是一个小问题。

如果有人遇到类似问题,这是我正在使用的代码。

Public Function Interplin_union(ByVal taxas_1 As Range, ByVal DC_1 As Range, ByVal dias As Integer) As Double
Dim tam1 As Long
Dim taxa1 As Double, taxa2 As Double, alfa As Double, d1 As Double, d2 As Double
Dim k As Long
Dim taxas As Variant
Dim DC As Variant

tam1 = taxas_1.Cells.Count
ReDim taxas(1 To tam1)
ReDim DC(1 To tam1)
Interplin_union = -1
Dim c As Range

    k = 1
For Each c In DC_1
    'taxas(k) = taxas_1(k)
    DC(k) = c
    If k > 1 Then
        'Debug.Print DC(k)
        If DC(k - 1) > DC(k) Then
            Interplin_union = CVErr(xlErrNA)
            Exit Function
        End If
    End If
    k = k + 1
Next

    k = 1
For Each c In taxas_1
    taxas(k) = c
        If k > 1 Then
          'Debug.Print DC(k), taxas(k)
        End If
    k = k + 1
Next


For k = 1 To (tam1 - 1)
    If ((DC(k) < dias) And (DC(k + 1) >= dias)) Then
        taxa1 = taxas(k)
        taxa2 = taxas(k + 1)
        alfa = (taxa2 - taxa1) / (DC(k + 1) - DC(k))
        Interplin_union = taxa1 + (alfa * (dias - DC(k)))
    End If
Next k

If (dias <= DC(1)) Then
    Interplin_union = taxas(1)
    ElseIf dias > DC(tam1) Then
    Interplin_union = taxas(tam1)
End If
End Function

1 个答案:

答案 0 :(得分:1)

可以实际上在不连续范围内的单元格上循环。

也就是说,许多Range属性在应用于不连续范围时,会返回第一个连续子范围的属性值。

演示:

left

那么,如何将其应用于您的情况?我建议两件事:

  1. 不要为UDF创建额外的参数,而要使用Excel的公式Union运算符的功能-将不连续的范围括在公式的方括号中。
  2. 如上所示环绕不连续范围,以将数据映射到变量数组。然后循环该数组以应用您的逻辑

1的演示

Dim cl as Range, SomeDiscontiguousRange as Range
Dim Rpt as String
Set SomeDiscontiguousRange = [A1:A3, C2:C5]
For each cl in SomeDiscontiguousRange
    'Do something with cl, eg
    Rpt = Rpt & "," & cl.Address
Next
Debug.Print Rpt 'returns the 7 cell addresses
Debug.Print SomeDiscontiguousRange.Rows.Count 'returns 3, the rows in the first sub-range

在这样的单元格中使用:Function Demo(r as range) as Variant Demo = r.Address End Function 请注意双括号,这告诉Excel将=Demo((A1:A3,C2:C5))视为单个参数。

您的代码经过重构以应用这些方法(以及其他一些优化方法)

(A1:A3,C2:C5)

旁注:

  • 我没有对您应用于数据的函数的逻辑发表评论,我没有对此进行分析
  • 要访问不连续范围的每个范围的属性,请先在Area上循环,然后在每个Area的单元格上循环。例如

    Public Function Interplin_union(ByVal taxas_1 As Range, ByVal DC_1 As Range, ByVal dias As Integer) As Double
        Dim tam1 As Long
        Dim taxa1 As Double, taxa2 As Double, alfa As Double, d1 As Double, d2 As Double
        Dim k As Long
        Dim taxas As Variant
        Dim DC As Variant
    
        tam1 = taxas_1.Cells.Count
        ReDim taxas(1 To tam1)
        ReDim DC(1 To tam1)
        Interplin_union = -1
        Dim c As Range
    
        k = 1
        For Each c In DC_1
            taxas(k) = taxas_1(k)
            DC(k) = c
            If k > 1 Then
                Debug.Print DC(k - 1), DC(k)
                If DC(k - 1) > DC(k) Then
                    Interplin_union = CVErr(xlErrNA)
                    Exit Function
                End If
            End If
            k = k + 1
        Next
    
        For k = 1 To (tam1 - 1)
            If ((DC(k) < dias) And (DC(k + 1) >= dias)) Then
                taxa1 = taxas(k)
                taxa2 = taxas(k + 1)
                alfa = (taxa2 - taxa1) / (DC(k + 1) - DC(k))
                Interplin_union = taxa1 + (alfa * (dias - DC(k)))
            End If
        Next k
    
        If (dias <= DC(1)) Then
            Interplin_union = taxas(1)
            ElseIf dias > DC(tam1) Then
            Interplin_union = taxas(tam1)
        End If
    End Function
    
  • Excels Formula Union运算符为Dim Arr as Range, Cl as Range For Each Arr in SomeDiscontiguousRange.Areas Debug.Print Arr.Rows.Count For Each Cl in Arr.Cells Debug.Print Cl.Address Next Next ,交集运算符为,(空格)。
    尝试来了解我的意思。 See this - "Under Reference operators" heading

  • 您将需要添加一些检查以验证范围形状,以防万一意外内容传递给UDF