マクロで実現したいこと
以下のように、注文書と価格表があったとします。
この注文書について、品名に対応する価格を価格表から探し、注文書の価格の列に入力するマクロを作ることを考えます。
期待される結果としては以下の通りです。
なお、価格表に存在しない品名については価格を -1
とすることとします。
マクロの処理手順を考える
まず、目的を実現するための処理手順を考えます。
例として、以下のような手順であれば目的を達成できます。
マクロの処理手順
- 価格を格納する変数
price
、品名を格納する変数product
を定義する - 注文書の各行について以下を繰り返す
- 品名列のセルの値を変数
product
に格納する - 変数
price
に-1
を格納する - 価格表を一行ずつ確認し、変数
product
と価格表の品名列の値が一致するかを確認する - 品名が一致した場合、価格表の対象行の価格列の値を変数
price
に格納し、価格表の確認を終える - 注文書の対象行の価格列に、変数
price
の値を入力する
- 品名列のセルの値を変数
マクロを作成する
処理手順が決まったら、マクロを作成していきます。
- 価格を格納する変数
price
、品名を格納する変数product
を定義する
この部分を作成すると以下のようになります。後の For
文で使用する変数 i,j
も定義しておきます。
Sub sample()
Dim price&, product$
Dim i%, j%
End Sub
- 価格を格納する変数
price
、品名を格納する変数product
を定義する - 注文書の各行について以下を繰り返す
この部分まで作成すると以下のようになります。
Sub sample()
Dim price&, product$
Dim i%, j%
For i = 3 To 6 '追加
Next '追加
End Sub
各行について繰り返すということで、For
文を使用します。
注文書はシート上で 3-6 行目まであるので、For 文で使用する変数 i
の値は 3 から 6 までとします。
- 価格を格納する変数
price
、品名を格納する変数product
を定義する - 注文書の各行について以下を繰り返す
- 品名列のセルの値を変数
product
に格納する
- 品名列のセルの値を変数
この部分まで作成すると以下のようになります。
Sub sample()
Dim price&, product$
Dim i%, j%
For i = 3 To 6
product = ActiveSheet.Cells(i, 3).Value '追加
Next
End Sub
注文書における品名列は C 列 = 3 列目のため、i 行 3 列のセルの値を product
に格納します。
- 価格を格納する変数
price
、品名を格納する変数product
を定義する - 注文書の各行について以下を繰り返す
- 品名列のセルの値を変数
product
に格納する - 変数
price
に-1
を格納する
- 品名列のセルの値を変数
この部分まで作成すると以下のようになります。
Sub sample()
Dim price&, product$
Dim i%, j%
For i = 3 To 6
product = ActiveSheet.Cells(i, 3).Value
price = -1 '追加
Next
End Sub
価格を格納する変数 price の値を -1
に初期化しています。 なぜ -1 かというと、マクロの仕様として価格表に存在しない品名の価格は -1
にすることとしているからです。
- 価格を格納する変数
price
、品名を格納する変数product
を定義する - 注文書の各行について以下を繰り返す
- 品名列のセルの値を変数
product
に格納する - 変数
price
に-1
を格納する - 価格表を一行ずつ確認し、変数
product
と価格表の品名列の値が一致するかを確認する
- 品名列のセルの値を変数
この部分まで作成すると以下のようになります。
Sub sample()
Dim price&, product$
Dim i%, j%
For i = 3 To 6
product = ActiveSheet.Cells(i, 3).Value
price = -1
For j = 3 To 8 '追加
If ActiveSheet.Cells(j, 7).Value = product Then '追加
End If '追加
Next '追加
Next
End Sub
注文書の各行に対して、価格表の各行を確認したいため、For 文の中にさらに For 文を記述します。
価格表はシート上で 3-8 行目まであるため、For 文の変数 j
の値は 3 から 8 までとします。
また、注文書の対象行の品名と価格表の j 行目の品名が一致しているかどうかを確認するために If
文を使用します。
- 価格を格納する変数
price
、品名を格納する変数product
を定義する - 注文書の各行について以下を繰り返す
- 品名列のセルの値を変数
product
に格納する - 変数
price
に-1
を格納する - 価格表を一行ずつ確認し、変数
product
と価格表の品名列の値が一致するかを確認する - 品名が一致した場合、価格表の対象行の価格列の値を変数
price
に格納し、価格表の確認を終える
- 品名列のセルの値を変数
この部分まで作成すると以下のようになります。
Sub sample()
Dim price&, product$
Dim i%, j%
For i = 3 To 6
product = ActiveSheet.Cells(i, 3).Value
price = -1
For j = 3 To 8
If ActiveSheet.Cells(j, 7).Value = product Then
price = ActiveSheet.Cells(j, 8).Value '追加
Exit For '追加
End If
Next
Next
End Sub
注文書の対象行の品名と価格表の j 行目の品名が一致していた場合、価格表の j 行目の価格列の値が求めたかった値となります。
そのため、j 行目の 8 列目(価格表の価格列)の値を、価格を格納する変数 price
に格納します。
その後、Exit For
を使用して内側の For 文を抜けます。なぜ抜けたいかというと、価格は決まったので、これ以降の行を確認する必要がないからです。これは処理時間の短縮につながります。
マクロの処理手順
- 価格を格納する変数
price
、品名を格納する変数product
を定義する - 注文書の各行について以下を繰り返す
- 品名列のセルの値を変数
product
に格納する - 変数
price
に-1
を格納する - 価格表を一行ずつ確認し、変数
product
と価格表の品名列の値が一致するかを確認する - 品名が一致した場合、価格表の対象行の価格列の値を変数
price
に格納し、価格表の確認を終える - 注文書の対象行の価格列に、変数
price
の値を入力する
- 品名列のセルの値を変数
この部分まで作成すると以下のようになります。
Sub sample()
Dim price&, product$
Dim i%, j%
For i = 3 To 6
product = ActiveSheet.Cells(i, 3).Value
price = -1
For j = 3 To 8
If ActiveSheet.Cells(j, 7).Value = product Then
price = ActiveSheet.Cells(j, 8).Value
Exit For
End If
Next
ActiveSheet.Cells(i, 4).Value = price '追加
Next
End Sub
内側の For 文を抜けた段階で、注文書の対象行の品名に対応する価格は変数 price
に格納されている状態になります。
そのため、内側の For 文を抜けた直後に、注文書の i
行目の価格列のセルの値に変数 price
の値を入力します。
もし、価格表で品名が見つからなかった場合は、price
の値は更新されないため初期値の -1
が入力されることになります。
これでマクロは完成です。
マクロを実行する
作成できたマクロを実行すると以下のような結果となります。
期待通りの結果となりました。
学んでほしいこと
For 文、If 文を組み合わせつつ、変数をうまく使うことで目的を達成できるマクロを作成することができます。
どう使ったら何が達成できるのかを把握しながらマクロを作って実行し、結果を確認してみてください。