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

Java, C++, C#, Delphi, ??? - Using the UNO bridges

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

Postby lostinai » Thu May 01, 2014 2:35 pm

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
lostinai
 
Posts: 5
Joined: Tue Apr 29, 2014 11:16 am

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

Postby MrProgrammer » Thu May 01, 2014 3:16 pm

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 on MacOS 10.14.6.   The locale for any menus or Calc formulas in my posts is English (USA).
User avatar
MrProgrammer
Moderator
 
Posts: 3983
Joined: Fri Jun 04, 2010 7:57 pm
Location: Wisconsin, USA

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

Postby lostinai » Thu May 01, 2014 9:28 pm

@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
lostinai
 
Posts: 5
Joined: Tue Apr 29, 2014 11:16 am

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

Postby Charlie Young » Sun May 04, 2014 2:20 pm

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   Expand viewCollapse view

      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.

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   Expand viewCollapse view
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   Expand viewCollapse view
      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
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++?

Postby lostinai » Mon May 05, 2014 1:08 pm

@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
lostinai
 
Posts: 5
Joined: Tue Apr 29, 2014 11:16 am

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

Postby YellowBird » Wed Jul 09, 2014 3:44 pm

@Charlie Young: Thanks for your solutions. Your tip of using CoreReflection worked for me with Python.
Apache OpenOffice 4.1.0 - Windows 8.1
YellowBird
 
Posts: 1
Joined: Wed Jul 09, 2014 2:57 pm


Return to External Programs

Who is online

Users browsing this forum: No registered users and 1 guest