ジーワンシステム社長のITコラム。
   ITについて、その他もろもろ
>> HOME >> コラム >> 第36回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その8」

« 第35回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その7」 | メイン | 第37回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その9」 »

第36回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その8」

前回は盤面にバブルを配置するところまでを説明しました。
エクセル de バブルブレーカー(Excel de Bubble Breaker)のダウンロードはこちらから
 今回は盤面のバブルを選択した時に背景の色を変更するプログラムを作ります。
 まず今回付け加えるコードを書きそれを説明していきます。
 赤文字が今回加えたコードです。

 
 1行目  Option Explicit
 2行目
 3行目  Private Sub CommandButton1_Click()
 4行目
 5行目   Call 盤面初期化
 6行目
 7行目  End Sub
 8行目
 9行目
 10行目 Private Sub Worksheet_SelectionChange(ByVal Target As Range)
 11行目
 12行目  Call checkBreak(Target)
 13行目
 14行目 End Sub
 「Worksheet_selectionChange」とはワークシートで選択範囲を変更したときに実行されるというものです。
 今回は盤面のセルをクリックすると実行されます。
 というわけで盤面にあるセルをクリックすると「checkBreak(Target)」が実行されます。
 引数として選択されている範囲 Range オブジェクトが渡されます。
 
 
 続いてモジュールです。

 1行目   Option Explicit
 2行目
 3行目   Public sht設定シート As Worksheet
 4行目   Public sht盤面シート As Worksheet
 5行目   Public rng盤面 As Range
 6行目
 7行目   Private rng開始位置 As Range
 8行目   Private str開始位置 As String
 9行目   Private int盤面縦 As Integer
 10行目  Private int盤面横 As Integer
 11行目  Private int開始位置縦 As Integer
 12行目  Private int開始位置横 As Integer
 13行目  Private rngバブル色範囲 As Range
 14行目  Private lngバブル色(1 To 5) As Long
 15行目  Private lng通常背景色 As Long
 16行目  Private lng選択背景色 As Long
 17行目
 18行目  Private Type typPlayField
 19行目    lngBackColor As Long
 20行目    lngBubbleColor As Long
 21行目  End Type
 22行目
 23行目  Private arrPlayField(1 To 30, 1 To 200) As typPlayField     '30は上限値。200は横。自由に設定すればよい  

 11行目の「int開始位置縦」には盤面内で選択されたセルの縦の値が入ります。
 同様に12行目の「int開始位置横」には盤面内で選択されたセルの横の値が入ります。
 18行目~23行目までは使い方だけ簡単に説明します。
 使い方は  arrPlayField(x, y).lngBackColor = 「Long型の何か」
         arrPlayField(x, y).lngBubbleColor = 「Long型の何か」
 のように使えます。
 今回の場合は盤面内のセルの背景の色とバブルの色に使ってますので、
 コードを見ながら使い方をつかんで下さい。
 
 
 Private Sub 設定値取得()
  Dim i As Integer
  Set sht設定シート = Application.Worksheets("Sheet1") '将来シート名が変わったときここだけを変更する。
  Set sht盤面シート = Application.Worksheets("Sheet1") '将来シート名が変わったときここだけを変更する。
     ↓↓(省略)
  int開始位置縦 = rng開始位置.Row
  int開始位置横 = rng開始位置.Column
 End Sub
 Subプロシージャ、設定値取得の1番下に2行追加します。
 「int開始位置縦 = rng開始位置.Row」 は盤面の開始位置のセルの縦を取得し
 最初の宣言で付け加えた「int開始位置縦」に代入しています。
 同様に「int開始位置横」には盤面の開始位置のセルの横を取得したものを代入しています。
 
 

■前回のコード■
 Public Sub 盤面初期化()
     ↓↓(省略)
  With rng盤面
     ↓↓(省略)
   With .Borders(xlEdgeRight)
    .LineStyle = xlContinuous
    .Weight = xlMedium
    .Color = RGB(0, 0, 0)
   End With
   .Value = "●"
   .Interior.Color = lng通常背景色
 End With
 'ランダムに色をつける
  With rng盤面
   For i = 1 To int盤面縦
    For j = 1 To int盤面横
     .Cells(i, j).Font.Color = lngバブル色(Int(Rnd() * 5) + 1)
    Next j
   Next i
  End With
 End Sub


■今回のコード■
     ↓↓(省略)
    With rng盤面
     ↓↓(省略)
      With .Borders(xlEdgeRight)
       .LineStyle = xlContinuous
       .Weight = xlMedium
       .Color = RGB(0, 0, 0)
      End With
      .Value = "●"
1行目   For i = 1 To int盤面縦
2行目    For j = 1 To int盤面横
3行目     arrPlayField(i, j).lngBackColor = lng通常背景色   '背景色を設定する
4行目     .Cells(i, j).Interior.Color = arrPlayField(i, j).lngBackColor
5行目     arrPlayField(i, j).lngBubbleColor = lngバブル色(Int(Rnd() * 5) + 1)
6行目     .Cells(i, j).Font.Color = arrPlayField(i, j).lngBubbleColor
7行目    Next j
8行目   Next i
     End With
    End Sub


 では、今回変えた部分について説明します。
 1行目 1から「int盤面縦」の範囲での繰り返しです。
 2行目 1から「int盤面横」の範囲での繰り返しです。
 3行目~4行目
   通常時の背景の色を配列arrPlayField(i, j).lngBackColorに代入しています。
   繰り返しが終了するときには「arrPlayField(1,1).lngBackColor」から「arrPlayField(int盤面縦,int盤面横).lngBackColor」のすべてに背景の色が代入されます。
   先ほど「arrPlayField(1,1)」から「arrPlayField(int盤面縦,int盤面横)」に入れた背景色を
   「Cells(1,1).Interior.Color」から「Cells(int盤面縦, int盤面横).Interior.Color」に再び入れます。
   この2つの処理で盤面のすべてのセルに背景の色がつきました。
 5行目~6行目
   3行目~4行目とほぼ同じです。
   「 lngバブル色(Int(Rnd() * 5) + 1)」を「arrPlayField(i, j).lngBubbleColor」に代入しています。
   「lngバブル色(Int(Rnd() * 5) + 1)」は前回にやりました。5色の中からランダムにバブルに色をつけていく処理でしたね。
   つまり「arrPlayField(1,1).lngBubbleColor」から「arrPlayField(int盤面縦,int盤面横).lngBubbleColor」に
   それぞれランダムに5つの色が入っています。
   先ほど「arrPlayField(i, j).lngBubbleColor」を「Cell(i, j).Font.Color」に入れていきます。
   Cellにはあらかじめ"●"が入っているのでそれぞれの"●"に色がついていきます。
   デバッグしながら実際の動きをみるとどの行がどの処理をしているのかわかりやすいと思います。
 
 
 ここからが盤面がクリックされた時の処理内容です。
 では早速コードを見てみましょう。

 1行目 Public Function checkBreak(ByRef Target As Range) As Boolean
 2行目   Dim intV As Integer
 3行目   Dim intH As Integer
 4行目
 5行目   intV = Target.Row - int開始位置縦 + 1
 6行目   intH = Target.Column - int開始位置横 + 1
 7行目   checkBreak = checkBreakSub(intV, intH)
 8行目
 9行目 End Function
 1行目 今回の最初に書いた「chekBreak」プロシージャの呼び出しです。
 2行目~3行目 プロシージャ内で使う変数の宣言です。
 5行目 intVに盤面内での縦の位置を代入しています。
   「Target.Row」は選択したセルの縦の位置です。「int開始位置縦」は盤面の開始位置でしたね。
   最後の+1は一番上の行を1にする為です。もし「Target.Row - int開始位置縦」だけだと
   一番上の列が選択されると「intVは0になってしまいます。
   0ではわかりにくいですし、今回は1になるようにプログラムしてきているので、+1します。
 6行目 同様に盤面内での横の位置を「intH」に代入しています。
 7行目 checkBreakSubをintVとintHを引数として呼び出しています。




      checkBreakSubプロシージャの内容
 1行目  Private Function checkBreakSub(intV As Integer, intH As Integer) As Boolean
 2行目    Dim lngCurrentColor As Long
 3行目    Dim i As Integer
 4行目    Dim j As Integer
 5行目
 6行目    lngCurrentColor = arrPlayField(intV, intH).lngBubbleColor
 7行目
 8行目    i = intV - 1
 9行目    j = intH
 10行目   If i >= LBound(arrPlayField, 1) Then
 11行目    If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
 12行目     Call changeBackColor(lngCurrentColor, intV, intH)
 13行目    End If
 14行目   End If
 15行目
 16行目   i = intV
 17行目   j = intH - 1
 18行目   If j >= LBound(arrPlayField, 2) Then
 19行目    If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
 20行目      Call changeBackColor(lngCurrentColor, intV, intH)
 21行目     End If
 22行目    End If
 23行目
 24行目   i = intV + 1
 25行目   j = intH
 26行目   If i <= UBound(arrPlayField, 1) Then
 27行目    If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
 28行目     Call changeBackColor(lngCurrentColor, intV, intH)
 29行目    End If
 30行目   End If
 31行目
 32行目   i = intV
 33行目   j = intH + 1
 34行目   If j <= UBound(arrPlayField, 1) Then
 35行目    If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
 36行目     Call changeBackColor(lngCurrentColor, intV, intH)
 37行目    End If
 38行目   End If
 39行目 End Function

 1行目 Functionプロシージャの宣言
 6行目 選択されたセルのバブルの色の値を「lngCurrentColor」に代入しています。
   8行目~9行目 選択したセルの縦(intV)から1引いた数をi に代入
   選択したセルの横(intH)をj に代入。つまり(i, j)は選択したセルの一つ上のセルを表します。
 10行目 LBound()関数は配列の最小値を求めます。第二引数の1は次元を表します。
   つまり10行目の意味はi が選択したセル一つ上のセルの縦が盤面の一番上の行以内であれば、となります。
 11行目 選択されたセルのバブルの色が一つ上のセルのバブルの色と同じならば、という意味です。
 12行目 引数lngCurrentColor,intV,intHでchangeBackColorプロシージャを呼び出しています。
 16行目~22行目
   8行目~14行目までとほぼ同じです。
   横「intH」から1を引いて一つ左のセルを見ています。
   Lbound()関数の第二引数は2で二次元目をさします。
   つまり盤面のj が一番左の列以内であれば、となります。
 24行目~30行目
   縦「intV」に1を足して一つ下のセルを見ています。
   UBound()関数はLBound()とは逆に最大値を求めます。
   つまり盤面のi が一番下の行以内であれば、となります。
 32行目~39行目
   横「intH」に1を足して一つ右のセルを見ています。
 このcheckBreakSubプロシージャの役割は?
   選択したセルの上下左右に同じ色のバブルがあるかどうかを判定しています。
   あればchangeBackColorを呼び出す、なければそのまま終了です。


 次はchangeBackColorプロシージャの説明です。
 
 
   うーん、ずいぶん長くなってますが、、、実際のプログラムです。
   今回の最重要点である再帰呼び出しが使われているのでしっかりと見てみて下さい。

 1行目  Private Function changeBackColor(lngCurrentColor As Long, intI As Integer, intJ As Integer)
 2行目   Dim i As Integer
 3行目   Dim j As Integer
 4行目
 5行目   arrPlayField(intI, intJ).lngBackColor = lng選択背景色
 6行目   rng盤面(intI, intJ).Interior.Color = lng選択背景色
 7行目
 8行目   i = intI - 1
 9行目   j = intJ
 10行目  If i >= LBound(arrPlayField, 1) Then
 11行目   If arrPlayField(i, j).lngBackColor <> lng選択背景色 Then
 12行目    If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
 13行目     Call changeBackColor(lngCurrentColor, i, j)
 14行目    End If
 15行目   End If
 16行目  End If
 17行目
 18行目  i = intI
 19行目  j = intJ - 1
 20行目  If j >= LBound(arrPlayField, 2) Then
 21行目   If arrPlayField(i, j).lngBackColor <> lng選択背景色 Then
 22行目    If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
 23行目     Call changeBackColor(lngCurrentColor, i, j)
 24行目    End If
 25行目   End If
 26行目  End If
 27行目
 28行目  i = intI + 1
 29行目  j = intJ
 30行目  If i <= UBound(arrPlayField, 1) Then
 31行目   If arrPlayField(i, j).lngBackColor <> lng選択背景色 Then
 32行目    If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
 33行目     Call changeBackColor(lngCurrentColor, i, j)
 34行目    End If
 35行目   End If
 36行目  End If
 37行目
 38行目  i = intI
 39行目  j = intJ + 1
 40行目  If j <= UBound(arrPlayField, 2) Then
 41行目   If arrPlayField(i, j).lngBackColor <> lng選択背景色 Then
 42行目    If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
 43行目     Call changeBackColor(lngCurrentColor, i, j)
 44行目    End If
 45行目   End If
 46行目  End If
 47行目 End Function


 1行目 Functionプロシージャの宣言です。
 2行目~3行目 このプロシージャで使用する変数の宣言です。
 5行目 「arrPlayField(intI, intJ).lngBackColor」に選択時の背景色を代入しています。
 6行目 選択したセルの背景色を選択背景色にしています。
 8行目~10行目
 checkBreakSubプロシージャの8行目から10行目の説明参照
 11行目 選択したセルの背景色と一つ上の背景色が同じならば、If文以下を実行する
 12行目 選択したセルのバブルの色と一つ上のバブルの色が同じならは、If文以下を実行する
 13行目 changeBackColor、引数(lngCurrentColor,i,j)を呼び出す。
   あれれ??確か今はchangeBackColorプロシージャの中のはず!!そうです。これが再帰呼び出しです。
   プロシージャの中でそのプロシージャ自身を呼び出すことができます。
   今回のように同じような処理が何度も続く場合は非常に便利ですが、処理が複雑になるので使わない方がいいこともあります。
 13行目の場合だと選択したセルと一つ上のセルの背景色が異なりバブルの色の値が同じならば
 処理がchangeBackColorプロシージャの最初に戻ります。
 5行目で一つ上のセルの色の値を選択背景色にし6行目でセルの選択背景色を変更します。
 18行目~26行目は左を28行目~36行目は下を38行目~46行目は右をそれぞれ見に行き
 再帰処理が呼び出される条件を満たしていれば先頭にもどり5行目から6行目でセルの背景を変更します。


 どうでしょう?少し長くなりましたが理解できたでしょうか?
 わからなければバブルの色を全部同じ色や二色位にして、デバッグをしながら見てみると分かりやすいでしょう。
 次回は、配列を使っていないバージョンのソースとなぜ配列を使うのかを簡単に説明します。

解説で利用したエクセルファイルのダウンロード

<< 第35回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その7」 | | 第37回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その9」 >>

>> HOME >> コラム >> 第36回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その8」

トラックバック

このエントリーのトラックバックURL:
http://www.g1sys.co.jp/cgi-bin/app/mt-tb.cgi/54

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

  • 製品案内
システム構築・運用、技術サポート・ビジネスブログ・ホームページ制作の株式会社ジーワンシステム
株式会社ジーワンシステム

〒550-0014
大阪市西区北堀江1-5-2
四ツ橋新興産ビル 11F

TEL: 06-6535-8660
FAX: 06-6535-8661

E-mail: info@g1sys.co.jp

Powered by
Movable Type 3.34