Add-In - to call (run) host application's procedure
Is it possible?
I have in Add-In the universal code Export function (for backup purposes). It is suitable for most projects, which are used this Add-In. However some projects (this Add-In project it self, particularly) has their own more sofisticated backup functional.
The goal is to detect existing in the specialy named module and the specialy named procedure in it. If it exist, so use it. If no - use common Export procedure, stored in Add-In.
Re: Add-In - to call (run) host application's procedure
Not sure if i understood you correctly, but i think "CallByName" is what might get you running....
Last edited by Zvoni; Tomorrow at 31:69 PM.
----------------------------------------------------------------------------------------
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------------------
People call me crazy because i'm jumping out of perfectly fine airplanes.
---------------------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad
Re: Add-In - to call (run) host application's procedure
Zvoni, hello.
Forgive for my English :(
I try to rephrase...
My add-in is developed to connect to both VB6 and VBA IDEs. So, in any project (host), being developed under VB6, or Access, or Excel, user can ask this add-in to simply backup this project to, say: "%CurDir%\_BackUp\TimeStamp\*.*", by pressing command button on add-in's control bar with the following calling of "sb_AddIn_BackUp", that is stored in compiled add-in. In case of VBA the modules are exported to tmp-place and then copied to backup-place. In case of VB6 the modules simply copied to backup-place.
However, several of my projects has their own, individual backup procedures (with extended specific functionality). In this case I want of add-in do not call its mentioned backup procedure "sb_AddIn_BackUp", but tried first of all to search for the procedure "sb_App_BackUp" in the module "m_App_BackUp" of maintained host, and then tried call it, instead of its own "sb_AddIn_BackUp".
Re: "CallByName"
Thank you for advice, but I I already thought this way.
Firstly, I never used it in my life and, accordingly, I do not know the nuances of its behavior.
And, the second, to be honest, I look a little obliquely at it, as a very surrogate and palliative way.
I very much hoped that there might be a more natural way to call. Maybe through the API ... maybe by raising some event in the host ... maybe through some form of callback ... maybe by AddressOf ... maybe somehow ... I don't know :(
.
Re: Add-In - to call (run) host application's procedure
OK. I tried CallByName(object, procname, calltype,[args()])
However, I can't give to it the right object it need as the first parameter,
cause after the Add-In is loaded in host,
all objects, that I have on the hands, are:
1. Application (As VBIDE.VBE) - the reference on host application (IDE) and
2. AddInInst (As VBIDE.AddIn) - the reference on Add-In instance in host.
Both are passed by Add-In event: OnConnection(Application, ConnectMode, AddInInst, Custom)
I unsuccessfully tried with various syntax of: GetObject([pathname] [, class])
and I have no idea now
- how to create the correct object, that will conform to the CallByName :(
Code:
' this is an Add-In's procedure that try to call procedure in host
' mi__HostVBE - local instance of host Application, passed with OnConnection
' sp_CallByName_F - procedure in host
Public Sub sp_CBN() ' CallByName
Dim vpr As VBIDE.VBProject
Dim vcm As VBIDE.VBComponent
Dim obj As Object
Dim sPcd$
Set vpr = mi__HostVBE.ActiveVBProject
For Each vcm In vpr.VBComponents
With vcm
Select Case .Name
Case "Form1"
Stop
sPcd = "sp_CallByName_F"
If fn_PcdExist(vcm, sPcd) Then ' If procedure exists in this module
Set obj = GetObject("???", "???")
Call CallByName(obj, sPcd, VbMethod)
End If
Case Else
Debug.Print .Name
End Select
End With
Next
End Sub
Another alternative way, that I see, is to put call string in 'Imrnediate Window' in host and try to emulate keystroke 'Enter'.
.
Re: Add-In - to call (run) host application's procedure
Originally Posted by asbo
However, several of my projects has their own, individual backup procedures (with extended specific functionality). In this case I want of add-in do not call its mentioned backup procedure "sb_AddIn_BackUp", but tried first of all to search for the procedure "sb_App_BackUp" in the module "m_App_BackUp" of maintained host, and then tried call it, instead of its own "sb_AddIn_BackUp".
But for the Add-In, the project is source code, it is text.
How are you going to call it? The program is not running.
It would have to run as vbScript, interpreted...
(...If I am understanding correctly what you want to do.)
Re: Add-In - to call (run) host application's procedure
Originally Posted by Eduardo-
But for the Add-In, the project is source code, it is text ...
Yeah. I'm clearly understand it.
And this is the reason why in the first sentence of the start post I not asked "How?", but asked "Is it possible?" ...
Originally Posted by Eduardo-
It would have to run as vbScript, interpreted...
However... however it is an idea. It is the another way.
Let Add-In can't run anything directly in host project, but the host can say to Add-In (by any comment line(s) in predefined place of project code): "Get saved vbscript on "Path-Name" and run it!"
Originally Posted by Eduardo-
(...If I am understanding correctly what you want to do.)
I tried to explain everything as much detail as possible.
Sorry for possible misunderstanding :(
.
Re: Add-In - to call (run) host application's procedure
A little bit wrong :)
Not "the program itself has code to backup its own source code", but the developer of this program has it. He use the Add-In for the same purposes - developing. And backup process is the part of developing.
As for me it is very actual for several projects under Access. And now I continue to develope this Add-In under VB6. As I wrote above, it is universal Add-In for VB6 & VBA. However it need more complex backup & synch procedures between VB6 & VBA related code. I develope current version of this Add-In having connected in IDE the previous it's release. But the backup functionality for common cases, implemented in my own Add-In, not satisfy me in its developing :)
Naturally, the need to have such a procedure inside the compiled release does not make sense. Only at the development stage it is needed ...
.
Re: Add-In - to call (run) host application's procedure
Then I think the Add-In should run the "custom backup" program from the developer compiled.
If I understood, the developer should enter in some option of the Add-In the path to the backup program (exe), and the Add-in would run it when it is needed (with Shell, ShellExecute or similar method).
Re: Add-In - to call (run) host application's procedure
Then I think the Add-In should run the "custom backup" program from the developer compiled.
No-no! Not compiled at all!
When I say "to backup", it means here:
to save current state of source code of not-compiled project that is being in developing(!) in current moment.
... the developer should enter in some option of the Add-In ...
And "Yes", and "No" at the same time :)
No - because the developer does not pass explicitly to Add-In any parameters at all.
This is the main concept of my Add-In (up to now, at least) - no setup, no ini files or registry records. This add-on is self-contained and works from box. And I want to keep it that way if I can...
Yes - because the Add-In receives, however, external directives, but in an implicit manner, through the presence of certain attributes in the code it investigated. That is to say - the specially named module(s) and the specially named procedure(s) in it (or any other uniquely interpretable and easy accessible for reading source code element).
---------------------
Now I will try explain the goal once more time :)
1. The common simple case
The suffixes _xls, _mdb and _VB6 are not significant and not used to define type of project.
They are here only for view clarity.
Let, there are three of independent (in their functionality) projects:
In case of VB6-project the "_Bup" folder created at one level up ".." to project folder, cause it has own folder unlike vba-projects, that has no folder, but all of its members are in one-file-container.
2. Rare special, individual case,
when the universal application, intended for both of VB6 & VBA environments,
is developing under VB6.
Here and below "the project" means the union of both VB6- and VBA- branches.
The peculiarity of this project is that both VB6 & VBA branches are identical,
excluding members under ' *** ATTENTION !!! line, i.e. _Class_*.cls & _Dvl_*.vbp
Reaching such identity I got the opportunity to develop any branch of the project - the one that is convenient for me at the moment.
However, the simple backup procedure, implemented in Add-In, is not satisfied me already.
So, I have the special backup procedure intended for this project only and placed in special module "Export.bas". This module will be removed from project when release code will be prepared (this functionality realised in its export procedures too).
Say, I made changes in VB6-branch and called (manually) backup procedure.
The result is:
Code:
Dvl\
_Bup\
mmdd_hhnn_VB6\ ' VB6 is master now
VBA\ ' VBA is slave
_Class_VBA.cls ' *** ATTENTION !!!
_Dvl_VBA.vbp
Form1_VB6.frm
Export_VB6.bas
Module1_VB6.bas
Module2_VB6.bas
Module3_VB6.bas
_Class_VB6.cls ' *** ATTENTION !!!
_Dvl_VB6.vbp
And vice-versa:
Code:
Dvl\
_Bup\
mmdd_hhnn_VBA\ ' VBA is master now
VB6\ ' VB6 is slave
_Class_VB6.cls ' *** ATTENTION !!!
_Dvl_VB6.vbp
Form1_VBA.frm
Export_VBA.bas
Module1_VBA.bas
Module2_VBA.bas
Module3_VBA.bas
_Class_VBA.cls ' *** ATTENTION !!!
_Dvl_VBA.vbp
Both of schemes above illustrated the case, when the slave folder was synchronized with master. If user didn't decide to synch them, then slave branch backuped in full, but not ATTENTION-members only.
---------------------
And what I want of my Add-In?!
Can it find module "Export_*"? Yes, it can.
Can it find export procedure in module "Export_*"? Yes, it can.
Can it run it instead of its own compiled backup routine? No answer :(
Re: Add-In - to call (run) host application's procedure
Hummm, every time I had a question regarding Add-ins I found very few people that knew something or had some experience with Add-Ins.
You can find a couple here in the forum, perhaps.
I have some experience with Add-Ins but I'm not an expert at all.
But my understanding is that what you are trying to do is not possible, at least not in the way you wants to do it.
What, I think it could be possible is:
1) To read the source code from that backup routine (that you already have managed to find).
2) To "copy" that source code and execute it line by line in the Add-In.
3) How? With a VBScript interpreter.
Another possibility of something to test would be to place the backup procedure in a bas module and use AddressOf and the API CallWindowProc with some window hwnd.
I don't have much hopes that these thinks could work, but I would test them.
If you don't know how to test these ideas, please provide sample projects of both: Add-In and host project, where you already managed to find the backup procedure.
Last edited by Eduardo-; Sep 6th, 2018 at 01:31 PM.
Re: Add-In - to call (run) host application's procedure
Eduardo-, dz32,
thank you very much for your support.
I need a some of time now to create and present here the testing source code package of Add-In and several host applications.
Moreover, I succsessfully tested the method from my post #4: "... put call string in 'Imrnediate Window' in host and try to emulate keystroke 'Enter'."
I want to include this solution to testing bundle.
Re: Add-In - to call (run) host application's procedure
So...
Hello all.
As I promised, I prepared the tested bundle at last:
(half a year hasn't passed (c) VSV)
Adi_Bnd.zip
(why I can not get a beautiful picture of attachment like the others?)
It based on MS VB6 Add-In template chassis of '98 conveyor,
and includes:
Code:
\AddIn - source code of
\_MS_Src - original MS chassis
\VB6 - 'asbo_VB6_Dsn' add-in
\VBA - 'asbo_VBA_Dsn' add-in
Both VB6 and VBA projects are identical, excluding:
- d_asbo.dsr (difs are in header fields only, not in code!)
- asbo_VB6_Dsn.vbp
and both are needed to be compiled, of course :)
(however, you can to try them under IDE too)
They, naturally, no need to be compiled, but overwise -
they intended to be in development mode, i.e. - in IDE.
After the specific add-in being compiled, it will appeared in host VBE, under: '> Add-Ins > Add-In Manager ...'
I hope, that it will be in non-auto-loading mode, so it need to be loaded
(by dbl-click on it or set 'Loaded/Unloaded' flag).
After it, the new option will be available at: '> Add-Ins > asbo_VB6_Dsn'
There are four buttons on the form, that appears on this option click -
two original MS buttons 'OK' and 'Cancel' with MS-programmed behavior and
two my buttons:
Fibo by AddIn
add-in calcs Fibo with a low accuracy by its own code
Fibo by Host (if exist)
add-in will try to find in Host project:
- the module, named 'm_Other' and
- the procedure, named 'sx_Fibo', in it,
to make more accurated Fibo calcs with its help.
If the mentioned module or procedure not founded,
add-in calcs Fibo by its own, low-accuracy procedure.
Initially, 'm_Other.sx_Fibo' is presents in Host project,
so, you need to rename (to comment or delete) this procedure or module at all
and save the Host project after it to fully test the behavior above.
As I wrote in post #4, I tricked with the Host's 'Immediate Window'.
Before, I manually copy-pasted 'm_Other.sx_Fibo' and pressed 'Enter'.
Now I do the same, but by more technological way:)
However, I got the new flexibility and extensibility with this approach.
It is possible now to pass some parameters for add-in in comment lines,
to calc Fibo (in add-in) with greater accuracy, for example :)
Of course, instead the example of Fibo calcs this scheme can be used for any other purposes.
But, in general, I do not like this solution,
as palliative and not elegant - to use string description of object instead of object itself.
Re: Add-In - to call (run) host application's procedure
Eduardo-, hello.
Thanks a lot for yor efforts!
I saw your meddage (#15) already, but I decided to not download attachment immediatelly,
but to delay to the moment, when my bundle will be ready to publishing.
Now I downloaded it already - thank you once more!
The common idea is understanable for me.
Several questions, that I have now, are not significant.
But the one only - VBA. I will try to play on it.
And, regardless of VBA, the serious obstacle is present - the necessarily to have an form and user-control.
.
Re: Add-In - to call (run) host application's procedure
Oh! This is a very valuable observation.
Lucky you have another locale :)
And, regardless of locale, your reference to an object by a predefined constant, but not by a name, is a more right approach.
I accept this gratefully and will make corrections to the code.
-----------
Re: your "Add-In_backup_test"
Unfortunately I can't find solution to implement User Control in VBA-based projects.
Moreover, investigating your code I discovered, that VBA VBIDE has no Enum vbext_ControlType
unlike VB6 VBIDE. It seems me, that it is unpossible to use User Controls in VBA :(
Two question I have of your code:
1. Does the following construction
Code:
If (iComp.Type = vbext_ct_VBForm) Or _
(iComp.Type = vbext_ct_UserControl) Or _
(iComp.Type = vbext_ct_VBMDIForm) Then
means that you try to find the User Control in all mentioned objects?
I never used User Controls before, so I don't know - may it be incapsulated not only in form, but in MDI Form or another User Control too?
2. You try to identify control by its right (after dot) part of its .ProgId property: If Right(iCtl.ProgId, 19) = "ctlBackupSourceCode" Then
that I transformed to: If Right$(iCtl.ProgId, Len(sCtlNam)) = sCtlNam Then
However, the .ClassName property is present there and code may be simplified to: If .ClassName = sCtlNam Then
But I'm afraid that your choice of .ProgId instead of .ClassName is a special and deliberate. Would you please, to clarify this point?
.
Re: Add-In - to call (run) host application's procedure
Hello asbo,
Originally Posted by asbo
Re: your "Add-In_backup_test"
Unfortunately I can't find solution to implement User Control in VBA-based projects.
Moreover, investigating your code I discovered, that VBA VBIDE has no Enum vbext_ControlType
unlike VB6 VBIDE. It seems me, that it is unpossible to use User Controls in VBA
I just opened Excel and went to the VBA editor and (as suspected) I don't see any UserControl.
So... there are no UserControls in VBA.
Originally Posted by asbo
Two question I have of your code:
1. Does the following construction
Code:
If (iComp.Type = vbext_ct_VBForm) Or _
(iComp.Type = vbext_ct_UserControl) Or _
(iComp.Type = vbext_ct_VBMDIForm) Then
means that you try to find the User Control in all mentioned objects?
I never used User Controls before, so I don't know - may it be incapsulated not only in form, but in MDI Form or another User Control too?
I used some code of an Add-In that I already had and modified it for making the test program.
It means that the UserControl control instance for the backup could be placed not only in a Form but also in a MDIForm or in any (other) UserControl (of any other type).
But I did that that way only because I had the code already written and I left it as I was.
Originally Posted by asbo
2. You try to identify control by its right (after dot) part of its .ProgId property: If Right(iCtl.ProgId, 19) = "ctlBackupSourceCode" Then
that I transformed to: If Right$(iCtl.ProgId, Len(sCtlNam)) = sCtlNam Then
However, the .ClassName property is present there and code may be simplified to: If .ClassName = sCtlNam Then
But I'm afraid that your choice of .ProgId instead of .ClassName is a special and deliberate. Would you please, to clarify this point?
.
Again, the same: that was made very fast and I used iCtl.ProgId because I found the Control type name in that property used in the code that I already had (of the old Add-in program I was modifying), and because I didn't remember about .ClassName.
I did that in a couple of minutes to test my idea of using an UserControl, and when I saw that it worked I posted it here.
They were not "special and deliberate" but only because I don't remember much about Add-Ins programming and always start by modifying some other Add-In program already working.