Page 1 of 1

Can a user instantiate a built-in object? (com.sun.star.*)

Posted: Sat Apr 23, 2016 8:58 pm
by octomancer
Hi all,

I have a spreadsheet that I've constructed by hand, making it more and more functional and complex over time. I'm now trying to write Basic macros to build it from scratch.

I was trying to do a particular job and it occurred to me that it would be much easier if I could create an object which inherited the XNameAccess interface so I could use hasByName and getByName methods on it (I was actually on the point of writing my own module to implement what I needed). I've done a lot of googling, I've searched Andrew Pitonyak's book, I have the Xray tool installed ... I can't find what I need.

The best I have come up with so far is to create an array of com.sun.star.beans.PropertyValue objects and assign that array to the value property of a parent PropertyValue object. Then I can write some functions to implement similar methods to hasByName etc. This all seems horrendous!

I've worked with objects in Perl and JavaScript before and they're pretty nice to work with because both languages have first-class functions and a flexible object model. As far as I'm aware, OO Basic lacks both first class functions and the facility for user-created classes/objects. Does OO JS retain these features of other JS implementations?

Thanks in advance for any and all suggestions :-)
Rich

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Sat Apr 23, 2016 11:42 pm
by JeJe
This place has stuff on classes etc

http://cereusapis.com/classes-and-objec ... ice-basic/

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Sun Apr 24, 2016 12:21 am
by Villeroy
ComponentContext.ServiceManager.getAvailableServiceNames() => 1000 services (objects) from scratch.
newObj = ServiceManager.createInstance(srvName)
StarBasic: createUnoService(srvName)

someObject.SupportedServiceNames => service names that are included in this service (subclasses)

someObject.AvailableServiceNames => names of services that can be derived from this service by someObject.createInstance(srvName)

There is an interesting innovation in LO 5.1 regarding the Python bridge:
https://wiki.documentfoundation.org/Rel ... Francis.29

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Sun Apr 24, 2016 12:46 am
by octomancer
Thank you both for the suggestions. They both seem promising! I will try to figure out what I need tomorrow and report back :-)

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Sat Apr 30, 2016 4:18 pm
by octomancer
Hi,

So I've been trying to solve my problem using built in Uno services. I inspected the available services with this code (and utilising the excellent XRay tool):

Code: Select all

dim oSM as object

oSM = GetProcessServiceManager
xray oSM
Then I double clicked the getAvailableServiceNames method to get the list

The 2 services that look interesting are com.sun.star.container.EnumerableMap and com.sun.star.beans.PropertyBag. I looked at both and decided that EnumerableMap would be preferable, but I'm having trouble using it. I've started with this code

Code: Select all

	dim oAccount as object

	oAccount = GetProcessServiceManager.createInstance("com.sun.star.container.EnumerableMap")
	oAccount.put("name1", "value1")
This gives me a com.sun.star.lang.NotInitializedException. So eventually after some googling I got to this code

Code: Select all

	dim oAccount as object
	dim mArgs(1)

	oAccount = GetProcessServiceManager.createInstance("com.sun.star.container.EnumerableMap")
	oAccount.initialize(mArgs)
	oAccount.put("name1", "value1")
Now this gives me a com.sun.star.lang.IllegalArgumentException: com.sun.star.uno.Type expected..

And that's where I'm stuck. No matter what I try, how much I google, I can't find out how to create an object of type Type. Googling for this is not easy as you can imagine! I did stumble across the function CreateUnoValue but I can't get that to work either.

I'm not even sure this is the right way to go about my task any more, but I would like to solve this problem just for satisfaction.

All comments gratefully received.

Cheers,
Rich

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Sat Apr 30, 2016 6:41 pm
by Villeroy
During all those years I've never came across com.sun.star.container.EnumerableMap. Looks like a hash (Perl), dictionary (Python), collection (VB). When I need any such structure, I use an appropriate programming language. Python is an excellent macro language for Open/LibreOffice.
I guess that you need to call the initialize() method of this object. But nobody knows the right arguments except for the programmers who don't shy away from the source code.

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Sat Apr 30, 2016 8:25 pm
by octomancer
Hi,

I agree it does look like a Perl hash. No surprise, they're both key/value stores :-) And I think I know the arguments to the constructor... a 2 element array of com.sun.star.uno.Type objects, specifying the type of the keys and the type of the values. I just haven't been able to find out how to instantiate the type objects :-) I've found examples in the OpenOffice wiki do what exactly what I'm trying to do, but in Java. So far my guessing has not resulted in me discovering the right syntax in LO Basic :-) I've tried

Code: Select all

Dim vA as com.sun.star.uno.Type

Dim vA
vA = new com.sun.star.uno.Type

vA = createunovalue("com.sun.star.uno.Type", "string")

vA = GetProcessServiceManager.createInstance("com.sun.star.uno.Type")
None works. I knew the last one would fail because Type is not a service. The Java examples all use bareword API classes, as in my second example. I just think what I want to do is not possible in LO Basic. I suppose I could look at the bridge code, but ... NO.

I don't know Python (I'd like to learn it), but I do know Perl so I think I am going to do the heavy lifting in Perl. I'll write out a text file which will essentially be an array of what I want in my spreadsheet cells. Simple enough to read it in and use .setFormulaArray. LO Basic definitely is a pretty kinky language, as I've read elsewhere on this forum ;-) I used to write a little VB and VBA years ago and I don't remember it being this difficult!

Thanks for your time.

Cheers,
Rich

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Sun May 01, 2016 1:04 pm
by Villeroy
Calc can import/export csv easily.
The database component can link spreadsheets to data sources such as other spreadsheets, csv, dBase and relational databases via ODBC or JDBC.
Many people do a lot of programming to export text from databases, import text into spreadsheets and apply formatting, calculations, charts to the imported text. All this can be performed easily without a single line of code just using links, templates and format styles.

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Mon May 02, 2016 1:34 pm
by karolus
Hallo

@octomancer
ask about the problem, not about how you think it should be solved…

Karolus

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Mon May 02, 2016 5:04 pm
by B Marcelly
Hello,
Here is a Basic example of using EnumerableMap

Code: Select all

Option Explicit

Sub Main1
Dim PostCodeFR As Object
Dim k As String
Dim enu As Object, elem As Variant

PostCodeFR = com.sun.star.container.EnumerableMap.create("string", "long")
With PostCodeFR
  .put("EMBRUN",   CreateUnoValue("long", 05200))
  .put("GIENS",    CreateUnoValue("long", 83400))
  .put("AUXERRE",  CreateUnoValue("long", 89000))
  .put("HYERES",   CreateUnoValue("long", 83400))
  .put("THIVILLE", CreateUnoValue("long", 28200))
  .put("TAUSSAT",  CreateUnoValue("long", 33148))
  
  Do
    k = InputBox("Give a name of a locality", "")
    if Len(k) = 0  then Exit Do
    if .containsKey(k)  then
      MsgBox(.get(k), 0, k)
    else
      MsgBox("Unknown locality", 0, k)
    end if
  Loop
  
  enu = .createKeyEnumeration(False)
  Do While enu.hasMoreElements
    elem = enu.nextElement
    MsgBox("Key : " & elem)
  Loop

  enu = .createValueEnumeration(False)
  Do While enu.hasMoreElements
    elem = enu.nextElement
    MsgBox("Value : " & elem)
  Loop

  enu = .createElementEnumeration(False)
  Do While enu.hasMoreElements
    elem = enu.nextElement
    MsgBox("Key : " & elem.First & _
      chr(10) & "Value : " & elem.Second)
  Loop
  
  .clear
  enu = .createElementEnumeration(False)
  MsgBox("Any element ? " & enu.hasMoreElements)
End With
End Sub
  • The first instruction is a constructor for new-style services. These services can have different constructors, like here.
  • The second argument of put method uses CreateUnoValue because if the number is lower than 32768 the binding converts it to a short, not a long. This is cumbersome, I wrote Issue 121192 to ask for an improvement.
  • In my example, the same post code is used by different localities. This is usual in France.
  • The key strings are case sensitive.

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Tue May 03, 2016 10:00 pm
by octomancer
Hi,

Thank you so much for posting such an informative chunk of code. It does indeed explain everything that I was finding so difficult. I'm not sure I'm going to stick with LO Basic though. It's quite tough to learn it. The only reason I decided on Basic for this task was because I have written VB and VBA before. But I think that the difficulty of navigating the learning resources obviates any advantage I might have gained. I was on the brink of learning Python anyway, so I'll be back in a few months with questions about Python programming for LO :-D

Thanks to all who took the time to post answers.

Cheers,
Rich

Re: Can a user instantiate a built-in object? (com.sun.star.

Posted: Tue May 03, 2016 10:02 pm
by octomancer
karolus wrote:Hallo

@octomancer
ask about the problem, not about how you think it should be solved…

Karolus
lol