ファイルのフルパスを簡単に取得する
はじめに
メール自動作成マクロ(その1/その2/その3/その4)では、添付ファイルをセットするために表の中に添付ファイルのフルパスを入力しておく必要があった。
しかし、「添付ファイルのフルパスの入力なんてめんどくせーよな!」と誰しも思う。だから、簡単に入力できる方法が必要だ。
そこで、今回は、
セルをダブルクリックしたらファイル選択ダイアログが出てきて、そこで選んだファイルのフルパスがセルに入力される
という方針でやってみよう。
今回も、おなじみのこの表を使う。この表のU列~AD列のセルにファイルのフルパスを書き込むためのマクロ、ということ。
「セルをダブルクリックしたら」なので、Worksheetオブジェクトのイベントプロシージャ・「Worksheet_BeforeDoubleClick」を使う。
コードの作成
イベントプロシージャを書くときは、プロジェクトエクスプローラで、対象のオブジェクト名をダブルクリックしたらいい。今回は、「Sheet1」のところをダブルクリック。
「Sheet1」モジュールのコードウインドウが表示されるので、上の2つの窓でそれぞれ「Worksheet」(左)と「BeforeDoubleClick」を選択すると、
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
End Sub
ってのが自動的に生成されるので、真ん中のところにコードを書いていきゃいい。
シートモジュールのコード
Option Explicit
Const PROMPT As String = "添付するファイルを指定してください。"
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
On Error Resume Next
Err.Clear
Application.EnableEvents = False '……(1)
Set flp = New FilePicker '……(2)
With Target
If .Column < colNum.att01 Or .Column > colNum.att10 Or .Row = 1 Then '……(3)
Application.EnableEvents = True '……(4)
Exit Sub
Else '……(5)
'添付ファイルが歯抜け状態で入力されないようにするための措置
If .Column > colNum.att01 And .Offset(0, -1).Value = "" Then
MsgBox "添付ファイルは左詰めになるように設定せよ。" & vbCrLf & "やり直すがよい。"
Cancel = True '……(6)
Application.EnableEvents = True
Exit Sub
End If
flp.showFilePicker PROMPT '……(7)
If flp.isCancelled = True Then '……(8)
Cancel = True
Application.EnableEvents = True
Exit Sub
End If
If LenB(flp.gotFileFullPath) > 220 Then '……(9)
MsgBox "添付ファイルのフルパスのサイズが220バイトを超えています。" & vbCrLf & _
"添付ファイルをデスクトップに貼り付けるなど、フルパスを短くしてください。"
Cancel = True
Application.EnableEvents = True
Exit Sub
Else
.Value = flp.gotFileFullPath '……(10)
Cancel = True
End If
End If
End With
Application.EnableEvents = True '……(11)
If Err.Number > 0 Then
If Err.Number = 1004 Then
MsgBox "指定したファイル名(フルパス)が長すぎます。" & vbCrLf & _
"フルパスが短くなるようにして、やり直してください。" & vbCrLf & _
"【例】添付ファイルをデスクトップに貼り付けるなど"
End If
Call errorCatch("WorkSheets(""Main"")のWorksheet_BeforeDoubleClickプロシージャ", Err.Number, Err.Description)
End If
Application.EnableEvents = True
End Sub
コードの説明
このブログでイベントマクロを紹介するのは初めてだと思うので、自分の復習も兼ねてちょっとこってり書いておこう。
- (1)で一旦イベントの発生を抑える。実は、今回のこのマクロだけだったらこれは必要ないんだけど、このシートではもう一つ「Worksheet_Change」というイベントマクロも書いているので、イベントの連鎖を防ぐためにこうしている。いきなり分かりにくくてすまん。
- (2)では自作クラスFilePickerをインスタンス化。FilePickerのコードはコチラをどうぞ。
- (3)では、ダブルクリックされた場所を判定。添付ファイル入力欄以外なら(4)に進む。
ちなみに、列番号の指定はおなじみ列挙体を使用しています。(コチラを参考にどうぞ。) - (4)に処理が移るということは、添付ファイル入力欄ではないということだから、イベントの発生抑止を解除して処理を終了する。処理を終了するときに「Application.EnableEvents」をTrueにしておかないと、いろいろおかしなことになるから注意。
※ダブルクリックしたのに何も起こらない、とか。 - (5)に処理が移ってくるということは、添付ファイル入力欄上でダブルクリックされた、ということ。
- ただし、ダブルクリックされたセルが添付ファイル2~10までのセルなのに、左隣のセルが空白だったら、歯抜け状態になっているとみなしてメッセージを表示して終了する。
- (6)の「Cancel = True」というのは「ダブルクリック」というイベントをキャンセルする、ということ。ふつうセルでダブルクリックしたら、編集モードに移るんだけど、それをキャンセルするので何も起こらない。要するに直接入力もさせない、ということだ。
- ここまでの条件をクリアしてきたら、それは、「ダブルクリックされたセルが添付ファイルのフルパスを入力しても良いセル」ということになる。そこで、(7)、FilePickerクラスのshowFilePickerメソッドの出番だ。ファイル選択ダイアログのタイトル欄に表示する文字列を引数として渡して実行する。
- (8)。ファイル選択ダイアログで[キャンセル]が選ばれたりしてファイルパスが取得できていなければ、isCancelledプロパティがTrueになっているので、処理を終了する。
- (9)は、取得したファイルフルパスのバイト数でふるいにかけている。添付ファイルのフルパスが長いと添付できないことがあるから。ここではそのバイト数を220にしているけど、これは目分量みたいなもん。正確なところが分からないので、知っている人がいたら教えろてください。
- ここまで、数々の苦難を乗り越えて(10)まで来たら、やっとここで取得したファイルのフルパスをダブルクリックしたセルに書き込んでいる。
- 最後に(11)のようにイベント発生を復活させておくのを忘れないように。
イベントマクロって、便利なんですけど、思いもかけないタイミングで発動することがあるので、慣れないうちは試行錯誤が必要ですね。ダブルクリックイベントなんかの場合、単独ではイベントの無限連鎖にはならないんだけど、他のイベントマクロとの合わせ技で無限連鎖が起こってしまうことがあるのでやっかいです。
【参考】クラスモジュールFilePickerのコード
Option Explicit
'フィールド
Private gotFileFullPath_ As String
Private isCancelled_ As Boolean
'アクセサ
Public Property Get gotFileFullPath() As String
gotFileFullPath = gotFileFullPath_
End Property
Public Property Get gotFileName() As String
gotFileName = Right(gotFileFullPath_, _
(Len(gotFileFullPath) - InStrRev(gotFileFullPath, "\")))
End Property
Public Property Get isCancelled() As Boolean
isCancelled = isCancelled_
End Property
'コンストラクタ
Private Sub Class_Initialize()
isCancelled_ = False
End Sub
'メソッド
Public Sub showFilePicker(ByVal titleStr As String)
Dim fileFullPath As Variant
fileFullPath = Application.GetOpenFilename(Title:=titleStr)
If fileFullPath = False Then
isCancelled_ = True
gotFileFullPath_ = ""
Else
isCancelled_ = False
gotFileFullPath_ = fileFullPath
End If
End Sub
【参考】標準モジュールのコード
'列挙体(列名を表すのに使用)
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 flp As FilePicker
おわりに
ここまで来ると、かなり便利なツールになってきます。