+ Reply to Thread
Results 1 to 11 of 11

Passing arguments from VBA to DLL

Hybrid View

  1. #1
    mkluwe@gmail.com
    Guest

    Passing arguments from VBA to DLL

    Hi!

    I just took the first few steps in writing a little DLL that should
    be called from Excel/VBA, and I stumbled upon some wierd behaviour.

    The function in my DLL is declared as

    int __stdcall foo( const char *t );

    and is used in VBA via

    Declare Function foo Lib "C:\foo\foo.dll" (ByVal t As String) As Long

    I noticed that foo didn't work internally as I expected and added
    writing *t to a file on each call of foo as a debugging measure.
    According to this output, only the first character of String t seems
    to be passed to foo when called directly from Excel (putting
    =foo("xyz") in a cell).

    However, if I wrap foo with

    Function call_foo(t As String) As Long
    call_foo = foo(t)
    End Function

    and use the formula =call_foo("xyz"), everything works ok.

    Any ideas?

    Regards,
    Matthias

    PS. Any other hints to "VBA calls DLL" documentation are appreciated


  2. #2
    sjoo
    Guest

    RE: Passing arguments from VBA to DLL

    hi,

    you can't directly call the dll function on the worksheet.
    if you like to do, you have to make XLL library that is a kind of dll.
    XLL is a special programming model for EXCEL.

    please refer this
    http://support.microsoft.com/default...NoWebContent=1

    "mkluwe@gmail.com" wrote:

    > Hi!
    >
    > I just took the first few steps in writing a little DLL that should
    > be called from Excel/VBA, and I stumbled upon some wierd behaviour.
    >
    > The function in my DLL is declared as
    >
    > int __stdcall foo( const char *t );
    >
    > and is used in VBA via
    >
    > Declare Function foo Lib "C:\foo\foo.dll" (ByVal t As String) As Long
    >
    > I noticed that foo didn't work internally as I expected and added
    > writing *t to a file on each call of foo as a debugging measure.
    > According to this output, only the first character of String t seems
    > to be passed to foo when called directly from Excel (putting
    > =foo("xyz") in a cell).
    >
    > However, if I wrap foo with
    >
    > Function call_foo(t As String) As Long
    > call_foo = foo(t)
    > End Function
    >
    > and use the formula =call_foo("xyz"), everything works ok.
    >
    > Any ideas?
    >
    > Regards,
    > Matthias
    >
    > PS. Any other hints to "VBA calls DLL" documentation are appreciated
    >
    >


  3. #3
    mkluwe@gmail.com
    Guest

    Re: Passing arguments from VBA to DLL

    Hi!

    sjoo wrote:
    > "mkluwe@gmail.com" wrote:
    > > I just took the first few steps in writing a little DLL that should
    > > be called from Excel/VBA, and I stumbled upon some wierd behaviour.
    > >
    > > [...]
    > >
    > > I noticed that foo didn't work internally as I expected and added
    > > writing *t to a file on each call of foo as a debugging measure.
    > > According to this output, only the first character of String t seems
    > > to be passed to foo when called directly from Excel (putting
    > > =foo("xyz") in a cell).


    > you can't directly call the dll function on the worksheet.


    In fact, I can, but lacking the correct result. Any guesses for the
    technical reason?

    > if you like to do, you have to make XLL library that is a kind of dll.
    > XLL is a special programming model for EXCEL.
    >
    > please refer this
    > http://support.microsoft.com/default...NoWebContent=1


    Sounds interesting, but I don't have the mentioned "Microsoft Excel 97
    Developer's Kit" available. Plus, Excel 97 is pretty old. What do I
    have to do when developing for more recent versions?

    Regards,
    Matthias


  4. #4
    NickHK
    Guest

    Re: Passing arguments from VBA to DLL

    does this help ?
    http://support.microsoft.com/kb/106553/EN-US/

    NickHK

    <mkluwe@gmail.com> wrote in message
    news:1155806964.926333.7930@75g2000cwc.googlegroups.com...
    > Hi!
    >
    > sjoo wrote:
    > > "mkluwe@gmail.com" wrote:
    > > > I just took the first few steps in writing a little DLL that should
    > > > be called from Excel/VBA, and I stumbled upon some wierd behaviour.
    > > >
    > > > [...]
    > > >
    > > > I noticed that foo didn't work internally as I expected and added
    > > > writing *t to a file on each call of foo as a debugging measure.
    > > > According to this output, only the first character of String t seems
    > > > to be passed to foo when called directly from Excel (putting
    > > > =foo("xyz") in a cell).

    >
    > > you can't directly call the dll function on the worksheet.

    >
    > In fact, I can, but lacking the correct result. Any guesses for the
    > technical reason?
    >
    > > if you like to do, you have to make XLL library that is a kind of dll.
    > > XLL is a special programming model for EXCEL.
    > >
    > > please refer this
    > >

    http://support.microsoft.com/default...NoWebContent=1
    >
    > Sounds interesting, but I don't have the mentioned "Microsoft Excel 97
    > Developer's Kit" available. Plus, Excel 97 is pretty old. What do I
    > have to do when developing for more recent versions?
    >
    > Regards,
    > Matthias
    >




  5. #5
    mkluwe@gmail.com
    Guest

    Re: Passing arguments from VBA to DLL

    Hi!

    NickHK schrieb:
    > <mkluwe@gmail.com> wrote in message
    > news:1155806964.926333.7930@75g2000cwc.googlegroups.com...
    > > sjoo wrote:
    > > > "mkluwe@gmail.com" wrote:
    > > > > [...]
    > > > >
    > > > > I noticed that foo didn't work internally as I expected and added
    > > > > writing *t to a file on each call of foo as a debugging measure.
    > > > > According to this output, only the first character of String t seems
    > > > > to be passed to foo when called directly from Excel (putting
    > > > > =foo("xyz") in a cell).

    > >
    > > > you can't directly call the dll function on the worksheet.

    > >
    > > In fact, I can, but lacking the correct result. Any guesses for the
    > > technical reason?
    > >
    > > > if you like to do, you have to make XLL library that is a kind of dll.
    > > > XLL is a special programming model for EXCEL.
    > > >
    > > > please refer this
    > > >

    > http://support.microsoft.com/default...NoWebContent=1
    > >
    > > Sounds interesting, but I don't have the mentioned "Microsoft Excel 97
    > > Developer's Kit" available. Plus, Excel 97 is pretty old. What do I
    > > have to do when developing for more recent versions?


    > does this help ?
    > http://support.microsoft.com/kb/106553/EN-US/


    No, sorry. The example DLL and VB code looks like mine, and I have no
    problems when calling the DLL from VBA functions or macros. The problem
    arises when calling it from wihtin Excel.

    Regards,
    Matthias


  6. #6
    NickHK
    Guest

    Re: Passing arguments from VBA to DLL

    I'm no C expert at all, but..
    I would assume it has to do with how VBA sends the string to your DLL. In
    VBA, internally, it is held as Unicode in a BSTR, which works fine when
    passed ByVal to your function. IIRC, you are actually passing a pointer to a
    pointer of the string.
    However, going directly from the worksheet, your are not actually passing
    the same thing (possibly not even in a BSTR) and hence only the first
    character is resolved instaed of the whole string.

    As a trivial example, using this Windows calls
    Public Declare Function lstrlenA Lib "kernel32" (ByVal lpString As String)
    As Long
    in a VBA function gives lstrlenA("qwerty") equal to 6. Correct.

    From the worksheet, lstrlenA("qwerty")=1. Wrong

    So I would guess you have to give VBA chance to create a variable so it can
    pass the string correctly. i.e. create a dummy VBA function to call each of
    your DLL functions that invlove strings.

    NickHK

    <mkluwe@gmail.com>
    ???????:1155820714.968976.24440@i42g2000cwa.googlegroups.com...
    > Hi!
    >
    > NickHK schrieb:
    >> <mkluwe@gmail.com> wrote in message
    >> news:1155806964.926333.7930@75g2000cwc.googlegroups.com...
    >> > sjoo wrote:
    >> > > "mkluwe@gmail.com" wrote:
    >> > > > [...]
    >> > > >
    >> > > > I noticed that foo didn't work internally as I expected and added
    >> > > > writing *t to a file on each call of foo as a debugging measure.
    >> > > > According to this output, only the first character of String t
    >> > > > seems
    >> > > > to be passed to foo when called directly from Excel (putting
    >> > > > =foo("xyz") in a cell).
    >> >
    >> > > you can't directly call the dll function on the worksheet.
    >> >
    >> > In fact, I can, but lacking the correct result. Any guesses for the
    >> > technical reason?
    >> >
    >> > > if you like to do, you have to make XLL library that is a kind of
    >> > > dll.
    >> > > XLL is a special programming model for EXCEL.
    >> > >
    >> > > please refer this
    >> > >

    >> http://support.microsoft.com/default...NoWebContent=1
    >> >
    >> > Sounds interesting, but I don't have the mentioned "Microsoft Excel 97
    >> > Developer's Kit" available. Plus, Excel 97 is pretty old. What do I
    >> > have to do when developing for more recent versions?

    >
    >> does this help ?
    >> http://support.microsoft.com/kb/106553/EN-US/

    >
    > No, sorry. The example DLL and VB code looks like mine, and I have no
    > problems when calling the DLL from VBA functions or macros. The problem
    > arises when calling it from wihtin Excel.
    >
    > Regards,
    > Matthias
    >




  7. #7
    mkluwe@gmail.com
    Guest

    Re: Passing arguments from VBA to DLL

    mkluwe@gmail.com schrieb:
    > I just took the first few steps in writing a little DLL that should
    > be called from Excel/VBA, and I stumbled upon some wierd behaviour.
    >
    > The function in my DLL is declared as
    >
    > int __stdcall foo( const char *t );
    >
    > and is used in VBA via
    >
    > Declare Function foo Lib "C:\foo\foo.dll" (ByVal t As String) As Long
    >
    > I noticed that foo didn't work internally as I expected and added
    > writing *t to a file on each call of foo as a debugging measure.
    > According to this output, only the first character of String t seems
    > to be passed to foo when called directly from Excel (putting
    > =foo("xyz") in a cell).


    Let me answer my own post:

    Excel passes the string as some kind of wide-character. Using
    const wchar_t *t in my function works perfectly.

    Regards,
    Matthias


  8. #8
    NickHK
    Guest

    Re: Passing arguments from VBA to DLL

    Now you mention that, changing the declare of lstrlenA to the Wide version;
    Public Declare Function lstrlenW Lib "kernel32" (ByVal lpString As String)
    As Long

    now works fine the worksheet also.

    IIRC normally when calling window function from VB there is Unicode > ANSI
    conversion. Hence the "A" versions of these function are used.
    If I wanted to use the W version it would be
    Public Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As
    Long
    and call it with
    lstrlenW(strPtr("MyString"))

    From the worksheet, seems the conversion does not occur.

    NickHK


    <mkluwe@gmail.com>
    ???????:1155826189.336921.303220@m79g2000cwm.googlegroups.com...
    > mkluwe@gmail.com schrieb:
    >> I just took the first few steps in writing a little DLL that should
    >> be called from Excel/VBA, and I stumbled upon some wierd behaviour.
    >>
    >> The function in my DLL is declared as
    >>
    >> int __stdcall foo( const char *t );
    >>
    >> and is used in VBA via
    >>
    >> Declare Function foo Lib "C:\foo\foo.dll" (ByVal t As String) As Long
    >>
    >> I noticed that foo didn't work internally as I expected and added
    >> writing *t to a file on each call of foo as a debugging measure.
    >> According to this output, only the first character of String t seems
    >> to be passed to foo when called directly from Excel (putting
    >> =foo("xyz") in a cell).

    >
    > Let me answer my own post:
    >
    > Excel passes the string as some kind of wide-character. Using
    > const wchar_t *t in my function works perfectly.
    >
    > Regards,
    > Matthias
    >




  9. #9
    mkluwe@gmail.com
    Guest

    Re: Passing arguments from VBA to DLL

    Hi!

    NickHK schrieb:
    > <mkluwe@gmail.com>
    > ???????:1155826189.336921.303220@m79g2000cwm.googlegroups.com...
    > > mkluwe@gmail.com schrieb:
    > >> I just took the first few steps in writing a little DLL that should
    > >> be called from Excel/VBA, and I stumbled upon some wierd behaviour.
    > >>
    > >> The function in my DLL is declared as
    > >>
    > >> int __stdcall foo( const char *t );
    > >>
    > >> and is used in VBA via
    > >>
    > >> Declare Function foo Lib "C:\foo\foo.dll" (ByVal t As String) As Long
    > >>
    > >> I noticed that foo didn't work internally as I expected and added
    > >> writing *t to a file on each call of foo as a debugging measure.
    > >> According to this output, only the first character of String t seems
    > >> to be passed to foo when called directly from Excel (putting
    > >> =foo("xyz") in a cell).

    > >
    > > Let me answer my own post:
    > >
    > > Excel passes the string as some kind of wide-character. Using
    > > const wchar_t *t in my function works perfectly.


    > Now you mention that, changing the declare of lstrlenA to the Wide version;
    > Public Declare Function lstrlenW Lib "kernel32" (ByVal lpString As String)
    > As Long
    >
    > now works fine the worksheet also.
    >
    > IIRC normally when calling window function from VB there is Unicode > ANSI
    > conversion. Hence the "A" versions of these function are used.
    > If I wanted to use the W version it would be
    > Public Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As
    > Long
    > and call it with
    > lstrlenW(strPtr("MyString"))
    >
    > From the worksheet, seems the conversion does not occur.


    Indeed. I just found the following document:
    http://msdn.microsoft.com/library/de...ce03082001.asp

    It says: "Although VBA uses Unicode internally, it converts all strings
    to ANSI strings before calling a function in a DLL". Thus, both Excel
    and VBA use Unicode internally, but only VBA insists on conversion.

    Sad situation -- I still have no better option than wrapping functions
    in VBA, otherwise my DLL would have to provide two different functions
    for each operation.

    Regards,
    Matthias


  10. #10
    NickHK
    Guest

    Re: Passing arguments from VBA to DLL


    <mkluwe@gmail.com> wrote in message
    news:1155884374.657132.31280@m73g2000cwd.googlegroups.com...
    > Hi!
    >
    > NickHK schrieb:
    > > <mkluwe@gmail.com>
    > > ???????:1155826189.336921.303220@m79g2000cwm.googlegroups.com...
    > > > mkluwe@gmail.com schrieb:
    > > >> I just took the first few steps in writing a little DLL that should
    > > >> be called from Excel/VBA, and I stumbled upon some wierd behaviour.
    > > >>
    > > >> The function in my DLL is declared as
    > > >>
    > > >> int __stdcall foo( const char *t );
    > > >>
    > > >> and is used in VBA via
    > > >>
    > > >> Declare Function foo Lib "C:\foo\foo.dll" (ByVal t As String) As Long
    > > >>
    > > >> I noticed that foo didn't work internally as I expected and added
    > > >> writing *t to a file on each call of foo as a debugging measure.
    > > >> According to this output, only the first character of String t seems
    > > >> to be passed to foo when called directly from Excel (putting
    > > >> =foo("xyz") in a cell).
    > > >
    > > > Let me answer my own post:
    > > >
    > > > Excel passes the string as some kind of wide-character. Using
    > > > const wchar_t *t in my function works perfectly.

    >
    > > Now you mention that, changing the declare of lstrlenA to the Wide

    version;
    > > Public Declare Function lstrlenW Lib "kernel32" (ByVal lpString As

    String)
    > > As Long
    > >
    > > now works fine the worksheet also.
    > >
    > > IIRC normally when calling window function from VB there is Unicode >

    ANSI
    > > conversion. Hence the "A" versions of these function are used.
    > > If I wanted to use the W version it would be
    > > Public Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long)

    As
    > > Long
    > > and call it with
    > > lstrlenW(strPtr("MyString"))
    > >
    > > From the worksheet, seems the conversion does not occur.

    >
    > Indeed. I just found the following document:
    >

    http://msdn.microsoft.com/library/de...ce03082001.asp
    >
    > It says: "Although VBA uses Unicode internally, it converts all strings
    > to ANSI strings before calling a function in a DLL". Thus, both Excel
    > and VBA use Unicode internally, but only VBA insists on conversion.
    >
    > Sad situation -- I still have no better option than wrapping functions
    > in VBA, otherwise my DLL would have to provide two different functions
    > for each operation.
    >
    > Regards,
    > Matthias


    Yes, given that one converts and other does not, it would be better to
    expose your function as wrapper to the private Declares. Otherwise, you will
    have to rely on the user knowing to call the W version from the worksheet
    and the A version from VBA.

    NickHK



+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.6.0 RC 1