何度でも、何度でも ~繰り返し処理:For next~
立ち上がり呼ぶんですあなたの名前を声が枯れるまで。
今回はいよいよ繰り返し処理の記事を書きます。
タイトルにあるとおり、同じ処理を何度も何度も行うVBAの記述です。
以前書いた変数とif文による条件分岐、そして今回の繰り返し処理は、定型業務の自動化には必須の要点といえるでしょう。
【説明:繰返し処理】
前回の成績判定を例にとりましょう。
通常、講義というからには受講生は複数いるものですね。一人しかいないものはもはや講義とは言いません。また、人数が少ないならばそもそもそんな成績判定ツールを作成する必要はないでしょう。
そう、多「数」の受講生に対して、「条件」に応じた判定を、「繰り返す」必要がある、というのがこういった業務の常でしょう。
それをVBAマクロで実現するための記述のひとつが、「For ~ next 」構文です。
【説明:For ~ next 構文】
For next構文の形は以下の通りです。
For カウント変数 = 始点 to 終点 (step カウント間隔)
繰返す処理
Next 変数
カウント変数とは、繰り返しの範囲を指定するための変数で、事前に宣言しておく必要があります。何でもいいですが、「i」がよく使われます。
この構文を用いると、繰返す処理を行ってNextに到達すると、カウント変数がstepの数だけ増減し、繰返す処理部分が再び実行されます。stepを省略すると変数は1ずつ足されます。カウント変数が終点の数値になると、Nextは実行されず、繰返し処理が修了します。
例文を書いてみましょう。
Dim i
For i = 1 to 10
Cells(1,i) = i * i
Next i
実行すると、1行目に1~10までの二乗がそれぞれ入力されます。
セル番地にカウント変数を入れることによって、繰返す回数ごとに入力セルを変えることもできます。成績判定の例で言えば、リスト内の受講生の成績を順番に入力する、といった感じですね。
【説明:For Nextの入れ子】
if文と同様、For Nextも入れ子にすることができます。こんな感じです。
For i = 1 to 10
For j = 1 to 10
Cells(i, j) = i * j
Next j
Next i
実行すると百マス計算ができます。
ロジックの構造としては、
・iが1のときにjについて1から10までの間繰り返し、
・iを1増やしてj=1 to 10の繰り返し・・・
って感じですね。
エクセルのワークシートは2次元なので、For Nextの入れ子は結構よく使います。
【実践:成績判定(多数)】
おそらく、今まで紹介してきた中で一番実践的なVBAマクロになると思います。
if文のときの設定を引き継ぎまして、以下のようなエクセルファイルを想定します。
・A~D列に受講生の「ID」「氏名」「課題」「得点」がそれぞれ入力されている。先頭行はタイトル行で、データは2行目から下。
・E列に「修了判定」の欄があり、マクロを実行すると判定が入力される。
・判定基準は前回の記事を見てね
では、参りましょう。
sub 一斉成績判定()
Dim task, score, i
For i = 2 to 101 '受講生が100人の場合
task = cells( i, 3) ‘提出なら1、未提出は0として入力する。
score = cells( i,4)
if task = 1 then
if score >= 80 then
cells( i, 5) = “A”
else
if score >= 50 then
cells( i, 5) = "B"
else
cells( i, 5) = "C"
end if
end if
else
cells( i,5) = "未修"
end if
Next i
end sub
こんな感じです。
一番実践的といいましたが何のことはなく、ただFor Next文の中に成績判定のif文を入れ子にして、判定の出力先セルの番地をいじっただけです。
For Next文を使うときは、こんな風に個別のデータにどういう処理をするかをきちんと組んだ後に、出力先のセル番地をカウント変数に変えると効果的に文を記述できます。
さて、ようやく実践的なものが組めましたので、気になる時間を計測してみました。
上記のマクロ、実行すると、約0.2秒で完了します。
もう一度言います。0.2秒です。
念のためもう一回言いましょうか。0.2秒です。
※追記。PCの性能や実行時の作業状態などで変わります。後にやったら.06~.07秒でした。
自分でやったらどれだけかかるか想像してみてください。
おそらく1人分入力するのですら、速くても5秒くらいじゃないでしょうか。
おそらくエクセルに詳しい人なら、こんなん関数使えば良いじゃん、と思うでしょう。それも正しいです。早けりゃ何でも良いんです。
が、より複雑な操作を自動化するとなると、セルに関数を入力する操作では限界があります。そう言った複雑な操作でも、マクロを組めば実装することができます。極論言えばエクセル上で行える操作は何でも出来ます。
初めてこれを組めた時は、そりゃあもう感動しました。これからマクロを組もうかと思ってる人達は、是非この感覚を掴んで頂きたい!と思います。
というわけで今回はここまで。
追伸
この記事なプロシージャをVBEにベタ張りすると、空白が文字列変換されてるらしくすこし変な文が入ったりするので気をつけてください。
習得するためにも、自分でタイプしてみるのをお勧めします。
また、実行時の秒数ですが、PC環境や使用メモリ状況などで変わるようです。先ほどやってみたら0.06~0.07秒でした。 ちなみに私の使っているPCは購入からそろそろ3年経つ化石ノートといっていい部類のものです。一応本文中でも訂正しておきます。
もし○○なら ~if文:条件分岐~
随分間隔があいてしまいました。
違うんです、仕事の自動化とかPythonかじり始めるとかやってたら(ry
そんなわけで、今回はif文を用いた条件分岐について書きます。
【説明:if文による条件分岐】
さて、皆様は「if」という英語の意味をご存知ですか?
・・・まあ、なめんなよって言わないでください。聞いてみただけです。
そうです、この記事のタイトルのとおり、「もし○○なら」という意味ですね。
マクロVBAにおいても実は同じような意味を持ちます。
この文を使うと、
★一定の条件のときだけ特定の操作を行う
といった形で、操作に条件をつけることができます。
これを条件分岐、といったりします。
この条件分岐の概念は、業務を自動化する際には必須といってもいいでしょう。
自動化とは言いつつ、おそらくどんな業務にも「この時はこうする」「あの時はあーする」といったパターンがあるはずで、その時々の条件で行う操作は変わりますよね。
たとえば、学生や社員の成績判定とかです。
100点満点中90点以上なら「A」、70点以上なら「B」・・・・
といった具合に、数値の大きさで判定をする場合はまさに、
★もし○○なら××
ですよね。これをVBAで設定するために、if文は必要なのです。
【説明:if文の構文】
VBA上でifを書く際の構文は、以下のとおりです。
if ○○(条件式)then
○○の時の処理
else
○○でない時の処理
end if
さっきの成績判定を例にとって見ると、
if score >= 90 then
Range("A1") = "A"
else
Range("A1") = "B"
end if
って感じですね。
※scoreはあらかじめ変数宣言、得点が代入された変数、A1セルが判定結果を表示するセルという想定です。
○○でない時に何も処理をしない場合は、elseと処理を省略してもいいです。が、何もしない場合でもelseを入れることをお勧めします。理由は後述 。
【説明:if文の入れ子】
先ほどの例だと、条件が1つしか分岐していません。成績判定の例で言えば、90以上か未満かしか判定できていませんね。
一般的に成績の判定なんてのはA~CだったりA~Eだったり、少なくとも2~4つくらいの基準で分類される物でしょう。
そんなときは、if文を複数指定することで条件を実装することができます。
成績の例に則して書いてみます。
if score >= 90 then
Range("A1") = "A"
else
if score >=70 then
Range("A1") = "B"
else
Range("A1") = "C"
end if
end if
上記の例だと、scoreが90以上なら”A”、90未満70以上なら”B”、70未満なら”C”と判定されます。
こんな風に、if文の中にさらにif文を入れ込むことを「入れ子にする」とか言います。
気をつけたいのは、入れ子にする位置で論理構造が結構変わるということです。例えば、
if score >= 90 then
if score = 100 then
Range("A1") = "S"
else
Range("A1") = "A"
end if
else
Range("A1") = "B"
end if
この場合だと、scoreが90点以上のとき、100点なら”S”、それ以外は”A”、そもそも90未満なら”B”という判定になります。
if文を記述するときには、ロジックに注意して記述するようにしましょう。
【実践 : 成績判定】
何度も成績判定を例示したので、実践もこれでいきましょう。
以下の様な設定を考えます。
・とある講義で、受講生には「課題」と「テスト」が課せられます。
・課題を提出しなければ、その時点で講義は未修となります。
・テストは100点満点で80点と50点をスコア(A〜C)の分かれ目にします。
例えば、課題を提出してテストで75点を取ったら、スコアBで修了、という具合です。
A1セルに課題の提出有無、A2セルにテスト点数を入力、マクロを実行すると判定結果がA3セルに出力される、という様なマクロを描いてみましょう。
sub 成績判定()
Dim task, score
task = cells(1, 1) ‘提出なら1、未提出は0として入力する。
score = cells(2,1)
if task = 1 then
if score >= 80 then
cells(3, 1) = “A”
else
if score >= 50 then
cells(3,1) = "B"
else
cells(3,1) = "C"
end if
end if
else
cells(3,1) = "未修"
end if
end sub
一応書いたマクロの””内の成績判定が上位から順になるようなif文にしてみました。
特に、設定した条件とelse以下の記述との関係はかなり重要です。
たとえば、「f score >= 50 then」以下の記述の位置がその直前のelseより前に来てしまうと、
・scoreが90以上のとき”A”を入力する。
・scoreが50以上のとき”B”を入力し、未満のときは”C”を入力する。
・scoreが90未満のときは何もしない。
という順番で実行され、scoreが90以上であったとしても後から”B”が上書きされます。
設定する条件の論理関係はきちんと把握した上で記述しましょう。
そういった意味でも、if文を練習するときは処理を何もしないときでもelseを記述することをお勧めします。「○○のときは(if ○○ then)処理A、そうじゃないとき(else)は何もしないで終わり(end if)」といった感じです。
この条件判定と次回書く予定の繰り返し処理を組み合わせると、業務自動化の世界がかなり広がります。正確に言えば、その世界を広げるための基礎になる、といったところでしょうか。
そんなわけで、今回はここまで。
変わりゆく数 〜変数定義〜
おそらくVBAを習得するにあたって、最初の難関がこの変数定義ですかね。
【説明:変数とは】
変数とは、そのまんま、変わる数です。
舐めてんのか、とか言わないでください。今から説明します。
例えば、A1セルに"こんにちは"と入力する時を想像してください。
この時、入力対象のセルは、何行目でしょうか。
当然答えは1行目ですよね。では、C5セルの時はどうでしょう。これも簡単、5行目ですよね。
というように、その場面場面に応じて変動するものの事を変数と言います。先の例で言えば、変数とはつまり行番号の事ですね。列番号にも同じことが言えます。
日常生活の中で言えば、時間とか、日付とかもそうですね。とにかく変数とは、
1つに固定されていることのないもの
の事です。
ここで、「数値」ではなく「もの」と書いたのは、実は結構重要です。
例えば、今までの記事では"VBA日記"という文字列を特定のセルに入力してきましたが、
仕事をする上で、"VBA日記"と入力する事しかない
ということは、100%ありえませんよね。壊れかけのラジオだってもう少しバリエーションあります。
そう、つまり、変数という名前に惑わされがちですが、文字列などの数値以外ものも変数なのです。
なので、先の例で言えば"こんにちは"という文字列も、場面場面で内容を変えたい時は変数なのです。
【説明:変数定義】
VBA上で変数を使えるようにするには、変数を宣言(定義)します。
以下は、"入力文字"という名前の変数を宣言するマクロです。
Dim 入力文字
入力文字 = "VBA日記"
Dim が、今から変数を使いますよーという合図になります。その後に変数の名前を入れます。変数の名前は、好きに決められます。ただし、一部の記号は使えません。変数名がダメな時はエラーになるので、その時は名前を調整してください。
で、変数に何かを代入する時は、=を使います。
また、代入する値を変えたい場合は、再度変数に別の値を代入すれば上書きされます。
Dim 入力文字
入力文字 = "VBA日記"
~入力文字が"VBA日記"の間の処理~
入力文字 = "こんにちは"
~入力文字が"こんにちは"の間の処理~
こんな具合ですね。
変数宣言は、使用する変数につき一回でいいので、Dimは複数書かなくていいです。というより、Dimを何回も書くとエクセルから「同じ変数もう聞いたよ?忘れたの?バカなの?」とツッコミが入りますので気をつけましょう。
実は変数定義には型指定とか色々奥深い側面がありますが、今回は割愛。
【実践】
今回は少しだけ役に立つかもしれない実践。
以下の場面を想定します。
- 毎日業務日誌を書かなければならない
- 業務日誌には「記入日付」と「○/○の業務報告をします」という定型文を入力しなければならない
毎日の業務日誌、面倒ですねぇ。しかも日付と定型文を手入力……Why Japanese people!!ですね。
マクロを実行するだけで、日付と定型文が入力されたら、楽ですね。
というわけでこんなマクロを組んでみました。
sub 日付、定型文入力()
Dim hiduke , bun '日付と文
hiduke = "=TODAY()"
Range("A2") = hiduke '日付を入力するセル番地を指定
bun = Range("A2").Value & "の業務報告をします"
Range("B3") = bun
end sub
A2セルが日付を入力するセル、B3セルが定型文のセルと想定してます。
.Valueの部分は今まで紹介していませんが、まあそのうち。今はそういうもんと思ってください。
大して複雑な処理をするわけではありませんが、皆さん秒数を想像してください。
- 今日の日付を確認(3秒)
- A2セルに日付を入力(1秒)
- B3セルに日付を含めた定型文を入力(6秒)
PC操作に慣れててもこんなもんじゃないですかね。当然、10秒くらい大したことないよ、と思うことでしょう。しかし、それが毎日です。週5勤務×4週間×12ヶ月で計算すると、1年で40分削減になります。ではこれが、1回1分かかるならどうでしょうか。5分の作業なら…と考えてみてください。
業務の改善は、この10秒の積み重ねです。
初めはこう行った単純かつ細かいことから、徐々に複雑で時間のかかる操作を自動化・高速化していくことを考えていくことになります。
というわけで、今回はここまで。
""とか()とか 〜VBAとしての意味の有無〜
RangeとCellsについて書いてきましたが、多分こう思う人達がいるのではないでしょうか。
()の中を""で囲ったり囲わなかったり、もうわけわからんちん
私も最初ピンとこなかったんですが、意外とここは重要な点だなぁと思うので、書いておきます。
【""の説明】
""は、端的にいうと、VBA上の意味を持たないものを使いたいときに用いる記号です。
Rangeの番地としてのA2を例にとって見ましょう。
A2という文字列自体には、VBA上の意味は付与されていません。なので、A2とだけある場合にはマクロを実行してもエラーになります。
このエラーは、以前の例えでいうと、
エクセルくんが、「僕このA2っての知らないよ」と言ってる。
ということを意味します。
入力した文字列の"VBA日記"にしてもそうです。その文言自体はVBA上で意味を持たないのです。したがって、そのままだとエクセル君が理解することができません。なので、エクセル君に「理解はできないだろうけどこういうものがあるんだ」と教えるための記号だと思えばいいと思います。
人間の感覚で言えば、
「ふんみゅれ」という文字を紙に書いてください
といわれるような感じですかね。
日本語として「ふんみゅれ」なんて言葉はおそらくありませんが、それを書けといわれれば、まあ書けますよね。余談ですが、エクセル君のすごいところは、それが英語だろうが数字だろうがなんだろうがすさまじい速度で正確に実行してくれるところです。
【()の説明】
()は、オブジェクトにくっつく場合はそのオブジェクトの名前や位置など、
そのオブジェクトを特定するための情報
を示します。
Rangeは、Rangeの回で書いた通り、範囲を示すオブジェクトです。
当然そのままだと、どこやねんというツッコミ受けること必定です。ですので、()内にその場所を特定する内容を入れるわけです。
ここでポイントになるのが、()内にセルの名前を使いたい場合は、””を使うという点です。前述の通り名前(セル番地)というのはVBA上意味を持たないものですから、””で囲ってやるわけです。
そして、Cellsの回の最後に書いたRange(Cells(○,○) , Cells(△,△))という指定の仕方は、()内に含まれるものがすべてVBA上の意味を持っています。なので、ここには””がないわけです
こんな感じでしょうか。ぶっちゃけこの辺の表現に関わる結論は
こーいうもんだと思え
これに尽きます。
ただまあ、文系人間がVBAに触れるにあたって、考え方の参考になれば幸いです。
〜オブジェクト : Cells〜
まだまだ一歩目の途中
というわけで今回はCellsについて。
【説明】
以下は、A2セルに"VBA日記"と入力するマクロです。
Cells(2,1) = "VBA日記"
前回のRangeと違う点は、
1. アルファベットは使わない
2. ()内は「行番号(縦),列番号(横)」
という点です。
Rangeが「ここ!」だったのに対し、Cellsは「縦○番目、横○番目のセル」という意味になります。
また、CellsはRangeと異なり、複数指定はできません。複数のセルに操作をする場合は、操作するセルの数だけマクロを書く必要があります。
何だよ、複数指定もできないんならRangeでいいやん、と思われるかもしれませんが、その点については後々書く予定の変数を用いる時に詳しく。業務の自動化、という事を考慮すると、Rangeだけでは対応しきれない(し辛い)事は多々出てきますので…。
【実践】
実践、というよりも、RangeとCellsを組み合わせて使う時の記述を書きます。
以下は、A1セルからD8セル迄の全てのセルにVBA日記"と入力するマクロです。
Range(Cells(1,1) , Cells(8,4)) = "VBA日記"
こんな具合です。
Rangeの時書いた通り、Rangeは「範囲」です。セルの番地名で指定できるときは()内を"A1:D8"とすればいいですが、そうもいかない場合もあります。
という時に、Rangeの範囲をCellsで指定してやるのが上記のセンテンスになります。
Rangeの()内に、「左上端のCells , 右下端のCells」を入れてやります。番地名指定の時と比べると、""がなく、: が , になってますね。
RangeとCellsは、同じような使い方ができる分混同しがちですが、意味も性質も全然違います。マクロを組んで、実行してみて、感覚的に理解できるようにすると、後々楽になります。
というわけで、今回はここまで。
値の入力 〜オブジェクト:Range〜
千里の道も一歩から。
というわけで、今回は値の入力について書きます。
【説明】
以下は、A2セルに"VBA日記"という文字を入力するマクロです。
Range("A2") = "VBA日記"
VBAは基本的に、
☆オブジェクト(操作したい対象)
☆操作内容
の順番で記述されます。
上記の例で言えば、
Range("A2") がオブジェクト
=以下が操作の内容になります。
Rangeとは、範囲という意味です。わかりやすく言えば、「ここ!」って意味です。
いや、どこやねん、ってツッコミが入らない様に、()内にその「ここ」の番地名を入れています。
他のセルに値を入れたい場合は""内をそのセルの番地名に変えれば良いです。
また、範囲であるため、複数のセルを表すこともできます。例えば、A1からC5までに値を入れたいときは、
Range("A1:C5") = "VBA日記"
とすれば良いです。
「A1からC5」の「から」のとこが「:」になりますね。
基本的にRangeは、A1とかB3とかいう、
そこって決まってる場所
を示す時に使うと思って下さい。
【実践】
この記事で紹介した記述でできることを紹介してみましょう。
・・・・・・・・・・・・
と思いましたが、Rangeの説明だけでできることははっきり言ってほぼないですね。
記事を積み重ねていって、できることが増えたときに紹介できればいいなぁ。
余談ですが、マクロの習得はTry&Errorが不可欠だと思います。
覚えた記述を実際に書いてみて、F5で実行して、
エラーが出たらなぜ出たのか考えて、ググッて・・・・・・・
私もその繰り返しでした。
もし、頑張ってみようかな、と思う方がいらっしゃれば、ぜひ根気強く続けてみてください。
というわけで、今回はここまで。
※マクロを使う方法について
本ブログでは、VBAを書いてマクロを組んだりする時の所感を纏めます。
エクセルの設定で「開発」タブを表示したり、
VBEのオブジェクトウィンドウ他の表示設定をしたり、
という、マクロを書くための準備に当たる部分は割愛しています。
ネット検索すればかなり多くのヒットがあると思いますので、初期の設定はそちらをご参照ください。
あれ、それならこのブログの存在意義は……?
備忘録です。それ以上でも以下でもありません。