2016-03-30 4 views
0

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

Public Sub Initialize_Object(ByRef TaskObject, Task_Collection) 

Dim Task_begin As Variant, Method_Parameters As Variant 

Task_begin = Task_Collection("Method") 

CallByName TaskObject, Task_begin, VbMethod, Method_Parameters 
+1

Читали ли вы на чём «PARAM массив» является ? Я не могу следовать этому утверждению: «К сожалению, CallByName принимает массив параметров, поэтому передать переменное число не просто». – MikeC

+0

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

+0

Вы пишете подпрограммы, которые могли бы быть вызваны? – MikeC

ответ

0

Вы не можете сделать это динамически, поскольку различные методы требуют различного количества аргументов, и вы не можете передать аргументы, где они не ожидали.

Если вы знаете количество аргументов требуется, то вы могли бы назвать каждый элемент массива и передать:

CallByName TaskObject, Task_begin, VbMethod, Method_Parameters(0), Method_Parameters(1), Method_Parameters(2) 

но вы, вероятно, придется создать Select Case блок или подобный обрабатывать все различные методы:

Select Case Method_Name 
    Case "Method_1": CallByName TaskObject, Task_begin, VbMethod, Method_Parameters(0), Method_Parameters(1) 
    Case "Method_2": CallByName TaskObject, Task_begin, VbMethod, Method_Parameters(0) 
    Case "Method_3": CallByName TaskObject, Task_begin, VbMethod, Method_Parameters(0), Method_Parameters(1), Method_Parameters(2) 
End Select 

Какой может быть довольно грязным.

+0

Это на самом деле неправильно и полностью противоречит тому, что вы ранее говорили. Я предлагаю вам прочитать статью MSDN о методе CallByName в VBA, где они используют 2 аргумента в рабочем примере. –

+0

. Мой плохой он работает, подпись неверна в проводнике объектов и документации: https://msdn.microsoft.com/en-us/library/office/gg278760.aspx –

+1

Если 'Method_Parameters' - это массив, выберите' Select Case UBound (Method_Parameters) 'будет иметь гораздо больше смысла. Включение 'Method_Name' поражает цель использования' CallByName'. Вы могли бы просто вызвать функцию напрямую ... – Comintern

2

Вы можете использовать CallByName с массивом в качестве аргумента, изменив сигнатуру метода:

#If VBA7 Or Win64 Then 
    Private Declare PtrSafe Function rtcCallByName Lib "VBE7.DLL" (_ 
    ByVal Object As Object, _ 
    ByVal ProcName As LongPtr, _ 
    ByVal CallType As VbCallType, _ 
    ByRef args() As Any, _ 
    Optional ByVal lcid As Long) As Variant 
#Else 
    Private Declare Function rtcCallByName Lib "VBE6.DLL" (_ 
    ByVal Object As Object, _ 
    ByVal ProcName As Long, _ 
    ByVal CallType As VbCallType, _ 
    ByRef args() As Any, _ 
    Optional ByVal lcid As Long) As Variant 
#End If 

Public Function CallByName2(Object As Object, ProcName As String, args() As Variant) 
    AssignResult CallByName2, rtcCallByName(Object, StrPtr(ProcName), VbMethod, args) 
End Function 

Private Sub AssignResult(target, result) 
    If VBA.IsObject(result) Then Set target = result Else target = result 
End Sub 

Вот пример использования:

Sub UsageExample() 
    Dim obj As Object, arguments() 

    Dim obj As New Class1 
    arguments = Array(1, 3) 

    CallByName2 obj, "MyMethod", arguments 
End Sub 
+0

Приятный. Просто нужно думать нестандартно. – Comintern

+0

'lcid' выглядит как« LongPtr »в x64 для меня. –

+0

@ Macro Man, No lcid - тип U4, но я исправил ProcName, которое должно было быть. Thx –