2011年4月30日土曜日

ドキュメントが開いたときにフォームを表示する

この項は、スプレッドシートドキュメントが開いた時にダイアログを表示
させる方法について。
「無題1.ods」ドキュメントが開いたときに、「Dialog1」フォームを表示させる
為の手順を考える。ここで、「Dialog1」は「フォームから別のフォームを開く」
の項で使用したものを流用する。
また、「Dialog1」フォームを開くマクロは、「フォームを開く」の項で用いた
マクロ「ExampleOpenDialog1」をそのまま流用する。
  
1. メニューの「表示」→「ツールバー」→「カスタマイズ」を選択

  
2. 「カスタマイズ」ウィンドウが開いたら「イベント」タブを選択し、イベント一覧
   の中の「文書が開いた時」を選択し、「マクロ」ボタンをクリック
  
3. 「マクロセレクター」ウィンドウが表示されたら、「無題1.ods」のマクロ一覧
   より「ExampleOpenDialog1」を選択し「OK」ボタンをクリック
  
4. 再び「カスタマイズ」ウィンドウに戻り、選択したマクロが「割り当てられた
   アクション」列に表示されていることを確認し、「OK」ボタンをクリックする。
  
以上の手順でドキュメントが開くときのイベントにフォームを開くマクロを割り
当てることにより、下図のように、ドキュメントが開いた時にフォームが表示
される。
  
今回の例と同様に、「カスタマイズ」ウィンドウにあるイベントの一覧にマクロ
を割り当てることにより、Calc アプリケーションやドキュメントのイベントに
対応したイベント駆動型の処理を作成することができそうである。

2011年4月28日木曜日

フォームから別のフォームを開く

下記二つのフォーム、「Dialog1」、「Dialog2」を用意する :
  
  
  
今回は、「Dialog1」フォームの「Dialog2を開く」ボタンをクリックすると「Dialog2」
フォームが開くようにしたい。それを実現する為の手順は下記の通りである :
  
1. 二つのフォーム「Dialog1」、「Dialog2」を作成する。作成手順は「フォーム
   の新規作成」の項を参照。
  
2. 「Dialog2」フォームを開くコードを作成する。「フォームを開く」の項と同様
   だが、念のため下記にコードを記す :
  
Sub ExampleOpenDialog2()
       Dim objDialog2 As Object
       '
       'フォームをメモリに読み込む
       DialogLibraries.LoadLibrary("Standard")
       objDialog2 = CreateUnoDialog(DialogLibraries.Standard.Dialog2)
       '
       'フォーム「Dialog2」を表示する
       objDialog2.execute()
End Sub
  
3. 「Dialog1」フォームのデザイン画面を開き、「Dialog2を開く」ボタンを選択し
   た後右クリックし、「プロパティ」を選択する
    
4. 「「プロパティー」ウィンドウが開いたら「イベント」タブを選択し、「実行時」
   の部分の「...」ボタンをクリックする。
  
5. 「アクションの割り当て」ウィンドウの「実行時」イベントの行が選択されて
   いることを確認し、「マクロ」ボタンをクリックする。
  
6. 「マクロセレクター」ウィンドウの「マクロ名」一覧より、2. で作成した
   「ExampleOpenDialog2」を選択し「OK」ボタンをクリックする。
  
7. 再び「アクションの割り当て」ウィンドウに戻り、選択したマクロが「割り
   当てられたアクション」列に表示されていることを確認し、「OK」ボタン
   をクリックする。
  
以上の手順により、「Dialog1」フォームの「Dialog2を開く」ボタンをクリック
する (=「クリック」イベントが発生する) とDialog2が開くようになる。

Calcの場合、Excel のように各イベント毎にプロシージャを書くのではなく、
あらかじめ作成してあるマクロをあとからイベントに関連付ける (割り当て
る)。これが、Excel と大きく異なる点である。

2011年4月27日水曜日

フォームを開く

「フォームの新規作成」の項で作成したフォームを開くサンプルコードを下記
に記す :
  
Sub ExampleOpenDialog1()
       Dim objDialog1 As Object
       '
       'フォームをメモリに読み込む
       DialogLibraries.LoadLibrary("Standard")
       objDialog1 = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
       '
       'フォーム「Dialog1」を表示する
       objDialog1.execute()
End Sub
  
フォームを開く処理は、
  
1. フォームをメモリに読み込んでから、
2. メモリに読み込んだフォームを表示する
  
の二段階の手順を踏む。
上記コードの詳細は不明だが、オマジナイと思ってこの通りやると、ちゃんと
フォームが表示される。

フォームの新規作成

Calc において、Excel のユーザーフォームに相当するものが、ダイアログ
のようである。そのダイアログ (どうも馴染めないので、以下フォームと呼ぶ
ことにする) を新規作成する手順は下記の通りである (当方も試行錯誤ゆえ
間違っているかも知れないが) :
  
1. 「ツール」メニューの「マクロ」→「ダイアログ」を選択。

  
2. 「LibreOffice Basic マクロの管理」画面が表示されるので、対象の
   ドキュメントを選択し、「新規作成」ボタンをクリック。

  
3. 「新しいダイアログ」ウィンドウが表示されるので、フォーム名を入力し
   「OK」ボタンをクリック。今回は、デフォルトのフォーム名「Dialog1」の
   ままにしておく。
  
4. 下の画面のように、対象のドキュメントに「Dialog1」フォームが追加された
   ので、それを選択し「編集」ボタンをクリック。
  
5. デザイン画面が表示されるので、「ツールボックス」から適当なコント
   ロールを選択し画面に貼り付けていく。

2011年4月26日火曜日

データが入力されている最終行・最終列を求める

  
上図のシートで、データが入力されている最終行と最終列を求めるサンプル
コードを下記に記す :
  
Sub ExampleGetLastCellPosition()
       Dim objSheet As Object
       Dim objRange As Object
       Dim objCursor As Object
       objSheet = ThisComponent.CurrentController.Activesheet
       objRange = objSheet.getCellRangeByName("A1")
       objCursor = objSheet.createCursorByRange(objRange)
       objCursor.gotoEndOfUsedArea(True)
       Msgbox("最終行 : " & objCursor.Rows.Count & Chr$(13) & _
                      "最終列 : " & objcursor.Columns.Count)
End Sub
  
結果は下図の通り :
  
  
データが入力されている最終行、及び、最終列を求める際は
gotoEndOfUsedArea メソッドを用いるらしい。また、
  
objCursor.gotoEndOfUsedArea(True)
  
の代わりに
  
objCursor.collapseToCurrentRegion()
  
としても全く同じ結果が得られたが、理屈はよくわからない。

2011年4月25日月曜日

列の削除

  
「列の挿入」の項とは逆に、シートから列を削除するサンプルコードを
記す。この例では、上図のシートの三列目から四列の空白列を削除し
て列を挿入する前の状態に戻す処理を行っている :
  
Sub ExampleDeleteColumns()
       Dim objSheet As Object
       objSheet = ThisComponent.CurrentController.Activesheet
       objSheet.Columns.removeByIndex(2, 4)
End Sub
  
結果は下図の通り、元の状態に戻った :
  
  

シートから列を削除する場合は removeByIndex メソッドを用いる。
removeByIndex メソッドの書式は下記の通り :
  
removeByIndex(ColumnNumberLines)
  
ColumnNumber には削除したい列の列番号を指定する。この例の
場合削除したい行が三列目なので、columnNumberには 2 を指定する。
Lines には削除したい列数を指定する。
removeByIndex メソッドは、戻り値を返さない。

列の挿入

  
上記アクティブシートの三列目 (= B 列の右) に四列追加するサンプル
コードを以下に記す :
  
Sub ExampleInsertColumns()
       Dim objSheet As Object
       objSheet = ThisComponent.CurrentController.Activesheet
       objSheet.Columns.insertByIndex(2, 4)
End Sub

  
結果は下図の通り :
  
  
シートに列を挿入する場合は insertByIndex メソッドを用いる。
insertByIndex メソッドの書式は下記の通り :

insertByIndex(ColumnNumberLines)

ColumnNumber には (列を) 挿入したい列番号を指定する。列番号は 0

から始まるので、この例の場合三列目に追加したいので ColumnNumber
には 2 を指定する。
Lines には挿入したい列数を指定する。
insertByIndex メソッドは、戻り値を返さない。

行の削除


  
「行の挿入」の項とは逆に、シートから行を削除するサンプルコードを
記す。この例では、上図のシートの三行目から三行の空白行を削除し
て行を挿入する前の状態に戻す処理を行っている :
  
Sub ExampleDeleteRows()
       Dim objSheet As Object
       objSheet = ThisComponent.CurrentController.Activesheet
       objSheet.Rows.removeByIndex(2, 3)
End Sub
  
結果は下図の通り、元の状態に戻った :
  

  
  
シートから行を削除する場合は removeByIndex メソッドを用いる。
removeByIndex メソッドの書式は下記の通り :
  
removeByIndex(RowNumberLines)
  
RowNumber には削除したい行の行番号を指定する。この例の場合
削除したい行が三行目なので、RowNumberには 2 を指定する。
Lines には削除したい行数を指定する。
removeByIndex メソッドは、戻り値を返さない。

行の挿入

    
上記アクティブシートの三行目 (= 二行目の下) に三行追加するサンプル
コードを以下に記す :
  
Sub ExampleInsertRows()
       Dim objSheet As Object
       objSheet = ThisComponent.CurrentController.Activesheet
       objSheet.Rows.insertByIndex(2, 3)
End Sub
  
結果は下図の通り :
  
  
シートに行を挿入する場合は insertByIndex メソッドを用いる。
insertByIndex メソッドの書式は下記の通り :
  
insertByIndex(RowNumber, Lines)
  
RowNumber には (行を) 挿入したい行番号を指定する。行番号は 0
から始まるので、この例の場合三行目に追加したいので RowNumber
には 2 を指定する。
Lines には挿入したい行数を指定する。
insertByIndex メソッドは、戻り値を返さない。

2011年4月24日日曜日

セルの内容をクリアする

Sub ExampleClearCell()
       Dim objSheet As Object
       Dim objCell As Object
       objSheet = ThisComponent.CurrentController.Activesheet
       objCell = objSheet.getCellRangeByName("B5")

       objCell.clearContents(1)
End Sub
  
セルの値や数式など、内容をクリアするには clearContents メソッドを
用いる。
clearContents メソッドの書式は下記の通り :
  
clearContents(Param)
  
Param には、クリアしたい内容に応じて、下記の値を指定する :
   1 : 数値をクリアする場合
   2 : 日付や時刻をクリアする場合
   4 : 文字列をクリアする場合
   8 : セルのコメントをクリアする場合
   16 : 関数 (数式) をクリアする場合
   32 : セルに直接指定された書式をクリアする場合
   64 : セルに間接的に指定された書式をクリアする場合
   128 : セルに配置された描画オブジェクトをクリアする場合
   256 : セル内の一部のテキストに対してのみ指定された書式をクリア
           する場合
  
上記のサンプルコードはセル内の数値をクリアする例だが、例えば
数値と同時に書式もクリアしたい場合は、
  
clearContents(1 + 32)
  
或いは、
  
clearContents(33)
  
のように、引数に上記の値を加算した数値を指定する。当然三つ以上
の値を加算することもできる。
  
尚、値 64 に書いてある「間接的に指定された書式」の意味については
わからなかった。

セルに関数を設定する

Sub ExampleSetCellFunction()
       Dim objSheet As Object
       Dim objCell As Object
       objSheet = ThisComponent.CurrentController.Activesheet
       objCell = objSheet.getCellRangeByName("B5")
       objCell.Formula = "TODAY()"

End Sub

  
セルに関数 (数式) を設定するには Formula プロパティを用いて下記
のように設定する :
  
セルオブジェクト.Formula = "関数"
  
上記サンプルコードは、TODAY 関数を設定した例である。

2011年4月23日土曜日

セルの位置を取得

Sub ExampleGetCellPosition()
       Dim objSheet As Object
       Dim objCell As Object
       objSheet = ThisComponent.CurrentController.Activesheet
       objCell = objSheet.getCellRangeByName("B5")
       Msgbox("B5の行番号 = " & objCell.CellAddress.Row & _

                      Chr$(13) & _
                      "B5の列番号 = " & objCell.CellAddress.Column)
End Sub
  
セルの行番号、列番号を取得する為には、それぞれ
  
セルオブジェクト.CellAddress.Row
セルオブジェクト.CellAddress.Column
  
で求めることができる。取得した行番号が、0 ならば 1 行目、1 ならば
2 行目であることに注意。列番号も同様に、0 ならば A 列、1 ならば B
列となる。

セルに値を設定する

Sub ExampleSetCellValue()
       Dim objSheet As Object
       Dim objCell As Object
       objSheet = ThisComponent.CurrentController.Activesheet
       '
       objCell = objSheet.getCellRangeByName("B5")
       objCell.Value = 1234567
       '
       objCell = objSheet.getCellRangeByName("C5")
       objCell.String = "abcdefgh"
       '
       objCell = objSheet.getCellRangeByName("D5")
       objCell.Value = "wxyzuvq"
       '
       objCell = objSheet.getCellRangeByName("E5")
       objCell.String = 9876543
End Sub
  
実行結果は下記の通り :
  
  
セル値の取得の場合と同様に、セルに数値を設定する場合は Value
プロパティを使用し、セルに文字列を値として設定する場合は String
プロパティを用いる。
上図の通り、文字列を Value プロパティを用いてセルに設定すると 0
になり、String プロパティを用いてセルに数値を設定すると左寄せに
なってしまうようである。

セルの値の取得

下記シートのセル B5、C5、D5、E5の値を取得するサンプルコードを下記に
記す :
  
  
Sub ExampleGetCellValue()
       Dim objSheet As Object
       Dim objCell As Object
       Dim strMessage As String
       objSheet = ThisComponent.CurrentController.Activesheet
       '
       objCell = objSheet.getCellRangeByName("B5")
       strMessage = strMessage & "B5の値 = " & objCell.Value & Chr$(13)
       '
       objCell = objSheet.getCellRangeByName("C5")
       strMessage = strMessage & "C5の値 = " & objCell.String & Chr$(13)
       '

       objCell = objSheet.getCellRangeByName("D5")
       strMessage = strMessage & "D5の値 = " & objCell.Value & Chr$(13)
       '
       objCell = objSheet.getCellRangeByName("E5")
       strMessage = strMessage & "E5の値 = " & objCell.String
       '
       Msgbox(strMessage)
End Sub

  
実行の結果、下記メッセージボックスが表示される :
  
  
Calc の場合、セル値を取得する場合、値が数値かそれ以外かで用いる
プロパティが異なる (らしい。後述するが、設定の場合も、同様)。
数値の場合は、Value プロパティを用いてセル値を取得し、文字列の場合
は String プロパティを用いて値を取得する。
文字列を Value プロパティで取得すると、上記メッセージボックスに表示
されている通り (D5 の値)、取得した値は 0 になってしまうようである。
数値を String プロパティで取得しても、特に問題はなさそうだが、おそらく
数字の文字列として取得されるのかも知れないので、四則演算などの計算
でエラーになる可能性がある。
数値は Value プロパティ、文字列は String プロパティでそれぞれ値を取得
するのが無難と思われる。

2011年4月22日金曜日

セルをアクティブにする

アクティブシートの B5 セルをアクティブにするサンプルコードを下記に記す :
  
Sub ExampleActivateCell()
       Dim objController As Object
       Dim objSheet As Object
       Dim objCell As Object
       objController = ThisComponent.getCurrentController()
       objSheet = objController.getActiveSheet()
       objCell = objSheet.getCellRangeByName("B5")
       objController.Select(objCell)
End Sub
  
CurrentController が何かは正確にはわからないが、その CurrentController
の Select メソッドの引数にセルオブジェクトを指定することによって、セルが
アクティブになるようである。セルオブジェクトを取得する為に、列・行番号を
指定しても、全く問題はない。
  
また、CurrentController や アクティブシートを取得するのに get~ メソッドを
用いてるが、代わりにプロパティを用いて下記コードのように記述することも
可能 :
  
Sub ExampleActivateCell2()
       Dim objController As Object
       Dim objSheet As Object
       Dim objCell As Object
       '
       '次の2 行を、プロパティを用いる方式に書き換えると。。。
       objController = ThisComponent.CurrentController
       objSheet = objController.ActiveSheet
       '
       objCell = objSheet.getCellRangeByName("B5")
       objController.Select(objCell)
End Sub