【ExcelVBA】For…Nextステートメント5
For…Nextステートメント⑤
今回は、前回の答え合わせの続きをやっていきましょう。
問題を確認したい方はこちらから。
Q3. 件名に名前を入れたい
Q3です。件名が固定の値(このようなプログラムに直接値が記述されているものを「リテラル」と言います。)になっているので、Excel側で設定し自由に変更できるようにしてみましょう。
Excel側の修正はこのようになります。「送信先メールアドレス」の隣に「件名」の欄が追加されています。
[010-【ExcelVBA】For…Nextステートメント4-004.png]修正箇所を見つけるのはそれほど難しくないかと思います。「objMail.Subject」に値を代入するとメールの件名を設定(変更)することができました。この部分がリテラル「”テストメール”」になっているために、送信される全てのメールの件名が同じになっているわけです。
ここを「To」と同じようにExcelシートから値を取ってくるように変えればOKです。
「To」に代入している値は「Cells(i, 2).Value」となっています。
「Cells」を使うことでExcelシートの特定のセルから値を取ってくることができました。このCellsの引数がポイントです。「Cells」では第1引数は行番号、第2引数は列番号を表しましたので、第1引数を「To」と同じように「i」にすれば同じ行のセルを表すことになります。第2引数は列番号ですので、今回Excelで追加した「C列」=「3列目」を指定すればよいことになります。
「Cells」を使う場合の注意点は列番号を数字で表すこと、及び引数の順番が「行」「列」となることです。
(Excelではセルを表すときによく「C1」というような指定をしますが、これは「列」「行」の順番になっています。「Cells」は逆になっています。)
'' 修正前 objMail.Subject = "テストメール"
'' 修正後 objMail.Subject = Cells(i, 3).Value
プログラム全体は次のようになります。
Sub VBA基礎第11回_1() Dim objOutlook As Object Dim objMail As Object Set objOutlook = CreateObject("Outlook.Application") Dim i As Integer For i = 2 To 11 Set objMail = objOutlook.CreateItem(0) If Cells(i, 2).Value <> "" Then objMail.To = Cells(i, 2).Value objMail.Subject = Cells(i, 3).Value objMail.Body = "メール本文" objMail.Send End If Set objMail = Nothing Next Set objOutlook = Nothing MsgBox "送信完了", vbInformation End Sub
Q4. 本文をExcelから入力できるようにしたい
Q4です。Q3と似ていますが、メール本文もExcel側で設定したものを取得して簡単に変更できるようにしてみようというカスタマイズになります。
Excel側の修正はこのようになります。件名の隣に名前と本文の欄を追加します。
また、表の外側に「本文フォーマット」という欄を追加します。名前の列(D列)には文字列が入力されていますが、本文の列(E列)はExcelの式が入力されています。「名前」と「本文フォーマット」を結合して表示しています。
(どのような式が入力されているかは、前々回を参照してください。)
プログラムの修正箇所の考え方は、Q3と同じですので割愛しますが、セルオブジェクトの「Value」プロパティは、対象のセルに式が入力されていた場合、その式ではなく計算結果の値を取得します。この特徴を生かすことで、簡単な計算(今回の場合は文字の結合)はExcel側でやらせてしまい、プログラム側のコード量を減らすといったことが可能です。Excel側とうまく連携するとプログラムがシンプルになるという例になります。
'' 修正前 objMail.Body = "メール本文"
'' 修正後 objMail.Body = Cells(i, 5).Value
ちなみに、Excel側で対応せずに全てプログラムで対応した場合(本文列を使わない場合)は、このようなプログラムになります。
'' 本文(E列)を使わない場合 objMail.Body = Cells(i, 4).Value & Cells(2, 7).Value
2つのセルの値を「&」演算子を使って結合しています。「Cells(i, 4).Value」は今までの「Subject」「Body」と同じ考え方ですので問題ないかと思います。結合しているもう1つのセルは「Cells(2, 7).Value」ですが、こちらは2つの引数がどちらもリテラル(2と7)になっています。つまり、ループの回数に関係なく常に2行7列(G2セル)の値を取得しています。
プログラム全体は次のようになります。
Sub VBA基礎第11回_2() Dim objOutlook As Object Dim objMail As Object Set objOutlook = CreateObject("Outlook.Application") Dim i As Integer For i = 2 To 11 Set objMail = objOutlook.CreateItem(0) If Cells(i, 2).Value <> "" Then objMail.To = Cells(i, 2).Value objMail.Subject = Cells(i, 3).Value objMail.Body = Cells(i, 5).Value objMail.Send End If Set objMail = Nothing Next Set objOutlook = Nothing MsgBox "送信完了", vbInformation End Sub
Q5. メールのCCに自分のメールアドレスを設定したい
Q5です。メールが送信できたかの確認のためにCCに自分のメールアドレスを設定してみます。「To」や「Body」と同様に「Cc」も存在します。設定の仕方は「To」「Subject」などと同じですので大丈夫かと思います。今回は常に自分宛に設定すればよいですので、自分のメールアドレスをリテラルで設定してしまいましょう。
Excelシートに設定してそこから読み込むようにしていただいても使いやすいかもしれませんね。
'' 修正前 objMail.Body = Cells(i, 5).Value objMail.Send
'' 修正後 objMail.Body = Cells(i, 5).Value objMail.Cc = "sudo@yahoo.co.jp" objMail.Send
プログラム全体は次のようになります。
Sub VBA基礎第11回_3() Dim objOutlook As Object Dim objMail As Object Set objOutlook = CreateObject("Outlook.Application") Dim i As Integer For i = 2 To 11 Set objMail = objOutlook.CreateItem(0) If Cells(i, 2).Value <> "" Then objMail.To = Cells(i, 2).Value objMail.Subject = Cells(i, 3).Value objMail.Body = Cells(i, 5).Value objMail.Cc = "sudo@yahoo.co.jp" objMail.Send End If Set objMail = Nothing Next Set objOutlook = Nothing MsgBox "送信完了", vbInformation End Sub
これで長かった「For…Nextステートメント」も終了です。
繰り返し構文は慣れるまでは取っつきにくい部分があるかもしれませんが、今回のようなループ回数が少ないケースでは比較的理解しやすいのではないかと思います。もし、まだよくわからないなという方は、めんどくさがらずにプログラムを1行1行追いかけてみて、ループの1回1回がそれぞれどのように動いているのか確認してみるといいです。
その際に頭の中だけではなく、メモ帳などに書き起こしながら追いかけてみるとより分かりやすいのではないかなと思います。
次回は、「シートとブックの操作」です。