VB制御フロー


条件分岐

If..Then

if condition Then
  [Exit Sub]
  [処理]
[ElseIf condition Then
  [処理]]
[Else
  [処理]]
End If
If condition Then [処理] [: 処理].. [Else [処理]

Exit SubでSubを抜け出せる.
条件を並べた場合,条件の判定は全てされる.
If func1() or func2() then
func1の是非に関わらず, func2もどちらも実行される.
end if

condition:

Boolean


Select Case

Select Case testexpression
  [Case expressionlist
    [処理]]
  [Case
    Else [処理]]
End Select

testexpression:

数値式 or 文字列式.
CInt(hoge)とか.

expressionlist:

21,10 To 15,Is < 3の形式,複数も可能.
Toは値の範囲なので小To大となるように.
Isは比較演算子と一緒に使う.IsなしでもIsだと認識される.




ループ構文

https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/control-flow-keyword-summary

Do…Loop

条件がTrueの間実行する。
WhileWend文もあるが、Exitすることができない。

Dim counter As Integer '方宣言する場合の例
counter = 0  '変数名は変えてもOK
Do [{While|Until} condition]
  [処理]
  [Exit Do] [処理]
Loop

Do
  [処理] 
  [Exit Do] [処理]
Loop [{ WhileUntil | } condition ]

condition

数式or文字列式.
省略した場合False?
Nullの場合False.
WhileUntilをつけるとFalseの間になる?
Whileを上,下のいずれかに加えられるが,その位置で条件判定される.
下にある場合は,必ずDo内の処理が1度実行される.

Exit Doに達すると抜ける.

回数指定してループ

Dim counter As Integer '型宣言する場合
For counter = start To end [Step step]
  [処理]
  [Exit For]
  [処理]
Next [counter]

ループするものを削除する場合,hogehoge.Count To 1 Step -1 として,後ろからやる.
breakのようにExit Forを使えば良い.

counter:

数値として使われる変数.
ブーリアンでも行列でもだめ.
途中でcounterの値を代入できることに注意.

Nextの後のcounterは記述しなくても,指定したのと同様に動作する.
複雑な入り子場合とかは,間違えないように書いたほうが良いと思う.

start: 数値

counterの初期値.

end: 数値

終了の判定値.
step ≥ 0の場合,counter <= endなら実行...ε= conter || end
step < 0の場合,counter >= endなら実行.end || counter=3...
1 To 10なら,10まで実行される.

step=1:

毎回counterに追加する数.
2なら,0, 2, 4, ...』


各要素を取り出してループ

Dim element As Object (型宣言をする場合)
For Each element In group
  [処理]
  [Exit For]
  [処理]
Next [elemnt]

ループするものが削除(追加も?)されるのはNG?エラーではないのかも.

element:

要素が格納される変数名.
Varient変数,汎用オブジェクト変数,特定のオブジェクト変数を指定できる.


group:

コレクション名,または,配列名.
ユーザ定義型の配列はNG.



挿入ソート

Sub InsertionSort(arr() As Long)
  Dim i As Long
  Dim j As Long
  Dim currentValue As Variant
   
   For i = LBound(arr) + 1 To UBound(arr)
    currentValue = arr(i)
    j = i - 1
     
    ' 適切な位置に要素を挿入する
    Do While j >= LBound(arr)
      If arr(j) > currentValue Then
        arr(j + 1) = arr(j)

      Else
        Exit Do
      End If
      j = j - 1
    Loop
    arr(j + 1) = currentValue

  Next i
End Sub






エラー処理

https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/on-error-statement

エラー無視

On Error Resume Next

この一文を関数の先頭に書いておけば、関数内でエラーが生じても次の分から再開される。

エラーハンドラに飛ばす方法

エラー処理を行うサブルーチン内1行目に次の文を書く。

On Error GoTo ErrorHandler

"ErrorHandler"の部分はエラーハンドラ名。自分で決められる。

同サブルーチンの下部に次のようなエラーハンドラーの定義を書く。

ErrorHandler:
    Debug.Print "エラーが発生しました:"
    Debug.Print "エラーコード: " & Err.Number
    Debug.Print "エラーメッセージ: " & Err.Description

    Resume Next

"ErrorHandler"の部分はインデントしないせず、Sub Hoge()の宣言と同位に記述する。
"Resume Next"を記載することで、実行を続行できる。
また、エラーが生じなかった場合に、ここの処理が実行されないよう"Exit Sub"をこの部分の前に追加する。

以上のことを合わせると次のようになる。

Sub ShowErrorInfo()
    On Error GoTo ErrorHandler
    
    ' エラーが発生する可能性のあるコードを記述します
    ' 例えば:
    ' Dim x As Integer
    ' x = 1 / 0
    
    Exit Sub

ErrorHandler:
    Debug.Print "エラーが発生しました:"
    Debug.Print "エラーコード: " & Err.Number
    Debug.Print "エラーメッセージ: " & Err.Description

    MsgBox "エラーが発生しました:" & vbCrLf & _
        "エラーコード: " & Err.Number & vbCrLf & _
        "エラーメッセージ: " & Err.Description, vbCritical, "エラー"
    Resume Next
End Sub


複数のエラー処理を同一のエラーハンドラで処理する方法

エラーハンドラはほかの関数を呼び出すことが可能。
したがって、その関数に別のサブルーチンのエラーも処理させて、次のように複数の処理を同一ハンドラで疑似的に処理することが可能。

Sub Sub1()
    On Error GoTo ErrorHandler  
    Exit Sub
ErrorHandler:
    HandleError Err.Number, Err.Description
    Resume Next
End Sub

Sub Sub2()
    On Error GoTo ErrorHandler
    Exit Sub
ErrorHandler:
    HandleError Err.Number, Err.Description
    Resume Next
End Sub

Sub HandleError(ErrNumber As Long, ErrDescription As String)
    MsgBox "エラーが発生しました:" & vbCrLf & _
        "エラーコード: " & ErrNumber & vbCrLf & _
        "エラーメッセージ: " & ErrDescription, vbCritical, "エラー"
End Sub