从 Basic 中调用 Python 脚本

可以从LibreOffice Basic宏调用Python脚本,从而获得一些有用的功能,例如:

tip

A reasonable exposure to LibreOffice Basic and to Application Programming Interface (API) features is recommended prior to perform inter-language calls from Basic to Python, to JavaScript or any other script engine.


检索Python脚本

Python脚本可以是个人的、共享的,也可以嵌入到文档中。为了执行它们,需要为LibreOffice Basic提供Python脚本位置。定位com.sun.star.script.provider.XScript兼容接口的UNO对象允许执行Python脚本:


         Option Explicit
             
         Public Function GetPythonScript(macro As String, _
                 Optional location As String) As com.sun.star.script.provider.Xscript
             '''在执行前抓取Python脚本对象
             ' 参数:
             '    宏   : 为 "library/module.py$macro" 或者 "module.py$macro"
             '    位置:作为“文档”、“共享”、“用户”或枚举 ENUM(eration)
             ' 结果:
             '    定位到的 com.sun.star.script.provider.XScript UNO 服务'''
             If IsMissing(location) Then location = "user"
             Dim mspf As Object ' com.sun.star.script.provider.MasterScriptProviderFactory
             Dim sp As Object ' 与 com.sun.star.script.provider.XScriptProvider 兼容
             Dim uri As String
             If location="document" Then
                 sp = ThisComponent.getScriptProvider()
             Else
                 mspf = CreateUNOService("com.sun.star.script.provider.MasterScriptProviderFactory")
                 sp = mspf.createScriptProvider("")
             End If
             uri = "vnd.sun.star.script:"& macro &"?language=Python&location="& location
             GetPythonScript = sp.getScript(uri)
         End Function ' GetPythonScript
      

执行Python脚本

LibreOffice 的应用程序编程接口 (API) 脚本框架支持在 Python 和 Basic 之间(或者其他受支持的编程语言之间)的跨语言脚本执行。参数可以互相之间来回传递,仅需要该参数是各个语言都能够识别的基本数据类型、且脚本框架能够对该参数进行适当的类型转换。

语法

workstation_name = script.invoke(Array(), Array(), Array())

opSysName = script.invoke(Array(), in_outs, Array()) ' in_out 为数组

file_len = script.invoke(Array(systemFilePath), Array(), Array())

normalizedPath = script.invoke(Array(systemFilePath), Array(), Array())

嵌入式脚本示例

下面的ComputerNameGetFilelen程序使用前面提到的GetPythonScript函数调用它们对应的Python程序。此处未对异常处理进行详细说明。


         Option Explicit
         Option Compatible ' 支持进行属性的设置
             
         Private scr As Object ' com.sun.star.script.provider.XScript
             
         Private Property Get ComputerName As String
             '''工作站名称'''
             scr = GetPythonScript("Platform.py$computer_name", "document")
             ComputerName = scr.invoke(Array(), Array(), Array())
         End Property ' ComputerName
             
         Private Function GetFilelen(systemFilePath As String) As Currency
             '''文件大小(字节)'''
             scr = GetPythonScript("Os/Path.py$get_size", Script.ISEMBEDDED)
             GetFilelen = scr.invoke(Array(systemFilePath), Array(), Array(),)
         End Function ' GetFilelen
             
         Private Type _SCRIPT_LOCATION
             ISEMBEDDED As String ' 文档级的脚本
             ISPERSONAL As String ' 用户级的脚本
             ISSHARED As String ' LibreOffice 级别的宏
         End Type ' _SCRIPT_LOCATION
             
         Public Function Script() As Object ' Text enumeration
             Static enums As _SCRIPT_LOCATION : With enums
             If .ISEMBEDDED = "" Then
                 .ISEMBEDDED = "document" '文档级别的脚本
                 .ISPERSONAL = "user" ' 用户级别的脚本
                 .ISSHARED = "share" ' LibreOffice 宏
             End If : End With ' enums
             Script = enums
         End Function ' Script
      

调用了两个不同的Python模块。它们可以嵌入到当前文档中,也可以存储在文件系统中。为清晰起见,此处跳过了参数类型检查:


         # -*- coding: utf-8 -*-
         from __future__ import unicode_literals
          
         import platform
          
         def computer_name() -> str:
             return platform.node()
          
         def OSname() -> str:
             return platform.system()
      

         # -*- coding: utf-8 -*-
         from __future__ import unicode_literals
          
         import os.path
          
         def get_size(systemFilePath: str) -> str:
             return str(os.path.getsize(systemFilePath))
          
         def normalyze(systemPath: str) -> str:
             return os.path.normpath(systemPath)
      

个人或共享脚本示例

个人或共享Python脚本的调用机制与嵌入式脚本的调用机制相同。库名称映射到文件夹。计算LibreOffice用户配置文件和共享模块系统文件路径可以按照获取会话信息中的详细说明执行。在OSName的下面,HelloWorldNormalizePath例程使用前面提到的GetPythonScript函数调用Python对应程序。异常处理未详细说明。


         Option Explicit
         Option Compatible ' 支持进行属性的设置
             
         Private scr As Object ' com.sun.star.script.provider.XScript
             
         Private Property Get OSName As String
             '''平台名称为“Linux”、“Darwin”或“Windows”'''
             scr = GetPythonScript("Platform.py$OSname", Script.ISPERSONAL)
             OSName = scr.invoke(Array(), Array(), Array()) 
         End Property ' OSName
             
         Private Sub HelloWorld()
             '''LibreOffice Python 共享示例'''
             scr = GetPythonScript("HelloWorld.py$HelloWorldPython", Script.ISSHARED)
             scr.invoke(Array(), Array(), Array(),)
         End Sub ' HelloWorld
             
         Public Function NormalizePath(systemFilePath As String) As String
             '''去除路径中多余的 '\..' '''
             scr = GetPythonScript("Os/Path.py$normalyze", "user")
             NormalizePath = scr.invoke(Array(systemFilePath), Array(), Array())
         End Function ' NormalizePath
      

Python标准模块

LibreOffice embedded Python包含许多可从中受益的标准库。它们具有丰富的功能集,例如但不限于:

请支持我们!