Solved

CallByName - Array Parameters Of An Unknown Type

Posted on 2001-07-20
11
1,103 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
  • 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
 
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
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

There are many ways to remove duplicate entries in an SQL or Access database. Most make you temporarily insert an ID field, make a temp table and copy data back and forth, and/or are slow. Here is an easy way in VB6 using ADO to remove duplicate row…
If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now