<このシリーズの、前の記事 | このシリーズの目次 | このシリーズの、次の記事>
LibreOfficeまたはApache OpenOfficeのCalcスプレッドシートを拡張機能を通してJavaまたはマクロプログラムから操作する(読むまたは書く)方法を知る
今や、我々は、UNO拡張機能を開発する方法を知っている。しかし、おそらくは、LibreOfficeドキュメントとやり取りしたいだろう。
おそらくは、そうだろう。LibreOfficeドキュメントとやり取りする必要がないのであれば、普通、通常のJavaプログラムを開発すればよい。
典型的な要件は、スプレッドシートセルから読んだりスプレッドシートセルに書いたりすることだ。
そうする方法を学べば、スプレッドシートドキュメントを操作することが可能になってくるだろう。
スプレッドシートドキュメントは特定のUNOコンポーネント群のインスタンス群で構成されているので、これらのUNOコンポーネントが何で、これらのUNOコンポーネントのインスタンスをどのように操作すればよいかを学ばなければならない。
いいだろう。
スプレッドシートドキュメントは、スプレッドシートドキュメントを新規作成したり、スプレッドシートドキュメントファイルを開いたときに、開くものだ。
ははあ。スプレッドシートドキュメントを新規作成すると、一つのウィンドウが開き、デフォルト設定では、それは1つのスプレッドシートを持っている。
そう。スプレッドシートドキュメントは、スプレッドシート群のコンテナだ。
スプレッドシートドキュメントコンポーネントは、以下のUNOインターフェースを実装している。
com.sun.star.container.XChild
com.sun.star.document.XDocumentPropertiesSupplier
com.sun.star.document.XCmisDocument
com.sun.star.rdf.XDocumentMetadataAccess
com.sun.star.document.XDocumentRecovery
com.sun.star.document.XUndoManagerSupplier
com.sun.star.document.XEventBroadcaster
com.sun.star.document.XDocumentEventBroadcaster
com.sun.star.lang.XEventListener
com.sun.star.document.XEventsSupplier
com.sun.star.document.XEmbeddedScripts
com.sun.star.document.XScriptInvocationContext
com.sun.star.frame.XModel2
com.sun.star.util.XModifiable2
com.sun.star.view.XPrintable
com.sun.star.view.XPrintJobBroadcaster
com.sun.star.frame.XStorable2
com.sun.star.frame.XLoadable
com.sun.star.script.XStarBasicAccess
com.sun.star.document.XViewDataSupplier
com.sun.star.util.XCloseable
com.sun.star.datatransfer.XTransferable
com.sun.star.document.XDocumentSubStorageSupplier
com.sun.star.document.XStorageBasedDocument
com.sun.star.script.provider.XScriptProviderSupplier
com.sun.star.ui.XUIConfigurationManagerSupplier
com.sun.star.embed.XVisualObject
com.sun.star.lang.XUnoTunnel
com.sun.star.frame.XModule
com.sun.star.frame.XTitle
com.sun.star.frame.XTitleChangeBroadcaster
com.sun.star.frame.XUntitledNumbers
com.sun.star.lang.XTypeProvider
com.sun.star.uno.XWeak
com.sun.star.sheet.XSpreadsheetDocument
com.sun.star.document.XActionLockable
com.sun.star.sheet.XCalculatable
com.sun.star.util.XProtectable
com.sun.star.drawing.XDrawPagesSupplier
com.sun.star.sheet.XGoalSeek
com.sun.star.sheet.XConsolidatable
com.sun.star.sheet.XDocumentAuditing
com.sun.star.style.XStyleFamiliesSupplier
com.sun.star.view.XRenderable
com.sun.star.document.XLinkTargetSupplier
com.sun.star.beans.XPropertySet
com.sun.star.lang.XMultiServiceFactory
com.sun.star.lang.XServiceInfo
com.sun.star.util.XChangesNotifier
com.sun.star.sheet.opencl.XOpenCLSelection
com.sun.star.util.XNumberFormatsSupplier
com.sun.star.lang.XUnoTunnel
com.sun.star.lang.XTypeProvider
com.sun.star.uno.XWeak
com.sun.star.uno.XAggregation
うーん、多くのUNOインターフェースを実装しているな . . .
UNOコンポーネントがどのUNOインターフェースを実装しているかを知ることが重要だ。それを知らなければ、UNOコンポーネントのメソッドを呼ぶことができない。
UNOコンポーネントに実装されているUNOインターフェースを我々はどのように知ることができるのか?
一般的に言って、どのオフィシャル文書からもそれを知ることができない。あるメソッドの戻りとしてあるUNOオブジェクトを得るとき、そのUNOオブジェクトのUNOコンポーネントがその戻りタイプのUNOインターフェースを実装していることしか、我々は知らない。そのUNOコンポーネントは他にどんなUNOインターフェースを実装しているのか?オフィシャル文書からは我々はそれを知ることができない。
ふーむ。
我々は、上記UNOインターフェースを、実行時にスプレッドシートドキュメントUNOオブジェクトを調べることで知った。
ふーむ、ここでは、どのようにそうしたかに深入りするのはやめよう。話が脱線するから。
スプレッドシートは、スプレッドシートドキュメントのスプレッドシートタブをクリックしたときに表示されるシートだ。スプレッドシートは、スプレッドシートセル群を持っている。
スプレッドシートコンポーネントは以下のUNOインターフェースを実装している。
com.sun.star.beans.XPropertySet
com.sun.star.beans.XMultiPropertySet
com.sun.star.beans.XPropertyState
com.sun.star.sheet.XSheetOperation
com.sun.star.chart.XChartDataArray
com.sun.star.util.XIndent
com.sun.star.sheet.XCellRangesQuery
com.sun.star.sheet.XFormulaQuery
com.sun.star.util.XReplaceable
com.sun.star.util.XModifyBroadcaster
com.sun.star.lang.XServiceInfo
com.sun.star.lang.XUnoTunnel
com.sun.star.lang.XTypeProvider
com.sun.star.sheet.XCellRangeAddressable
com.sun.star.sheet.XSheetCellRange
com.sun.star.sheet.XArrayFormulaRange
com.sun.star.sheet.XArrayFormulaTokens
com.sun.star.sheet.XCellRangeData
com.sun.star.sheet.XCellRangeFormula
com.sun.star.sheet.XMultipleOperation
com.sun.star.util.XMergeable
com.sun.star.sheet.XCellSeries
com.sun.star.table.XAutoFormattable
com.sun.star.util.XSortable
com.sun.star.sheet.XSheetFilterableEx
com.sun.star.sheet.XSubTotalCalculatable
com.sun.star.table.XColumnRowRange
com.sun.star.util.XImportable
com.sun.star.sheet.XCellFormatRangesSupplier
com.sun.star.sheet.XUniqueCellFormatRangesSupplier
com.sun.star.sheet.XSpreadsheet
com.sun.star.container.XNamed
com.sun.star.sheet.XSheetPageBreak
com.sun.star.sheet.XCellRangeMovement
com.sun.star.table.XTableChartsSupplier
com.sun.star.sheet.XDataPilotTablesSupplier
com.sun.star.sheet.XScenariosSupplier
com.sun.star.sheet.XSheetAnnotationsSupplier
com.sun.star.drawing.XDrawPageSupplier
com.sun.star.sheet.XPrintAreas
com.sun.star.sheet.XSheetAuditing
com.sun.star.sheet.XSheetOutline
com.sun.star.util.XProtectable
com.sun.star.sheet.XScenario
com.sun.star.sheet.XScenarioEnhanced
com.sun.star.sheet.XSheetLinkable
com.sun.star.sheet.XExternalSheetName
com.sun.star.document.XEventsSupplier
ははあ。
そして、スプレッドシートセルは、スプレッドシートにグリッド状に置かれているセル群の中の1つだ。
スプレッドシートセルコンポーネントは以下のUNOインターフェースを実装している。
com.sun.star.beans.XPropertySet
com.sun.star.beans.XMultiPropertySet
com.sun.star.beans.XPropertyState
com.sun.star.sheet.XSheetOperation
com.sun.star.chart.XChartDataArray
com.sun.star.util.XIndent
com.sun.star.sheet.XCellRangesQuery
com.sun.star.sheet.XFormulaQuery
com.sun.star.util.XReplaceable
com.sun.star.util.XModifyBroadcaster
com.sun.star.lang.XServiceInfo
com.sun.star.lang.XUnoTunnel
com.sun.star.lang.XTypeProvider
com.sun.star.sheet.XCellRangeAddressable
com.sun.star.sheet.XSheetCellRange
com.sun.star.sheet.XArrayFormulaRange
com.sun.star.sheet.XArrayFormulaTokens
com.sun.star.sheet.XCellRangeData
com.sun.star.sheet.XCellRangeFormula
com.sun.star.sheet.XMultipleOperation
com.sun.star.util.XMergeable
com.sun.star.sheet.XCellSeries
com.sun.star.table.XAutoFormattable
com.sun.star.util.XSortable
com.sun.star.sheet.XSheetFilterableEx
com.sun.star.sheet.XSubTotalCalculatable
com.sun.star.table.XColumnRowRange
com.sun.star.util.XImportable
com.sun.star.sheet.XCellFormatRangesSupplier
com.sun.star.sheet.XUniqueCellFormatRangesSupplier
com.sun.star.table.XCell
com.sun.star.sheet.XCellAddressable
com.sun.star.text.XText
com.sun.star.container.XEnumerationAccess
com.sun.star.sheet.XSheetAnnotationAnchor
com.sun.star.text.XTextFieldsSupplier
com.sun.star.document.XActionLockable
com.sun.star.sheet.XFormulaTokens
com.sun.star.table.XCell2
ははあ。
これで、これらのUNOコンポーネントがどのUNOインターフェースを実装しているかを知ったが、まず、UNOオブジェクトへのリファレンスを得ることが必要だ。
勿論。
典型的なユースケースは、カレントスプレッドシートへのリファレンスを得ることだろう。
「カレント」というのは、現在フォーカスされているスプレッドシートのことか?
そう。それは、以下のようにしてできる。ここで、'componentContext'はコンポーネントコンテキストだ。
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.frame.XDesktop;
import com.sun.star.frame.XModel;
import com.sun.star.sheet.XSpreadsheetDocument;
import com.sun.star.sheet.XSpreadsheet;
import com.sun.star.sheet.XSpreadsheetView;
import thebiasplanet.coreutilities.messaging.Publisher;
XDesktop l_unoDesktop = null;
try {
l_unoDesktop = (XDesktop) UnoRuntime.queryInterface (XDesktop.class, componentContext.getServiceManager ().createInstanceWithContext ("com.sun.star.frame.Desktop", componentContext));
}
catch (com.sun.star.uno.Exception l_exception) {
Publisher.show (l_exception.toString ());
}
XSpreadsheetDocument l_currentSpreadSheetsDocument = (XSpreadsheetDocument) UnoRuntime.queryInterface (XSpreadsheetDocument.class, l_unoDesktop.getCurrentComponent ());
Publisher.show (l_currentSpreadSheetsDocument.toString ());
XModel l_currentSpreadSheetsDocumentModel = (XModel) UnoRuntime.queryInterface (XModel.class, l_currentSpreadSheetsDocument);
XSpreadsheetView l_currentSpreadSheetsDocumentView = (XSpreadsheetView) UnoRuntime.queryInterface (XSpreadsheetView.class, l_currentSpreadSheetsDocumentModel.getCurrentController ());
Object l_currentSpreadSheet = l_currentSpreadSheetsDocumentView .getActiveSheet ();
Publisher.show (l_currentSpreadSheet.toString ());
'l_currentSpreadSheet'がカレントスプレッドシートで、カレントスプレッドシートドキュメントは既に'l_currentSpreadSheetsDocument'として得られている。
それにしても、ただカレントスプレッドシートを得るだけなのに面倒だな。
基本的に、UNOオブジェクトを操作するのは面倒だ。というのは、1つのUNOオブジェクトが多くのUNOインターフェースを実装しており、使おうとする各UNOインターフェース毎にUNOプロキシを得なければならないから。面倒だから、便利なように、我々は、後に、ユーティリティクラスやラッパークラスを作るだろう。
いいだろう。
ところで、我々は、サービス、'com.sun.star.frame.Desktop'のインスタンスを生成した。これはシングルトンではないのか?つまり、デスクトップは、1個しかないはずで、既に存在しているはずだ。複数のデスクトップを生成するのは妙に思える。
うーん、 . . . 私が知る限りでは、それはシングルトンであるようだ。2つのUNOプロキシが参照するUNOオブジェクトの同一性を、メソッド、'UnoRuntime.areSame'でチェックできるが、'componentContext.getServiceManager ().createInstanceWithContext ("com.sun.star.frame.Desktop", componentContext)' を2度呼んで得られる2つのUNOプロキシは同一のUNOオブジェクトを参照しているようだ。'createInstanceWithContext'メソッドがどのようにこのシングルトンを戻しているのか?私には分からない。
ふーむ . . .、我々のサンプルUNO拡張機能を開発した方法からすると、どのようにそれが可能なのか、私には理解できない。
参考文書には、それについての説明を見つけられなかった。. . . これは、将来、調査することにしよう。
いいだろう。
同じスプレッドシートドキュメントの別のスプレッドシートへのリファレンスを得たければ、それは以下のようにして得ることができる。
import com.sun.star.sheet.XSpreadsheets;
import com.sun.star.container.NoSuchElementException;
import com.sun.star.lang.WrappedTargetException;
XSpreadsheets l_currentSpreadSheets = l_currentSpreadSheetsDocument.getSheets ();
Object l_anotherSpreadSheet = null;
try {
l_anotherSpreadSheet = l_currentSpreadSheets .getByName ("Sheet2");
Publisher.show (l_anotherSpreadSheet.toString ());
}
catch (NoSuchElementException | WrappedTargetException l_exception) {
Publisher.show (l_exception.toString ());
}}
スプレッドシート名によってそれを得ることができる。
スプレッドシート上のあるスプレッドシートセルへのリファレンスを得たければ、以下のようにしてそれを得ることができる。ここで、2は列のインデックスで、0は行のインデックスだ。
import com.sun.star.table.XCell;
XSpreadsheet l_currentSpreadSheetInXSpreadsheet = (XSpreadsheet) UnoRuntime.queryInterface (XSpreadsheet .class, l_currentSpreadSheet );
XCell l_spreadSheetCell = null;
try {
l_spreadSheetCell = l_currentSpreadSheetInXSpreadsheet.getCellByPosition (2, 0);
Publisher.show (l_spreadSheetCell.toString ());
}
catch (com.sun.star.lang.IndexOutOfBoundsException l_exception) {
Publisher.show (l_exception.toString ());
}
列インデックスや行インデックスは0から開始するわけだ。
スプレッドシートセルの列インデックスと行インデックスによって、スプレッドシート上の任意のスプレッドシートセルへの参照を得ることができるが、場合によっては、カレントスプレッドシートセルへの参照を得たいと思うだろう。
それは、予期できる要求だ。
それは、以下のようにして得られる。
import com.sun.star.table.XCellRange;
XCellRange l_currentCells = (XCellRange) UnoRuntime.queryInterface (XCellRange.class, l_currentSpreadSheetsDocumentModel.getCurrentSelection ());
XCell l_currentSpreadSheetCell = null;
try {
l_currentSpreadSheetCell = l_currentCells.getCellByPosition (0, 0);
Publisher.show (l_currentSpreadSheetCell.toString ());
}
catch (com.sun.star.lang.IndexOutOfBoundsException l_exception) {
Publisher.show (l_exception.toString ());
}
なるほど。