Обработка несмежных ячеек как единого диапазона, используемого в качестве аргумента UDF - PullRequest
0 голосов
/ 06 мая 2019

Я пытаюсь построить кривую доходности путем интерполяции, используя два набора данных: диапазон календарных дней до погашения и другой диапазон процентных ставок.

У меня есть UDF на VBA, который интерполирует процентные ставки. Он использует в качестве аргументов два диапазона ячеек, выбранных пользователем на листе Excel.

Мне известно, что Excel требует, чтобы эти диапазоны состояли из смежных ячеек. Я пытаюсь выбрать несмежные ячейки на листе и использовать их значения в качестве диапазонов для аргументов UDF.

В частности, у меня есть два столбца данных, которые я использую в качестве диапазонов. Но иногда мне нужно пропустить одно значение в каждом из этих столбцов и использовать оставшиеся значения в качестве диапазонов для моей пользовательской функции.

Я попытался включить еще два аргумента диапазона в свой UDF и использовать метод объединения, чтобы объединить два диапазона в один, чтобы использовать полученный диапазон в моем коде. Это не сработало.

**** редактировать

Крис, Спасибо за указание на часы и немедленную Windows. После многих попыток код наконец-то работает, как я и предполагал, но только с отдельными циклами для диапазонов DC_1 и taxas_1. Как ни странно, это не сработает, если я уберу инструкцию «If k> 1 Then» из цикла. Поэтому мне нужно было сохранить его и заставить ничего не делать.

Я заметил, что косвенная функция не будет работать с таким аргументом, как (A1: A3, C2: C5), поэтому я не могу использовать косвенный ((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 Ответ

1 голос
/ 06 мая 2019

Вы можете фактически зацикливать ячейки на непрерывном диапазоне.

При этом многие свойства Range, при применении к непрерывному диапазону, возвращают значение свойства первого смежного поддиапазона..

Демонстрация:

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

Итак, как применить это к вашей ситуации?Я бы предложил две вещи:

  1. Не создавайте дополнительных параметров для вашей пользовательской функции, вместо этого используйте силу оператора объединения формулы Excel - заключите в формулу отдельные диапазоны в скобках.
  2. Зациклить непрерывный диапазон, как показано выше, чтобы отобразить данные в массив Variant.Затем зациклите этот массив, чтобы применить вашу логику

Демонстрация 1

Function Demo(r as range) as Variant
    Demo = r.Address
End Function

Использовать в такой ячейке: =Demo((A1:A3,C2:C5)) Обратите внимание на двойные скобки, это говорит Excel об обработке (A1:A3,C2:C5) как один параметр.

Ваш код реорганизован для применения этих методов (и некоторых других оптимизаций)

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

Примечания:

  • Я не комментирую логику функции, которую вы применяете к данным, я не анализировал это
  • Чтобы получить доступ к свойствам каждого диапазона несмежного диапазона, сначала выполните цикл по областям, затем ячейкикаждой области.Например,

    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
    
  • Превышает оператор объединения формул , и оператор пересечения (Пробел).
    Попробуйте =demo((C4:D7 C2:C12)), чтобы понять, что я имею в виду. См. Это - заголовок «Под справочными операторами»

  • Вы захотите добавить несколько проверок для проверки форм диапазона, если в UDF
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...