Developer

【ExcelVBA】For…Nextステートメント4
2020.12.28
Lv1

【ExcelVBA】For…Nextステートメント4

For…Nextステートメント④

今回は、前回に作成したメール送信プログラムのカスタマイズの答え合わせを行っていきたいと思います。
ここで紹介する答えはあくまでも一例に過ぎません。実際にプログラミングしている中で悩みながらトライ&エラーを繰り返し、思った通りに動いた時がプログラムの一番の楽しさだと思います。
いきなり答えを見てその楽しさを感じれないことはとてももったいないと思いますので、今回の答えを見るだけでなく課題にまずはチャレンジしてみてください。

カスタマイズ前のメール一斉送信プログラム

まずは、修正前のプログラムを確認しておきましょう。
Outlookを使ってメールを送信しますので、Outlookでメールの送受信ができることを確認しておきましょう。(このように、Microsoft社のソフト同士で連携できるのが、VBAを使用する大きなメリットの1つです。)
Excelのシートはこのよう作ります。

[010-【ExcelVBA】For…Nextステートメント4-001.png]

プログラムの方はこのようになります。

Sub VBA基礎第10回_1()
    Dim objOutlook As Object
    Dim objMail As Object
    
    Set objOutlook = CreateObject("Outlook.Application")
    
    Dim i As Integer
    For i = 2 To 4
    
        Set objMail = objOutlook.CreateItem(0)
    
        objMail.To = Cells(i, 2).Value
        objMail.Subject = "テストメール"
        objMail.Body = "メール本文"
        objMail.Send
        
        Set objMail = Nothing
    Next

    Set objOutlook = Nothing
    MsgBox "送信完了", vbInformation
End Sub

まだ説明していない機能(Outlookと連携する機能)がありますので、全てを理解するのは難しいかもしれません。ポイントを抑えて理解していきましょう。
このプログラムを実行すると、3件のメールが送信されます。つまり、「メールを送信する」という処理が3回ループされていそうです。実際に8~18行目がForを用いた繰り返し構文になっていて、ループカウンタは2から4までと指定しているので、3回繰り返すことがわかります。3通のメールを送っていることと3回繰り返すループが作られており、同じ回数であることから予想通りといえそうです。

では、予想通りであれば、ループの中に書かれているプログラムがメールを送信する処理のはずです。実際に12~13行目は、普段のメールで使っている「To」=「メールの送信先」、「Subject」=「メールの件名」、「Body」=「メールの本文」ではないかと予想できます。
「objMail」が分かりにくいですが、これは「To」や「Subject」と組み合わせて以前紹介している「オブジェクト式のプロパティ」となっています。「objMail」はオブジェクトで、VBAで操作される対象(この場合は書きかけのメールのこと)を表し、「To」や「Subject」はプロパティなので「書きかけのメール」の「様子」や「状態」(この場合はメールの送信先やメールの件名のこと)を表しているわけです。
これらのプロパティに値を代入することで書きかけのメールを徐々に完成させていっていることになります。

最後に15行目で「Send」=「送信」していることになります。これまでと異なり代入式になっていませんので、メソッド(オブジェクトへの命令)になっています。

ここまでが課題を解くにあたって必要となる部分になります。
気になる方のために他の部分に関しても簡単な説明を記載しておきますが、飛ばしていただいても差し支えないかと思います。

2、3行目

    Dim objOutlook As Object
    Dim objMail As Object

「objOutlook」「objMail」という2つの変数を定義しています。分かりにくいポイントとしてはデータ型が「Object」になっているところでしょうか。この連載ではまだデータ型に関して詳しく説明しておらず、これまで登場してきたものは「Integer」「String」くらいかと思います。
前述している「objMail」は「書きかけのメール」を表す「オブジェクト」です。このようなオブジェクトを保存するためには、変数のデータ型をこのようにあらかじめ「Object」としておく必要があります。(他にも方法がありますが、別途ご紹介します。)

5行目

    Set objOutlook = CreateObject("Outlook.Application")

2行目で定義した変数にオブジェクトを代入しています。先頭に「Set」というキーワードがついていますが、VBAではオブジェクトを変数に代入するときには通常の代入ではなくこのように「Set」を使用した代入式にします。
代入式の右辺では、Outlookと連携するために「Outlook.Application」オブジェクトを作成しています。

10行目

        Set objMail = objOutlook.CreateItem(0)

こちらも、3行目で定義した変数にオブジェクトを代入しています。「Set」キーワードを使用しているところも同じです。右辺では、Outlookに対してメソッドを用いて命令を出しています。ここでは、「Item(0)」=「新しい空のメール」を作成しています。
このメソッドの引数に「0」と入れるとメールになり、「1」を入れると予定になります。Outlookはメールだけでなく予定表としての機能もありますよね。予定を作った場合は、メールの「To」や「Subject」とは違うプロパティになります。扱うオブジェクトの種類によってプロパティやメソッドは変わるんでしたね。

17、20行目

        Set objMail = Nothing
    Set objOutlook = Nothing

メールを送信しましたので、変数に保存してあるオブジェクトを空にしています。これは行わなくてもエラーになりません。ただし、プログラムの世界では「使い終わったものは消す」というような風習があり、その風習に則った念のための処理です。
注意点としては、オブジェクトを空にする場合は「Nothing」を代入するというところです。「””」ではありません。少々ややこしいですが、「””」では空の文字列(オブジェクト)を表してしまうため、変数に代入したオブジェクトを空にできていないことになってしまいます。

21行目

    MsgBox "送信完了", vbInformation

処理が終わるとVBAは何事もなかったかのように、いつものExcelに戻ります。VBAの処理が終わったことに気づきにくいのです。
そのため、よくこのようにMsgBoxというものを使ってユーザーに何かしらの情報を知らせることができます。他にも、ユーザーからのリアクションを待つこともできます。第2引数の「vbInformation」はメッセージを表示するときのアイコンの種類を指定しています。他にも「vbCritical」「vbQuestion」「vbExclamation」といったアイコンや、「vbYesNo」を使うと「OK」ではなく「Yes」「No」ボタンを作ったりすることもできます。

[010-【ExcelVBA】For…Nextステートメント4-006.png]

MsgBox "本当によろしいですか?", vbQuestion + vbYesNo

使い方はこんな感じです。(第2引数を足し算にするところが独特ですね。)

Q1. 送信できるメールアドレス数を増やす

では、前置きが長くなってしまいましたが、Q1を解説していきましょう。
Excel側の修正はこのようになります。入力できるメールアドレスを10件まで増やします。

[010-【ExcelVBA】For…Nextステートメント4-002.png]

前置きを見て頂いた方であれば、それほど難しくないかなと思います。
今回は10件(Excelの行数では11行目)までループすればいいので、ループカウンタを「4」から「11」に変更すればOKです。

    '' 変更前
    For i = 2 To 4
    '' 変更後
    For i = 2 To 11

プログラム全体は次のようになります。

Sub VBA基礎第10回_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)
    
        objMail.To = Cells(i, 2).Value
        objMail.Subject = "テストメール"
        objMail.Body = "メール本文"
        objMail.Send
        
        Set objMail = Nothing
    Next

    Set objOutlook = Nothing
    MsgBox "送信完了", vbInformation
End Sub

Q2. メールアドレスが入力されていないとエラーになってしまう

Q2です。毎回10人分ちょうどのメールを送りたいということは少ないかと思います。
メールアドレスを入力している分だけメールを送信できたら便利そうです。

Excelのイメージは次のようになります。
4件目以降が空白になっています。

[010-【ExcelVBA】For…Nextステートメント4-003.png]

まずは、修正を始める前に「なぜエラーになるのか」をしっかり確認しておきましょう。Excelを修正したら実行してみてください。
エラーの見方は前回に説明していますので、参照してください。
今回のエラーは「送信先」=「To」が指定されていないために発生してしまったのではないかと推測できます。
そこでExcelで送信先メールアドレスが入力されているときのみ、メール送信するようにプログラムを書き換えましょう。
(この辺の考え方も前回解説していますので、忘れてしまった方は参照ください。)

        '' 修正前
        objMail.To = Cells(i, 2).Value
        objMail.Subject = "テストメール"
        objMail.Body = "メール本文"
        objMail.Send
        '' 修正後
        If Cells(i, 2).Value <> "" Then
            objMail.To = Cells(i, 2).Value
            objMail.Subject = "テストメール"
            objMail.Body = "メール本文"
            objMail.Send
        End If

プログラム全体は次のようになります。

Sub VBA基礎第10回_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 = "テストメール"
            objMail.Body = "メール本文"
            objMail.Send
        End If
        
        Set objMail = Nothing
    Next

    Set objOutlook = Nothing
    MsgBox "送信完了", vbInformation
End Sub

次回は、カスタマイズの答え合わせ(続き)です。

 
 

連載目次リンク

ExcelVBA 入門 連載目次