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

Java, C++, C#, Delphi... - Using the UNO bridges
Post Reply
lostinai
Posts: 5
Joined: Tue Apr 29, 2014 11:16 am

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

Post 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?
Last edited by Hagar Delest on Mon May 05, 2014 9:28 pm, edited 1 time in total.
Reason: tagged [Solved].
OpenOffice 4.0.1 on Windows 7
User avatar
MrProgrammer
Moderator
Posts: 4905
Joined: Fri Jun 04, 2010 7:57 pm
Location: Wisconsin, USA

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

Post 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.
Mr. Programmer
AOO 4.1.7 Build 9800, MacOS 13.6.3, iMac Intel.   The locale for any menus or Calc formulas in my posts is English (USA).
lostinai
Posts: 5
Joined: Tue Apr 29, 2014 11:16 am

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

Post 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. :-)
OpenOffice 4.0.1 on Windows 7
User avatar
Charlie Young
Volunteer
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

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

Post 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.
Apache OpenOffice 4.1.1
Windows XP
lostinai
Posts: 5
Joined: Tue Apr 29, 2014 11:16 am

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

Post 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.
OpenOffice 4.0.1 on Windows 7
YellowBird
Posts: 1
Joined: Wed Jul 09, 2014 2:57 pm

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

Post by YellowBird »

@Charlie Young: Thanks for your solutions. Your tip of using CoreReflection worked for me with Python.
Apache OpenOffice 4.1.0 - Windows 8.1
Post Reply