Solved

CallByName - Array Parameters Of An Unknown Type

Posted on 2001-07-20
11
1,178 Views
Last Modified: 2009-12-16
When using CallByName to run a method of a COM component, if a parameter expected is of a certain type, when calling it, you can actually pass in a variant, as long as the variant contains a variable of the right type.

However, if the parameter expected is an array of a certain type (say Long), then when calling it you must pass an array dimensioned as that type, rather than an array dimensioned as a variant, or a variant storing an array.

So, say your COM component has a function as follows:
Public Function Blah(x as long, y() as long)

When calling it, you should do this:
Dim x As Long
Dim y() As Long
CallByName MyObj, "Blah", VbMethod, x, y

Our problem is that we don't know at compile time what the COM object is expecting, so we have to do this:
Dim x As Variant
Dim y() As Variant

'Now convert the array to the relevant type - in this instance assume Long is the data type
x=CLng(0)
Redim y(0)
y(0)=CLng(0)
CallByName MyObj, "Blah", VbMethod, x, y

This is causing a Type Mismatch error.  The x parameter works fine, but the y parameter (the array) isn't.

Any ideas would be greatly appreciated.
0
Comment
Question by:ygibbs
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 2
  • +2
11 Comments
 
LVL 3

Expert Comment

by:nigelrowe
ID: 6301860
There doesn't seem to be a one line solution, so..
Dim y As variant
    y = Array("1", "2", 3)
    For i = 0 To UBound(y)
        y(i) = CLng(y(i))
    Next
0
 
LVL 22

Expert Comment

by:CJ_S
ID: 6301869
I think he wants to determine the type of parameters at run-time...

regards,
CJ
0
 
LVL 4

Expert Comment

by:VincentLawlor
ID: 6301870
That's because your COM object is probably expecting a array of longs not a variant.

The IDL for the file probably declares it as a specific type. i.e. long

To get this to work the COM object must be able to accept either Variant or Variant array data types.

Check the types it is expection using object browser.

What language were the COM object written in.

Vin.
0
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 
LVL 3

Expert Comment

by:nigelrowe
ID: 6301871
Please forget that, I see what you are getting at now. I will look more closely.
0
 
LVL 4

Expert Comment

by:VincentLawlor
ID: 6301886
If you wrote them in VB then you will have to change your data types in the COM objects to Variants and do the Conversions internally.

If the were written in C++ then the data types will have to be changed to VARIANT and the appropriate conversions done on the values passed to it internally in the com object.

Vin.
0
 

Author Comment

by:ygibbs
ID: 6301901
Yeah, the only easy solution is to change the COM component to receive variants (generally our clients' COM components will be written in VB, but we allow them to define which components they want to use, so it could theoretically be anything).  However I would like to try and avoid that if at all possible.

The other thing we're investigating is using the Type Library Information DLL and its InvokeHook method.  Has anyone had any experience of this?

I'll post a solution if we manage to get one ourselves, but thanks for the input anyway.
0
 
LVL 15

Accepted Solution

by:
ameba earned 200 total points
ID: 6301988
This will make your callbyname work, but you should know that if you don't pass right variable type, ByRef won't work - you will be passing argument ByVal.

Option Explicit

Private Sub Form_Load()
    Dim x As Variant
    ReDim y(0) As Variant
    x = 1
    y(0) = 1
   
    Dim vntY As Variant  ' this variable will hold our array
    vntY = ConvertArray(y, vbLong)
   
    ' don't pass vntY variable directly - gives "Type mismatch" error
    '    pass Expression (vntY)
    CallByName Me, "Blah", VbMethod, CLng(x), (vntY)

End Sub

Public Sub Blah(px As Long, py() As Long)
    px = 2
    py(0) = 2
End Sub

' converts variant array to
'     variant variable which holds 'right' type of array
' I modified code from: http://www.vb2themax.com/Item.asp?PageID=CodeBank&ID=72
Public Function ConvertArray(arr() As Variant, NewType As VBA.VbVarType) As Variant
    Dim i As Long
    Dim maxEl As Long
    Dim res As Variant
   
    maxEl = UBound(arr)
   
    ' create different arrays, depending on the
    ' type of the first argument
    Select Case NewType
    Case vbInteger
        ReDim arrInt(0 To maxEl) As Integer
        res = arrInt()
    Case vbLong
        ReDim arrLng(0 To maxEl) As Long
        res = arrLng()
    Case vbSingle
        ReDim arrSng(0 To maxEl) As Single
        res = arrSng()
    Case vbDouble
        ReDim arrDbl(0 To maxEl) As Double
        res = arrDbl()
    Case vbCurrency
        ReDim arrCur(0 To maxEl) As Currency
        res = arrCur()
    Case vbString
        ReDim arrStr(0 To maxEl) As String
        res = arrStr()
    Case vbDate
        ReDim arrDat(0 To maxEl) As Date
        res = arrDat()
    Case vbBoolean
        ReDim arrBol(0 To maxEl) As Boolean
        res = arrBol()
    Case vbObject
        ' special case
        ReDim arrObj(0 To maxEl) As Object
        For i = 0 To maxEl
            Set arrObj(i) = arr(i)
        Next
        ConvertArray = arrObj()
        Exit Function
    Case Else
        ' unsupported data type
        ' (might be a UDT or an array)
        Err.Raise 5
    End Select
           
    ' now we can copy all values into the array
    For i = 0 To maxEl
        res(i) = arr(i)
    Next
    ConvertArray = res
End Function
0
 
LVL 4

Expert Comment

by:VincentLawlor
ID: 6301992
Have you checked out MSDN.

There is an article in there about it.

http://support.microsoft.com/support/kb/articles/Q194/4/18.ASP

This might help.

Tried it it works.

Vin.
0
 

Author Comment

by:ygibbs
ID: 6302004
Superb - thank you so much.  That's it working perfectly now.
0
 
LVL 15

Expert Comment

by:ameba
ID: 6302005
My code was version 0.1  :-)
Do not redim arrays:
    "0 To maxEl"
but use "minEl To maxEl", where  minEl = LBound(arr)
0
 
LVL 15

Expert Comment

by:ameba
ID: 6302018
Thanks!
0

Featured Post

Enroll in June's Course of the Month

June's Course of the Month is now available! Every 10 seconds, a consumer gets hit with ransomware. Refresh your knowledge of ransomware best practices by enrolling in this month's complimentary course for Premium Members, Team Accounts, and Qualified Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction While answering a recent question (http://www.experts-exchange.com/Q_27402310.html) in the VB classic zone, I wrote some VB code in the (Office) VBA environment, rather than fire up my older PC.  I didn't post completely correct code o…
Most everyone who has done any programming in VB6 knows that you can do something in code like Debug.Print MyVar and that when the program runs from the IDE, the value of MyVar will be displayed in the Immediate Window. Less well known is Debug.Asse…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question