2017年7月15日土曜日

23: スプレッドシートセルから読んだりスプレッドシートセルに書いたりする、パート1

<このシリーズの、前の記事 | このシリーズの目次 | このシリーズの、次の記事>

Main body START

LibreOfficeまたはApache OpenOfficeのCalcスプレッドシートを拡張機能を通してJavaまたはマクロプログラムから操作する(読むまたは書く)方法を知る

スプレッドシートセルから読んだりスプレッドシートセルに書いたりしたい

-Hypothesizer

今や、我々は、UNO拡張機能を開発する方法を知っている。しかし、おそらくは、LibreOfficeドキュメントとやり取りしたいだろう。

-Rebutter

おそらくは、そうだろう。LibreOfficeドキュメントとやり取りする必要がないのであれば、普通、通常のJavaプログラムを開発すればよい。

-Hypothesizer

典型的な要件は、スプレッドシートセルから読んだりスプレッドシートセルに書いたりすることだ。

-Rebutter

そうする方法を学べば、スプレッドシートドキュメントを操作することが可能になってくるだろう。

-Hypothesizer

スプレッドシートドキュメントは特定のUNOコンポーネント群のインスタンス群で構成されているので、これらのUNOコンポーネントが何で、これらのUNOコンポーネントのインスタンスをどのように操作すればよいかを学ばなければならない。

-Rebutter

いいだろう。

スプレッドシートドキュメントとは何か?スプレッドシートとは何か?スプレッドシートセルとは何か?

-Hypothesizer

スプレッドシートドキュメントは、スプレッドシートドキュメントを新規作成したり、スプレッドシートドキュメントファイルを開いたときに、開くものだ。

-Rebutter

ははあ。スプレッドシートドキュメントを新規作成すると、一つのウィンドウが開き、デフォルト設定では、それは1つのスプレッドシートを持っている。

-Hypothesizer

そう。スプレッドシートドキュメントは、スプレッドシート群のコンテナだ。

スプレッドシートドキュメントコンポーネントは、以下の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
-Rebutter

うーん、多くのUNOインターフェースを実装しているな . . .

-Hypothesizer

UNOコンポーネントがどのUNOインターフェースを実装しているかを知ることが重要だ。それを知らなければ、UNOコンポーネントのメソッドを呼ぶことができない。

-Rebutter

UNOコンポーネントに実装されているUNOインターフェースを我々はどのように知ることができるのか?

-Hypothesizer

一般的に言って、どのオフィシャル文書からもそれを知ることができない。あるメソッドの戻りとしてあるUNOオブジェクトを得るとき、そのUNOオブジェクトのUNOコンポーネントがその戻りタイプのUNOインターフェースを実装していることしか、我々は知らない。そのUNOコンポーネントは他にどんなUNOインターフェースを実装しているのか?オフィシャル文書からは我々はそれを知ることができない。

-Rebutter

ふーむ。

-Hypothesizer

我々は、上記UNOインターフェースを、実行時にスプレッドシートドキュメントUNOオブジェクトを調べることで知った。

-Rebutter

ふーむ、ここでは、どのようにそうしたかに深入りするのはやめよう。話が脱線するから。

-Hypothesizer

スプレッドシートは、スプレッドシートドキュメントのスプレッドシートタブをクリックしたときに表示されるシートだ。スプレッドシートは、スプレッドシートセル群を持っている。

スプレッドシートコンポーネントは以下の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
-Rebutter

ははあ。

-Hypothesizer

そして、スプレッドシートセルは、スプレッドシートにグリッド状に置かれているセル群の中の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
-Rebutter

ははあ。

カレントスプレッドシートはどのように得られるか?

-Hypothesizer

これで、これらのUNOコンポーネントがどのUNOインターフェースを実装しているかを知ったが、まず、UNOオブジェクトへのリファレンスを得ることが必要だ。

-Rebutter

勿論。

-Hypothesizer

典型的なユースケースは、カレントスプレッドシートへのリファレンスを得ることだろう。

-Rebutter

「カレント」というのは、現在フォーカスされているスプレッドシートのことか?

-Hypothesizer

そう。それは、以下のようにしてできる。ここで、'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 ());
-Rebutter

'l_currentSpreadSheet'がカレントスプレッドシートで、カレントスプレッドシートドキュメントは既に'l_currentSpreadSheetsDocument'として得られている。

それにしても、ただカレントスプレッドシートを得るだけなのに面倒だな。

-Hypothesizer

基本的に、UNOオブジェクトを操作するのは面倒だ。というのは、1つのUNOオブジェクトが多くのUNOインターフェースを実装しており、使おうとする各UNOインターフェース毎にUNOプロキシを得なければならないから。面倒だから、便利なように、我々は、後に、ユーティリティクラスやラッパークラスを作るだろう。

-Rebutter

いいだろう。

ところで、我々は、サービス、'com.sun.star.frame.Desktop'のインスタンスを生成した。これはシングルトンではないのか?つまり、デスクトップは、1個しかないはずで、既に存在しているはずだ。複数のデスクトップを生成するのは妙に思える。

-Hypothesizer

うーん、 . . . 私が知る限りでは、それはシングルトンであるようだ。2つのUNOプロキシが参照するUNOオブジェクトの同一性を、メソッド、'UnoRuntime.areSame'でチェックできるが、'componentContext.getServiceManager ().createInstanceWithContext ("com.sun.star.frame.Desktop", componentContext)' を2度呼んで得られる2つのUNOプロキシは同一のUNOオブジェクトを参照しているようだ。'createInstanceWithContext'メソッドがどのようにこのシングルトンを戻しているのか?私には分からない。

-Rebutter

ふーむ . . .、我々のサンプルUNO拡張機能を開発した方法からすると、どのようにそれが可能なのか、私には理解できない。

-Hypothesizer

参考文書には、それについての説明を見つけられなかった。. . . これは、将来、調査することにしよう。

-Rebutter

いいだろう。

-Hypothesizer

同じスプレッドシートドキュメントの別のスプレッドシートへのリファレンスを得たければ、それは以下のようにして得ることができる。

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 ());
  }}
-Rebutter

スプレッドシート名によってそれを得ることができる。

-Hypothesizer

スプレッドシート上のあるスプレッドシートセルへのリファレンスを得たければ、以下のようにしてそれを得ることができる。ここで、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 ());
  }
-Rebutter

列インデックスや行インデックスは0から開始するわけだ。

カレントスプレッドシートセルはどのように得られるか?

-Hypothesizer

スプレッドシートセルの列インデックスと行インデックスによって、スプレッドシート上の任意のスプレッドシートセルへの参照を得ることができるが、場合によっては、カレントスプレッドシートセルへの参照を得たいと思うだろう。

-Rebutter

それは、予期できる要求だ。

-Hypothesizer

それは、以下のようにして得られる。

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 ());
  }
-Rebutter

なるほど。

Main body END

<このシリーズの、前の記事 | このシリーズの目次 | このシリーズの、次の記事>