Step も)Cells(0, 1) がエラーになることを知り、添字の始まりに気をつけられる元資料 6〜8 枚目の例です。「薬を 7 錠飲む」という手順を流れ図で書きます。
この流れ図には「薬を 1 錠飲む」が 2 か所(①と③)にあります。 元資料 8 枚目のトレースを見ると、①で 1 錠飲んでから②で判断し、 ③でもう 1 錠飲む ── という動きになっています。7 錠になるので答えは合いますが、 同じ処理を 2 か所に書くのは、繰り返しの形が整っていない印です。
整えると、飲む処理は 1 か所で済みます。
なぜこれが大事か。 同じ処理が 2 か所にあると、直すときに片方だけ直して不具合になります (「1 錠」を「2 錠」に変えるとき、③だけ変えたら 1 錠目が取り残される)。 繰り返しの目的は「回数を減らすこと」ではなく「同じことを 1 か所にまとめること」です。
回数が決まっている繰り返しに使います(元資料 4・5 枚目)。
For 制御変数 = 初期値 To 最終値 [Step 増分値]
ブロック
Next 制御変数
Step を書かなければ1 ずつ増えるStep -2 のように負にもできる(この場合は最終値まで減っていく)Sub Macro1()
Dim i As Integer
Dim s As Integer
Dim N As Integer
N = 5
s = 0
For i = 1 To N
s = s + i
' 途中の様子をシートに書き出す(自分で追える)
Cells(i, 1) = "i = " & i
Cells(i, 2) = "s = " & s
Next i
Cells(7, 1) = "1 から " & N & " までの和"
Cells(7, 2) = s
End Sub
元資料 13 枚目のトレースです。変数の値を 1 行ずつ書き出して追うこれを 「トレースする」といい、プログラムを読む基本の技術です。
ループが終わったあとの i の値に注意。
元資料 13 枚目のトレースは
「s = 0+1+2+3+4+5 → i = 5+1 = 6 ④ ②で判断」で終わっています。
つまりループを抜けたとき、i は最終値より 1 大きい(6)のです。
条件を判断するために、いったん増やしてから比べるからです。
ループのあとで i を使うと N ではなく N+1 なので、ここでよく間違えます。
Sub Macro2()
Dim i As Integer
Dim r As Integer
' 1 から 10 まで、2 つ飛ばし
r = 1
For i = 1 To 10 Step 2
Cells(r, 1) = i
r = r + 1
Next i
Cells(1, 2) = "← Step 2"
' 10 から 1 まで、逆向き
r = 1
For i = 10 To 1 Step -3
Cells(r, 4) = i
r = r + 1
Next i
Cells(1, 5) = "← Step -3"
' 9 の段(かけ算九九の一部)
For i = 1 To 9
Cells(i, 6) = 9 * i
Next i
End Sub
元資料 12 枚目の書き方です。条件が真である間、繰り返します。
While 条件式
ブロック
Wend
Sub Macro3()
Dim i As Integer
Dim s As Integer
Dim N As Integer
N = 5
s = 0
i = 1 ' ① 初期化を自分で書く
While i <= N ' ② 条件を自分で書く
s = s + i ' ③ 本体
i = i + 1 ' ④ 増やすのも自分で書く
Wend
Cells(1, 1) = "和"
Cells(1, 2) = s
Cells(2, 1) = "抜けたときの i"
Cells(2, 2) = i
End Sub
For 〜 Next | While 〜 Wend | |
|---|---|---|
| 向いている場合 | 回数が決まっている | いつ終わるか分からない |
| 初期化・増加 | 1 行にまとめて書ける | 自分で書く(3 か所) |
| 書き忘れの危険 | 少ない | 増やす行を忘れると無限ループ |
| 例 | 1〜N の和、表の 10 行を処理 | 互除法、収束するまで計算(第 8 章) |
回数が分かっているなら For を使ってください。
While で書くと、初期化・条件・増加が3 か所に散るので、
どれか 1 つを書き忘れて無限ループになります。
上のプログラムで i = i + 1 の行を消して実行してみてください ──
本物の Excel なら固まりますが、この教材では 200 万手で自動的に止まります。
安心して失敗を試せます。
While 〜 Wend は古い書き方です。
元資料はこれを使っていますが、現在の VBA では
Do While 〜 Loop が推奨されます(第 8 章)。
理由は Do なら Exit Do で途中脱出でき、
終了条件を後ろにも書けるからです。
While 〜 Wend は互換のために残されているだけなので、
これから書くなら Do While 〜 Loop にしてください。
元資料 15・16 枚目の例です。同じ文字列を 5 行ぶん書きます。
元資料 16 枚目のトレースは、こう書かれています。
Cells(i,1) = "*****" を実行Cells(i,1) = "*****" を実行しかし Cells(0, 1) は実行できません。
Excel の行番号・列番号は 1 から始まるので、
0 を指定すると実行時エラー(1004: アプリケーション定義またはオブジェクト定義のエラー)になります。
「0〜4 までの 5 回」という数え方は配列の添字では正しいのですが(第 11 章)、
セルの番号としては使えません。
下のプログラムで確かめてください (この教材の処理系も、同じようにエラーで止まります)。
Sub Macro4()
Dim i As Integer
' 元資料のとおり 0 から始めると……
For i = 0 To 4
Cells(i, 1) = "*****"
Next i
End Sub
Sub Macro5()
Dim i As Integer
' 直し方 ①:1 から 5 まで数える
For i = 1 To 5
Cells(i, 1) = "*****"
Next i
' 直し方 ②:0 から数えたいなら、書くときに +1 する
For i = 0 To 4
Cells(i + 1, 3) = "#####"
Next i
Cells(6, 1) = "① 1 To 5"
Cells(6, 3) = "② 0 To 4 で i+1"
End Sub
「0 から数えるか、1 から数えるか」は、
プログラミングでいちばん間違いの多いところです。
Excel のセル・行・列は 1 から、
VBA の配列は既定で 0 から(第 11 章)、
文字列の Mid は 1 から(第 3 章)──
ものによって違います。
迷ったら「最初の 1 個」と「最後の 1 個」を実際に試すのが確実です。
ループの中にループを書くと、表全体を扱えます(元資料 17・18 枚目)。 外側が 1 周する間に、内側が全部まわります。
Sub Macro6()
Dim i As Integer
Dim j As Integer
' i 行目に、* を i 個ならべる
For i = 1 To 8
For j = 1 To i
Cells(i, j) = "*"
Cells(i, j).Interior.Color = RGB(0, 112, 192)
Next j
Next i
Cells(10, 1) = "内側のループの回数が、外側の i によって変わります"
End Sub
内側の For j = 1 To i に注目してください。
終わりの値が固定ではなく i(外側の変数)になっています。
だから 1 行目は 1 個、2 行目は 2 個…と増えていきます。
二重ループの威力はここにあります ──
内側の回数を外側で変えられるのです。
Sub Macro7()
Dim i As Integer
Dim j As Integer
' 見出し
For i = 1 To 9
Cells(1, i + 1) = i
Cells(i + 1, 1) = i
Cells(1, i + 1).Interior.Color = RGB(0, 63, 140)
Cells(1, i + 1).Font.Color = RGB(255, 255, 255)
Cells(i + 1, 1).Interior.Color = RGB(0, 63, 140)
Cells(i + 1, 1).Font.Color = RGB(255, 255, 255)
Next i
' 本体
For i = 1 To 9
For j = 1 To 9
Cells(i + 1, j + 1) = i * j
' 平方数(i = j)に色をつける
If i = j Then Cells(i + 1, j + 1).Interior.Color = RGB(255, 235, 156)
Next j
Next i
End Sub
Sub Macro8()
Dim i As Integer
Cells(1, 1) = "n"
Cells(1, 2) = "√n"
Cells(1, 3) = "n の 2 乗"
Cells(1, 1).Font.Bold = True
Cells(1, 2).Font.Bold = True
Cells(1, 3).Font.Bold = True
For i = 1 To 10
Cells(i + 1, 1) = i
Cells(i + 1, 2) = Format(Sqr(i), "#.#####")
Cells(i + 1, 3) = i ^ 2
Next i
End Sub
数表を作るのは、繰り返しのいちばん素直な使い方です。
「i を 1 から 10 まで変えて、同じ計算を i について行い、i 行目に書く」──
この形は、あとでグラフを描く(第 15 章)ときにもそのまま使います。
Format(Sqr(i), "#.#####") で桁をそろえているのは、
表として読みやすくするためです(第 3 章の Format)。
身長と体重を入力し、標準体重、肥満度、BMI(肥満係数)を求めるとともに、 BMI によってメッセージを切り替えよ。
身長の単位は m(メートル)であり、 cm で入力した場合は単位の調整が必要である。
元資料 28 枚目のプログラムは、そのまま動きます。cm で入力するので、
/ 10000 と * 10000 で単位を調整しているところが要点です
(1 m = 100 cm なので、2 乗すると 10000 倍の差になります)。
Sub Macro520()
Dim Height As Single, Weight As Single
Dim sw As Single, ob As Single, BMI As Single
Height = Range("A2").Value
Weight = Range("B2").Value
sw = Height ^ 2 / 10000 * 22 ' cm を m に直して 2 乗
ob = (Weight - sw) / sw * 100 ' 肥満度(%)
BMI = Weight / Height ^ 2 * 10000 ' 体重 ÷ 身長(m)^2
Range("A4").Value = Format(sw, "#.##")
Range("B4").Value = Format(ob, "#.##")
Range("A6").Value = Format(BMI, "#.##")
If BMI < 18.5 Then
Range("A8").Value = "低体重"
ElseIf BMI < 25 Then
Range("A8").Value = "普通体重"
ElseIf BMI < 30 Then
Range("A8").Value = "肥満度1"
ElseIf BMI < 35 Then
Range("A8").Value = "肥満度2"
ElseIf BMI < 40 Then
Range("A8").Value = "肥満度3"
Else
Range("A8").Value = "肥満度4"
End If
End Sub
この判定の区切りは、日本肥満学会の基準に一致しています
(18.5 未満=低体重、18.5〜25=普通体重、25〜30=肥満 1 度、30〜35=2 度、35〜40=3 度、40 以上=4 度)。
ElseIf が上から順に調べるので、
BMI < 25 は「18.5 以上 25 未満」の意味になります(第 6 章 §1)。
ここで繰り返しを使うと。
元資料のプログラムは 1 人分です。クラス 30 人ぶんを一度に処理したいなら、
全体を For で囲んで、Range("A2") を
Cells(i, 1) に変えるだけです。
「1 人分を書いてから、ループで囲む」── これがプログラムを育てる基本の手順です。
Sub Macro9()
Dim i As Integer
Dim Height As Single, Weight As Single
Dim sw As Single, ob As Single, BMI As Single
For i = 2 To 6 ' 2 行目から 6 行目まで
Height = Cells(i, 1).Value
Weight = Cells(i, 2).Value
sw = Height ^ 2 / 10000 * 22
ob = (Weight - sw) / sw * 100
BMI = Weight / Height ^ 2 * 10000
Cells(i, 3) = Format(sw, "#.##")
Cells(i, 4) = Format(ob, "#.##")
Cells(i, 5) = Format(BMI, "#.##")
If BMI < 18.5 Then
Cells(i, 6) = "低体重"
Cells(i, 6).Interior.Color = RGB(183, 230, 240)
ElseIf BMI < 25 Then
Cells(i, 6) = "普通体重"
Cells(i, 6).Interior.Color = RGB(198, 239, 206)
Else
Cells(i, 6) = "肥満"
Cells(i, 6).Interior.Color = RGB(255, 235, 156)
End If
Next i
End Sub
For 制御変数 = 初期値 To 最終値 [Step 増分値] 〜 Next。
回数が決まっているならこちらWhile 〜 Wend は条件による繰り返し。増やす行を忘れると無限ループ。
新しく書くなら Do While 〜 Loop(第 8 章)Cells(0, 1) はエラー。セルの行・列は 1 からもとにしたのは「情報学入門(VBA)142-2021」全 31 枚 (および同内容の 140-2019・19 枚)です。
| 元資料 | この教材 | 種別 |
|---|---|---|
16 枚目のトレースが i=0 で Cells(i,1) を実行すると書いている |
Excel の行・列は 1 から。Cells(0,1) は実行時エラーになる。
実際にエラーになる例と、直し方 2 通りを載せた | 誤り |
| 「薬を飲む」の流れ図で「薬を 1 錠飲む」が 2 か所にある(①と③) | 答えは合うが繰り返しの形が整っていない。 処理を 1 か所にまとめた流れ図を並べ、なぜそれが大事か(片方だけ直す事故)を示した | 構成 |
While 〜 Wend を使っているが、古い書き方であることに触れていない |
現在は Do While 〜 Loop が推奨(Exit Do が使える)。互換のために残っている書き方だと明記 | 古い |
| トレース(13 枚目)が画像で、抜けたときの制御変数が最終値+1 になることを本文で説明していない | 1 行ずつたどれるトレース表にし、i が 6 になることを明示 | 不足 |
| For と While の使い分けの指針がない | 比較表を追加(回数が決まっているか/書き忘れの危険) | 不足 |
| 図形の表示・二重ループがスクリーンショットのみ | 実行できる形にし、内側の回数を外側の変数で変えられることを要点として示した | 体裁 |
| 標準体重のプログラムは 1 人分のみ | 「1 件分を書いてからループで囲む」手順を示し、5 人ぶんの版を追加 | 不足 |
| 資料 140(19 枚)と 142(31 枚)がほぼ同内容で 2 本ある | 142(2021 年改訂版)を採り、1 つの章にまとめた | 重複 |
元資料で正しかったこと。
For と While の書式、13 枚目のトレースの数値
(s が 1→3→6→10→15、i が 2→3→4→5→6)、
27 枚目の 3 つの計算式(標準体重=身長2×22、肥満度、
BMI=体重/身長2)、
28 枚目のプログラム(cm→m の単位調整 / 10000・* 10000、
Dim Height As Single, Weight As Single と型を 1 つずつ書いている点、
BMI の 6 段階の区切りが日本肥満学会の基準と一致すること)── いずれも正確です。
28 枚目のプログラムはこのページで実行して確認しました。