Calc(63)セルの固定、ウィンドウの分割、の境界を取得する

2018-01-25

旧ブログ

t f B! P L
表示→セルの固定、または、ウィンドウの分割、としたときの境界を取得します。ウィンドウの分割では分割後の枠内でシート上のすべてのセルにアクセスできるのに対して、セルの固定では分割したときの境界までのセルしかアクセスできない点が異なります。

前の関連記事:Calc(62)選択したセルの上下左右に枠線を引くマクロ


XViewSplitableインターフェイスはDeprecatedになっている


コントローラがサポートしているXViewSplitableインターフェイスのgetSplitRow()メソッドでは左上の枠に表示されている最下行の次の行インデックス、getSplitColumn()メソッドでは左上の枠に表示されている右端列の右の列インデックスが取得できます。


ウィンドウの分割のこの状態ではgetSplitRow()で23、getSplitColumn()で3が返ってきます。

これらの戻り値は左上の枠の最下行と右端列のインデックスのみ依存して、他の枠の状態には依存しません。

ウィンドウの分割のときはXViewSplitableインターフェイスでは左上の枠以外のインデックスを取得することはできません。

セルの固定の時はgetSplitRow()が左下と右下のの枠の最初の行インデックス、getSplitColumn()が右上と右下の最初の列インデックスに該当します。

APIリファレンスではXViewSplitableインターフェイスはDeprecatedと書いてあるのですが、代替手段は書いてありませんでした。

Spreadsheet Document Controller - Apache OpenOffice Wiki

デベロッパーガイドにも代替手段は書いてありませんでしたが、ビューが分割か固定されているときはXIndexAccessインターフェイスで最大4つまでの枠にアクセスできると書いてあり、コントローラにインデックスアクセスがあることがわかりました。

コントローラのインデックス0のサービスとインターフェイス一覧


コントローラのインデックス0の枠は常に存在するはずなのでそのサービスとインターフェイス一覧を調べました。
def macro():
 ctx = XSCRIPTCONTEXT.getComponentContext()  # コンポーネントコンテクストの取得。
 smgr = ctx.getServiceManager()  # サービスマネージャーの取得。 
 tcu = smgr.createInstanceWithContext("pq.Tcu", ctx)  # サービス名か実装名でインスタンス化。
 doc = XSCRIPTCONTEXT.getDocument()
 controller = doc.getCurrentController()  # コントローラの取得。
 tcu.wtree(controller[0])

object
├─.sheet.SpreadsheetViewPane
│   ├─.sheet.XCellRangeReferrer
│   │      .table.XCellRange  getReferredCells()
│   ├─.sheet.XViewPane
│   │                         long  getFirstVisibleColumn()
│   │                         long  getFirstVisibleRow()
│   │      .table.CellRangeAddress  getVisibleRange()
│   │                         void  setFirstVisibleColumn( [in] long nFirstVisibleColumn)
│   │                         void  setFirstVisibleRow( [in] long nFirstVisibleRow)
│   └─.view.XControlAccess
│         .awt.XControl  getControl( [in] .awt.XControlModel xModel
│                         ) raises ( .container.NoSuchElementException)
└─.view.XFormLayerAccess
        .form.runtime.XFormController  getFormController( [in] .form.XForm Form)
                              boolean  isFormDesignMode()
                                 void  setFormDesignMode( [in] boolean DesignMode

Calc(19)Calcコントローラのサービスとインターフェイス一覧と比べるとサポートしているサービスとインターフェイスはかなり少ないです。

分割した各枠のセル範囲を取得するマクロ

def macro(documentevent=None):  # 引数は文書のイベント駆動用。
 doc = XSCRIPTCONTEXT.getDocument()  # 現在開いているドキュメントを取得。
 controller = doc.getCurrentController()  # コントローラの取得。
 for i, subcontroller in enumerate(controller):  # インデックスも取得する。
  cellrangeaddress = subcontroller.getVisibleRange()  # 見えているセル範囲のアドレスを取得。
  cellrange = subcontroller.getReferredCells()  # 見えているセル範囲を取得。
  cellrange[0, 0].setString("Index: {}\nStartRow: {}, EndRow: {}\nStartColumn: {}, EndColumn: {}"\
   .format(i, cellrangeaddress.StartRow, cellrangeaddress.EndRow, cellrangeaddress.StartColumn, cellrangeaddress.EndColumn))  # 各コントローラーのセル範囲の左上端セルにセル範囲アドレスを代入する。
  cellrange[0, 0].getRows()[0].setPropertyValue("OptimalHeight", True)
g_exportedScripts = macro, #マクロセレクターに限定表示させる関数をタプルで指定。
getReferredCells()で枠内の表示されているセル範囲が返ってくるのでそこからセル範囲アドレスも取得できるのですが、このマクロではgetVisibleRange()でセル範囲アドレスを取得しています。


D10セルを選択して表示→ウィンドウの分割、としたあとに左下の枠の開始列をBに開始行を16に変更し、上記のマクロを実行した結果です。

各枠の左上端のセルにその枠のインデックスとセル範囲アドレスのアトリビュートを表示し、その行の高さを最適化しています。

枠のインデックスは左上の0から始まり左下の枠が1、右上が2、右下が3になっていました。

各枠のセル範囲アドレスはそれぞれの枠内で画面に表示されているセル範囲に一致するのですが、左下の枠のアドレスを取得した後に行の高さを最適化しているので、右下の枠のEndRowよりずれています。


D10セルを選択して表示→セルの固定→行と列の固定、としたシートでこのマクロを実行した結果です。

セルの固定をしたときはスクロールできるのは右下の枠だけなので、インデックス0の枠のEndRow+1とEndColumn+1がセルの固定をしたときの行と列とわかります。

ウィンドウの分割のときは左上の枠の行数と列数から分割をしたときの選択セルを取得できます。

セルの固定はXViewFreezableインターフェイスのfreezeAtPosition()メソッドでできますが、ウィンドウの分割はDeprecatedになっているXViewSplitableインターフェイスのsplitAtPosition()メソッドに代わる方法はディスパッチコマンドを使う方法以外は思いつきませんでした。


セルの固定をすると左上の枠はスクロールできないのでその枠より上の行と左の列のセルは表示できなくなります。

(2018.5.26追記。 この方法は必ずしもうまくいかないようで、LibreOffice5.4ではマクロでシートを切り替えた時に切り替えた先のシートではうまく境界の列インデックスが取得できませんでした。)

次の関連記事:Calc(64)コンテナウィンドウとコンポーネントウィンドウの位置の取得

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ