Difference between revisions of "Python/Transfer from Basic to Python"

From Apache OpenOffice Wiki
Jump to: navigation, search
(Add descriptions in Functions to be Executed)
(Adding code coloring definition)
Line 1: Line 1:
 
{{DISPLAYTITLE:Transfer from Basic to Python}}
 
{{DISPLAYTITLE:Transfer from Basic to Python}}
 +
 +
  
 
If you feel some displeasure at StarBasic/OpenOffice Basic or you meet requirement of custom UNO component, now it is the time to transfer coding environment from Basic to Python.
 
If you feel some displeasure at StarBasic/OpenOffice Basic or you meet requirement of custom UNO component, now it is the time to transfer coding environment from Basic to Python.
Line 8: Line 10:
  
 
== Macro Location ==
 
== Macro Location ==
 +
 +
  
 
== Macro Editor ==
 
== Macro Editor ==
 +
 
There is no built-in editor dedicated to code in Python. But you can choose your favorite text editor application to edit your Python script.
 
There is no built-in editor dedicated to code in Python. But you can choose your favorite text editor application to edit your Python script.
  
Line 19: Line 24:
 
== Usable Modules ==
 
== Usable Modules ==
  
 +
<source lang="Python">
 
  import uno
 
  import uno
 +
 
  import unohelper
 
  import unohelper
 +
</source>
  
 
== Script Context ==
 
== Script Context ==
 +
 
StarBasic is embedded runtime and it always works with living instance of the office. So the context is always the match with the office's one. But Python-UNO bridge provides the way to work as RPC client. At that time, remote Python instance does have different context from the office instance. Therefore you have to use correct component context to tell to the multi component factory to instantiate a service.
 
StarBasic is embedded runtime and it always works with living instance of the office. So the context is always the match with the office's one. But Python-UNO bridge provides the way to work as RPC client. At that time, remote Python instance does have different context from the office instance. Therefore you have to use correct component context to tell to the multi component factory to instantiate a service.
  
Line 30: Line 39:
  
 
* com.sun.star.frame.XModel '''getDocument'''()
 
* com.sun.star.frame.XModel '''getDocument'''()
 +
 
:Returns current document object.
 
:Returns current document object.
 +
 
* com.sun.star.document.XScriptInvocationContext '''getInvocationContext'''();
 
* com.sun.star.document.XScriptInvocationContext '''getInvocationContext'''();
 +
 
:Returns invocation dependent object.
 
:Returns invocation dependent object.
 +
 
* com.sun.star.frame.XDesktop '''getDesktop''()
 
* com.sun.star.frame.XDesktop '''getDesktop''()
 +
 
:Returns instance of com.sun.star.frame.Desktop service.
 
:Returns instance of com.sun.star.frame.Desktop service.
 +
 
* com.sun.star.uno.XComponentContext '''getComponentContext'''()
 
* com.sun.star.uno.XComponentContext '''getComponentContext'''()
 +
 
:Returns current component context that is used to tell the which context is.
 
:Returns current component context that is used to tell the which context is.
  
Line 41: Line 57:
  
 
== Component Context ==
 
== Component Context ==
 +
 
In StarBasic, you can get component context as follows:  
 
In StarBasic, you can get component context as follows:  
 +
<source lang="Python">
 
  ctx = GetDefaultContext()
 
  ctx = GetDefaultContext()
 +
</source>
 
But you do not need to access to it until you need to get singletons.
 
But you do not need to access to it until you need to get singletons.
  
 
In Python, you can get access to the component context through the script context.
 
In Python, you can get access to the component context through the script context.
 
+
<source lang="Python">
 
  ctx = XSCRIPTCONTEXT.getComponentContext()
 
  ctx = XSCRIPTCONTEXT.getComponentContext()
 +
</source>
  
 
You need this value to instantiate services.
 
You need this value to instantiate services.
 +
 +
  
 
== Service Manager ==
 
== Service Manager ==
 +
 
In StarBasic, you can get service manager as follows:
 
In StarBasic, you can get service manager as follows:
 +
<source lang="Python">
 
  smgr = GetProcessServiceManger()
 
  smgr = GetProcessServiceManger()
 +
</source>
 
But not so many people having to access to it.
 
But not so many people having to access to it.
  
 
In Python, this instance is most important value to instantiate services to work with the office APIs.
 
In Python, this instance is most important value to instantiate services to work with the office APIs.
 
+
<source lang="Python">
 
  ctx = XSCRIPTCONTEXT.getComponentContext()
 
  ctx = XSCRIPTCONTEXT.getComponentContext()
 
  smgr = ctx.getServiceManager()
 
  smgr = ctx.getServiceManager()
 +
</source>
  
 
You need both the component context and the service manager to instantiate services.
 
You need both the component context and the service manager to instantiate services.
 +
 +
  
 
== Service Instance ==
 
== Service Instance ==
 +
 
In StarBasic, you can instantiate services by built-in function as follows:
 
In StarBasic, you can instantiate services by built-in function as follows:
 +
<source lang="Python">
 
  sfa = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")
 
  sfa = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")
 +
</source>
 
or with initialize arguments:  
 
or with initialize arguments:  
 +
<source lang="Python">
 
  arg = com.sun.star.ui.dialogs.TemplateDescription.FILESAVE_SIMPLE
 
  arg = com.sun.star.ui.dialogs.TemplateDescription.FILESAVE_SIMPLE
 
  file_picker = CreateUnoServiceWithArguments("com.sun.star.ui.dialogs.FilePicker", Array(arg))
 
  file_picker = CreateUnoServiceWithArguments("com.sun.star.ui.dialogs.FilePicker", Array(arg))
 +
</source>
 +
  
 
In Python, you have to work with com.sun.star.lang.XMultiComponentFactory interface as follows:  
 
In Python, you have to work with com.sun.star.lang.XMultiComponentFactory interface as follows:  
 +
<source lang="Python">
 
  ctx = XSCRIPTCONTEXT.getComponentContext()
 
  ctx = XSCRIPTCONTEXT.getComponentContext()
 
  smgr = ctx.getServiceManager()
 
  smgr = ctx.getServiceManager()
 
  sfa = smgr.createInstanceWithContext("com.sun.star.ucb.SimpleFileAccess", ctx)
 
  sfa = smgr.createInstanceWithContext("com.sun.star.ucb.SimpleFileAccess", ctx)
 +
</source>
 
If you need to initialize the instance, use createInstanceWithArgumentsAndContext method:  
 
If you need to initialize the instance, use createInstanceWithArgumentsAndContext method:  
 +
<source lang="Python">
 
  from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_SIMPLE
 
  from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_SIMPLE
 
  file_picker = smgr.createInstanceWithArgumentsAndContext("com.sun.star.ui.dialogs.FilePicker", (FILESAVE_SIMPLE,) ctx)
 
  file_picker = smgr.createInstanceWithArgumentsAndContext("com.sun.star.ui.dialogs.FilePicker", (FILESAVE_SIMPLE,) ctx)
 +
</source>
 
or initialize after the instantiation:  
 
or initialize after the instantiation:  
 +
<source lang="Python">
 
  file_picker = smgr.createInstanceWithContext("com.sun.star.ui.dialogs.FilePicker", ctx)
 
  file_picker = smgr.createInstanceWithContext("com.sun.star.ui.dialogs.FilePicker", ctx)
 
  file_picker.initialize((FILESAVE_SIMPLE,))
 
  file_picker.initialize((FILESAVE_SIMPLE,))
 +
</source>
 +
  
 
== Service with Constructor ==
 
== Service with Constructor ==
 +
 
In StarBasic, you can call service construct from its module:  
 
In StarBasic, you can call service construct from its module:  
 +
<source lang="Python">
 
  shell_execute = com.sun.star.system.SystemShellExecute.create()
 
  shell_execute = com.sun.star.system.SystemShellExecute.create()
 
+
</source>
 
In Python, you have to instantiate it with XMultiComponentFactory::createInstanceWithArgumentsAndContext method with initial arguments or instantiate after the instantiation.
 
In Python, you have to instantiate it with XMultiComponentFactory::createInstanceWithArgumentsAndContext method with initial arguments or instantiate after the instantiation.
  
Line 90: Line 133:
  
 
== Current Document ==
 
== Current Document ==
 +
 
In StarBasic, ThisComponent runtime function provides access to the current document:  
 
In StarBasic, ThisComponent runtime function provides access to the current document:  
 +
<source lang="Python">
 
  doc = ThisComponent
 
  doc = ThisComponent
 +
</source>
 
Its return value is bound to the macro location. If the macro stored in a document, the result of ThisComponent is the document that the storage of the macro belongs to. And if your macro is stored in application wide, the returned value is the document model of currently active frame, this is the same result taken from StarDesktop.getCurrentComponent().  
 
Its return value is bound to the macro location. If the macro stored in a document, the result of ThisComponent is the document that the storage of the macro belongs to. And if your macro is stored in application wide, the returned value is the document model of currently active frame, this is the same result taken from StarDesktop.getCurrentComponent().  
  
 
In Python, you can access to the current document through the script context:  
 
In Python, you can access to the current document through the script context:  
 +
<source lang="Python">
 
  doc = XSCRIPTCONTEXT.getDocument()
 
  doc = XSCRIPTCONTEXT.getDocument()
 +
</source>
 
If your macro is embedded in the document, the document model is match with the document that the macro stored in. If your macro is stored in user or shared location, the document object is from active frame.
 
If your macro is embedded in the document, the document model is match with the document that the macro stored in. If your macro is stored in user or shared location, the document object is from active frame.
  
 
== Desktop ==
 
== Desktop ==
 +
 
In StarBasic, StarDesktop runtime function is provided:  
 
In StarBasic, StarDesktop runtime function is provided:  
 +
<source lang="Python">
 
  desktop = StarDesktop()
 
  desktop = StarDesktop()
 +
</source>
  
 
In Python, you can get access to the desktop through the script context:  
 
In Python, you can get access to the desktop through the script context:  
 +
<source lang="Python">
 
  desktop = XSCRIPTCONTEXT.getDesktop()
 
  desktop = XSCRIPTCONTEXT.getDesktop()
 +
</source>
  
 
== Struct Instance ==
 
== Struct Instance ==
 +
 
In Basic, instance of struct can be instantiated in two ways:  
 
In Basic, instance of struct can be instantiated in two ways:  
 +
<source lang="oobas">
 
  Dim a As New com.sun.star.awt.Point
 
  Dim a As New com.sun.star.awt.Point
 
  a = CreateUnoStruct("com.sun.star.awt.Point")
 
  a = CreateUnoStruct("com.sun.star.awt.Point")
 +
</source>
 
With Dim statement and New keyword, you can instantiate a struct or array of structs. Or CreateUnoStruct method provides the way to instantiate a struct at runtime. You can not initialize the instance at the creation, you have to set its value of members.
 
With Dim statement and New keyword, you can instantiate a struct or array of structs. Or CreateUnoStruct method provides the way to instantiate a struct at runtime. You can not initialize the instance at the creation, you have to set its value of members.
  
 
In Python, you can use the following ways to instantiate a struct. Import struct class and call it.
 
In Python, you can use the following ways to instantiate a struct. Import struct class and call it.
 +
<source lang="Python">
 
  from com.sun.star.awt import Point
 
  from com.sun.star.awt import Point
 +
 
  a = Point()        # instantiate with default values, X=0, Y=0
 
  a = Point()        # instantiate with default values, X=0, Y=0
 
  b = Point(100, 200) # initialize with initial values, X=100, Y=200
 
  b = Point(100, 200) # initialize with initial values, X=100, Y=200
 +
</source>
 
Calling the class to create new instance of the struct, you can empty its arguments or you have to pass values for all fields. In other words, you can not pass insufficient number of arguments to initialize. And its order should be match with definition of the struct in its IDL. For example, instance of struct b having X=100 and Y=200 in the above piece of code.
 
Calling the class to create new instance of the struct, you can empty its arguments or you have to pass values for all fields. In other words, you can not pass insufficient number of arguments to initialize. And its order should be match with definition of the struct in its IDL. For example, instance of struct b having X=100 and Y=200 in the above piece of code.
  
 
You can initialize without to import the class of your target struct with uno.createUnoStruct function as follows:  
 
You can initialize without to import the class of your target struct with uno.createUnoStruct function as follows:  
 +
<source lang="Python">
 
  import uno
 
  import uno
 +
 
  a = uno.createUnoStruct("com.sun.star.awt.Point")
 
  a = uno.createUnoStruct("com.sun.star.awt.Point")
 
  b = uno.createUnoStruct("com.sun.star.awt.Point", 100, 200)
 
  b = uno.createUnoStruct("com.sun.star.awt.Point", 100, 200)
 +
</source>
 
This makes the same result with the above example. The first parameter of the createUnoStruct method is the name of the struct to initialize. The following arguments are initial values for new instance.
 
This makes the same result with the above example. The first parameter of the createUnoStruct method is the name of the struct to initialize. The following arguments are initial values for new instance.
  
 
== Enum ==
 
== Enum ==
 +
 
In Basic, you can access to the module of the enum as follows:  
 
In Basic, you can access to the module of the enum as follows:  
 +
<source lang="Python">
 
  ITALIC = com.sun.star.awt.FontSlant.ITALIC
 
  ITALIC = com.sun.star.awt.FontSlant.ITALIC
 +
</source>
  
 
In Python, the following ways can be used:  
 
In Python, the following ways can be used:  
 +
<source lang="Python">
 
  import uno
 
  import uno
 +
 
  from com.sun.star.awt.FontSlant import ITALIC
 
  from com.sun.star.awt.FontSlant import ITALIC
 
  ITALIC = uno.getConstantByName("com.sun.star.awt.FontSlant.ITALIC")
 
  ITALIC = uno.getConstantByName("com.sun.star.awt.FontSlant.ITALIC")
 
  ITALIC = uno.Enum("com.sun.star.awt.FontSlant", "ITALIC")
 
  ITALIC = uno.Enum("com.sun.star.awt.FontSlant", "ITALIC")
 +
</source>
 
All of the way results the instance of uno.Enum class.
 
All of the way results the instance of uno.Enum class.
  
 
== Constants ==
 
== Constants ==
 +
 
In StarBasic, you can get access to constants through its module:  
 
In StarBasic, you can get access to constants through its module:  
 +
<source lang="Python">
 
  BOLD = com.sun.star.awt.FontWeight.BOLD
 
  BOLD = com.sun.star.awt.FontWeight.BOLD
  
 
In Python, the following ways are provided:  
 
In Python, the following ways are provided:  
 +
<source lang="Python">
 
  import uno
 
  import uno
 +
 
  from com.sun.star.awt.FontWeight import BOLD
 
  from com.sun.star.awt.FontWeight import BOLD
 
  BOLD = uno.getConstantsByName("com.sun.star.awt.FontWeight.BOLD")
 
  BOLD = uno.getConstantsByName("com.sun.star.awt.FontWeight.BOLD")
 +
</source>
  
 
== Sequence ==
 
== Sequence ==
 +
 
The sequence is sequential value of the same type.
 
The sequence is sequential value of the same type.
  
Line 151: Line 225:
  
 
== Boolean ==
 
== Boolean ==
 +
 
In Python, True or False.
 
In Python, True or False.
  
 
== String ==
 
== String ==
 +
 
Python's string can contain over 64K bytes.
 
Python's string can contain over 64K bytes.
  
 
If you have to write non Ascii 7 bit characters in your script, write magic comment at the head of your file. This is standard Python instructions.
 
If you have to write non Ascii 7 bit characters in your script, write magic comment at the head of your file. This is standard Python instructions.
  
 +
<source lang="Python">
 
  # -*- coding: utf_8 -*-
 
  # -*- coding: utf_8 -*-
 +
</source>
  
 
Please read Python's documentation for more detail.
 
Please read Python's documentation for more detail.
  
 
== Char ==
 
== Char ==
 +
 
There is no dedicated value for char type in StarBasic.
 
There is no dedicated value for char type in StarBasic.
  
 
In Python, uno.Char class is defined for char type.
 
In Python, uno.Char class is defined for char type.
 +
<source lang="Python">
 
  import uno
 
  import uno
 
  c = uno.Char("a")
 
  c = uno.Char("a")
 +
</source>
 +
  
 
== Byte Sequence ==
 
== Byte Sequence ==
 +
 
The byte sequence is sequence of byte type.
 
The byte sequence is sequence of byte type.
  
Line 177: Line 260:
  
 
== Exception ==
 
== Exception ==
 +
 
In StarBasic, you get thrown exception as some error. And On Error statement is used to catch it.
 
In StarBasic, you get thrown exception as some error. And On Error statement is used to catch it.
  
 +
<source lang="oobas">
 
  Sub ErrorExample
 
  Sub ErrorExample
 +
 
   On Error GoTo Handler
 
   On Error GoTo Handler
 +
 
   ' ... error
 
   ' ... error
 +
 
   Exit Sub
 
   Exit Sub
 +
 
   Handler:  
 
   Handler:  
 +
 
  End Sub
 
  End Sub
 +
</source>
 
And you can not throw any exceptions from StarBasic.
 
And you can not throw any exceptions from StarBasic.
  
 
In Python, the exception thrown in UNO world can be treated as normal Python's exception. Here is an example:  
 
In Python, the exception thrown in UNO world can be treated as normal Python's exception. Here is an example:  
 +
<source lang="Python">
 
  from com.sun.star.container import IndexOutOfBoundsException
 
  from com.sun.star.container import IndexOutOfBoundsException
 +
 
  try:
 
  try:
 
     obj.getByIndex(100) # raises IndexOutOfBoundsException
 
     obj.getByIndex(100) # raises IndexOutOfBoundsException
 
  except IndexOutOfBoundsException as e:
 
  except IndexOutOfBoundsException as e:
 
     print(e)
 
     print(e)
 +
</source>
 
If getByIndex method raises IndexOutOfBoundsException, it can be caught in except statement because all exceptions inherit Python's Exception class.
 
If getByIndex method raises IndexOutOfBoundsException, it can be caught in except statement because all exceptions inherit Python's Exception class.
  
 
And also you can throw UNO's exception from your Python code as follows:  
 
And also you can throw UNO's exception from your Python code as follows:  
 +
<source lang="Python">
 
  from com.sun.star.uno import RuntimeException
 
  from com.sun.star.uno import RuntimeException
 
  raise RuntimeException("Some message", None)
 
  raise RuntimeException("Some message", None)
 +
</source>
 +
  
 
== Empty Value ==
 
== Empty Value ==
 +
 
In Basic, there are some situations to meet variables that they do not contain any value (this is not correct). Null, empty, missing, nothing and so on.
 
In Basic, there are some situations to meet variables that they do not contain any value (this is not correct). Null, empty, missing, nothing and so on.
  
Line 207: Line 305:
  
 
In StarBasic, you can create new listener using CreateUnoListener runtime function with some subroutines or functions.
 
In StarBasic, you can create new listener using CreateUnoListener runtime function with some subroutines or functions.
 +
<source lang="oobas">
 
  Sub Add
 
  Sub Add
 +
 
   d = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
 
   d = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
 
   listener = CreateUnoListener("ActionListener", "com.sun.star.awt.XActionListener")
 
   listener = CreateUnoListener("ActionListener", "com.sun.star.awt.XActionListener")
Line 213: Line 313:
 
   d.execute()
 
   d.execute()
 
   d.dispose()
 
   d.dispose()
 +
 
  End Sub
 
  End Sub
 +
 
   
 
   
 +
 
  Sub ActionListener_actionPerformed(ev)
 
  Sub ActionListener_actionPerformed(ev)
 +
 
  End Sub
 
  End Sub
 +
 
  Sub ActionListener_disposing(ev)
 
  Sub ActionListener_disposing(ev)
 +
 
  End Sub
 
  End Sub
 +
</source>
  
 
In Python, you have define your own class with desired interfaces. With helper class, you can define easily as follows:  
 
In Python, you have define your own class with desired interfaces. With helper class, you can define easily as follows:  
 +
<source lang="Python">
 
  import unohelper
 
  import unohelper
 +
 
  from com.sun.star.awt import XActionListener
 
  from com.sun.star.awt import XActionListener
 +
 
   
 
   
 
  class ActionListener(unohelper.Base, XActionListener):
 
  class ActionListener(unohelper.Base, XActionListener):
 
     def __init__(self):
 
     def __init__(self):
 
         pass
 
         pass
 +
 
     def disposing(self, ev):
 
     def disposing(self, ev):
 
         pass
 
         pass
 +
 
     def actionPerformed(self, ev):
 
     def actionPerformed(self, ev):
 +
 
         pass
 
         pass
 +
</source>
  
 
unohelper.Base class provides required interface for UNO components.
 
unohelper.Base class provides required interface for UNO components.
  
 
== Containers ==
 
== Containers ==
 +
 
In StarBasic, container object provides the way to access to its contents in sequentially.
 
In StarBasic, container object provides the way to access to its contents in sequentially.
  
 
In Python, there is no shortcut provided.  
 
In Python, there is no shortcut provided.  
 +
 
If you need to access to elements of indexed container, use range function to generate sequential indexes.
 
If you need to access to elements of indexed container, use range function to generate sequential indexes.
 +
<source lang="Python">
 
  for i in range(container.getCount()):
 
  for i in range(container.getCount()):
 
     obj = container.getByIndex(i)
 
     obj = container.getByIndex(i)
 +
</source>
  
 
== URL and System Path ==
 
== URL and System Path ==
 +
 
If you work with a file stored in your local file system, you have to get its corresponding URL.
 
If you work with a file stored in your local file system, you have to get its corresponding URL.
  
Line 248: Line 367:
  
 
In Python, the following functions are defined in uno module for such task.
 
In Python, the following functions are defined in uno module for such task.
 +
<source lang="Python">
 
  import uno
 
  import uno
 +
 
  path = "/home/foo/Documents/file.odt"
 
  path = "/home/foo/Documents/file.odt"
 
  url = uno.sytemPathToFileUrl(path)
 
  url = uno.sytemPathToFileUrl(path)
 
  path = uno.fileUrlToSystemPath(url)
 
  path = uno.fileUrlToSystemPath(url)
 +
</source>
  
 
== Arguments and Return Value ==
 
== Arguments and Return Value ==
 +
 
In StarBasic, mode of the first argument of parseStrict method is "inout" in the following code:  
 
In StarBasic, mode of the first argument of parseStrict method is "inout" in the following code:  
 +
<source lang="oobas">
 
  aURL = CreateUnoStruct("com.sun.star.util.URL")
 
  aURL = CreateUnoStruct("com.sun.star.util.URL")
 
  aURL.Complete = ".uno:Paste"
 
  aURL.Complete = ".uno:Paste"
 
  CreateUnoService("com.sun.star.util.URLTransformer").parseStrict(aURL)
 
  CreateUnoService("com.sun.star.util.URLTransformer").parseStrict(aURL)
 +
</source>
 
The content of aURL variable is updated after calling the method.
 
The content of aURL variable is updated after calling the method.
  
 
In Python, out mode parameter is returned as part of return value.
 
In Python, out mode parameter is returned as part of return value.
 +
<source lang="Python">
 
  from com.sun.star.util import URL
 
  from com.sun.star.util import URL
 +
 
  aURL = URL()
 
  aURL = URL()
 
  aURL.Complete = ".uno:Paste"
 
  aURL.Complete = ".uno:Paste"
Line 267: Line 394:
 
  # Definition of com.sun.star.util.XURLTransformer::parseStrict method:  
 
  # Definition of com.sun.star.util.XURLTransformer::parseStrict method:  
 
  # void parseStrict([inout] com.sun.star.util.URL aURL);
 
  # void parseStrict([inout] com.sun.star.util.URL aURL);
 +
</source>
 
If a method has out mode in its parameters, its return is always tuple that contains original return value and values for out parameters.
 
If a method has out mode in its parameters, its return is always tuple that contains original return value and values for out parameters.
  
 
Here is a potential example:  
 
Here is a potential example:  
 +
<source lang="Python">
 
  # boolean getSomeValue([in] string aName, [out] short aNum, [inout] long aNum2);
 
  # boolean getSomeValue([in] string aName, [out] short aNum, [inout] long aNum2);
 
  result, num, num2 = obj.getSomeValue("foo", 100, 200)
 
  result, num, num2 = obj.getSomeValue("foo", 100, 200)
 +
</source>
 
In the above example, ''result'' variable takes original return value, ''num'' takes output value for second parameter and ''num2'' takes output value for third parameter. The method takes 100 as the second parameter but it is not used as input of value. No entry in returned tuple for in mode parameter.
 
In the above example, ''result'' variable takes original return value, ''num'' takes output value for second parameter and ''num2'' takes output value for third parameter. The method takes 100 as the second parameter but it is not used as input of value. No entry in returned tuple for in mode parameter.
  
 
== Functions to be Executed ==
 
== Functions to be Executed ==
 +
 
In Basic, you can not choose routines to be executed by users.
 
In Basic, you can not choose routines to be executed by users.
  
 
In Python, define g_exportedScripts variable that contains tuple of callable in your macro file.
 
In Python, define g_exportedScripts variable that contains tuple of callable in your macro file.
 +
<source lang="Python">
 
  def func_a(): pass
 
  def func_a(): pass
 
  def func_b(): pass
 
  def func_b(): pass
Line 283: Line 415:
 
   
 
   
 
  g_exportedScripts = func_a, func_b
 
  g_exportedScripts = func_a, func_b
 +
</source>
 
In the above code, func_hidden is not shown in execution dialog of macros.
 
In the above code, func_hidden is not shown in execution dialog of macros.
  

Revision as of 18:40, 20 August 2013



If you feel some displeasure at StarBasic/OpenOffice Basic or you meet requirement of custom UNO component, now it is the time to transfer coding environment from Basic to Python.

In StarBasic, there are some runtime function provides short cut to do something. But using Python-UNO bridge, you have to do such task by API ways.

Let's start with Python's tutorial and return back to here when you have learned a bit about Python language.

Macro Location

Macro Editor

There is no built-in editor dedicated to code in Python. But you can choose your favorite text editor application to edit your Python script.

This is discussed in another page.

Short Example

Usable Modules

 import uno
 
 import unohelper

Script Context

StarBasic is embedded runtime and it always works with living instance of the office. So the context is always the match with the office's one. But Python-UNO bridge provides the way to work as RPC client. At that time, remote Python instance does have different context from the office instance. Therefore you have to use correct component context to tell to the multi component factory to instantiate a service.

In StarBasic, you have no matching object provided.

In Python macro, you have to use XSCRIPTCONTEXT module variable that provides com.sun.star.script.provider.XScriptContext interface.

  • com.sun.star.frame.XModel getDocument()
Returns current document object.
  • com.sun.star.document.XScriptInvocationContext getInvocationContext();
Returns invocation dependent object.
  • com.sun.star.frame.XDesktop 'getDesktop()
Returns instance of com.sun.star.frame.Desktop service.
  • com.sun.star.uno.XComponentContext getComponentContext()
Returns current component context that is used to tell the which context is.

Please keep in mind, XSCRIPTCONTEXT variable is defined in module level and it is not provided to imported modules from your script.

Component Context

In StarBasic, you can get component context as follows:

 ctx = GetDefaultContext()

But you do not need to access to it until you need to get singletons.

In Python, you can get access to the component context through the script context.

 ctx = XSCRIPTCONTEXT.getComponentContext()

You need this value to instantiate services.


Service Manager

In StarBasic, you can get service manager as follows:

 smgr = GetProcessServiceManger()

But not so many people having to access to it.

In Python, this instance is most important value to instantiate services to work with the office APIs.

 ctx = XSCRIPTCONTEXT.getComponentContext()
 smgr = ctx.getServiceManager()

You need both the component context and the service manager to instantiate services.


Service Instance

In StarBasic, you can instantiate services by built-in function as follows:

 sfa = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")

or with initialize arguments:

 arg = com.sun.star.ui.dialogs.TemplateDescription.FILESAVE_SIMPLE
 file_picker = CreateUnoServiceWithArguments("com.sun.star.ui.dialogs.FilePicker", Array(arg))


In Python, you have to work with com.sun.star.lang.XMultiComponentFactory interface as follows:

 ctx = XSCRIPTCONTEXT.getComponentContext()
 smgr = ctx.getServiceManager()
 sfa = smgr.createInstanceWithContext("com.sun.star.ucb.SimpleFileAccess", ctx)

If you need to initialize the instance, use createInstanceWithArgumentsAndContext method:

 from com.sun.star.ui.dialogs.TemplateDescription import FILESAVE_SIMPLE
 file_picker = smgr.createInstanceWithArgumentsAndContext("com.sun.star.ui.dialogs.FilePicker", (FILESAVE_SIMPLE,) ctx)

or initialize after the instantiation:

 file_picker = smgr.createInstanceWithContext("com.sun.star.ui.dialogs.FilePicker", ctx)
 file_picker.initialize((FILESAVE_SIMPLE,))


Service with Constructor

In StarBasic, you can call service construct from its module:

 shell_execute = com.sun.star.system.SystemShellExecute.create()

In Python, you have to instantiate it with XMultiComponentFactory::createInstanceWithArgumentsAndContext method with initial arguments or instantiate after the instantiation.

The constructor calling does type checking before to pass arguments to createInstanceWithArgumentsAndContext method.

Current Document

In StarBasic, ThisComponent runtime function provides access to the current document:

 doc = ThisComponent

Its return value is bound to the macro location. If the macro stored in a document, the result of ThisComponent is the document that the storage of the macro belongs to. And if your macro is stored in application wide, the returned value is the document model of currently active frame, this is the same result taken from StarDesktop.getCurrentComponent().

In Python, you can access to the current document through the script context:

 doc = XSCRIPTCONTEXT.getDocument()

If your macro is embedded in the document, the document model is match with the document that the macro stored in. If your macro is stored in user or shared location, the document object is from active frame.

Desktop

In StarBasic, StarDesktop runtime function is provided:

 desktop = StarDesktop()

In Python, you can get access to the desktop through the script context:

 desktop = XSCRIPTCONTEXT.getDesktop()

Struct Instance

In Basic, instance of struct can be instantiated in two ways:

 Dim a As New com.sun.star.awt.Point
 a = CreateUnoStruct("com.sun.star.awt.Point")

With Dim statement and New keyword, you can instantiate a struct or array of structs. Or CreateUnoStruct method provides the way to instantiate a struct at runtime. You can not initialize the instance at the creation, you have to set its value of members.

In Python, you can use the following ways to instantiate a struct. Import struct class and call it.

 from com.sun.star.awt import Point
 
 a = Point()         # instantiate with default values, X=0, Y=0
 b = Point(100, 200) # initialize with initial values, X=100, Y=200

Calling the class to create new instance of the struct, you can empty its arguments or you have to pass values for all fields. In other words, you can not pass insufficient number of arguments to initialize. And its order should be match with definition of the struct in its IDL. For example, instance of struct b having X=100 and Y=200 in the above piece of code.

You can initialize without to import the class of your target struct with uno.createUnoStruct function as follows:

 import uno
 
 a = uno.createUnoStruct("com.sun.star.awt.Point")
 b = uno.createUnoStruct("com.sun.star.awt.Point", 100, 200)

This makes the same result with the above example. The first parameter of the createUnoStruct method is the name of the struct to initialize. The following arguments are initial values for new instance.

Enum

In Basic, you can access to the module of the enum as follows:

 ITALIC = com.sun.star.awt.FontSlant.ITALIC

In Python, the following ways can be used:

 import uno
 
 from com.sun.star.awt.FontSlant import ITALIC
 ITALIC = uno.getConstantByName("com.sun.star.awt.FontSlant.ITALIC")
 ITALIC = uno.Enum("com.sun.star.awt.FontSlant", "ITALIC")

All of the way results the instance of uno.Enum class.

Constants

In StarBasic, you can get access to constants through its module:

 BOLD = com.sun.star.awt.FontWeight.BOLD
 
In Python, the following ways are provided: 
<source lang="Python">
 import uno
 
 from com.sun.star.awt.FontWeight import BOLD
 BOLD = uno.getConstantsByName("com.sun.star.awt.FontWeight.BOLD")

Sequence

The sequence is sequential value of the same type.

In StarBasic, array is used.

In Python, tuple is chosen to represent UNO's sequence. Note, list is not allowed to pass as sequence value.

Boolean

In Python, True or False.

String

Python's string can contain over 64K bytes.

If you have to write non Ascii 7 bit characters in your script, write magic comment at the head of your file. This is standard Python instructions.

 # -*- coding: utf_8 -*-

Please read Python's documentation for more detail.

Char

There is no dedicated value for char type in StarBasic.

In Python, uno.Char class is defined for char type.

 import uno
 c = uno.Char("a")


Byte Sequence

The byte sequence is sequence of byte type.

In Basic, array of byte is used to represent it.

In Python, it is represented by str wrapped by uno.ByteSequence class. If you takes some byte sequences from UNO, they are the instance of uno.ByteSequence. If you need to get real value of them, refer its value instance variable.

Exception

In StarBasic, you get thrown exception as some error. And On Error statement is used to catch it.

 Sub ErrorExample
 
   On Error GoTo Handler
 
   ' ... error
 
   Exit Sub
 
   Handler: 
 
 End Sub

And you can not throw any exceptions from StarBasic.

In Python, the exception thrown in UNO world can be treated as normal Python's exception. Here is an example:

 from com.sun.star.container import IndexOutOfBoundsException
 
 try:
     obj.getByIndex(100) # raises IndexOutOfBoundsException
 except IndexOutOfBoundsException as e:
     print(e)

If getByIndex method raises IndexOutOfBoundsException, it can be caught in except statement because all exceptions inherit Python's Exception class.

And also you can throw UNO's exception from your Python code as follows:

 from com.sun.star.uno import RuntimeException
 raise RuntimeException("Some message", None)


Empty Value

In Basic, there are some situations to meet variables that they do not contain any value (this is not correct). Null, empty, missing, nothing and so on.

In Python, None is used. If a method defined as void return value in its IDL, it results None if you call it. If you need to pass invalid interface as an argument for the method that takes some interface, pass None for it. The result of this behavior is fully dependent to the implementation of the method.

Listener and Interface

In StarBasic, you can create new listener using CreateUnoListener runtime function with some subroutines or functions.

 Sub Add
 
   d = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
   listener = CreateUnoListener("ActionListener", "com.sun.star.awt.XActionListener")
   d.getControl("CommandButton1").addActionListener(listener)
   d.execute()
   d.dispose()
 
 End Sub
 
 
 
 Sub ActionListener_actionPerformed(ev)
 
 End Sub
 
 Sub ActionListener_disposing(ev)
 
 End Sub

In Python, you have define your own class with desired interfaces. With helper class, you can define easily as follows:

 import unohelper
 
 from com.sun.star.awt import XActionListener
 
 
 class ActionListener(unohelper.Base, XActionListener):
     def __init__(self):
         pass
 
     def disposing(self, ev):
         pass
 
     def actionPerformed(self, ev):
 
         pass

unohelper.Base class provides required interface for UNO components.

Containers

In StarBasic, container object provides the way to access to its contents in sequentially.

In Python, there is no shortcut provided.

If you need to access to elements of indexed container, use range function to generate sequential indexes.

 for i in range(container.getCount()):
     obj = container.getByIndex(i)

URL and System Path

If you work with a file stored in your local file system, you have to get its corresponding URL.

In StarBasic, ConvertToURL runtime function is prepared for this task. And there is ConvertFromURL runtime function for reverse conversion.

In Python, the following functions are defined in uno module for such task.

 import uno
 
 path = "/home/foo/Documents/file.odt"
 url = uno.sytemPathToFileUrl(path)
 path = uno.fileUrlToSystemPath(url)

Arguments and Return Value

In StarBasic, mode of the first argument of parseStrict method is "inout" in the following code:

 aURL = CreateUnoStruct("com.sun.star.util.URL")
 aURL.Complete = ".uno:Paste"
 CreateUnoService("com.sun.star.util.URLTransformer").parseStrict(aURL)

The content of aURL variable is updated after calling the method.

In Python, out mode parameter is returned as part of return value.

 from com.sun.star.util import URL
 
 aURL = URL()
 aURL.Complete = ".uno:Paste"
 dummy, aURL = smgr.createInstanceWithContext("com.sun.star.util.URLTransformer", ctx).parseStrict(aURL)
 # Definition of com.sun.star.util.XURLTransformer::parseStrict method: 
 # void parseStrict([inout] com.sun.star.util.URL aURL);

If a method has out mode in its parameters, its return is always tuple that contains original return value and values for out parameters.

Here is a potential example:

 # boolean getSomeValue([in] string aName, [out] short aNum, [inout] long aNum2);
 result, num, num2 = obj.getSomeValue("foo", 100, 200)

In the above example, result variable takes original return value, num takes output value for second parameter and num2 takes output value for third parameter. The method takes 100 as the second parameter but it is not used as input of value. No entry in returned tuple for in mode parameter.

Functions to be Executed

In Basic, you can not choose routines to be executed by users.

In Python, define g_exportedScripts variable that contains tuple of callable in your macro file.

 def func_a(): pass
 def func_b(): pass
 def func_hidden(): pass # not shown in the UI
 
 g_exportedScripts = func_a, func_b

In the above code, func_hidden is not shown in execution dialog of macros.

Importing Modules

Dialog

Message Box

Input Box

Personal tools