Page 1 of 2 12 LastLast
Results 1 to 40 of 53

Thread: [RESOLVED] How to use CallByName in a Class to call methods or functions in modules?

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Resolved [RESOLVED] How to use CallByName in a Class to call methods or functions in modules?

    Dear All,

    I'm creating a ActiveX DLL in VB6.0, there are a lot of methods and functions in modules. If I want to use this DLL, then in the class, a lot of modules or functions are needed.

    If the CallByName function can be used in class to Call methods or functions in module, it would be great, only an "caller" is needed in Class, only input the method/function's name is enough.

    Could you please provide some method for me?

    Thank you very much.

    Sniperhgy

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: How to use CallByName in a Class to call methods or functions in modules?

    CallByName is intended for IDispatch supported interfaces, i.e., forms, classes, etc. Not modules, can't do it using CallByName without creating some class that calls the module functions and then you can use CallByName on that class.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by LaVolpe View Post
    CallByName is intended for IDispatch supported interfaces, i.e., forms, classes, etc. Not modules, can't do it using CallByName without creating some class that calls the module functions and then you can use CallByName on that class.
    Hi LaVolpe,

    Thank you for your reply. But in my opinion, some functions can't be used in Class, for example: AddressOf.

    Is there a alternative method exist? In VBA, we can use Application.Run to implement this, but in VB6.0, can't use Application.Run.

    Thank you.

    Best Regards,

    Sniperhgy

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: How to use CallByName in a Class to call methods or functions in modules?

    You might want to give us some specific examples of what you are trying to do that can't be done with a class. Generalities are a bit more difficult to discuss sometimes.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,904

    Re: How to use CallByName in a Class to call methods or functions in modules?

    When creating an activex dll then you also want intellisense.
    Thus in the main class of the active dll you create the "interface" for all subs and functions you have created in all modules.
    Code:
    Public Sub DoX(Param1 As Long)
      modRoutines.DoX Param1
    End Sub
    
    Public Function CalcY(x As Double) As Double
      CalcY = modFunctions.CalcY(x)
    End Function

  6. #6

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by LaVolpe View Post
    You might want to give us some specific examples of what you are trying to do that can't be done with a class. Generalities are a bit more difficult to discuss sometimes.
    Ok, I'll take a shot on it then reply. Thank you.

  7. #7

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Arnoutdv View Post
    When creating an activex dll then you also want intellisense.
    Thus in the main class of the active dll you create the "interface" for all subs and functions you have created in all modules.
    Code:
    Public Sub DoX(Param1 As Long)
      modRoutines.DoX Param1
    End Sub
    
    Public Function CalcY(x As Double) As Double
      CalcY = modFunctions.CalcY(x)
    End Function
    Thank you for your reply. But If there are hundreds of functions or subs, write the callers one by one will be suffered.

  8. #8
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: How to use CallByName in a Class to call methods or functions in modules?

    gyhu,

    If I had many BAS modules that I wanted to wrap into an ActiveX DLL, I'd possibly just create another class (CLS) that served as stubs for calling into those BAS procedures. That would seem to solve the problem. Also, I'm not sure what you'd be doing with AddressOf, but it can't be used when calling into an ActiveX DLL anyway (BAS module or not). However, if you're doing subclassing, callbacks, or hooks in your ActiveX DLL, you could still build a stub procedure in a CLS module that called the procedure in the BAS module that used the AddressOf. Again, if you're willing to use a CLS module as a wrapper for your BAS module procedures, there doesn't seem to be any problem.

    Personally, I've found CallByName to be particularly useful in certain situations. This particular example doesn't involve an ActiveX DLL, but the following is a small snippet out of a class I have named clsParamsCalc. These are what we call gait (walking) parameters. For instance, the maximum amount you bend your knee when you walk. (That would be KfaPeak. [knee flexion angle peak]). There are 100s of these things.

    Code:
    
    
    Public Function KfaMin() As Variant
        KfaMin = MinVal(KneeFlexExt)
    End Function
    
    Public Function KfaPeak() As Variant
        KfaPeak = MaxVal(KneeFlexExt)
    End Function
    
    Public Function KfaMean() As Variant
        KfaMean = MeanVal(KneeFlexExt)
    End Function
    
    Public Function KfaRange() As Variant
        KfaRange = RangeVal(KneeFlexExt)
    End Function
    
    Public Function KfaAtIc() As Variant
        KfaAtIc = FrameVal(KneeFlexExt, 1)
    End Function
    
    Public Function KfaLoading() As Variant
        ' Looks from frame 1 to half way to Opposite Foot Strike.
        KfaLoading = MaxVal(KneeFlexExt, 1, FrameFromPct(OfsPct / 2))
    End Function
    
    Public Function KfaMinInStance() As Variant
        KfaMinInStance = MinVal(KneeFlexExt, 1, SfoFrame)
    End Function
    
    Public Function KfaPeakInStance() As Variant
        KfaPeakInStance = MaxVal(KneeFlexExt, 1, SfoFrame)
    End Function
    
    Public Function KfaMeanInStance() As Variant
        KfaMeanInStance = MeanVal(KneeFlexExt, 1, SfoFrame)
    End Function
    
    Public Function KfaRangeInStance() As Variant
        KfaRangeInStance = RangeVal(KneeFlexExt, 1, SfoFrame)
    End Function
    
    Public Function KfaMinInIpsiStance() As Variant
        KfaMinInIpsiStance = MinVal(KneeFlexExt, OfoFrame, OfsFrame) ' Ipsilateral single support phase only (contralateral is swinging).
    End Function
    
    Public Function KfaPeakInIpsiStance() As Variant
        KfaPeakInIpsiStance = MaxVal(KneeFlexExt, OfoFrame, OfsFrame) ' Ipsilateral single support phase only (contralateral is swinging).
    End Function
    
    Public Function KfaMeanInIpsiStance() As Variant
        KfaMeanInIpsiStance = MeanVal(KneeFlexExt, OfoFrame, OfsFrame) ' Ipsilateral single support phase only (contralateral is swinging).
    End Function
    
    Public Function KfaRangeInIpsiStance() As Variant
        KfaRangeInIpsiStance = RangeVal(KneeFlexExt, OfoFrame, OfsFrame) ' Ipsilateral single support phase only (contralateral is swinging).
    End Function
    
    Public Function KfaMinInSwing() As Variant
        KfaMinInSwing = MinVal(KneeFlexExt, SfoFrame, 51)
    End Function
    
    Public Function KfaPeakInSwing() As Variant
        KfaPeakInSwing = MaxVal(KneeFlexExt, SfoFrame, 51)
    End Function
    
    Public Function KfaMeanInSwing() As Variant
        KfaMeanInSwing = MeanVal(KneeFlexExt, SfoFrame, 51)
    End Function
    
    Public Function KfaRangeInSwing() As Variant
        KfaRangeInSwing = RangeVal(KneeFlexExt, SfoFrame, 51)
    End Function
    
    Public Function KfaTimePctToPeak() As Variant
        KfaTimePctToPeak = PctOfCycleAtMax(KneeFlexExt)
    End Function
    
    Public Function KfaSwingTimePctToPeak() As Variant
        On Error Resume Next
            KfaSwingTimePctToPeak = (PctOfCycleAtMax(KneeFlexExt, SfoFrame, 51) - SfoPct) / (1 - SfoPct)
            If Err Then KfaSwingTimePctToPeak = vbNullString
        On Error GoTo 0
    End Function
    
    
    And here's a procedure where I use CallByName:

    Code:
    
    Private Sub CalcAndLoadNormGaitParams(oParamsCalc As clsParamsCalc, NormsWbk As Object, iRowOffset As Long, GcdFileSideInfo As GcdFileSideType)
        Dim wsh As Object
        Dim i As Long
        Dim oParamsRowColSlot As New clsParamsRowColSlot
        Dim sFn As String
        Dim vVal As Variant
        Dim sCol As String
        Dim iCol As Long
        '
        Set wsh = NormsWbk.Worksheets("NormalSubjectData")
        '
        For i = 1 To oParamsRowColSlot.Count
            If oParamsRowColSlot.TypicalParam(i) Then   ' This knocks out the spatiotemporal and indexes stuff.
                sFn = oParamsRowColSlot.Fn(i)
                sCol = oParamsRowColSlot.NormColStr(i)
                If sFn <> vbNullString And sCol <> vbNullString Then
                    vVal = CallByName(oParamsCalc, sFn, VbMethod)
                    iCol = ColNumberFromLetter(sCol)
                    wsh.Cells(iRowOffset, iCol) = vVal
                End If
            End If
        Next i
    End Sub
    
    
    Best Of Luck,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  9. #9

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Elroy View Post
    gyhu,

    If I had many BAS modules that I wanted to wrap into an ActiveX DLL, I'd possibly just create another class (CLS) that served as stubs for calling into those BAS procedures. That would seem to solve the problem. Also, I'm not sure what you'd be doing with AddressOf, but it can't be used when calling into an ActiveX DLL anyway (BAS module or not). However, if you're doing subclassing, callbacks, or hooks in your ActiveX DLL, you could still build a stub procedure in a CLS module that called the procedure in the BAS module that used the AddressOf. Again, if you're willing to use a CLS module as a wrapper for your BAS module procedures, there doesn't seem to be any problem.

    Personally, I've found CallByName to be particularly useful in certain situations. This particular example doesn't involve an ActiveX DLL, but the following is a small snippet out of a class I have named clsParamsCalc. These are what we call gait (walking) parameters. For instance, the maximum amount you bend your knee when you walk. (That would be KfaPeak. [knee flexion angle peak]). There are 100s of these things.

    Code:
    
    
    Public Function KfaMin() As Variant
        KfaMin = MinVal(KneeFlexExt)
    End Function
    
    Public Function KfaPeak() As Variant
        KfaPeak = MaxVal(KneeFlexExt)
    End Function
    
    Public Function KfaMean() As Variant
        KfaMean = MeanVal(KneeFlexExt)
    End Function
    
    Public Function KfaRange() As Variant
        KfaRange = RangeVal(KneeFlexExt)
    End Function
    
    Public Function KfaAtIc() As Variant
        KfaAtIc = FrameVal(KneeFlexExt, 1)
    End Function
    
    Public Function KfaLoading() As Variant
        ' Looks from frame 1 to half way to Opposite Foot Strike.
        KfaLoading = MaxVal(KneeFlexExt, 1, FrameFromPct(OfsPct / 2))
    End Function
    
    Public Function KfaMinInStance() As Variant
        KfaMinInStance = MinVal(KneeFlexExt, 1, SfoFrame)
    End Function
    
    Public Function KfaPeakInStance() As Variant
        KfaPeakInStance = MaxVal(KneeFlexExt, 1, SfoFrame)
    End Function
    
    Public Function KfaMeanInStance() As Variant
        KfaMeanInStance = MeanVal(KneeFlexExt, 1, SfoFrame)
    End Function
    
    Public Function KfaRangeInStance() As Variant
        KfaRangeInStance = RangeVal(KneeFlexExt, 1, SfoFrame)
    End Function
    
    Public Function KfaMinInIpsiStance() As Variant
        KfaMinInIpsiStance = MinVal(KneeFlexExt, OfoFrame, OfsFrame) ' Ipsilateral single support phase only (contralateral is swinging).
    End Function
    
    Public Function KfaPeakInIpsiStance() As Variant
        KfaPeakInIpsiStance = MaxVal(KneeFlexExt, OfoFrame, OfsFrame) ' Ipsilateral single support phase only (contralateral is swinging).
    End Function
    
    Public Function KfaMeanInIpsiStance() As Variant
        KfaMeanInIpsiStance = MeanVal(KneeFlexExt, OfoFrame, OfsFrame) ' Ipsilateral single support phase only (contralateral is swinging).
    End Function
    
    Public Function KfaRangeInIpsiStance() As Variant
        KfaRangeInIpsiStance = RangeVal(KneeFlexExt, OfoFrame, OfsFrame) ' Ipsilateral single support phase only (contralateral is swinging).
    End Function
    
    Public Function KfaMinInSwing() As Variant
        KfaMinInSwing = MinVal(KneeFlexExt, SfoFrame, 51)
    End Function
    
    Public Function KfaPeakInSwing() As Variant
        KfaPeakInSwing = MaxVal(KneeFlexExt, SfoFrame, 51)
    End Function
    
    Public Function KfaMeanInSwing() As Variant
        KfaMeanInSwing = MeanVal(KneeFlexExt, SfoFrame, 51)
    End Function
    
    Public Function KfaRangeInSwing() As Variant
        KfaRangeInSwing = RangeVal(KneeFlexExt, SfoFrame, 51)
    End Function
    
    Public Function KfaTimePctToPeak() As Variant
        KfaTimePctToPeak = PctOfCycleAtMax(KneeFlexExt)
    End Function
    
    Public Function KfaSwingTimePctToPeak() As Variant
        On Error Resume Next
            KfaSwingTimePctToPeak = (PctOfCycleAtMax(KneeFlexExt, SfoFrame, 51) - SfoPct) / (1 - SfoPct)
            If Err Then KfaSwingTimePctToPeak = vbNullString
        On Error GoTo 0
    End Function
    
    
    And here's a procedure where I use CallByName:

    Code:
    
    Private Sub CalcAndLoadNormGaitParams(oParamsCalc As clsParamsCalc, NormsWbk As Object, iRowOffset As Long, GcdFileSideInfo As GcdFileSideType)
        Dim wsh As Object
        Dim i As Long
        Dim oParamsRowColSlot As New clsParamsRowColSlot
        Dim sFn As String
        Dim vVal As Variant
        Dim sCol As String
        Dim iCol As Long
        '
        Set wsh = NormsWbk.Worksheets("NormalSubjectData")
        '
        For i = 1 To oParamsRowColSlot.Count
            If oParamsRowColSlot.TypicalParam(i) Then   ' This knocks out the spatiotemporal and indexes stuff.
                sFn = oParamsRowColSlot.Fn(i)
                sCol = oParamsRowColSlot.NormColStr(i)
                If sFn <> vbNullString And sCol <> vbNullString Then
                    vVal = CallByName(oParamsCalc, sFn, VbMethod)
                    iCol = ColNumberFromLetter(sCol)
                    wsh.Cells(iRowOffset, iCol) = vVal
                End If
            End If
        Next i
    End Sub
    
    
    Best Of Luck,
    Elroy
    Hi Elroy,

    Thank you for your example. Actually, there is a class exist. For now, I just want to write a "interface" to load all functions or subs in module.

    Best Regards,

    Sniperhgy

  10. #10

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by gyhu View Post
    Ok, I'll take a shot on it then reply. Thank you.
    Hi LaVolpe,

    I took a shot on your method, but it seems can't work properly. When I tried to create the DLL, the IDE raised error message : Sub or Function is not defined.

    Best Regards,

    Sniperhgy

  11. #11
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: How to use CallByName in a Class to call methods or functions in modules?

    What method did I suggest? To be honest sounds like you may have a design flaw and don't want to rewrite/reorganize? No insult intended.

    There are many of us that can help solve the problem, but we need to see some sample code and details of what is expected and what doesn't work.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  12. #12

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by LaVolpe View Post
    What method did I suggest? To be honest sounds like you may have a design flaw and don't want to rewrite/reorganize? No insult intended.

    There are many of us that can help solve the problem, but we need to see some sample code and details of what is expected and what doesn't work.
    Your suggestion : Move subs and functions to CLASS. After do it, IDE can't find the define of subs or functions.

    Could you please write a demo: There are a lot of functions and subs, and only one function caller had been exported. Then the users can use obj.Caller("The name of the function or sub", parameters) to execute all the functions or subs?

    Thank you.

  13. #13
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: How to use CallByName in a Class to call methods or functions in modules?

    There are a few ways to do this, but one size does not fit all situations.

    1. Create "stubs" as mentioned. For each module function, you create a class function that calls the module function
    -- obviously the class needs to be public so it can be called from outside the DLL
    2. Move needed functions into a class. Make the class public to the user so they can instantiate it an make calls to it
    -- to use this within the DLL, you would create a public declaration for the class in the module and use that within the DLL
    3. Move needed functions into a class. Make the class instance global and user doesn't need to instantiate the class to make calls to it
    -- to use this within the DLL, you would create a public declaration for the class in the module and use that within the DLL

    As a side note. I can't see how a generic CallByName method helps much in the long run. This requires you (or the user) to know in advance the function names, required parameters, and whether method is function/sub/property. You also lose any intelli-sense. I agree with Elroy that CallByName can have its use, but I feel that it is not user-friendly if the function is exposed to potential users. You'd almost have to provide documentation of every function that could be called by it just so users would know what needs to be passed (function name, number of parameters, vartypes of parameters, etc)
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  14. #14

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by LaVolpe View Post
    There are a few ways to do this, but one size does not fit all situations.

    1. Create "stubs" as mentioned. For each module function, you create a class function that calls the module function
    -- obviously the class needs to be public so it can be called from outside the DLL
    2. Move needed functions into a class. Make the class public to the user so they can instantiate it an make calls to it
    -- to use this within the DLL, you would create a public declaration for the class in the module and use that within the DLL
    3. Move needed functions into a class. Make the class instance global and user doesn't need to instantiate the class to make calls to it
    -- to use this within the DLL, you would create a public declaration for the class in the module and use that within the DLL

    As a side note. I can't see how a generic CallByName method helps much in the long run. This requires you (or the user) to know in advance the function names, required parameters, and whether method is function/sub/property. You also lose any intelli-sense. I agree with Elroy that CallByName can have its use, but I feel that it is not user-friendly if the function is exposed to potential users. You'd almost have to provide documentation of every function that could be called by it just so users would know what needs to be passed (function name, number of parameters, vartypes of parameters, etc)
    It seems my imagination is not a good idea. Thank you.

  15. #15
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: How to use CallByName in a Class to call methods or functions in modules?

    gyhu,

    Also, from your post #10, I'm worried that you don't fully understand how to use a class (CLS) module. As opposed to a BAS module, you must instantiate a CLS module before you can use it. And then, once it's instantiated and has an object variable to reference it, you'd use that object variable as a preface for calling any of the procedures (functions, subs, properties) within it. For instance, in the code above that I supplied, you see the line:

    Dim oParamsRowColSlot As New clsParamsRowColSlot

    That's creating the object variable oParamsRowColSlot from the class clsParamsRowColSlot. Furthermore, the New keyword is telling it to auto-instantiate whenever I start using it. (Optionally, I could have explicitly instantiated it.)

    And then, the following statement uses this object/class:

    oParamsRowColSlot.TypicalParam(i)

    You see the object variable oParamsRowColSlot as a preface (with . between) the TypicalParam function. If the TypicalParam function was in a BAS module, I wouldn't need that preface.

    This is the way CLS modules work.

    Good Luck,
    Elroy

    EDIT1: Now, with CallByName, you still need an instantiated object variable. However, you get to use a string for your function name, rather than having it explicitly specified.
    Last edited by Elroy; Mar 31st, 2018 at 09:44 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  16. #16
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,064

    Re: How to use CallByName in a Class to call methods or functions in modules?

    I think the OP is confused. Functions in a bas module of a DLL (or OCX) can't be called from the client program.
    They are only callable in the scope of the DLL program.

    One straightforward way to make them available for client programs is to add a new Class module to the DLL, make its instancing property to Global Multiuse, and then mirror each function:

    In the Global Multiuse class:

    Code:
    Public Function MyFunction(nParameter as Variant) as Variant
        MyFunction = MyBasModule.MyFunction(nParameter)
    End Function
    You'll need to do this for each function.
    If you have a lot of functions, then you have work to do.

    PS: no CallByName is needed.

  17. #17

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Elroy View Post
    gyhu,

    Also, from your post #10, I'm worried that you don't fully understand how to use a class (CLS) module. As opposed to a BAS module, you must instantiate a CLS module before you can use it. And then, once it's instantiated and has an object variable to reference it, you'd use that object variable as a preface for calling any of the procedures (functions, subs, properties) within it. For instance, in the code above that I supplied, you see the line:

    Dim oParamsRowColSlot As New clsParamsRowColSlot

    That's creating the object variable oParamsRowColSlot from the class clsParamsRowColSlot. Furthermore, the New keyword is telling it to auto-instantiate whenever I start using it. (Optionally, I could have explicitly instantiated it.)

    And then, the following statement uses this object/class:

    oParamsRowColSlot.TypicalParam(i)

    You see the object variable oParamsRowColSlot as a preface (with . between) the TypicalParam function. If the TypicalParam function was in a BAS module, I wouldn't need that preface.

    This is the way CLS modules work.

    Good Luck,
    Elroy

    EDIT1: Now, with CallByName, you still need an instantiated object variable. However, you get to use a string for your function name, rather than having it explicitly specified.
    Yes, I'm a new comer in VB6.0, and there are a lot of things not clear for now. Thank you for your detailed explanation.

  18. #18

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Eduardo- View Post
    I think the OP is confused. Functions in a bas module of a DLL (or OCX) can't be called from the client program.
    They are only callable in the scope of the DLL program.

    One straightforward way to make them available for client programs is to add a new Class module to the DLL, make its instancing property to Global Multiuse, and then mirror each function:

    In the Global Multiuse class:

    Code:
    Public Function MyFunction(nParameter as Variant) as Variant
        MyFunction = MyBasModule.MyFunction(nParameter)
    End Function
    You'll need to do this for each function.
    If you have a lot of functions, then you have work to do.

    PS: no CallByName is needed.
    Hi Eduardo-,

    Thank you for your reply. I know that "the functions or subs in module only can be called from the class". There are four subs in the module, I wrote four callers in the class. So if there are 100 functions or subs in module, I'll write 100 callers in class. That's why I want to find out a way, only write an universal caller in class, then it can call all the functions or subs in the module.

    Best Regards,

    Sniperhgy

  19. #19
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Let's say you have two classes and a module, air-code follows

    The module..... your project would start with Sub Main()
    Code:
    Public gFunctions As cFunctions
    Private Sub Main()
        Set gFunctions =New cFunctions
    End Sub
    Class: named cFunctions that is not exposed to users, private use only
    Code:
    Public Function TestA(... params) As WhatEver
       do stuff
    End Function
    Public Function TestB(... params) As WhatEver
       do stuff
    End Function
    Class: named DLLFunctions which is exposed to the user, public use
    Code:
    Function CallByNameEx(FunctionName As String, CallType As vbCallType, ParamArray Args() As Variant) As Variant
     ' note: target function parameters should be ByVal else ensure correct VarTypes passed to Args
        Select Case UBound(Args)
        Case -1: CallByNameEx = CallByName(gFunctions, FunctionName, CallType )
        Case 0: CallByNameEx = CallByName(gFunctions, FunctionName, CallType , Args(0))
        Case 1: CallByNameEx = CallByName(gFunctions, FunctionName, CallType , Args(0), Args(1))
        Case 2: CallByNameEx = CallByName(gFunctions, FunctionName, CallType , Args(0), Args(1), Args(2))
        ' etc
        End Select
    End Function
    Within your DLL, you won't have "module functions" to call, that's why you have the global gFunctions. You would simply call gFunctions.FunctionName(params) instead.

    The above is proof of concept. Obviously this can get more complex if any functions return objects that require the return function value to be used with the keyword SET.

    Reason why we are having a separate line per parameter count is that you can't pass a paramarray as a paramarray. There is a codebank submission that attempts to do this and I'll leave it up to you to locate that submission and apply it if interested.
    Last edited by LaVolpe; Mar 31st, 2018 at 10:08 AM. Reason: forgot to add keyword: New
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  20. #20
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,064

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by gyhu View Post
    Hi Eduardo-,

    Thank you for your reply. I know that "the functions or subs in module only can be called from the class". There are four subs in the module, I wrote four callers in the class. So if there are 100 functions or subs in module, I'll write 100 callers in class. That's why I want to find out a way, only write an universal caller in class, then it can call all the functions or subs in the module.

    Best Regards,

    Sniperhgy
    AFAIK there is no way.

    And what's the problem writing 100 Functions interfaces? Too much work?

    If you want to implement your own CallByName is a bas module, you could, but still you would have to hardwrite it for all and every function to be handled.

    Code:
    Public Function MyCallByName(FuncName As String, ParamArray mParameters()) As Variant
        Select Case FuncName
            Case "MyFunct1"
                MyCallByName = MyFunct1(mParameters(0))
            Case "MyFunct2"
                MyCallByName = MyFunct2(mParameters(0), mParameters(1))
            Case...
        End Select
    End Function

  21. #21

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by LaVolpe View Post
    Let's say you have two classes and a module, air-code follows

    The module..... your project would start with Sub Main()
    Code:
    Public gFunctions As cFunctions
    Private Sub Main()
        Set gFunctions =New cFunctions
    End Sub
    Class: named cFunctions that is not exposed to users, private use only
    Code:
    Public Function TestA(... params) As WhatEver
       do stuff
    End Function
    Public Function TestB(... params) As WhatEver
       do stuff
    End Function
    Class: named DLLFunctions which is exposed to the user, public use
    Code:
    Function CallByNameEx(FunctionName As String, CallType As vbCallType, ParamArray Args() As Variant) As Variant
     ' note: target function parameters should be ByVal else ensure correct VarTypes passed to Args
        Select Case UBound(Args)
        Case -1: CallByNameEx = CallByName(gFunctions, FunctionName, CallType )
        Case 0: CallByNameEx = CallByName(gFunctions, FunctionName, CallType , Args(0))
        Case 1: CallByNameEx = CallByName(gFunctions, FunctionName, CallType , Args(0), Args(1))
        Case 2: CallByNameEx = CallByName(gFunctions, FunctionName, CallType , Args(0), Args(1), Args(2))
        ' etc
        End Select
    End Function
    Within your DLL, you won't have "module functions" to call, that's why you have the global gFunctions. You would simply call gFunctions.FunctionName(params) instead.

    The above is proof of concept. Obviously this can get more complex if any functions return objects that require the return function value to be used with the keyword SET.

    Reason why we are having a separate line per parameter count is that you can't pass a paramarray as a paramarray. There is a codebank submission that attempts to do this and I'll leave it up to you to locate that submission and apply it if interested.
    Thank you for your code.

  22. #22

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Eduardo- View Post
    AFAIK there is no way.

    And what's the problem writing 100 Functions interfaces? Too much work?

    If you want to implement your own CallByName is a bas module, you could, but still you would have to hardwrite it for all and every function to be handled.

    Code:
    Public Function MyCallByName(FuncName As String, ParamArray mParameters()) As Variant
        Select Case FuncName
            Case "MyFunct1"
                MyCallByName = MyFunct1(mParameters(0))
            Case "MyFunct2"
                MyCallByName = MyFunct2(mParameters(0), mParameters(1))
            Case...
        End Select
    End Function
    Thank you for your code.

  23. #23
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by gyhu View Post
    Yes, I'm a new comer in VB6.0
    gyhu,

    I'd seriously consider just pulling it all into a single (standard) VBP project, and forget about any DLLs. It seems you have the source code to everything, so I don't see the problem there. Creating DLLs is a rather advanced area of VB6, and not recommended for a newcomer.

    Just a thought,
    Elroy

    EDIT1: And CallByName is also a bit advanced. Although, if everything is in a single standard VBP project, it's not too bad.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  24. #24
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Eduardo- View Post
    AFAIK there is no way.

    And what's the problem writing 100 Functions interfaces? Too much work?
    I wonder why no one is insisting, that the OP solves this as LaVolpe suggested already in:
    - post #13 -> Point 2

    That's the obvious thing to do (the only "work" being, to copy the entire content (as is)
    of the current *.bas-Module into a (Public) Class-Module...

    Olaf

  25. #25
    Junior Member
    Join Date
    Oct 2013
    Posts
    30

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Hi gyhu,

    May I ask if you are familiar with using CallByName in a "normal" procedure? Not in a class?

    Lisa

  26. #26
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,064

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Schmidt View Post
    I wonder why no one is insisting, that the OP solves this as LaVolpe suggested already in:
    - post #13 -> Point 2

    That's the obvious thing to do (the only "work" being, to copy the entire content (as is)
    of the current *.bas-Module into a (Public) Class-Module...

    Olaf
    The problem with that Olaf is that the functions won't be available anymore in the DLL project.

    Since the OP posted:

    Quote Originally Posted by gyhu View Post
    Your suggestion : Move subs and functions to CLASS. After do it, IDE can't find the define of subs or functions.
    I guess he is calling at least some of them from the DLL project (from other modules).

    But it is just a guess, because as LaVolpe said the OP wasn't very clear about his project.

  27. #27
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Eduardo- View Post
    The problem with that Olaf is that the functions won't be available anymore in the DLL project.
    That's not quite correct. By declaring a public class instance of the class that contains the functions, the functions can be called from that public class instance anywhere within the DLL project.

    However, this doesn't address any functions that may be using AddressOf; however, that can be addressed also.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  28. #28
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,064

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by LaVolpe View Post
    That's not quite correct. By declaring a public class instance of the class that contains the functions, the functions can be called from that public class instance anywhere within the DLL project.

    However, this doesn't address any functions that may be using AddressOf; however, that can be addressed also.
    Watch at the sample project LaVolpe.
    Attached Files Attached Files

  29. #29
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Eduardo- View Post
    Watch at the sample project LaVolpe.
    Maybe some confusion... that is not what I was suggesting, not quite.

    1. Create a class called MyDLLFunctions. This class would replace the module functions. This class should have multiuse instancing
    2. Create a module and declare a public variable: gFunctions As MyDLLFunctions
    3. In that module, create Private Sub Main() and add this to it: Set gFunctions = New MyDLLFunctions
    4. Make the project's startup Sub Main(). This way, gFunctions is set each time DLL is first initialized.

    Now the user can call functions from the class and so can the project via the gFunctions variable. Of course, we don't actually need the public gFunctions variable. We could just create a new class instance each time we wanted to use any of its functions.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  30. #30
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,064

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by LaVolpe View Post
    Maybe some confusion... that is not what I was suggesting, not quite.

    1. Create a class called MyDLLFunctions. This class would replace the module functions. This class should have multiuse instancing
    2. Create a module and declare a public variable: gFunctions As MyDLLFunctions
    3. In that module, create Private Sub Main() and add this to it: Set gFunctions = New MyDLLFunctions
    4. Make the project's startup Sub Main(). This way, gFunctions is set each time DLL is first initialized.

    Now the user can call functions from the class and so can the project via the gFunctions variable. Of course, we don't actually need the public gFunctions variable. We could just create a new class instance each time we wanted to use any of its functions.
    It require to add gFunctions. before any function call from within the DLL. (and to instantiate the class from outside)

    Yes, it is an alternative of course.

  31. #31
    Junior Member
    Join Date
    Oct 2013
    Posts
    30

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Hi gyhu,

    May I ask if you are familiar with using CallByName in a "normal" procedure? Not in a class?

    Lisa

  32. #32
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: How to use CallByName in a Class to call methods or functions in modules?

    You can edit a class module to have Attribute VB_PredeclaredId = True which gives you a gobal predeclared instance with the same name as the class. This is the default for a Form module, which is how you get your "free" Form instances in the first place.

  33. #33
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,064

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by dilettante View Post
    You can edit a class module to have Attribute VB_PredeclaredId = True which gives you a gobal predeclared instance with the same name as the class. This is the default for a Form module, which is how you get your "free" Form instances in the first place.
    Or declaring it As New should do more or less the same in this case.

  34. #34

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Elroy View Post
    gyhu,

    I'd seriously consider just pulling it all into a single (standard) VBP project, and forget about any DLLs. It seems you have the source code to everything, so I don't see the problem there. Creating DLLs is a rather advanced area of VB6, and not recommended for a newcomer.

    Just a thought,
    Elroy

    EDIT1: And CallByName is also a bit advanced. Although, if everything is in a single standard VBP project, it's not too bad.
    Hi Elroy,

    I have to create DLL, because excel can use import DLL, but can't import EXE.

    Best Regards,

    Sniperhgy

  35. #35

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Schmidt View Post
    I wonder why no one is insisting, that the OP solves this as LaVolpe suggested already in:
    - post #13 -> Point 2

    That's the obvious thing to do (the only "work" being, to copy the entire content (as is)
    of the current *.bas-Module into a (Public) Class-Module...

    Olaf
    Yes, post #13 is very useful.

  36. #36

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by lisagreen View Post
    Hi gyhu,

    May I ask if you are familiar with using CallByName in a "normal" procedure? Not in a class?

    Lisa
    Hi lisagreen,

    I'm not familiar with using CallByName. Only now Application.Run in VBA can do what I want.

    Best Regards,

    Sniperhgy

  37. #37

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by dilettante View Post
    You can edit a class module to have Attribute VB_PredeclaredId = True which gives you a gobal predeclared instance with the same name as the class. This is the default for a Form module, which is how you get your "free" Form instances in the first place.
    Ok, I'll take a shot, thank you.

  38. #38

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by LaVolpe View Post
    Maybe some confusion... that is not what I was suggesting, not quite.

    1. Create a class called MyDLLFunctions. This class would replace the module functions. This class should have multiuse instancing
    2. Create a module and declare a public variable: gFunctions As MyDLLFunctions
    3. In that module, create Private Sub Main() and add this to it: Set gFunctions = New MyDLLFunctions
    4. Make the project's startup Sub Main(). This way, gFunctions is set each time DLL is first initialized.

    Now the user can call functions from the class and so can the project via the gFunctions variable. Of course, we don't actually need the public gFunctions variable. We could just create a new class instance each time we wanted to use any of its functions.
    Hi LaVolpe,

    I followed your suggestion, tried to create one demo, I found that if there is no parameter, then CallByName can be executed successfully. But if I tried to pass one parameter to it, then the error message "mistype" raised. Could you please help to check it out?

    In the attachment, there are two folders:
    1) ExcelUtility : The DLL file.
    2) TestDLL : The tester for 1). Please open TestDLL.vbg, then you can do debug on it.

    Thank you and Best Regards,

    Sniperhgy
    Attached Files Attached Files
    Last edited by gyhu; Apr 1st, 2018 at 09:28 AM.

  39. #39
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by gyhu View Post
    I have to create DLL, because excel can use import DLL, but can't import EXE.
    gyhu,

    If you have the VB6 source code, VBA code is, on most ways, identical to VB6 code. Building forms is a bit different, but you haven't said anything about user interfaces in this code you're trying to make into a DLL. If there are no user interfaces (i.e., forms), then it should possibly be as simple as a copy-paste into VBA modules.

    Just saying, it seems that would greatly simplify your problems. Then, you could make your calls in VBA code (no prefix) just as you had been making them while testing in VB6. Just copy-paste from VB6 BAS module into Excel "Module" (not "Class Module").

    Good Luck,
    Elroy

    EDIT1: Also, if you do that, it opens the possibility of everything working in 64-bit office as well as 32-bit office. If you have API calls, there are a couple of hoops to jump through to make it work with 64-bit office, but it's not that big a deal. In fact, IMHO, it'd be much easier than what you're trying to do. If there are no API calls, then VB6 code will compile as 64-bit p-code in 64-bit VBA just fine.
    Last edited by Elroy; Apr 1st, 2018 at 08:59 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  40. #40

    Thread Starter
    Lively Member
    Join Date
    Mar 2018
    Posts
    64

    Re: How to use CallByName in a Class to call methods or functions in modules?

    Quote Originally Posted by Elroy View Post
    gyhu,

    If you have the VB6 source code, VBA code is, on most ways, identical to VB6 code. Building forms is a bit different, but you haven't said anything about user interfaces in this code you're trying to make into a DLL. If there are no user interfaces (i.e., forms), then it should possibly be as simple as a copy-paste into VBA modules.

    Just saying, it seems that would greatly simplify your problems. Then, you could make your calls in VBA code (no prefix) just as you had been making them while testing in VB6. Just copy-paste from VB6 BAS module into Excel "Module" (not "Class Module").

    Good Luck,
    Elroy

    EDIT1: Also, if you do that, it opens the possibility of everything working in 64-bit office as well as 32-bit office. If you have API calls, there are a couple of hoops to jump through to make it work with 64-bit office, but it's not that big a deal. In fact, IMHO, it'd be much easier than what you're trying to do. If there are no API calls, then VB6 code will compile as 64-bit p-code in 64-bit VBA just fine.
    Hi Elroy,

    Could you please help to check the attachment above your last reply? Thank you.

    Best Regards,

    Sniperhgy

Page 1 of 2 12 LastLast

Posting Permissions

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



Click Here to Expand Forum to Full Width