Page 1 of 1

[Solved] How to read enum values ​​through OLE with C++?

Posted: Thu May 01, 2014 2:35 pm
by lostinai
I am doing OpenOffice automation using C++ with OLE Bridge.
But i cannot find, how to read value of UNO enums through OLE.
For example how to get value of com.sun.star.awt.FontSlant.ITALIC?
For structures exist Bridge_GetStruct method - exist something like "Bridge_GetEnumValue" for enums?

Or is somewhere documented what concrete value enum items have?
And is concrete values of enums used in UNO guaranted to not change in future?

Re: How to read enum values ​​through OLE with C++?

Posted: Thu May 01, 2014 3:16 pm
by MrProgrammer
lostinai wrote:But i cannot find, how to read value of UNO enums through OLE.
Enumerate enumeration names
lostinai wrote:And is concrete values of enums used in UNO guaranted to not change in future?
I am not a developer, but I would guess that the set of enumeration values could be expanded. However, one would expect existing members of the set will not be deleted, though they might become deprecated.

If this answered your question please go to your first post use the Edit button and add [Solved] to the start of the title. You can select the green checkmark icon at the same time.

Re: How to read enum values ​​through OLE with C++?

Posted: Thu May 01, 2014 9:28 pm
by lostinai
@MrProgrammer:
Thank you. I tried the approach from your link, but there is some problem, it does not work for me. I correctly created instance of com.sun.star.reflection.TypeDescriptionManager but when i call getByHierarchicalName i am getting NoSuchElementException for any input parameter i tried. I dont understand whats wrong, there are some indicies of bug in OpenOffice internals, but i don't know if its's relevant to my problem. So finaly i downloaded OpenOffice source and simply searched enum definition and i am using hard-boiled numerical values now. Hope it will be Ok. :-)

Re: How to read enum values ​​through OLE with C++?

Posted: Sun May 04, 2014 2:20 pm
by Charlie Young
Playing around with this. I don't find any bug, I think it's how one gets the TypeDescriptionManager that might be the problem.

Getting it via the singleton, I can do this in c++. A c++ automation program will generally have a Reference<XComponentContext> laying around somewhere (though this can be slightly tricky in a c++ add-in function), in the following it's called xComponentContext.

This just writes the names into a Calc CellRange called outRange, assumed to be at least two columns wide and to have enough rows to hold the output. Obviously there are many other things one can do with the names and values.

Code: Select all


		OUString sFullName = OUString::createFromAscii("com.sun.star.awt.FontSlant");
		Any oTDMA = xComponentContext->getValueByName(OUString::createFromAscii("/singletons/com.sun.star.reflection.theTypeDescriptionManager"));
		Reference<XEnumTypeDescription> oTDM; //(oTDMA,UNO_QUERY);
		Reference<XHierarchicalNameAccess> oTDMH(oTDMA,UNO_QUERY);
		if(oTDMH->hasByHierarchicalName(sFullName)) {

			Any EnumNamesA = oTDMH->getByHierarchicalName(sFullName);
			oTDM = Reference<XEnumTypeDescription>(EnumNamesA,UNO_QUERY);
			Sequence<OUString> EnumNames = oTDM->getEnumNames();
			Sequence<long> EnumValues = oTDM->getEnumValues();
			for(i = 0;i < EnumNames.getLength();i++)
			{
				xText = Reference<XTextRange>(outRange->getCellByPosition(0,i),UNO_QUERY);
				xText->setString(EnumNames[i]);
				outRange->getCellByPosition(1,i)->setValue((double) EnumValues[i]);
			}
		}
Getting the EnumValues isn't really necessary of course, since it is always true that EnumValues = i.

I also wondered if there was an alternative to using the TypeDescriptionManager, and there is; we can use CoreReflection.

In Basic, this function returns an array of the Names

Code: Select all

Function getEnumNames(sFullName As String)
	Dim oSM As Object
	Dim oNames
	Dim oFields
	Dim i As Long
	
	oSM = createUnoService("com.sun.star.reflection.CoreReflection")
	
	If oSM.hasByHierarchicalName(sFullName) Then
		oNames = oSM.getByHierarchicalName(sFullName) '.getEnumNames()
		oFields = oNames.getFields()
		Dim eNames(UBound(oFields)) As String
		For i = 0 To UBound(oFields)
			eNames(i) = oFields(i).getName()
		Next i
		getEnumNames = eNames
	Else
		getEnumNames = "Invalid Enum Name."
	End If	
End Function
Since in c++ one will also generally have a ServiceManager handy, we can do (assuming all the appropriate header files are included)

Code: Select all

		OUString sFullName = OUString::createFromAscii("com.sun.star.awt.FontSlant");
				
		Reference< XInterface  > oTDMA = rOfficeServiceManager->createInstance(
    OUString::createFromAscii( "com.sun.star.reflection.CoreReflection" ));
		
		Reference<XIdlClass> oTDM; 
		Reference<XHierarchicalNameAccess> oTDMH(oTDMA,UNO_QUERY);
		if(oTDMH->hasByHierarchicalName(sFullName)) {

			Any EnumNamesA = oTDMH->getByHierarchicalName(sFullName);
			oTDM = Reference<XIdlClass>(EnumNamesA,UNO_QUERY);
			Sequence<Reference<XIdlField>> EnumNames = oTDM->getFields();
			Reference<XIdlMember> xMember;
			for(i = 0;i < EnumNames.getLength();i++)
			{
				xMember = Reference<XIdlMember> (EnumNames[i],UNO_QUERY);
				xText = Reference<XTextRange>(outRange->getCellByPosition(0, i),UNO_QUERY);
				xText->setString(xMember->getName());
				outRange->getCellByPosition(1, i)->setValue((double) i);
			}
		}
I also am playing with a c++ class to get this stuff, but I'll present it later, if I haven't decided it's too baroque.

Re: How to read enum values ​​through OLE with C++?

Posted: Mon May 05, 2014 1:08 pm
by lostinai
@Charlie Young: Nice reply. But I am crazy man. I am trying to automate OpenOffice from external C++ application through OLE Bridge. I have no comfort of headers from OpenOffice SDK - i am not using UNO directly. Yes, its not ideal, but thats my choice :-)

I dont understand UNO and its OLE Bridge deep enough to find whats wrong, but workaround with direct usage of numerical values of enum items works. And this is curently good enough solution for my purposes without needs of investing more time to this concrete problem. Therefore this question is solved for me. Thanks.

Re: [Solved] How to read enum values ​​through OLE with C++?

Posted: Wed Jul 09, 2014 3:44 pm
by YellowBird
@Charlie Young: Thanks for your solutions. Your tip of using CoreReflection worked for me with Python.