Page 1 of 1
A question to COMate experts
Posted: Sun Sep 09, 2018 5:58 pm
by Yuri_D
Hello!
Could you please advise how to read properties from an COMate Enumeration object?
This COMate object doesn't support GetString/Integer etc. methods but in my case, besides the collection itself it returns a number of elements and other useful properties.
Of course I can create two objects with CreateEnumeration() and GetObjectProperty() but it triggers 2x same queries to the DB which is not good
Re: A question to COMate experts
Posted: Mon Sep 10, 2018 5:50 pm
by srod
Yes COMate destroys the temporary object it creates whilst getting hold of the relevant Enum interface pointer in the COMateClass_CreateEnumeration() procedure. You are thus correct in thinking that you would need to create 2 separate objects in your case in order to make use of any additional properties etc.
You can easily modify the above procedure to, say, not destroy the temporary object and instead place it in a separate buffer so that you can make use of it separately. Just make sure you destroy that object when you are done with it using the COMate \Release() method. Alternatively, create a bespoke version of the COMateClass_CreateEnumeration() procedure just for your use.
Re: A question to COMate experts
Posted: Mon Sep 10, 2018 6:16 pm
by Yuri_D
Hello srod,
Thank you for your explanation!
Just checked the COMate code and I think I found the temp object destroyer
Code: Select all
If command$
COMateClass_Release(*tempCOMateObject)
EndIf
but there are too many asterisks for my programming level so I'm not sure how to modify it to return 2x objects and not to spoil anything else

(through a structure?)
Re: A question to COMate experts
Posted: Mon Sep 10, 2018 6:53 pm
by srod
Struggling for time right now to do anything with this. I'll sort something out as soon as I can. In the meantime just use the two separate objects.
Re: A question to COMate experts
Posted: Mon Sep 10, 2018 7:00 pm
by Yuri_D
Thank you in advance!
Re: A question to COMate experts
Posted: Tue Sep 11, 2018 8:34 am
by srod
Hang on a cotton picking minute! COMatePLUS will already do what you are after - doh!
If you invoke the \CreateEnumeration() method with an empty string as a parameter then it will simply return the enumeration object associated with the underlying object!
So taking some code from one of the COMate demo programs, instead of the following :
Code: Select all
;Declare COMate objects.
Define.COMateObject DomObject, NodeObject
;Declare COMateEnum objects.
Define.COMateEnumObject DomENUMObject
DomObject = COMate_CreateObject("MSXML.DOMDocument")
If DomObject
DomObject\Invoke("LoadXml('" + XML$ + "')")
;Begin enumeration.
DomENUMObject = DomObject\CreateEnumeration("SelectNodes('addresses/address')")
If DomENUMObject
etc.
We can use the following instead :
Code: Select all
;Declare COMate objects.
Define.COMateObject DomObject, NodesObject, NodeObject
;Declare COMateEnum objects.
Define.COMateEnumObject DomENUMObject
DomObject = COMate_CreateObject("MSXML.DOMDocument")
If DomObject
DomObject\Invoke("LoadXml('" + XML$ + "')")
;Begin enumeration.
NodesObject = DomObject\GetObjectProperty("SelectNodes('addresses/address')")
If NodesObject
DomENUMObject = NodesObject\CreateEnumeration("")
If DomENUMObject
etc.
This second version gives you access to the original 'NodesObject' and the enumeration object 'DomENUMObject' without any additional (and repeated) object creation (well no more than would be the case under the first snippet above). Tested and works fine with the above demo program.
Wonder why this didn't end up in the COMatePLUS manual?
Re: A question to COMate experts
Posted: Tue Sep 11, 2018 9:45 am
by Yuri_D
Hi srod!
Thank you so much! It works like a charm!)
May I ask you a couple of other questions regarding COMate?
1- "COM Error [1]: The operation completed, but was only partially successful." during enumeration processing (I filter it out but I wonder why it appears)
2 - When I'm using COMate with Excel with one common event callback procedure + objExcel and objWorkbook objects, as soon as I resize the Excel window (from the program, didn't tried manual resize) any attempt to use objWorkbook causes COMate crash but if I disable events before resize, it works. Can it happens because I need to attach events handling to the Workbook as well?
Re: A question to COMate experts
Posted: Tue Sep 11, 2018 6:18 pm
by srod
1. I would need more info.
2. I am not that familiar with the Excel object, but can you post some code for me to look at? Just did some basic tests and it all seemed to work fine.
Re: A question to COMate experts
Posted: Wed Sep 12, 2018 12:04 pm
by Yuri_D
1 - it appears when no more objects in the enumeration left and \GetNextObject() returns zero. I think it shall be silent...
2 - I can't make it working separately.. I don't know why but it stops processing events after workbook is opened and 4 events received
It works normally in my project. I can tell only that everything is forking if I'm operating only with Excel object like
Code: Select all
\objExcel\SetProperty( "WindowState ="+ #xlMaximized)
\objExcel\GetStringProperty( "ActiveWorkbook\Name")
\objExcel\GetIntegerProperty( "ActiveWorkbook\Sheets\Count")
But it doesn't with
Code: Select all
\objExcel\SetProperty( "WindowState ="+ #xlMaximized)
\objWorkbookl\GetStringProperty( "Name")
\objWorkbook\GetIntegerProperty( "Sheets\Count")
Re: A question to COMate experts
Posted: Wed Sep 12, 2018 5:29 pm
by srod
Code: Select all
\objExcel\SetProperty( "WindowState ="+ #xlMaximized)
You cannot combine a string with a numeric constant so there is something wrong there.
I tested using the "WindowState" property of the "Application" object and it resized the window fine and all events seemed to work fine with no crashes.
Re: A question to COMate experts
Posted: Wed Sep 12, 2018 6:47 pm
by Yuri_D
PB casts them automatically so Str( 100) = ""+ 100
The problem is not in the resizing but what happening with objWorkbook after that if events handling is active.
Can you try this please (but it has a different problem I mentioned earlier)
Code: Select all
XIncludeFile "\COMatePLUS.pbi"
;--#xlWindowState
#xlMaximized = -4137
#xlMinimized = -4140
#xlNormal = -4143
objExcel.COMateObject
objWorkbook.COMateObject
Declare ComEventCallback( _object.COMateObject, _sEventName.s, _objUnknowneterCount.i, *_result.VARIANT)
objExcel = COMate_CreateObject( "Excel.Application")
If objExcel
objExcel\SetEventHandler( #COMate_CatchAllEvents, @ComEventCallback(), #COMate_OtherReturn)
objExcel\SetProperty( "Visible = #True")
objWorkbook = objExcel\GetObjectProperty( "Workbooks\Open('C:.............................') = #True")
If objWorkbook
Debug objWorkbook\GetStringProperty( "Name")
Debug objExcel\GetStringProperty( "ActiveWorkbook\Name")
objExcel\SetProperty( "WindowState ="+ #xlMaximized)
Debug objWorkbook\GetStringProperty( "Name") ;<<<< COMate crashes here
Debug objExcel\GetStringProperty( "ActiveWorkbook\Name") ;<<<< this one will work If above is commented
EndIf
Repeat
Until objExcel = 0
EndIf
End
Procedure ComEventCallback( _object.COMateObject, _sEventName.s, _objUnknowneterCount.i, *_result.VARIANT)
Shared objExcel
Debug "Event: < "+ _sEventName +" > Params: "+ _objUnknowneterCount
Select _sEventName
Case "WorkbookBeforeClose"
objExcel\SetEventHandler( #COMate_CatchAllEvents, #Null, #COMate_OtherReturn)
objExcel\Release()
EndSelect
EndProcedure
Re: A question to COMate experts
Posted: Thu Sep 13, 2018 8:26 am
by srod
You have an infinite loop running hogging all the program time! Remove that (stick a message requester in there) and it all runs fine here.
Re: A question to COMate experts
Posted: Thu Sep 13, 2018 3:28 pm
by Yuri_D
Yep... I tried to use Delay() there but it seems it doesn't release CPU and WaitWindowEvent( xx) doesn't work without window :/
With the messagebox it works and has no crashes so I need to look into my code, thank you!
Another question: is it possible to clear the COMate error code after it was processed and what is the bestest way to realise "OnError" for COMate?
Re: A question to COMate experts
Posted: Fri Sep 14, 2018 12:25 am
by Olliv
Hello Stephen,
hope u r fine, and thank you for your presence !
I add some remarks, but it s imho : can be corrected.
@Yuri hello first,
1)
Normally, it seems to work fine. Give details of the argument (milliseconds) of your Delay() invoking. But normally 100 ms is good.
2) WaitWindowEvent() requires a window : all right, and it is not a problem. A window can be invisible by setting its flag during its opening, or by sizing (or resizing) to a null dimension, or by moving to an extraneous position. The first of these 3 ways seems to be the best way.
3) You declare objExcel. All right, but declare it
globalllyAnd, if you do not like global var, what it could be normal sometimes... No reason to sing nake everytime... In this way, you have to insure by inserting a shared directive in
every procedure which uses such a variable, obviously, in your example, in the callback procedure. Actually neither Global, neither Shared : Sure there is a problem.
Also I wish you a good pleasure to use Comate. I used it only once, 9 years ago but appreciate a lot this feature added by SRod.
Re: A question to COMate experts
Posted: Sat Apr 06, 2019 6:25 pm
by Yuri_D
Hello community!
Once again your help wanted, could you please help?
There are few VBA methods which can do a single or batch data manipulation.
Code: Select all
Create(DObject[], async As Boolean)
Delete(DObject[], async As Boolean)
......
I know how to perform single opertations
VBA usage (single):
Code: Select all
Dim user As DObject >>>>>>>>>>>>>>>>>>>>>>> Define.COMateObject objUser
Set user = Api.CreateObject("user") >>>>>>>>>>>> objUser = objAPI\GetObjectProperty( "CreateObject('user')")
user("name") = "Test0" >>>>>>>>>>>>>>>>>>>>>> objUser\SetProperty( "Item('Name')\Value = 'Test0'")
user.Create() >>>>>>>>>>>>>>>>>>>>>>>>>>>>> objUser\Invoke("Create")
but I don't understand how to create an array of objects and to feed it to these methods to perform batch operations
VBA usage (batch):
Code: Select all
Dim users(2) As DObject >>>>>>>>>>>>>>>>>>>>>>>> ???
Set users(0) = dApi.CreateObject("user") >>>>>>>>>>>> ??? = objAPI\GetObjectProperty( "CreateObject('user')")
users(0)("name") = "Test0" >>>>>>>>>>>>>>>>>>>>>> ???\SetProperty( "Item('Name')\Value = 'Test0'")
Set users(1) = dApi.CreateObject("user") >>>>>>>>>>>> ??? = objAPI\GetObjectProperty( "CreateObject('user')")
users(1)("name") = "Test1" >>>>>>>>>>>>>>>>>>>>>> ???\SetProperty( "Item('Name')\Value = 'Test1'")
'call batch method
dApi.Create users, False >>>>>>>>>>>>>>>>>>>>>>>> objAPI\Invoke("Create ????, #False")
I think I shall create a safearray of objects but how to do it - no ideas(
If somebody knows, please explain.