Solved

CallByName - Array Parameters Of An Unknown Type

Posted on 2001-07-20
11
1,164 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
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 
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

PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

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…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
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…

732 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