Excel VBA 別解集 繰り返し処理 分岐処理 part2

問題1

問題:売上金額に応じた評価をコマンドボタンをクリックすることで行う。100万円以上はA、80万円以上はB、60万円以上はC、40万円以上はD、20万円以上はE、20万円未満はランク外とする。

1)For~Next文とIf文を用いて実現せよ

2)For~Next文とSelect文を用いて実現せよ

3)配列とFunctionプロシージャを用い、For文とDo While文を用いて実現せよ

4)配列とサブルーチンを用いて、For文とサブルーチンのなかにDo Until文を仕込んで実現せよ

5)CurrentRegionとサブルーチンを用いて実現せよ。繰り返しと分岐処理はサブルーチンのなかで行うものとする

6)CurrentRegionとFunctionプロシージャを用い、Do Until文を用いて実現せよ

解答

1)

Sub main()
    Dim i As Integer
    
    For i = 2 To 7
        If Cells(i, 2) >= 1000000 Then
            Cells(i, 4) = "A"
        ElseIf Cells(i, 2) >= 800000 Then
            Cells(i, 4) = "B"
        ElseIf Cells(i, 2) >= 600000 Then
            Cells(i, 4) = "C"
        ElseIf Cells(i, 2) >= 400000 Then
            Cells(i, 4) = "D"
        ElseIf Cells(i, 2) >= 200000 Then
            Cells(i, 4) = "E"
        Else
            Cells(i, 4) = "ランク外"
        End If
    Next i
End Sub

ElseIf文があれば、どれだけ長い分岐処理でもIf文で書けるが、分岐が4つ以上あれば、通常は2)の方法を取るべきである。

2)

Sub main1()
    Dim i As Integer
    
    For i = 2 To 7
        Select Case Cells(i, 2)
            Case Is >= 1000000
                Cells(i, 4) = "A"
            Case Is >= 800000
                Cells(i, 4) = "B"
            Case Is >= 600000
                Cells(i, 4) = "C"
            Case Is >= 400000
                Cells(i, 4) = "D"
            Case Is >= 200000
                Cells(i, 4) = "E"
            Case Else
                Cells(i, 4) = "ランク外"
        End Select
    Next i
End Sub

Case文は多数の分岐処理を記述するのに最適な方法である。If文との優劣はないにせよ、どちらもケースバイケースで使えるようになって欲しい。

3)

Sub main2()
    Dim myarry(6) As Integer, i As Integer
    
    For i = 1 To 6
        myarry(i) = Cells(i + 1, 2) / 1000
    Next i
    
    i = 1
    Do While Cells(i + 1, 2) <> ""
        Cells(i + 1, 4) = getMoneydt(myarry(), i)
        i = i + 1
    Loop
End Sub

ーーーーーーーーーーーーーーーーーーーーーーー
Function getMoneydt(myarry() As Integer, i As Integer) As String
    Select Case myarry(i)
        Case Is >= 1000
            getMoneydt = "A"
        Case Is >= 800
            getMoneydt = "B"
        Case Is >= 600
            getMoneydt = "C"
        Case Is >= 400
            getMoneydt = "D"
        Case Is >= 200
            getMoneydt = "E"
        Case Else
            getMoneydt = "ランク外"
    End Select
End Function

1000で割っているのはInteger型を使うためである。いまはメモリーがふんだんにあるので、Long型を使うのが普通になっているが、昔の癖である。Long型を普通に使うのがいまの流行らしい。

このルーチンは、一度配列に1000で割った配列の値を代入し、それをDo While文で空白ではない間(〇〇ではない間はWhileを使う)、Functionプロシージャを使ってセルに値を入れている。カウンター変数のiは入力するセルを制御している。

4)

Sub main3()
    Dim myarry(6) As Integer, i As Integer
    
    For i = 1 To 6
        myarry(i) = Cells(i + 1, 2) / 1000
    Next i
    
    Call getMoney(myarry())


End Sub

ーーーーーーーーーーーーーーーーーーーーーーー
Sub getMoney(myarry() As Integer)
    Dim i As Integer
    
    i = 1
    Do Until Cells(i + 1, 2) = ""
        If myarry(i) >= 1000 Then
            Cells(i + 1, 4) = "A"
        ElseIf myarry(i) >= 800 Then
            Cells(i + 1, 4) = "B"
        ElseIf myarry(i) >= 600 Then
            Cells(i + 1, 4) = "C"
        ElseIf myarry(i) >= 400 Then
            Cells(i + 1, 4) = "D"
        ElseIf myarry(i) >= 200 Then
            Cells(i + 1, 4) = "E"
        Else
            Cells(i + 1, 4) = "ランク外"
        End If
    
        i = i + 1
        
    Loop
End Sub

配列にFor文でまわして変数を入れ、サブルーチンでセルに値を入れている。If文をDo Until文で回している、すこし保守性が悪いサブルーチンである。

5)

Sub main4()
    Dim myarry As Variant
    
    myarry = Range("A1").CurrentRegion
    Call getMoneyList(myarry)
    
End Sub

ーーーーーーーーーーーーーーーーーーーーーーー
Sub getMoneyList(myarry As Variant)
    Dim i As Integer

    For i = 2 To UBound(myarry)
        If myarry(i, 2) / 1000 >= 1000 Then
            Cells(i, 4) = "A"
        ElseIf myarry(i, 2) / 1000 >= 800 Then
            Cells(i, 4) = "B"
        ElseIf myarry(i, 2) / 1000 >= 600 Then
            Cells(i, 4) = "C"
        ElseIf myarry(i, 2) / 1000 >= 400 Then
            Cells(i, 4) = "D"
        ElseIf myarry(i, 2) / 1000 >= 200 Then
            Cells(i, 4) = "E"
        Else
            Cells(i, 4) = "ランク外"
        End If
    Next i
End Sub

名前(String型)と数値が混在している表を一発でとる(CurrentRegion)にはVariant型が必要である。そのVariant型を引数としてサブルーチンへ渡して、その中で処理をしている例である。サブルーチンのUBoundはVariant型の最終行を取り、If文のなかで1000で割ることで、Integer型を使えるようにしている。

6)

Sub main5()
    Dim myarry As Variant
    Dim i As Integer
    
    myarry = Range("A1").CurrentRegion
    
    i = 1
    Do Until Cells(i + 1, 2) = ""
        Cells(i + 1, 4) = getMoneyListdt(myarry, i)
        i = i + 1
    Loop
End Sub

ーーーーーーーーーーーーーーーーーーーーーーー

Function getMoneyListdt(myarry As Variant, i As Integer) As String

    Select Case myarry(i + 1, 2) / 1000
        Case Is >= 1000
            getMoneyListdt = "A"
        Case Is >= 800
            getMoneyListdt = "B"
        Case Is >= 600
            getMoneyListdt = "C"
        Case Is >= 400
            getMoneyListdt = "D"
        Case Is >= 200
            getMoneyListdt = "E"
        Case Else
            getMoneyListdt = "ランク外"
    End Select
End Function

5)と同様にVariant型で表を一発でとり、Functionプロシージャを使って、Do Until文でセルに値を入れ、制御カウンターiで入力セルを確定している。