実は既に以下のステップで、ほとんど説明済みです。
・Step55で完成図
・Step56、Step57でプログラムのヒント
・Step57で解答例
そこで今回は、大事なポイントだけを、解説することにします。
また以前のステップと重なっている説明もあるのですが、ご了承ください。繰り返し書いているということは、それだけ重要な部分です。
(1)最大ステップを代入するための変数を宣言している部分です。
Dim maxStep As Long
変数の有効範囲に気をつけてください。
この変数は、複数のプロシージャで共通して使います。したがって宣言セクションで、変数の宣言をしています。
(2)文章を取得して配列にセットする部分については、Step57で説明済みです。
Dim textArray() As String からの部分
この部分が、ステップメールで一番重要なところです。
文章とタイトルは、配列を使って、あらかじめ取得しておきます。
ただし、メール送信フォームを開いたからといって、必ずしも送信するとは限りません。
そこでユーザーが、「メール送信」ボタンをクリックした時に取得しています。
この部分は、サブプロシージャとして分けたほうが、スッキリするかもしれません。
(3)ステップメールでも、ユーザーフォームから、件名と本文を取得します。
'件名取得
subj = Me.txtSubject
'本文取得
body = Me.txtBody
これらは、ステップメールで、どのメールにも共通する文字になります。
(4)件名と本文を、一時的に格納するため、変数を宣言している部分です。
Dim tmpSubj As String
Dim tmpBody As String
ステップメールでは、個々のメールの内容が異なるため、元になる変数(subj、body)を直接書き換えてしまうと、不都合があります。
そのため、変数の内容をコピーするための一時変数を準備しています。
(5)次のステップを代入する変数を宣言している部分です。
Dim nextStep As Long
この変数の有効範囲は、宣言したプロシージャ内だけです。
(6)次のステップを計算している部分です。
nextStep = CLng(Trim(Range("C" & i).Value)) + 1
次のステップは、現在のステップに1を加算するだけです。
現在のステップは、Excelのワークシートからセルの値を取得します。
これはフォームが表示されている時に、対象となっているワークシートの場合です。
変数 i には、行番号が入っています。iが変化することで、異なる行の値を取得できます。
Trim関数を使っているのは、前後の空白を取り除くためです。
あとは、取得したセルの値を、念のため CLng で長整数型に変換してから、1をプラスしています。
(7)次のステップが、最大ステップ数以下の場合だけ、処理を行なうようにしている部分です。
If nextStep <= maxStep Then
省略
End If
最大ステップを超える場合は、メールを作成しないようにするための処理です。
(8)件名に値を自動挿入している部分です。
tmpSubj = subj
tmpSubj = Replace(tmpSubj, "[氏名]", tName)
tmpSubj = Replace(tmpSubj, "[タイトル]", titleArray(nextStep))
元の変数の値(subj)は変えずに置換したいので、一時変数(tmpSubj)に代入しています。
自動挿入するためには、Replace関数を使って置換します。
*置換するのは tmpSubj のほうです。
件名では、挿入タグ(検索文字列)に、以下のものが使えます。
[氏名]、[タイトル]
配列からデータを取り出すには、添え字を指定します。
titleArray(nextStep)
ポイントは、添え字を変数で指定することです。変数の値が変われば、取得できるデータが変わります。
(9)本文に値を自動挿入している部分です。
tmpBody = body
tmpBody = Replace(tmpBody, "[氏名]", tName)
tmpBody = Replace(tmpBody, "[文章]", textArray(nextStep))
要領は件名と同じです。
本文では、挿入タグ(検索文字列)に、以下のものが使えます。
[氏名]、[文章]
(10)個々のメールを作成している部分です。
msg = bobj.SendMail(mailq, mailto, mailfrom, tmpSubj, tmpBody, files)
件名と本文の引数には、一時変数(tmpSubj、tmpBody)を使っている点に注目してください。
これにより、個々のメールで内容を変えることができます。
元の変数(subj、body)を使うと、全部同じメールになるので注意してください。それに挿入タグ(検索文字列)も、残ったままになるはずです。
(11)送信チェックを行なっているプログラムを変更しました。
'送信チェック
If rc <= -1 Then
MsgBox "送信できませんでした。" & vbCrLf & "エラー:" & rc, vbOKOnly + vbCritical, "送信時エラー"
ElseIf rc = 0 Then
MsgBox "送信に該当するメールがありませんでした。", vbOKOnly + vbInformation, "情報"
Else
'送信に成功したら、ステップアップする
updateStep
MsgBox rc & "件のメールを送信しました。", vbOKOnly + vbInformation, "完了"
End If
ステップメールでは、必ずしも該当するメールがあるとは限りません。
例えば、全ての人が既に最大ステップに達している場合も考えられます。
そのままでは、送信するメールが無い時に、「送信時エラー」が表示されてしまうので、少しだけ変更しました。
該当するメールが無い場合は、変数rc に「0」が代入されています。それを利用して、メッセージを表示することにしました。
ElseIf rc = 0 Then の部分
また、送信が成功した場合は、ステップアップする必要があるので、updateStep というサブプロシージャを呼び出しています。
Call命令を使って、以下のように書いても同じ結果になります。
Call updateStep
(12)最大ステップを更新した時のイベントプロシージャです。
Private Sub txtMaxStep_Exit(ByVal Cancel As MSForms.ReturnBoolean)
省略
End Sub
ユーザーフォームで、最大ステップに入力した値をチェックするため、イベントプロシージャを新たに作成しました。
行番号のテキストボックスと、ほとんど同じ処理です。少し書き換えただけです。
(13)フォームを初期化時のイベントプロシージャに、プログラムを追加しています。
Private Sub UserForm_Initialize()
省略
Me.txtMaxStep = 10
省略
maxStep = 10
省略
最大ステップのテキストボックス(txtMaxStep)と変数(maxStep)に、初期値として「10」を代入しています。
変数maxStepにも初期値を代入するのは、ユーザーフォームを開いた時に、テキストボックスの値を変更せずに送信することもあるからです。
maxStepの値は、テキストボックスを更新したタイミングで代入される仕組みにしているので、テキストボックスを操作しない場合は、変数の値が空になります。
それを防ぐための処理です。
(14)ステップを更新するためのSubプロシージャを、新しく作成しました。
Private Sub updateStep()
'ステップ更新
Dim i As Long
Dim nextStep As Long
For i = startPos To endPos
'次のステップ
nextStep = CLng(Trim(Range("C" & i).Value)) + 1
'最大ステップ数以下の場合
If nextStep <= maxStep Then
'ステップアップ
Range("C" & i).Value = nextStep
End If
Next i
End Sub
メール送信が成功したら、ワークシート「送信」のステップを、更新する必要があります。
ポイントは、最大ステップを超える場合は、ステップアップしないことです。つまり最大ステップ数以下の場合だけステップアップします。
If nextStep <= maxStep Then の部分
このように、処理をSubプロシージャに分けることで、本体のプログラムがシンプルになります。

