Worksheetクラスを継承したクラスを作る(4)

Worksheetクラスを継承したクラスを作る(4)

すでに「継承」というのは詐欺同然の題名である。

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com

懲りずに続ける。

Cellsプロパティの実装

実は、数々の挫折にもめげず、着々とメソッド・プロパティの実装は続けているのであった。

Intellisenseの表示をたよりに、なるべく漏れがないように、アルファベット順に実装している。

いよいよみんな大好きCellsプロパティの登場だ!

Cellsプロパティの謎挙動

ご承知のように、Cellsプロパティの引数といえば、

f:id:akashi_keirin:20191003200833j:plain

ご覧のようにRowIndexColumnIndexである。

では、次のコードはそれぞれ何を返すだろうか。

?ActiveSheet.Cells(,2).Address    '……(1)'
?ActiveSheet.Cells(2).Address   '……(2)'
?ActiveSheet.Cells(2,).Address   '……(3)'
?ActiveSheet.Cells(0,2).Address   '……(4)'
?ActiveSheet.Cells(RowIndex:=2).Address   '……(5)'

こいつらを、それぞれイミディエイト・ウインドウで実行すると、

  • (1)--->"$B$1"が返る
  • (2)--->"$B$1"が返る
  • (3)--->コンパイルエラー
  • (4)--->実行時エラー1004
  • (5)--->"$B$1"が返る

(1)、(4)はまあ納得。

しかし、(2)がなぜ"$A$2"でないのかよくわからないし、(3)がなぜ許されないのかよくわからない。(5)に至っては全く以て意味不明。

なんとも不思議な結果であるが、仕方がない。

以上の点を踏まえて、いよいよCellsプロパティを実装する。

Cellsプロパティの実装

クラスモジュールPoweredSheetCellsプロパティの部分のみ掲載。

リスト1 クラスモジュール PoweredSheet
Public Property Get Cells( _
      Optional ByVal RowIndex As Variant, _
      Optional ByVal ColumnIndex As Variant) As Range
  Dim ret As Range
  If IsMissing(RowIndex) And _
     IsMissing(ColumnIndex) Then    '……(6)'
    Set ret = realSh.Cells
    GoTo Finalizer
  End If
  If IsMissing(RowIndex) Then    '……(7)'
    RowIndex = 1
    Set ret = realSh.Cells(RowIndex, ColumnIndex)
    GoTo Finalizer
  End If
  If IsMissing(ColumnIndex) Then    '……(8)'
    Set ret = realSh.Cells(RowIndex)
  End If
  Set ret = realSh.Cells(RowIndex, ColumnIndex)    '……(9)'
Finalizer:
  Set Cells = ret
End Property

(6)の

If IsMissing(RowIndex) And _
   IsMissing(ColumnIndex) Then
  Set ret = realSh.Cells
  GoTo Finalizer
End If

は、引数が両方とも省略されている場合。

このときは、セル範囲全体を返す。

引数を両方ともVariantにしているのは、省略検知のため。

(7)の

If IsMissing(RowIndex) Then
  RowIndex = 1
  Set ret = realSh.Cells(RowIndex, ColumnIndex)
  GoTo Finalizer
End If

は、引数RowIndexが省略されたときの処理。

ActiveSheet.Cells(,2).Address

$B$1を返すということは、引数RowIndexだけが省略されたときは、「1行目」と見なされる、ということらしい。だからこうした。

(8)の

If IsMissing(ColumnIndex) Then
  Set ret = realSh.Cells(RowIndex)
End If

は、引数ColumnIndexだけが省略されたときの処理。

意味不明ながら上の(5)の挙動を再現した。

ここまでで、引数省略パターンは網羅しているので、(9)の

Set ret = realSh.Cells(RowIndex, ColumnIndex)

で普通にCellsプロパティの返り値を取得。

使ってみる

次のコードで実験。

スト2
Private Sub test04()
  Dim ps As PoweredSheet
  Set ps = New PoweredSheet
  Call ps.init(Sheet1)
  With ps
    Debug.Print .Cells.Address
    Debug.Print .Cells(, 2).Address
    Debug.Print .Cells(2).Address
    Debug.Print .Cells(2, 3).Address
  End With
End Sub

こいつを実行すると、

f:id:akashi_keirin:20191003200836j:plain

うむ。

おわりに

(6)、(7)、(8)は別になくても良かったような気がする。

書き終わってから気づいた。

と思って、(6)、(7)、(8)をコメントアウトしてリスト2を実行すると、「メモリが不足しています。」というおっそろしいエラーが出て、[デバッグ]をクリックすると、

f:id:akashi_keirin:20191003200838j:plain

こんな状態になった。やっぱり(6)、(7)、(8)は要るみたい。

2019/10/5 追記

Cellsプロパティの引数」とか言っているのはたぶんまちがい。

そこらあたりは、「Worksheetクラスを継承したクラスを作る(5)」で詳しく述べた。いいかげんなことを言って、正直スマンカッタ。

続きはコチラ

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com