前の関連記事:LibreOffice5(97)SimpleFileAccess、TextOutputStream、TextInputStream、Pipeのサービスとインターフェイスの一覧
Javaの例:ChildrenRetrieverをPythonにする
import unohelper # オートメーションには必須(必須なのはuno)。
from itertools import zip_longest
from com.sun.star.sheet import CellFlags as cf # 定数
from com.sun.star.beans import Property # Struct
from com.sun.star.ucb import OpenCommandArgument2 # Struct
from com.sun.star.ucb import OpenMode # 定数
from com.sun.star.ucb import Command # Struct
def macro(documentevent=None): # 引数は文書のイベント駆動用。
doc = XSCRIPTCONTEXT.getDocument() if documentevent is None else documentevent.Source # ドキュメントのモデルを取得。
contenturl = "file:///" # 子要素のプロパティを取得したい親要素のfileurl
propnames = "Title", "IsDocument" # 取得するプロパティのタプル。
ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。
smgr = ctx.getServiceManager() # サービスマネージャーの取得。
ucb = smgr.createInstanceWithContext("com.sun.star.ucb.UniversalContentBroker", ctx) # UniversalContentBroker
content = ucb.queryContent(ucb.createContentIdentifier(contenturl)) # fileurlを元にFile Contentsを取得。
if content: # File Contentsが取得できた時。
props = [Property(Name=propname, Handle=-1) for propname in propnames]
arg = OpenCommandArgument2(Mode=OpenMode.ALL, Priority=32768, Properties=props)
command = Command(Name="open", Handle=-1, Argument=arg) # NameとArgumentでexecute()の戻り値の型が決まる。
dynamicresultset = content.execute(command, 0, None) # XDynamicResultSet型が返る。
resultset = dynamicresultset.getStaticResultSet()
outputs = []
flg = resultset.first()
while flg:
propsvalues = [resultset.queryContentIdentifierString()]
for i in range(1, len(props)+1):
propvalue = resultset.getObject(i, None)
if isinstance(propvalue, bool): # ブール型の時
propvalue = str(propvalue) # 文字列に変換する。シートに出力するため。
elif propvalue is None:
propvalue = "[ Property not found ]"
propsvalues.append(propvalue)
outputs.append(propsvalues)
flg = resultset.next()
sheet = getNewSheet(doc, "ChidrenRetriever") # 新規シートの取得。
datarows = [("URL:", *["{}:".format(p) for p in propnames])]
datarows.extend(outputs)
rowsToSheet(sheet[2, 0], datarows) # datarowsをシートに書き出し。代入範囲の列幅も最適化される。
sheet[0, 0].setString("ChildrenRetriever - obtains the children of a folder resource")
sheet[1, 0].setString("Children of resource {}".format(contenturl))
controller = doc.getCurrentController() # コントローラの取得。
controller.setActiveSheet(sheet) # シートをアクティブにする。
def rowsToSheet(cellrange, datarows): # 引数のセル範囲を左上端にして一括書き込みして列幅を最適化する。datarowsはタプルのタプル。
datarows = tuple(zip(*zip_longest(*datarows, fillvalue=""))) # 一番長い行の長さに合わせて空文字を代入。
sheet = cellrange.getSpreadsheet() # セル範囲のあるシートを取得。
cellcursor = sheet.createCursorByRange(cellrange) # セル範囲のセルカーサーを取得。
cellcursor.collapseToSize(len(datarows[0]), len(datarows)) # (列、行)で指定。セルカーサーの範囲をdatarowsに合せる。
cellcursor.setDataArray(datarows) # セルカーサーにdatarowsを代入。代入できるのは整数(int、ただしboolを除く)か文字列のみ。
cellcursor.getColumns().setPropertyValue("OptimalWidth", True) # セルカーサーのセル範囲の列幅を最適化する。行幅は限定サれない。
def getNewSheet(doc, sheetname): # docに名前sheetnameのシートを返す。sheetnameがすでにあれば連番名を使う。
cellflags = cf.VALUE+cf.DATETIME+cf.STRING+cf.ANNOTATION+cf.FORMULA+cf.HARDATTR+cf.STYLES
sheets = doc.getSheets() # シートコレクションを取得。
c = 1 # 連番名の最初の番号。
newname = sheetname
while newname in sheets: # 同名のシートがあるとき。sheets[newname]ではFalseのときKeyErrorになる。
if not sheets[newname].queryContentCells(cellflags): # シートが未使用のとき
return sheets[newname] # 未使用の同名シートを返す。
newname = "{}{}".format(sheetname, c) # 連番名を作成。
c += 1
sheets.insertNewByName(newname, len(sheets)) # 新しいシートを挿入。同名のシートがあるとRuntimeExceptionがでる。
if "Sheet1" in sheets: # デフォルトシートがあるとき。
if not sheets["Sheet1"].queryContentCells(cellflags): # シートが未使用のとき
del sheets["Sheet1"] # シートを削除する。
return sheets[newname]
g_exportedScripts = macro, #マクロセレクターに限定表示させる関数をタプルで指定。
結果はCalcに出力しています。ChildrenRetriever.ods
このマクロを埋め込んだCalcドキュメントです。
linuxBeanで実行すると以下のような出力が得られました。
10行目でfileurlで指定しているフォルダの子要素のプロパティのTitleとIsDocumentの結果を取得して出力しています。
Windows10で実行すると次のようになりました。
LibreOffice 6.0 SDK - Developer's Guide Examplesの例はUCBの実装するための例のようで、実際に応用して使う機会はなさそうです、、、と思ったのですが、LibreOffice5(109)子要素にフォルダしか持たないドキュメント内フォルダでサブフォルダの要素まで再帰的に求めるマクロを作成しました。
UniversalContentBrokerのサービスとインターフェイスの一覧
def macro():
ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。
smgr = ctx.getServiceManager() # サービスマネージャーの取得。
tcu = smgr.createInstanceWithContext("pq.Tcu", ctx) # サービス名か実装名でインスタンス化。
ucb = smgr.createInstanceWithContext("com.sun.star.ucb.UniversalContentBroker", ctx)
tcu.wtree(ucb)
├─.ucb.UniversalContentBroker
│ └─.ucb.XUniversalContentBroker
│ ├─.lang.XComponent
│ │ void addEventListener( [in] .lang.XEventListener xListener)
│ │ void dispose()
│ │ void removeEventListener( [in] .lang.XEventListener aListener)
│ ├─.ucb.XCommandProcessor2
│ │ │ void releaseCommandIdentifier( [in] long CommandId)
│ │ └─.ucb.XCommandProcessor
│ │ void abort( [in] long CommandId)
│ │ long createCommandIdentifier()
│ │ any execute( [in] .ucb.Command aCommand,
│ │ [in] long CommandId,
│ │ [in] .ucb.XCommandEnvironment Environment
│ │ ) raises ( .ucb.CommandAbortedException,
│ │ .uno.Exception)
│ ├─.ucb.XContentIdentifierFactory
│ │ .ucb.XContentIdentifier createContentIdentifier( [in] string ContentId)
│ ├─.ucb.XContentProvider
│ │ long compareContentIds( [in] .ucb.XContentIdentifier Id1,
│ │ [in] .ucb.XContentIdentifier Id2)
│ │ .ucb.XContent queryContent( [in] .ucb.XContentIdentifier Identifier
│ │ ) raises ( .ucb.IllegalIdentifierException)
│ └─.ucb.XContentProviderManager
│ void deregisterContentProvider( [in] .ucb.XContentProvider Provider,
│ [in] string Scheme)
│ .ucb.XContentProvider queryContentProvider( [in] string Identifier)
│ [.ucb.ContentProviderInfo] queryContentProviders()
│ .ucb.XContentProvider registerContentProvider( [in] .ucb.XContentProvider Provider,
│ [in] string Scheme,
│ [in] boolean ReplaceExisting
│ ) raises ( .ucb.DuplicateProviderException)
└─.lang.XInitialization
void initialize( [in] [any] aArguments
) raises ( .uno.Exception)
│ └─.ucb.XUniversalContentBroker
│ ├─.lang.XComponent
│ │ void addEventListener( [in] .lang.XEventListener xListener)
│ │ void dispose()
│ │ void removeEventListener( [in] .lang.XEventListener aListener)
│ ├─.ucb.XCommandProcessor2
│ │ │ void releaseCommandIdentifier( [in] long CommandId)
│ │ └─.ucb.XCommandProcessor
│ │ void abort( [in] long CommandId)
│ │ long createCommandIdentifier()
│ │ any execute( [in] .ucb.Command aCommand,
│ │ [in] long CommandId,
│ │ [in] .ucb.XCommandEnvironment Environment
│ │ ) raises ( .ucb.CommandAbortedException,
│ │ .uno.Exception)
│ ├─.ucb.XContentIdentifierFactory
│ │ .ucb.XContentIdentifier createContentIdentifier( [in] string ContentId)
│ ├─.ucb.XContentProvider
│ │ long compareContentIds( [in] .ucb.XContentIdentifier Id1,
│ │ [in] .ucb.XContentIdentifier Id2)
│ │ .ucb.XContent queryContent( [in] .ucb.XContentIdentifier Identifier
│ │ ) raises ( .ucb.IllegalIdentifierException)
│ └─.ucb.XContentProviderManager
│ void deregisterContentProvider( [in] .ucb.XContentProvider Provider,
│ [in] string Scheme)
│ .ucb.XContentProvider queryContentProvider( [in] string Identifier)
│ [.ucb.ContentProviderInfo] queryContentProviders()
│ .ucb.XContentProvider registerContentProvider( [in] .ucb.XContentProvider Provider,
│ [in] string Scheme,
│ [in] boolean ReplaceExisting
│ ) raises ( .ucb.DuplicateProviderException)
└─.lang.XInitialization
void initialize( [in] [any] aArguments
) raises ( .uno.Exception)
参考にしたサイト
LibreOffice 6.0 SDK - Developer's Guide Examples
Javaの例:Universal Content Broker (UCB) examplesのChildrenRetrieverをPythonにしました。


0 件のコメント:
コメントを投稿