アルゴリズムを考える

2019.03.25マクロ、VBA

Excelで何かを作る時は、何かしたいことが思いついたときにはじまると思います。
最初の作業は、目的を果たすためにどんな機能にするのかです。
その後に、どんな順序で動くものにするのかを考えます。
Excelに限らず、このような動作の順番のことをアルゴリズムといいます。
今回は、実際にVBAで動作するツールを作成しながら、アルゴリズムについて解説していきます。

アルゴリズムの種類

アルゴリズムは、いくつかの動作を組み合わせて作り上げます。
アルゴリズムの種類は次のようなものがあります。

処理

実際のセルに入力したり、編集したり、書式を設定したり、フィルターをかけたりする動作です。

ループ

繰り返し行う作業をループと呼びます。
Excelでループ作業を行うためにはVBAのFor文などでループにする必要があります。
VBAでのループの手法はこちらの記事で詳しく解説しています。

分岐

セルの値など、ある条件によって動作を変えることを分岐と呼びます。
ループと同様、分岐はVBAのIf文などを使う必要があります。
VBAでの分岐のうち、もしもの条件であるIf文の使い方はこちらの記事で詳しく解説しています。
分岐のうち、ある値だったらこの動作をするというSelect Case文の使い方はこちらの記事で詳しく解説しています。

今回のテーマ

今回は、次のようなお絵描きツールを作ります。
セルに設定されている背景の色があります。セルA1には「取り込み」と入力されています。

ツール

 

セルA1をクリックするたびに「取り込み」モードと「描き込み」モードが切り替わります。

切り替え

 

取り込みモードでセルをクリックすると、その背景色をセルB2にセットし、今セットされている色として取り込み、描き込みモードに移行します。

色を取り込み

 

描き込みモードでセルをクリックすると、今セットされている色で、背景色を設定します。

色を描き込む

 

アルゴリズムを考える

どんな動きをするか、まずは日本語でまとめます。

  1. 動きの始まりは、セルのクリックです。セルのクリックで始まるVBAは、こちらのページで解説してある「Worksheet_SelectionChangeイベント」を使います。「Worksheet_SelectionChangeイベント」はシートに対するVBAです。
  2. クリックしたら、そのセルがセルA1かどうか調べます。クリックしたセルは変数Targetにセットされていますので、その参照はTarget.Addressで調べることができます。
  3. もし、セルA1がクリックされていれば、セルA1の値を調べます。セルA1の値はRange(“A1”).Valueで調べることができます。
  4. もしも、セルA1の値が「読み込み」なら「描き込み」に書き換えます。「描き込み」なら「読み込み」に書き換えます。クリックしたセルがA1ならば、これ以降の処理を終了します。クリックしたセルがA1ではなければ処理が続行されます。
  5. もしもセルA1の値が「読み込み」なら、今の色として、クリックしたセルの背景色を設定します。セルの背景はInterior、色はColorなので、Target.Interior.Colorでクリックしたセルの背景色を調べることができます。セルA2の色を今の色にします。そして、セルA1を「描き込み」にすれば、そのままその色で描き込めます。
  6. もしもセルA1の値が「描き込み」なら(「読み込み」ではなければ)、クリックしたセルの背景色を今の色に設定します。

以上の流れをもう少しプログラム的にまとめていきます。
左側の空白のインデントにご注目ください。

Worksheet_SelectionChangeイベント
Target.AddressでクリックしたセルがA1か調べる
クリックしたセルがA1ならば、
  セルA1の値が「読み込み」ならば、
    セルA1の値を「描き込み」にする
  そうでなければ
    セルA1の値を「読み込み」にする
  処理を終了
セルA1が「読み込み」ならば、
  今の色をクリックしたセルの背景色であるTarget.Interior.Colorにセットする
  セルA2の背景色を今の色にする
  セルA1の値を「描き込み」にする
そうでなければ
  クリックしたセルの背景色であるTarget.Interior.Colorを今の色にする

以上のような流れになります。
ここで重要なのは、今の色は、処理が終わるとリセットされてしまいます。
忘れられないようにするためには、すべての処理の外側で、変数の宣言をする必要があります。

変数の型が不明な変数の型の調べ方

今回は、背景色を表すTarget.Interior.Colorを「今の色」を表す変数に入れ、すべての処理の外側で宣言する必要があります。
ところが、Target.Interior.Colorは色なのですが、色はどんな変数の型なのでしょうか。一見すると思いつきません。
変数の型がわからなければ宣言はできないので、変数の型を調べる必要があります。
このような場合、実際にVBAを作成し、ウォッチウィンドウでその変数を調べます。
今回は、選択したセルであるTargetについて調べていきましょう。
ウォッチウィンドウについては、こちらの記事で詳しく解説してあります。
シート見出しを右クリックして、コードの表示をします。

コードの表示

 

すると、Sheet1に対してのVBAの作成を開始することができます。

VBA作成開始

 

Worksheetを選択します。

Worksheetを選択

 

すると、自動でクリックしたときにはじまるSelectionChangeがセットされ、Worksheet_SelectionChangeイベントが作成されます。

イベント作成

 

この時点で、End Subの行の左側をクリックすると、そこで動作を一時的に止めることができる、ブレークポイントを設定できます。

ブレークポイント

 

この状態にして、実際にセルをクリックしてみます。

動作させてみる

 

End Subの行で動作が一時的に止まっています。

動作が止まる

 

ここで、Targetの文字を選択し、右クリックしてウォッチ式の追加をクリックしOKします。

ウォッチ式の追加

 

すると、画面右下のウォッチのところにTargetが追加されます。この左側にある+のマークをクリックします。

Targetが追加

 

Targetの内容が細分化されて表示されます。その中のInteriorを見つけ、左の+のマークをクリックします。

Interiorがある

 

ここに、Colorがあるので見つけます。Colorの変数の型が表示されます。

Colorがある

 

Variant/Doubleと書いてあります。
Variantは特殊な変数の型で、型の決まっていない変数の型を表します。
そしてそのVariantではないDoubleがTarget.Interior.Colorの変数の型なのです。
ちなみにDoubleは桁の大きい整数を表しています。VBAでは、色は、赤、緑、青の色の濃さをそれぞれ表した番号で表されているので、その番号が数値として表現されています。
では、せっかく調べましたので、変数の型を宣言してしまいましょう。
今回、今の型の変数名は「mycolor」とします。
Worksheet_SelectionChangeイベントの上に1行挿入して、次のように記述しましょう。

Dim mycolor As Double

変数宣言

 

これで、変数の中身がリセットされないで覚えたままになっている、mycolorという色を表す変数を設定することができました。
このような変数の中身がリセットされない変数のことを「グローバル変数」と呼びます。
それに対し、中身がリセットされる変数は「ローカル変数」と呼びます。
ここまで設定したら、VBAの動作を一度止め、End Subの左のブレークポイントをクリックして解除します。

ブレークポイント解除

 

クリックしたセルがA1だった場合のプログラムを作成する

クリックしたセルの参照を調べるには、Targetに対するAddressを調べます。
Target.Addressは絶対参照で求まりますので、クリックしたセルがセルA1かどうか調べるには、次のようなプログラムになります。これを、Private Sub Worksheet_SelectionChangeの行とEnd Subの間の行に書きます。

  If Target.Address = "$A$1" Then

  End If

セルがA1だったら

 

Ifの構文はIfから始まり、どこがどうだったら、という条件があり、Thenと書きます。
セル参照の「$A$1」は文字列なので「" "」で囲みます。
Ifの終わりはEnd Ifで締めくくります。
つまり、Ifの行からEnd Ifの間に、クリックしたセルがA1だった時の処理を書きます。
この中で処理するのはセルA1が「読み込み」かどうかということです。
IfとEnd Ifの間に次のように入力します。

    If Range("A1").Value = "読み込み" Then

    Else

    End If

読み込みならば

 

Ifから始まり、セルA1の値が「読み込み」ならばとなっています。
そして、Elseはそうではなかったらという意味になります。
最後はEnd Ifで終わっています。
つまり、Ifの後にセルA1の値が「読み込み」だった場合の処理、Elseの後にそうではなかった場合の処理を書けばいいのです。
このようになります。

    If Range("A1").Value = "読み込み" Then
      Range("A1").Value = "描き込み"
    Else
      Range("A1").Value = "読み込み"
    End If

描き込み、読み込み

 

セルA1の値が「読み込み」ならば、セルA1が「描き込み」、そうではなければセルA1が「読み込み」になります。
Target.AddressがセルA1だった場合、それ以降の処理をやめ、ここでクリックしてからの処理を終わらせます。
その場合は、Endと書きます。

  If Target.Address = "$A$1" Then
    If Range("A1").Value = "読み込み" Then
     Range("A1").Value = "描き込み"
    Else
     Range("A1").Value = "読み込み"
    End If
    End
  End If

End

 

ここまでで、

クリックしたアドレスがセルA1ならば、
  セルA1の値が「読み込み」ならば、
    セルA1を「描き込み」にする
  そうではなければ
    セルA1を「読み込み」にする
  処理を終了する

という流れができました。

クリックしたセルに対するアクションを作成する

クリックしたセルがA1だった場合は、上記のプログラムでの動作後に止まるようにしました。
クリックしたセルがA1以外だった場合、止まらずにその下へと動作が進んできます。
そこに、クリックしたセルに対して、「読み込み」モードならそのセルの色を今の色として記憶、「描き込み」モードなら今の色をセルに設定するという動作を入れ込みます。
以下のような分岐の構造になります。

  If Range("A1").Value = "読み込み" Then

  Else

  End If

読み込みならば

 

読み込みモードだった場合の動作をIfとElseの間に書き、そうではない場合(描き込みモード)の動作をElseとEnd Ifの間に書きます。

  If Range("A1").Value = "読み込み" Then
    mycolor = Target.Interior.Color
    Range("A2").Interior.Color = mycolor
    Range("A1").Value = "描き込み"

  Else
    Target.Interior.Color = mycolor
  End If

読み込み時と書き込み時の動作

 

読み込みモードなら、今の色(mycolor)にクリックしたセルの背景色(Target.Interior.Color)を設定、その色をセルA2の背景色に設定し、描き込みモードへ変更しています。
そうではない(描き込みモード)なら、クリックしたセルの背景色(Target.Interior.Color)を今の色(mycolor)に設定します。
ここまででVBAは完了です。

動作チェック

最終的な出来上がりのVBAは次の通りです。
このVBAが操作するシートのVBAとして記述してあります。

Dim mycolor As Double

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Target.Address = "$A$1" Then
    If Range("A1").Value = "読み込み" Then
      Range("A1").Value = "描き込み"
    Else
      Range("A1").Value = "読み込み"
    End If
    End
  End If

  If Range("A1").Value = "読み込み" Then
    mycolor = Target.Interior.Color
    Range("A2").Interior.Color = mycolor
    Range("A1").Value = "描き込み"
  Else
    Target.Interior.Color = mycolor
  End If
End Sub

VBA全部

 

このあと、動作チェックを行いたいのですが、すでにクリックすると作成したプログラムが動き出してしまいます。
これでは初期設定ができません。
そこで、「Worksheet_SelectionChange」というイベント名だと、クリックしたとたんに動き出してしまうので、イベント名の最後に「x」を付け、「Worksheet_SelectionChangex」とし、一時的にイベントが動き出さないようにします。

起動しなくする

 

セルA1の値を「読み込み」にし、実際のセルにいくつか背景色を設定しましょう。

動作確認のための初期設定

 

先ほど付けた「x」を削除し、イベントが発生するようにします。

動作するようにする

 

セルA1をクリックすると描き込みモードが読み込みモードに変わるか確認します。
セルA1は選択されているとクリックできないため、セルA1、セルA2と交互にクリックすることで、クリックイベントを発生させます。

動作確認1

 

読み込みモードで色の付いたセルA1以外のセルをクリックすると、描き込みモードになり、そのセルの背景色がセルA2に設定されることを確認します。

動作確認2

 

描き込みモードでセルA1以外のセルをクリックしたときに、そのセルに設定された色が付くことを確認します。

動作確認3

 

まとめ

今回は、Excelのお絵描きツールをVBAで作成しながら、プログラムの動作の順番(アルゴリズム)について考えながら作成することが重要ということを解説しました。
アルゴリズムは、本来、フローチャートと呼ばれる作業順が図示されているものによって明確にわかるようにしておくと、その後のプログラム作成作業が楽になります。

フローチャート

 

手書きでもいいので、どのようなループ、どのような分岐があるかを自分なりに分かりやすい形でまとめておくといいでしょう。
また、今回はVBAでプログラムをする上で、実務的なテクニックをいくつか紹介しました。これらも実際に使いながらプログラムするとVBAの作成が楽になります。

  • 変数の中身は一回動作してしまうと消えてしまうので、それを避けるために変数をグローバル変数にする必要がある。グローバル変数は記述したVBAの一番上で変数の宣言をすればよい。
  • 変数の型がわからない時は、実際にプログラムを作成してブレークポイントを設定し一時停止させた状態でウォッチウィンドウを使うと調べられる。
  • Worksheet_SelectionChangeのようなイベントで始まるVBAでは、動作確認がしにくくなるので、動作確認時は一時的に「x」などの文字をイベント名に加え、イベントが発生しないようにする。

Excel業務をもっと「ラク」にするなら

Excel業務を自動化したい!
Excelをデータベース化したい!

 

Back to top