はじめに
セルにコマンドボタンを入れるやり方は、
を参照して欲しい。
問題1
上記の問題で
1)If文でコーディングせよ
2)Select文でコーディングせよ。
解答
1)
Sub Macro1()
If Range("B2") >= 90 Then
Range("D2") = "優です"
ElseIf Range("B2") >= 80 Then
Range("D2") = "良です"
ElseIf Range("B2") >= 70 Then
Range("D2") = "可です"
Else
Range("D2") = "不可です"
End If
End Sub
if文で記述する場合、分岐が長くなるので、if~else~end if だけではだめで、途中にelseif文をかませて記述する必要がある。
このようにif文が長くなる場合には、2)で扱うSelect文が有効である。
2)
Sub main()
Select Case Range("B2").Value
Case Is >= 90
Range("D2") = "優です"
Case Is >= 80
Range("D2") = "良です"
Case Is >= 70
Range("D2") = "可です"
Case Else
Range("D2") = "不可です"
End Select
End Sub
こちらの方がコードが簡潔に書ける。優劣はないにせよ、両方使えるようになって欲しい。
問題2
上記の問題で
1)For文のみでコピーせよ
2)Functionプロシージャを作成してセルの最終行を取り、For文のみでコピーせよ
3)配列を用いてFor文とUBoundを用いてコピーせよ
4)配列とFor文、UBoundとDo Until~loopを用いてコピーせよ
5)配列を使い、Functionプロシージャで最終行を取り、サブルーチンで都県の名前を取り、Do while~loopでコピーせよ。
6)Functionプロシージャを作成してセルの最終行を取り、For Each文のみでコピーせよ。
7).copyを使い、Rangeのみでコピーせよ。
8)Functionプロシージャで最終行を取り、.copyを使い、cellsとRangeを使ってコピーせよ。
9)Functionプロシージャで最終行を取り、.copyを使い、一度クリップボードへコピーしてからペーストでコピーせよ。
解答
1)
Sub main7()
Dim i As Integer
For i = 2 To 8
Cells(i, 4) = Cells(i, 2)
Next i
End Sub
一番素直で簡潔なやり方である。本来ならこれで十分。
2)
Sub main()
Dim i As Integer, lcr As Integer
lcr = getLastCellRow
For i = 2 To lcr
Cells(i, 4) = Cells(i, 2).Value
Next i
End Sub
ーーーーーーーーーーーーーーーーーーーーーーー
Function getLastCellRow() As Integer
getLastCellRow = Cells(Rows.Count, 2).End(xlUp).Row
End Function
Functionプロシージャというのは、Subプロシージャと同じだが、相違点は戻り値があるかどうか、である。Functionプロシージャの方はプロシージャ名に値を代入して、一種の関数のようにして扱う。
3)
Sub Macro1()
Dim myarry(7) As String
Dim i As Integer
For i = 2 To UBound(myarry) + 1
myarry(i - 1) = Cells(i, 2).Value
Cells(i, 4) = myarry(i - 1)
Next i
End Sub
UBoundは配列などの最大値をとるものである。ここでは、わざと一度配列にデータを入れて、それから記入するセルにその値を入れている。
4)
Sub main1()
Dim lcr As Integer, i As Integer
Dim myarry(7) As String
For i = 1 To UBound(myarry)
myarry(i) = Cells(i + 1, 2).Value
Next i
i = 1
Do Until Cells(i + 1, 2) = ""
Cells(i + 1, 4) = myarry(i)
i = i + 1
Loop
End Sub
配列をFor文で回してあらかじめすべての値を代入し、Doループを使って表現している。ここではセルが空白になるまで(〇〇になるまで、はUntilを使う)回し、iというカウンター変数でセルを制御している。
5)
Sub main2()
Dim lcr As Integer, i As Integer
Dim myarry(7) As String
lcr = getLastCellRow
Call getCityName(myarry(), lcr)
i = 1
Do While Cells(i + 1, 2) <> ""
Cells(i + 1, 4) = myarry(i)
i = i + 1
Loop
End Sub
ーーーーーーーーーーーーーーーーーーーーーーー
Sub getCityName(myarry() As String, lcr As Integer)
Dim i As Integer
For i = 1 To lcr - 1
myarry(i) = Cells(i + 1, 2).Value
Next i
End Sub
getLastRowは、2)でつくったものを再度使っている。セルの最終行をとり、サブルーチンgetCityNameで配列にデータを入れているが戻り値はない。発展でByVal,ByRefで引数を渡すが、この場合は指定がないので、参照渡し(ByRef)で、内部で処理したものが、そのままの状態を保ってmainのルーチンに使える。
6)
Sub main5()
Dim myrng As Range
Dim lcr As Integer, i As Integer
lcr = getLastCellRow
i = 2
For Each myrng In Range(Cells(2, 2), Cells(lcr, 2))
Range("D" & i) = myrng
i = i + 1
Next myrng
End Sub
For Each文はオブジェクト変数(workbook,worksheet,rangeなど)を繰り返し処理する場合に使う方法である。2)でつくったFunctionプロシージャで最終行をとり、Rangeで回してセルに代入している。iはカウンター変数として用い、入力セルを制御している。
7)
Sub main6()
Range("B2:B8").Copy Range("D2")
End Sub
これはコピー関数を使った例である。Rangeオブジェクトに対して.Copyを入れ、入れる先を書けばそれで済む。お気楽、お手軽な方法であるが、なぜか取り上げているものは見かけない。
8)
Sub main3()
Dim lcr As Integer
lcr = getLastCellRow
Range(Cells(2, 2), Cells(lcr, 2)).Copy Range(Cells(2, 4), Cells(lcr, 4))
End Sub
.Copy関数と2)でつくったFunctionプロシージャとの組み合わせで、Rangeオブジェクトのなかに、cellsで範囲を取るという手法である。7)よりはデータ数が増えたときにも使える方法である。
9)
Sub main4()
Dim lcr As Integer
lcr = getLastCellRow
Range(Cells(2, 2), Cells(lcr, 2)).Copy
Range(Cells(2, 4), Cells(lcr, 4)).PasteSpecial
Application.CutCopyMode = False
End Sub
一度クリップボードへコピーしてから、ペーストする、いわゆるコピペという方法を使っている。Application.CutCopyMode = Falseは、コピーしたとき点線が残るのを防ぐための処理である。