Страницы: 1
RSS
Возможно ли в VBA передавать в функцию имена других функций?
 
Добрый День!
Подскажите, пожалуйста, возможно ли в VBA передавать в функцию имена других функций?

вопрос:
Возможно ли в одном цикле:
1. вызвать имя конкретной функции по параметру содержащему её имя
2. передать ей массив в качестве параметра функции в внутри цикла
3. иметь возможность в условии вызова функции 2 выбирать название функции1 или другой функции обработки
Или как правильно записать?
т.е. есть
Код
функция 2()

for i=1 to 34
    m = функция1 (mF(i, 16),....)
next i

вызов функции
Код
функция 2( функция1 (mF(i, 16)) )
одинокий странник
 
Не совсем понимаю зачем такое, но видимо имеется ввиду вот так?
Код
Function f1(ByVal d As Long, s As Long)
For i = d To s
    f1 = f2(i) * s
Next i
End Function
Function f2(ByVal d As Long)
    f2 = d * 2
End Function
Sub test_F()
    For i = 1 To 1
        res = f2(f1(i, i + 1))
    Next i
    MsgBox res
End Sub
 
SvetaS_love, чисто VBшное решение - сделать функции методами класса и вызывать их с помощью CallByName.
В VBA для вызова функции по переменному имени также можно использовать Application.Run.
 
Сравнил по скорости CallByName и Application.Run - первый способ более чем в 2 раза быстрее.
Скрытый текст

Результат (проц. 1.6 ГГц)
Код
CallByName     3,796875 
App.Run        8,828125 
Причем если методу Application.Run указывать полный путь к процедурам
Код
  x = Application.Run("Module1.Mul2", x)
  x = Application.Run("Книга1!Module1.Mul2", x)
, то становится только хуже.
Изменено: Казанский - 03.10.2015 20:41:33 (Исправил опечатку в 1 строке поста)
 
сравнила по скорости первый способ (класс-модуль) с обычным программным использованием функции - БЕЗ Application.Run
Код
t = Timer
For i = 1 To N
  x = Mul2(x)
  x = Div2(x)
Next
Debug.Print "function(x)", Timer - t
результат (проц 2,8ГГц, озу 2):
Код
CallByName     3.195313 
function(x)    0.234375 
- всё-таки обращение к Application, и даже в модуль-класса - это лишнее время, чем "обычное" использование функции?!..
(Казанский, спасибо за тест)
Изменено: JeyCi - 03.10.2015 19:08:31
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Доброе время суток
Если исходить, что требуется использование делегатов для передачи в функцию метода вычислений внутри неё с единой структурой параметров метода. Увы,которых в VBA нет, то можно воспользоваться следующим более быстрым подходом, чем CallByName.
Создаём класс-интерфейс ITrigable с кодом
Код
Public Function TrigFunction(ByVal Value As Double) As Double
End Function

Класс, реализующий функцию синуса Siner ;) с кодом
Код
Implements ITrigable
Private Function ITrigable_TrigFunction(ByVal Value As Double) As Double
    ITrigable_TrigFunction = Sin(Value)
End Function

Класс, реализующий функцию косинуса Coser ;) с кодом
Код
Implements ITrigable
Private Function ITrigable_TrigFunction(ByVal Value As Double) As Double
    ITrigable_TrigFunction = Cos(Value)
End Function

Собственно, функция, использующая псевдо делегатный подход
Код
Public Function ArraySum(ByVal Trig As ITrigable, ByRef Args() As Double) As Double
    Dim vResult As Double, i As Long
    vResult = 0#
    With Trig
        For i = LBound(Args) To UBound(Args)
            vResult = vResult + .TrigFunction(Args(i))
        Next
    End With
    ArraySum = vResult
End Function

И пример использования
Код
Public Sub Example()
    Dim p As ITrigable, Args() As Double
    Dim vSum As Double

    '.....

    'так - сумма синусов
    Set p = New Siner
    vSum = ArraySum(p, Args)
    'так - сумма косинусов
    Set p = New Coser
    vSum = ArraySum(p, Args)
End Sub

Время выполнения
Через псевдо делегат 1,54 сек
Через прямой вызов Cos 0,52 сек
Разница есть - в 3 раза медленнее - как плата за дополнительные вызовы и за универсальность (с другой стороны - будут использоваться свои функции VBA). Но это не столь "смертельная" в 13 раз, как в вашем примере.
Страницы: 1
Наверх