Solved

Array as olevariant

Posted on 2004-10-29
6,764 Views
Last Modified: 2007-12-19
IN VB I have:


Dim aArgs(2) As String
 
aArgs(0) = sFilePath
aArgs(1) = "QuoteFileName"
aArgs(2) = "N"

Test.InvokeMethod("ABC", aArgs).

Try to do the same from delphi.

The problem is that the second parameter of InvokeMethod is an ole variant

(so I can't send in my array of string there).

How do I convert my array of string to an olevariant?


0
Question by:pucko
    12 Comments
     
    LVL 17

    Expert Comment

    by:geobul
    Test.InvokeMethod('ABC', VarArrayOf([aArgs[0],aArgs[1],aArgs[2]]));
    0
     
    LVL 17

    Expert Comment

    by:geobul
    Another way is to declare aArgs as Variant instead:

    var
      aArgs: Variant;
      sFilePath: string;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      aArgs := VarArrayCreate([0,2], varVariant);
      aArgs[0] := sFilePath;
      aArgs[1] := 'QuoteFileName';
      aArgs[2] := 'N';

      Test.InvokeMethod('ABC', aArgs) then ShowMessage('OK');
    end;

    Regards, Geo
    0
     
    LVL 17

    Expert Comment

    by:geobul
    Or try the function below for converting an array of string to variant:

    var
      aArgs: array [0..2] of string;
      sFilePath: string;

    function StringArrayToVariant(ar: array of string): Variant;
    var
      Min,Max, i: integer;
    begin
      Min := Low(ar);
      Max := High(ar);
      result := VarArrayCreate([Min,Max], varVariant);
      for i := Min to Max do begin
        result[i] := ar[i];
      end;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      sFilePath := 'c:\';
      aArgs[0] := sFilePath;
      aArgs[1] := 'QuoteFileName';
      aArgs[2] := 'N';

      Test.InvokeMethod('ABC', StringArrayToVariant(aArgs));
    end;
    0
     
    LVL 12

    Expert Comment

    by:Ivanov_G
    as Geobul said - VarArrayCreate. In addition to his answer, if you want to access the array server-side:

    var
      i : Integer;
    begin
      for i := VarArrayLowBound(aArgs, 1) to VarArrayHighBound(aArgs, 1) do
        begin
          aArgs[i] := ..............
          .............
        end;
    end;
    0
     
    LVL 1

    Author Comment

    by:pucko
    It seems like I still have this problem.

    To be more specific:

    Function in VB:


    Private Function CreateAttachment(sFilePath As String)

        Dim errCode As Integer
        Dim aArgs(2) As String
        Dim RetValue As String

        CreateAttachment = True
       
        With bcQuoteAtt
            Set bcQuoteAtt = boOpty.GetBusComp("Quote Attachment")
           
            aArgs(0) = sFilePath
            aArgs(1) = "QuoteFileName"
            aArgs(2) = "N"

            bcQuoteAtt.NewRecord 0
            RetValue = bcQuoteAtt.InvokeMethod("CreateFile", aArgs)
           
            End If
        End With
       
    End Function


    In Delphi:



    function  CreateAttachment(sFilePath : WideString) :String;
    var
       Args : Array [0..2] Of WideString;
       TmpArgs : OleVariant;

    begin
      Result:= '';

      bcQuoteAtt:= boOpty.GetBusComp('Quote Attachment');
      with bcQuoteAtt do
      begin
        NewRecord(0);


        args[0]:= sFilePath;
        args[1]:= 'QuoteFileName2';
        args[2]:= 'N';
        tmpArgs:= StringArrayToVariant(args);
      end;
      Result:= bcQuoteAtt.InvokeMethod('CreateFile',Args);
     
    end;


    And from the TypeLibrary:

    function InvokeMethod(const Name: WideString; args: OleVariant): WideString; safecall;


    When running from VB the server do what it shuld.

    But not from the delphi code.


    When running the VB code


    0
     
    LVL 1

    Author Comment

    by:pucko
    I found this but I don't know how to do. (how to pass the array as a widestring)


    The Ole Automation method was called with an invalid argument when a string or an array of strings was expected."

    Initially it was thought that the declaration of the methodArgs variable (argument), as type OleVariant was incorrect, as according to Technical Note number 198 (Accessing File Attachments through Siebel VB and Siebel BusObject Interfaces), the GetFile method, invoked through InvokeMethod is expecting this argument as a String.

    However, Delphi's structure definition of InvokeMethod is (SiebelApplicationServer_TLB Unit Created by Delphi When importing the Type Library):
    ...
    SiebelBusComp = dispinterface
        ['{2F076E20-0B36-11D0-A52E-00C04FD20274}']
        ...
        function InvokeMethod(const methodName: WideString; var methodArgs: OleVariant; var errCode: Smallint): WideString; dispid 32;
    ...

    Delphi is interpreting methodArgs as the Delphi data type, OleVariant.

    This issue was resolved by simply changing the type of the MethodArgs argument to WideString instead of OleVariant in the Delphi function declaration. This now compiles and the function completes correctly at run time.

     

    Bu
    0
     
    LVL 17

    Expert Comment

    by:geobul
    Your aArgs is array is of WideString type (in your Delphi representation) and that is totally different compared to array of string. Make the function StringArrayToVariant to accept 'array of WideString' instead. That, perhaps, will solve the problem.
    0
     
    LVL 1

    Author Comment

    by:pucko
    No it don't help.

    I tried array of string first. And then array of widestring since VB's String is a widestring.
    0
     
    LVL 17

    Expert Comment

    by:geobul
    I've just read your last comment and don't think that replacing OveVariant with WideString in the method definition (Delphi code) would be correct enough (well, in a particular case it might be but not speaking in general). OveVariant is a generic type designed for COM communication that can represent everything. Same as in VB (Variant type was designed by VB developers because there were lots of VB programmers who were unable to distingush an integer number from a real one ;-) Simply try changing the StringArrayToVariant function definition as descrbed in my previous post and see what's going on. I understand now (hope I'm right) that you're communicating with a COM object,
    0
     
    LVL 1

    Author Comment

    by:pucko
    It's realy hard for me to understand what's happening here.

    The server gives me some strange response when I send this in from delphi.

    When I do it from VB it looks ok.

    As I said before, my first try was with array of string.

    Then I tried what I wrote above since vb's string definition is the same as widestring in delphi (not ansi string).
    0
     
    LVL 17

    Expert Comment

    by:geobul
    Have you tried my first proposal? Using VarArrayOf function?

    Another thing: OleVariant in Delphi is just a 'subset' of Variant which should automatically convert string to WideString. So, your code

    var
      TmpArgs : OleVariant;
    ...
      tmpArgs:= StringArrayToVariant(args);

    should have done it if you have called the method like:
      Result:= bcQuoteAtt.InvokeMethod('CreateFile',tmpArgs);

    Regards, Geo
    0
     
    LVL 17

    Accepted Solution

    by:
    One more thing:

    the result of the CreateAttachment function should be of WideString type, not string!
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    How your wiki can always stay up-to-date

    Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
    - Increase transparency
    - Onboard new hires faster
    - Access from mobile/offline

    Suggested Solutions

    A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
    The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
    This video Micro Tutorial is the first in a two-part series that shows how to create and use custom scanning profiles in Nuance's PaperPort 14.5 (http://www.experts-exchange.com/articles/17490/). But the ability to create custom scanning profiles al…
    To add imagery to an HTML email signature, you have two options available to you. You can either add a logo/image by embedding it directly into the signature or hosting it externally and linking to it. The vast majority of email clients display l…

    884 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

    16 Experts available now in Live!

    Get 1:1 Help Now