Правильный способ вернуть массив из функции VBA - PullRequest
2 голосов
/ 03 марта 2020

В моей школе используется Excel 2016 (до - {= массив} эра), поэтому я использую VBA, чтобы определить некоторые недостающие функции, которые мне нужны. Одна функция, которую я пытался реализовать в VBA, - это SEQUENCE -замена, например,

Function MYSEQ(n As Integer, m As Integer) As Variant
    ReDim seq(m - n) As Variant

    For i = LBound(seq) To UBound(seq)
        seq(i) = i + n
    Next i

    MYSEQ = seq
End Function

. Это хорошо работает, в том случае, если я делаю в ячейке =SUM(MYSEQ(1,3)), я правильно получаю 6. Однако, как ни странно возвращаемое значение не очень хорошо работает с другими операторами Excel. Например, если я сделаю =SUM(MYSEQ(1,3)+1), я получу 2 вместо ожидаемых 9. Обратите внимание, что константные массивы прекрасно работают с другими операторами, т. Е. =SUM({1;2;3}+1) выводит 9 правильно.

Есть ли способ исправить это так, чтобы мои возвращенные массивы обрабатывались как постоянные массивы?

1 Ответ

0 голосов
/ 03 марта 2020

Вы возвращаете Variant() и вводите UDF как функцию массива (с помощью CTRL + SHIFT + ENTER )

Пример функции, которая удваивает значение в массиве

scr

Public Function ScaleValues(ByRef r As Range, ByVal factor As Double) As Variant()
    Dim n As Long, m As Long, i As Long, j As Long
    n = r.Rows.Count:   m = r.Columns.Count

    Dim vals() As Variant
    vals = r.Value

    For i = 1 To n
        For j = 1 To m
            vals(i, j) = factor * vals(i, j)
        Next j
    Next i

    ScaleValues = vals
End Function

В частности, функция для заполнения ячеек в последовательности будет:

scr2

Public Function MySeq(ByVal start_value As Long, ByVal end_value As Long) As Variant()
    Dim n As Long, i As Long
    n = end_value - start_value + 1

    Dim vals() As Variant
    ReDim vals(1 To n, 1 To 1)

    For i = 1 To n
        vals(i, 1) = start_value + (i - 1)
    Next i

    MySeq = vals

End Function

Это хорошо, как вы можете проверить. Введите =SUM(MySeq(1,24)) в ячейку, и вы получите 300, что является правильным ответом. Если вы хотите использовать линейную алгебру, например, масштабирование или добавление массивов, то для каждого шага вы должны отделить операцию от столбца к столбцу.

example

Обратите внимание, что вы не можете хранить весь массив в одной ячейке. Поверьте мне, я пробовал множество способов (например, установил формулу на ={1,2,3,4}). Даже если это удастся, нет никакого способа извлечь значения любым стандартным способом для использования в SUM(), TRANSPOSE() или MMULT().

Для потомков есть версия функции последовательности который обрабатывает нецелые значения и не единичный шаг (шаг)

Public Function MySeq2(ByVal start_value As Double, ByVal end_value As Double, Optional stride As Double = 1) As Variant()
    Dim n As Long, i As Long
    n = (end_value - start_value + stride) / stride

    Dim vals() As Variant
    ReDim vals(1 To n, 1 To 1)

    For i = 1 To n
        vals(i, 1) = start_value + (i - 1) * stride
    Next i

    MySeq2 = vals

End Function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...