配列変数の宣言(動的)

配列変数の中でも、要素数が未定で処理中に可変にさせる事のできる動的配列の解説

'動的配列の宣言
Dim 動的配列() As Long
'動的配列要素数の宣言
ReDim 動的配列(5)
'動的配列の要素数の宣言(代入済みデータ保持)
ReDim Preserve 動的配列(8)

配列とは、同じ変数名を複数同時に宣言することができる変数です
動的配列は、要素数が宣言時点では未定の状態で処理中に可変させることの出来る配列変数です

通常の変数の宣言方法とほぼ同じで、変数名の後に「()」を追加するだけです
この時に、なにも「()」の中には入れないことで動的配列となります

ただ、このままでは要素が無い状態なので使用はできません
「ReDim」を使用して要素数の宣言をすることで使用可能になります

動的配列変数の要素数の宣言の動き
動的配列の要素数の宣言の動き

画像の動きを見てください。
1回目の「ReDim 動的配列(2)」で、配列変数が使用可能になっています
そして2つの要素に値を代入させていますが、2回目の「ReDim 動的配列(5)」では代入させた値がクリアされてしまっています

「ReDim」で要素数の宣言を行うと、それまでに代入したデータは初期化されます

既存のデータはそのままに、あらたに要素数を追加してデータを追加させたい場合には「ReDim Preserve」を使用します

3回目の要素数宣言の「ReDim Preserve 動的配列(8)」の時点ではそれまでのデータはクリアされていません

処理が始まらないと要素数が分からない場合に、動的配列は使用します
ですが、要素数の確定するタイミング次第でこの要素数宣言の使い分けを行います

要素数の最大値がすぐに取得できる場合は、「ReDim」を使用します
要素数をループなどで随時追加していく場合には、「ReDim Preserve」を使用します

なお、「ReDim」でデータをクリアできますが、その目的では使用しないようにしてください、専用のコードがちゃんとあります
(配列変数のデータを初期化する方法)

配列変数の宣言(静的)

同じ目的の変数を一括して使用できる配列変数の内、要素数が固定のもの

'4つの要素数の配列変数の宣言
Dim 静的配列(3) As Long
'各要素へのデータの代入
静的配列(0) = 1
静的配列(1) = 10
静的配列(2) = 100
静的配列(3) = 1000
’要素の取得
MsgBox 静的配列(2)

配列変数とは、同じ名前の変数を複数まとめて使用することが出来る変数です
その変数のそれぞれを要素といいます

静的配列とは、その配列の中でも数が固定の状態の配列をいいます

配列変数の宣言方法は通常の変数の宣言方法とほぼ同じで、変数名の後に「(要素数)」を追加するだけです
要素の連番は「0」から始まるため、「静的配列(3)」は「静的配列(0)~静的配列(3)」までの4つの変数が宣言されている形になります
同じ役割の変数を10個20個と必要になったときに、すべてを宣言していては大変なことになりますので、役割が同一であれば配列にまとめてしまってください

静的配列変数の代入の動き
静的配列変数の代入の動き

画像の動きを見てもらうと分かるように代入する場合は、それぞれの要素数を指定することでその要素数の配列変数に代入できます

逆に取得する際もその連番を指定することで、そのデータを取得できます
コードの「MsgBox 静的配列(2)」では「100」が表示されます

動的配列と違い、処理が実行される前に要素数が確定しているならこちらを使用してください
動的配列は要素数を可変できますが、いちいち宣言する必要があります
(動的配列に関してはこちら)

処理を終了する

Sub・Functionプロシージャを強制的に終了させるコードとEndステートメントについて

'Subプロシージャを終了する
Exit Sub
'Functionプロシージャを終了する
Exit Function

Subプロシージャを終了させるには「Exit Sub」を使用し、Functionプロシージャを終了する場合は「Exit Function」を使用します

プロシージャの種類を「Exit」の後に記載すればいいだけですね

Exit Subの動きについて

ExitSubの動き
ExitSubの動き

画像の動きを確認してください
「Exit Sub」の動きですが、このコードが実行された時点でSubプロシージャは終了するので、「MsgBox」以下の処理は実行されていません

また、「End Sub」にも移動はしません、これと同じ意味になるためです

主には、処理の実行前に条件が整っているかを調べて整っていなければ終了させる場合に使用します

Exit FunctionとEndについて

ExitFunctionとEndの動き
Exit FunctionとEndの動き

画像の動きを少し、大きくしてみます
この画像であれば、「Exit Function」の動きが分かります

処理テストAにて、MsgBoxの本文引数として処理テストCのFunctionが呼び出されています
このFunctionプロシージャは、ただ「100」を返すだけの関数ですが、その代入前に「Exit」が実行されるためLong型の初期値「0」が返されてメッセージに表示されます

また処理テストBがその後、Callにより実行されています
この処理テストBには、例にはない「End」というコードが記載されています

この「End」というコードは、実行された時点でVBAの処理が全て強制終了するコードです
そのため、呼び出し元の処理テストAに戻らず、処理テストBの時点で終了しています

このコードが実行された時点で処理はもちろん、変数も全て解放され、メモリ内で開いているファイルも全て閉じられます
完全に処理が終了する形になります

さらに、このコードはイベントさえも実行させません
ユーザーフォームで「QueryClose」イベント(フォームの終了時に発生するイベント)を作成していても、そのイベントが実行されずに終了します

全てまっさらで、逆にせいせいするね
なんて事を言ってられない程、まっさらにしてしまうのでこのコードは恐いです
Excelの強制終了コードと同じレベルの強制力なので、使用することはほぼあり得ないと思いますが、使用するような場面に遭遇したら逃げ出してください
使用しないようになんとか頑張ってください、ここまで全ての終了をあいまいにさせることは非常に危険です

処理を終了させることも、変数を開放することも、開いたファイルを閉じることも専用のコードがちゃんとあります
そちらを使用して、しっかりそれぞれを終了させてください

それでも全く利用場面がない訳ではありません、利用場面の解説は以下の記事にあります

ループを終了する

For・Doの各ループ処理を強制的に終了させるコード

'Doループを終了する
Exit Do
'Forループを終了する
Exit For

ループ処理において、ループの中で終了条件を判定させて満たした時点でループを強制終了するには、「Exit」を使用します

ループは「Do」と「For」の2つなので、「Exit Do」「Exit For」のどちらかを使用します
(Doループはこちら - Forループはこちら)

ループの強制終了の動き
Exit使用時の動き

画像の様な動きになります

1つ目はDoループの強制終了の動きです、本来空白セルになるまでループしますが条件判定前にExitを使用することによりそこでループが終了します
「Loop」には移動せずに次のForループに移動しています

2つ目のForループも同様にExit使用時に「Next」移動せず終了します

画像とは違って、Doループで終了条件を指定せず処理の途中でIf分岐を使用して、この構文で終了させることも可能で、これが途中判定になります
途中判定を使う理由としては、ネストさせたIfやSelectCaseによる詳細な終了条件の指定が可能だという点になります
Unitlでは1つの条件式になってしまうので、それだけでは終了させられない場合に使用します

戻り値のあるプログラムの入れ物を作る

Functionプロシージャとは戻り値を持つプロシージャの事、使い方とコード

'戻り値のあるプログラムコードの入れ物
Function プログラム名() As Long

’↑この間にプログラムコードを入力する↓

’処理結果を代入する
プログラム名 = 100

End Function

戻り値のあるプログラムの作成には「Function」プロシージャを使用します

戻り値とFunctionプロシージャ

戻り値とは、処理の結果を呼び出し元に戻す結果の事です
要は関数の動きが同等のものとなります

例えば、Date関数は引数無しの関数です
「Date」とすれば、本日日付が返されます
この本日日付が戻り値と呼ばれます

Functionプロシージャでは、戻り値の代入先はプロシージャ名自身になりますので、例の内の「プログラム名 = 100」がそれに当たります
ここで、戻り値を取得させています
これが無いと戻り値は初期値のままになってしまいます

例のコードでは、プログラム内では最後に「100」を代入しているので常に「100」を返す関数になります

関数と同じという意味の通り、FunctionプロシージャはCallで呼び出さずに関数のように記載して実行できます

Functionプロシージャの動き
Functionプロシージャの動き

画像の動きを確認してみます

まずは、Subプロシージャによって関数の様にプログラム名のみで実行されます
今回はMsgBoxの文字として取得しています

このFunctionプロシージャは常に100を返すので、MsgBoxでは「200+100」が実行されて、300のメッセージが表示されます

またSubと違うのが、プロシージャ名の後にデータ型の指定を行う点です
今回は数値なのでLong型になっています
他の型も使用可能です

関数の便利さは実感出来ているはずですので、このFunctionプロシージャも使いこなすと非常に便利な機能なのが分かってきます

ユーザー定義関数とは

ユーザー定義関数の動き
ワークシート関数の様に使用可能

また、ユーザー定義関数というものの作成も行えます
セルに「=プログラム名()」と入力して確定させてみてください
すると数値の100が表示されます

これは関数と同じ動きなので、データの更新で再計算されます(この関数は意味ありませんが)
リアルタイムでの実行が可能になるので、関数を頑張って作成するよりはるかに楽に目的の関数を作成できたりします
なんなら、Functionプロシージャ内をワークシート関数だけで作成してしまって
本来ならネストされまくってる関数をたった1つの関数で実行してるようにも見せられます(こんなことをしても自己満足ですけどね~)

ただしループ処理やエラー対応にはしっかり準備してから使用してください
ユーザー定義関数でのバグは、Excelが強制終了することがあります

他のプロシージャを実行する

Callステートメントを使用することにより他のプロシージャが実行できます

'別の処理を実行する
Call プロシージャ名

現在実行中の処理中に、別の処理を実行するには「Call」を使用します
「Call ~~」の「~~」にプロシージャ名を指定することで、別の処理を実行できます

Callステートメントでの処理呼び出しの動き
Callで呼び出された時のコードの動き

画像の動きを確認してください(黄色い背景色が実行されている順番です)

処理テストAの中で呼び出しを行っています
呼び出された所から、処理テストBに移動して処理が実行されます
「End Sub」まで実行されたら、呼び出し元の処理テストAの続きが実行されます

主な使用場面は、同じ処理を連続して行ったり(「Call 処理テストB」を5回記載すれば5回実行される)、処理が複雑で長いコードを小分けにして別の場所に作成して処理を呼び出したりする際に使用します

なお、呼び出し先の処理で強制的に処理を終了させる方法もあります
例でいうと、処理テストBの途中で「End」を使用することで、処理テストAに戻らずに処理が終了します

ただこの動きは、処理テストAの終了があいまいになり非常に不安定要素となってしまうのでおすすめしません

定数の宣言方法

処理の実行中は変更される事の無い定数の使用方法と解説

'定数を宣言して値の代入を行う
Const パス名 As String = "ファイルパス文字列"

定数を使用するには「Const」を使用します

基本的な宣言の仕方は変数と同じで、定数名とその後にデータの型を宣言します
(文字列型変数の宣言方法はこちら)

定数とは、文字通り定まったデータです
宣言時にデータの代入を行い、代入後にデータの変更は出来ません

基本的には変数を変更しなければ同じ役割で対応できますが、使用する利点は何より宣言セクションで値の代入ができる点です
変数の場合はプロシージャの中でデータを代入しますが、定数はコンパイル時に代入されます

コンパイルとは、実際に処理が実行される前段階の事です

宣言セクションについて

定数の宣言方法と場所
赤枠内のプロシージャの外上が宣言セクション

このように宣言セクションで値を代入させることは、コードの可読性を高めます

例のような固定パスを定数とした場合に、フォルダ名の変更などによりパスが変更される可能性があります
これを変数でプロシージャ内の使用部分で宣言、代入をしていた場合にその位置を探すのが大変です

宣言セクションに定数で代入をしておけば、モジュール最上段にそのコードがあるので、パスの修正が必要な際に見つけやすくなります
これは、自分だけでなく他の人のためにも有用な方法です
優位性が薄まりますが、プロシージャ内に宣言することも変数同様に可能です

なお、定数は文字列や数値で使用しオブジェクトは使用できません
また、宣言セクションで変数に値を代入することは出来ません(宣言自体は可能です)

オブジェクトでループする(For Each)

オブジェクトに対して行うループ処理の解説

'A1からA10までのセルでループ
For Each オブジェクト変数 In Range("A1:A10")

'処理内容

Next オブジェクト変数

オブジェクトに対してのループには「For Each」を使用します

このオブジェクトに対してループというのは、初心者では難しい内容です
オブジェクトの操作自体が出来てきて、便利さが分かってくると確実に使う場面が出てきます
なにより、戻り値がオブジェクトというものもありそれに対応するには必要です

Forループでの解説同様にこれも変数とセットで使用します
その際の変数はObject型になります(この変数についてはこちら)

「Object」という型でもいいのですが、より読み取りやすくするために対象を絞った型宣言をおすすめします
今回のようにセルを代入するのであれば、「Range」を使用してください

変数の代入式には「In」を使用します
このループ処理でのオブジェクト変数にはA1~A10までのセルが順番に代入されます
一括で全て代入する通常の変数使用時と違い、1要素ずつなので「=」ではなく「In」が使用されます

A1~A10のそれぞれのセルが、「Next オブジェクト変数」の時点で次の要素が代入され、最後の要素が代入されて次の要素が無ければループは終了します
この際にオブジェクト変数は初期値の「Nothing」が代入されるので、通常の変数の解放操作は必要ありません

オブジェクトでループする理由は、まさにオブジェクトの持つ特性の利用です
オブジェクトにはそれぞれさまざまなプロパティが存在していますので、それらをまとめて参照できるようになります
オブジェクトループが出来れば、ループ処理はコンプリートです

数値でループする(For)

終了条件が確定している状態でのループ処理

'変数が0~10までループ、加算値は1
For 変数 = 0 To 10 Step 1

'処理内容

Next 変数

ループ処理には大きく分けて2つあり、「Do」と「For」です
Forループは数値を条件としてループさせるため、ループの回数が明確な場合に使用します

またForループでは変数にループ回数の数値を代入することから、Forループの使用にはセットで変数が必要です(変数の使用はこちらの記事になります)

「For 変数 = 0 To 10」の赤字範囲が開始と終了の条件になります
0から始まり10でループを終了します、その際に数値は変数に代入されます

「Step 1」の部分が数値の加算値になり、「0 → 1 → 2 ・・・」と続きます
なお、この「Step」と数値は省略でき、省略した場合は加算値が1になります
「For 変数 = 0 To 10」という書き方をすれば省略になります

ForループとDoループについて

内容によってはDoループで代用はできるので、変数がめんどくさい人はDoループでいいと思います

それでも、DoよりForを使用する利点

・変数に自動的に加算していってくれること(Nextの時に加算される)
・加算の幅も指定できること
・初期値を自動的に入力してくれること
・Doループより処理速度が速いこと

加算と幅の指定は、使ってみると結構楽になるのでいいですし、初期値の入力構文がいらないのが楽です
処理速度はほとんどの場合は誤差の範囲内かもしれませんが優位なのは確かです

どちらもいい部分がそれぞれにあるので、どちらかに固定して使う必要はありませんし優先順位も無いと思います
使いたい場面で使えるほうを使えばいいと思います

ループ処理-後判定-(Do Until)

処理を実行してから判定を行い条件が成り立つまでループするコード

'アクティブセルが10以上になるまで1を足す
Do
ActiveCell = ActiveCell + 1
Loop Until ActiveCell >= 10

通常のループ処理には「Do」ループを使用します
後判定を使用する場合は、最後の「Loop ~~」の「~~」に条件を指定します
Until以下条件式の解説は、前判定記事にあります

後判定とは、ループ処理を実行後に判定を行うものです
「後」なので、最初に判定は行われないため最初の1回は必ず実行されます

この例では、アクティブセルが9であった場合に1度実行するとアクティブセルが10になり処理終了、もう一度実行すると1回は無条件実行なので11になって終了します
前判定であれば加算処理は行われませんが、後判定では必ず1回は実行されるので加算され続けます、そこが違う点です

1回目が必ず実行されるという以外は前判定と変わりません
つまり2回目以降は後も前も関係は無いので「最初の1回を実行するかしないか」で前か後かを判断して作成してください