読者です 読者をやめる 読者になる 読者になる

メール自動作成マクロ用のクラスを作る

Excelから、VBAでLotusNotesやThunderbirdのメールを作るマクロ。

メンテナンスしやすくて拡張性のあるものにしたいと思って試行錯誤中。「これでうまく行くんじゃね?」というところまで漕ぎ着けたので、うpしておく。

なるべく〈オブジェクト指向〉っぽくしたいんだけど、所詮素人なので、「オメー、そりゃダメだよw」というところがあったら、教えてください。

前回書いたように、

「Main」と名付けたワークシートに

f:id:akashi_keirin:20170311114734j:plain

f:id:akashi_keirin:20170311114741j:plain

f:id:akashi_keirin:20170311114749j:plain

こんな表を作って送信先アドレスとか本文とか添付ファイルのフルパスとかを入れておき、

「ユーザ情報」と名付けたワークシートに

f:id:akashi_keirin:20170311114804j:plain

こんな表を作って、送信者のデータを入れておくこととする。

んで、標準モジュールの宣言セクションでは、

'定数
Public Const EMBED_ATTACHMENT As Integer = 1454
Public Const MAIN_SHEET_NAME As String = "Main"
Public Const MAIN_FONTSIZE As Integer = 12      '本文のフォントサイズ
Public Const SUB_FONTSIZE As Integer = 10       '添付ファイル名、署名のフォントサイズ

定数の宣言をこんな風に(今回は関係ないのもあるけど)。

'構造体の宣言
Public Type mlData
  mailTo As String
  CC As String
  BCC As String
  mailSubject As String
  belongsTo As String
  jobTitle As String
  personName As String
  returnReceipt As String
End Type
'構造体変数の宣言
Public mldt As mlData

今回は、構造体変数を使用してみる。

'列挙体(列名を表すのに使用)
Public Enum colNum
  isSent = 1
  numOf
  sendTo
  mailTo
  CC
  BCC
  mailSubj
  belongsTo
  jobTitle
  personName
  p01
  p02
  p03
  p04
  p05
  p06
  p07
  p08
  p09
  p10
  att01
  att02
  att03
  att04
  att05
  att06
  att07
  att08
  att09
  att10
  returnReceipt
End Enum

前回同様、列挙体を宣言。

'クラス変数
Public md As MailData
Public nsc As NotesStartedChecker
'モジュールレベル変数
Dim mlBody() As String
Dim mlAttFiles() As String
Dim mlSenderData() As String

あとは、クラスのインスタンス用のPublic変数と、モジュールレベル変数を準備する。
※「nsc」は今回は使いません。

クラスモジュールを挿入して、「オブジェクト名」を「MailData」にする。

クラスモジュールに下記のコードを書く。

Option Explicit

'フィールド
Private mailTo_ As String             '送信先アドレス
Private CC_ As String                 'CC
Private BCC_ As String                'BCC
Private mailSubject_ As String        'メール件名
Private belongsTo_ As String          '送信相手の勤務先
Private jobTitle_ As String           '送信相手の肩書
Private personName_ As String         '送信相手の氏名
Private returnReceipt_ As String      '受信確認の有無
Private mailBody_() As String         'メール本文の配列
Private attFiles_() As String         '添付ファイルフルパスの配列
Private senderData_() As String       '送信者データの配列
Private numOfBody_ As Integer         'メール本文配列の要素数
Private numOfAttFiles_ As Integer     '添付ファイルフルパス配列の要素数
Private numOfSenderData_ As Integer   '送信者データ配列の要素数

'アクセサ
Public Property Get mailTo() As String
  mailTo = mailTo_
End Property
Public Property Get CC() As String
  CC = CC_
End Property
Public Property Get BCC() As String
  BCC = BCC_
End Property
Public Property Get mailSubject() As String
  mailSubject = mailSubject_
End Property
Public Property Get belongsTo() As String
  belongsTo = belongsTo_
End Property
Public Property Get jobTitle() As String
  jobTitle = jobTitle_
End Property
Public Property Get personName() As String
  personName = personName_
End Property
Public Property Get returnReceipt() As String
  returnReceipt = returnReceipt_
End Property
Public Property Get mailBody(ByVal i As Integer) As String
  mailBody = mailBody_(i)
End Property
Public Property Get attFiles(ByVal i As Integer) As String
  attFiles = attFiles_(i)
End Property
Public Property Get senderData(ByVal i As Integer) As String
  senderData = senderData_(i)
End Property
Public Property Get numOfBody() As Integer
  numOfBody = numOfBody_
End Property
Public Property Get numOfAttFiles() As Integer
  numOfAttFiles = numOfAttFiles_
End Property
Public Property Get numOfSenderData() As Integer
  numOfSenderData = numOfSenderData_
End Property
'コンストラクタ
Private Sub Class_Initialize()

End Sub

'メソッド
Public Sub getMailBasicData(ByRef mldt As mlData)             '……(1)
  'メールの基礎データを取得する
  mailTo_ = mldt.mailTo
  CC_ = mldt.CC
  BCC_ = mldt.BCC
  mailSubject_ = mldt.mailSubject
  belongsTo_ = mldt.belongsTo
  jobTitle_ = mldt.jobTitle
  personName_ = mldt.personName
  returnReceipt_ = mldt.returnReceipt
End Sub

Public Sub getMailBodyArray(ByRef mlBody() As String)         '……(2)
  'メール本文の配列を取得する
  Dim i As Integer
  numOfBody_ = UBound(mlBody())                               '……(3)
  ReDim mailBody_(numOfBody_)                                 '……(4)
  For i = 1 To UBound(mlBody())
    mailBody_(i) = mlBody(i)                                  '……(5)
  Next
End Sub

Public Sub getMailAttFilesArray(ByRef mlAttFiles() As String) '……(6)
  '添付ファイルフルパスの配列を取得する
  Dim i As Integer
  numOfAttFiles_ = UBound(mlAttFiles())
  ReDim attFiles_(numOfAttFiles_)
  For i = 1 To UBound(mlAttFiles())
    attFiles_(i) = mlAttFiles(i)
  Next
End Sub

Public Sub getSenderDataArray(ByRef mlSenderData() As String) '……(7)
  '送信者データの配列を取得する
  Dim i As Integer
  numOfSenderData_ = UBound(mlSenderData())
  ReDim senderData_(numOfSenderData_)
  For i = 1 To UBound(mlSenderData())
    senderData_(i) = mlSenderData(i)
  Next
End Sub

Public Sub createLotusNotesMail()                             '……(8)
  'LotusNotesのメールを作成する
  
End Sub

Public Sub createThunderbirdMail()                            '……(9)
  'Thunderbirdのメールを作成する
  
End Sub

 

なんだかものすごく長いコードになってしまったが、前回との最大の違いは、

クラスとワークシートとの関係を完全に断ち切った

こと。

こうすることで、メール作成用のデータを入力したExcelワークシートの作り方が変わった場合でも、このクラスに関しては使い回しをすることができる。おおっ、ちょっと〈オブジェクト指向〉っぽいぞw

例によって、コードの解説。

  • まず、コンストラクタがなくなっちゃってます。Private変数にデフォルト値が入って不都合な点が思い浮かばないので。コンストラクタのうまい使い道があったら教えてほしいぐらい。
  • (1)は、メールの基礎情報……というか、実際は値が一つしかないようなパラメータを一気にMailDataオブジェクトのプロパティにセットするメソッド。引数を構造体で渡しているところがミソ。
  • (2)は、本文の配列をMailDataオブジェクトのプロパティにセットするメソッド。引数に配列をまるごと渡している。
  • 引数で渡された配列をUboundで調べたら要素数が分かるので、(3)でnumOfBodyプロパティにセット。
  • その要素数を早速使って、(4)で仮配列mailBody_()をReDimする。
  • あとは、Forループを使って(5)で引数として渡された配列の要素を、MailDataオブジェクトのプロパティ配列にセットしている。
  • (6)では、添付ファイルのフルパスについて(2)と同じことをしている。
  • (7)では、送信者のデータについて(2)と同じことをしているだけ。
  • (8)と(9)は、今後実装予定のメソッド。(7)までで、およそメールを作成するために必要なデータは全て取得済みなので、あとはそれぞれのメーラーに合わせてメールを作成する処理を書けば良い。

で、このクラスにメール作成用のデータを渡す処理は、メール用データのあるワークシートの作りに合わせて標準モジュールに書く。まあ、これは、前回コンストラクタに書いていたものを移植すれば良いだけなので、もはや大した手間ではあるまい。

とりあえず、今回はここまで。このクラスにメール作成用データを渡す処理は、もう書いているんだけど、今回すでにかなり長くなってしまっているので、次回投稿します。

@akashi_keirin on Twitter