【動作環境、条件】
①OSに元から入っていないバージョンの.NET Frameworkなどを必要としないこと
②将来的にWindows7やExcel2003になっても使用不能にならないこと
③既定のメーラーの機能を活かしたい。
(環境に添付ファイルサイズ最大2MBの制限があり、OEの分割送信機能が必須)
(基本はOE・MAPI系で構わないが, 指名することは避けたい)
【現在まで自分で調べたこと】
1、標準のCDOを使えばVBAで送信できるが、既定のメーラーが持つ機能を使えない。
(アドレス帳、分割送信、送信認証 など)
2、「mailto:」プロトコルは、添付ファイルに対応できない。
3、送りたいファイルを右クリックして「送る」⇒「メール受信者」(.MAPImail)で既定のメーラーが立ち上がり、SendToフォルダにある同アイコンにファイルをD&Dしても同様に立ち上がる。しかし、Excel2000VBAからそれをやるコードがわからない。
4、Application.Dialogs(xlSendMail).Show のようなコードはエラーになる。
プログラミング素人ではないのですが
とにかく時間が無いため、お願いします。
レジストリから既定のメーラーが何になっているかはわかります。oeに限ったコードでも
欲しいです。なんとかexcelVBAで送れるようにしたいです。
もうCDOでも実用性の高いものを頂けるなら構わないです。
お願いいたします。宛先は複数です。
3、送りたいファイルを右クリックして「送る」⇒「メール受信者」(.MAPImail)
既定のメーラにてファイルを添付する機能は OS 付属のコンポーネントである sendmail.dll により実装されていますが、シェル拡張用のコンポーネントである為、通常の、Win32 API に比べ、呼び出し方が少し面倒です。
具体的には、SendMail コンポーネントの IDropTarget インターフェイスを取得し、DragEnter / Drop メソッドを呼び出す必要があります。
ただし、この IDropTarget インターフェイスは、既定の状態では VBA にて使用できない(参照設定が行われていない)為、呼び出す手段を考える必要があります。
方法として考えられるのは、以下にあるような方法かと思います。
<タイプライブラリ化し VBA より呼び出す方法>
■ OLELIB.TLB (tl_ole.zip に内包)
http://www.mvps.org/emorcillo/download/vb6/tl_ole.zip
■ Sending a file to "Mail Recipient" using sendmail.dll
http://www.mvps.org/emorcillo/en/code/vb6/sendmail.shtml
<Win32 API 形式の DLL を作成し、VBA より呼び出す方法>
■ Convert MFC/C++ to VB [Small Code]-VBForums
http://www.vbforums.com/showthread.php?269271-Convert-MFC-C-to-VB-Small-Code
<単体 EXE として実装する方法>
■ SendTo mail recipient - CodeProject
http://www.codeproject.com/Articles/3839/SendTo-mail-recipient
■ SendTo mail recipient
http://www.arstdesign.com/articles/sendtomail.html
■ SendTo mail recipient (part II)
http://www.arstdesign.com/articles/sendto.exe.html
このうち、上記の「タイプライブラリ化し VBA より呼び出す方法」にて紹介しているサンプルコードを動作するのに必要な部分だけを切り出したタイプライブラリ用のソースファイル(oleliblt.odl)を用意してみました。
/* File : oleliblt.odl Compile : midl.exe oleliblt.odl [Enter] */ [ uuid(578a13f1-ad1a-4fa8-8def-25c1b45874de), helpstring("OLELIB Lite"), version(0.01) ] library oleliblt { importlib("stdole2.tlb"); typedef unsigned char BYTE; typedef LONG BOOL; typedef enum HRESULTS { S_OK = 0, S_FALSE = 1 } HRESULTS; typedef enum DROPEFFECTS { DROPEFFECT_NONE = 0, DROPEFFECT_COPY = 1, DROPEFFECT_MOVE = 2, DROPEFFECT_LINK = 4, DROPEFFECT_SCROLL = 0x80000000, } DROPEFFECTS; typedef struct UUID { LONG Data1; SHORT Data2; SHORT Data3; BYTE Data4[8]; } UUID; [ odl, uuid(00000122-0000-0000-C000-000000000046) ] interface IDropTarget : IUnknown { HRESULT DragEnter( [in] IDataObject *pDataObj, [in] LONG grfKeyState, [in] LONG ptX, [in] LONG ptY, [in, out] DROPEFFECTS *pdwEffect); HRESULT DragOver( [in] LONG grfKeyState, [in] LONG ptX, [in] LONG ptY, [in, out] DROPEFFECTS *pdwEffect); HRESULT DragLeave(); HRESULT Drop( [in] IDataObject *pDataObj, [in] LONG grfKeyState, [in] LONG ptX, [in] LONG ptY, [in, out] DROPEFFECTS *pdwEffect); }; typedef enum ESTRRET { STRRET_WSTR = 0, STRRET_OFFSET = 1, STRRET_CSTR = 2 } ESTRRET; typedef struct STRRET { ESTRRET uType; BYTE cStr[260]; } STRRET; typedef enum SHGNO_Flags { SHGDN_NORMAL = 0, SHGDN_INFOLDER = 1, SHGDN_FORADDRESSBAR = 0x4000, SHGDN_FORPARSING = 0x8000, } SHGNO_Flags; typedef enum SHCONTF { SHCONTF_FOLDERS = 0x0020, SHCONTF_NONFOLDERS = 0x0040, SHCONTF_INCLUDEHIDDEN = 0x0080, SHCONTF_INIT_ON_FIRST_NEXT = 0x0100, SHCONTF_NETPRINTERSRCH = 0x0200, SHCONTF_SHAREABLE = 0x0400, SHCONTF_STORAGE = 0x0800, } SHCONTF; [ odl, uuid(000214F2-0000-0000-C000-000000000046) ] interface IEnumIDList : IUnknown { HRESULT Next( [in] LONG celt, [in, out] LONG *rgelt, [out, retval] LONG *pceltFetched); HRESULT Skip( [in] LONG celt); HRESULT Reset(); HRESULT Clone( [out, retval] IEnumIDList **ppenum); }; [ odl, uuid(000214E6-0000-0000-C000-000000000046) ] interface IShellFolder : IUnknown { HRESULT ParseDisplayName( [in] long hwndOwner, [in] long pbcReserved, [in] long lpszDisplayName, [in, out] long* pchEaten, [in, out] long* ppidl, [in, out] long* pdwAttributes); HRESULT EnumObjects( [in] long hwndOwner, [in] SHCONTF grfFlags, [out, retval] IEnumIDList** ppenumIDList); HRESULT BindToObject( [in] long pidl, [in] long pbcReserved, [in, out] UUID *riid, [in, out] long *ppvOut); HRESULT BindToStorage( [in] long pidl, [in] long pbcReserved, [in, out] UUID *riid, [out, retval] IStorage **ppvObj); HRESULT CompareIDs( [in] long lparam, [in] long pidl1, [in] long pidl2); HRESULT CreateViewObject( [in] long hwndOwner, [in, out] UUID* riid, [out, retval] long *ppvOut); HRESULT GetAttributesOf( [in] long cidl, [in, out] long* apidl, [in, out] long* rgfInOut); HRESULT GetUIObjectOf( [in] long hwndOwner, [in] long cidl, [in, out] long *apidl, [in, out] UUID *riid, [in, out] long *prgfInOut, [out, retval] long *ppvOut); HRESULT GetDisplayNameOf( [in] long pidl, [in] SHGNO_Flags uFlags, [in, out] STRRET* lpName); HRESULT SetNameOf( [in] long hwndOwner, [in] long pidl, [in] long lpszName, [in] SHGNO_Flags uFlags, [out, retval] long* ppidlOut); }; [ dllname("OLE32.DLL") ] module ole32 { [entry("CLSIDFromString")] HRESULT CLSIDFromString( [in] LPWSTR lpszProgID, [in, out] UUID *lpclsid); [entry("CoCreateInstance")] LONG CoCreateInstance( [in] UUID *CLSID, [in] stdole.IUnknown *pUnkOuter, [in] CLSCTX dwClsContext, [in] UUID *IID, [out] void *ppv); [entry("CoTaskMemFree")] LONG CoTaskMemFree( [in] LONG Ptr); } [ dllname("KERNEL32.DLL") ] module kernel32 { [entry("RtlMoveMemory")] void MoveMemory( [in] void *pDest, [in] void *pSource, [in] LONG ByteLen); } [ dllname("SHELL32.DLL") ] module shell32 { [entry("SHGetDesktopFolder")] HRESULT SHGetDesktopFolder( [out, retval] IShellFolder **ppshf); } [ dllname("dummy") ] module constants { const LPSTR IIDSTR_IShellFolder = "{000214E6-0000-0000-C000-000000000046}"; } };
<使用方法> 1. MIDL コンパイラ(Visual C++ or Windows SDK 付属ツール)によりコンパイルを実施 C:\work\oleliblt> midl.exe oleliblt.odl [Enter] → 上記のコンパイルにより「oleliblt.tlb」が作成されます。 2. VBE の [ツール]-[参照設定] により「oleliblt.tlb」を選択。 → IDataObject / IDropTarget 等が参照できるようになります。 3. 以下のサイトにあるサンプルコードを入力します。 ■ Sending a file to "Mail Recipient" using sendmail.dll http://www.mvps.org/emorcillo/en/code/vb6/sendmail.shtml 4. テストコードを作成します。 Sub MailTest() Call SendToMailRecipient("C:\work\mailtest\test.txt") End Sub 5. テストコードを実行し、既定のメーラにてファイルが添付されることを確認します。
この方式にて、Windows 2000 + Excel 2000 環境で動作すること確認しました。
難点としては、特定のパスでタイプライブラリの参照を行った後、他の端末に
Excel ファイルを持って行った場合に「参照不可(MISSING)」となってしまう点でしょうか。
プログラムにより、動的に参照設定を行う方法はありますが、「参照不可」と、なってしまった場合、手動で再設定するしか無いようようです。
(この問題を回避する方法としては「毎回、Excel ブックオープン時にプログラムで参照設定を行い、クローズするときに、参照設定を解除する」という方法があるようです。)
<参考情報>
■ Office TANAKA - Excel VBA Tips[マクロで参照設定を操作する]
http://officetanaka.net/excel/vba/tips/tips100.htm
Sub try_3()
Const HKEY = "HKEY_CLASSES_ROOT\mailto\shell\open\command\"
Dim Flg As Boolean
Dim Arg As String
Dim sPath As String
Dim i As Long
Dim b() As Byte
Dim tmp, ary
On Error GoTo errHandler
tmp = Selection.Value
If IsArray(tmp) Then
ReDim ary(1 To UBound(tmp))
For i = 1 To UBound(tmp)
ary(i) = Join(Application.Index(tmp, i, 0), "")
Next
Arg = Join(ary, vbLf)
Else
Arg = tmp
End If
'既定メーラー取得(WinXP)
With CreateObject("WScript.Shell")
sPath = .ExpandEnvironmentStrings(.RegRead(HKEY))
End With
sPath = Replace$(Replace$(sPath, """%1""", ""), "%1", "")
Flg = InStr(1, sPath, "thunderbird", vbTextCompare)
If Flg Then
'thunderbirdだと文字化けしたのでUTFエンコード
With CreateObject("ScriptControl")
.Language = "JScript"
Arg = .CodeObject.encodeURI(Arg)
End With
Else
'簡易的にSJISエンコード
b = StrConv(Arg, vbFromUnicode)
Arg = ""
For i = 0 To UBound(b)
Arg = Arg & "%" & Right$("0" & Hex$(b(i)), 2)
Next
End If
Arg = "mailto:メールアドレス?" & _
"subject=件名&" & _
"body=" & Arg
Shell sPath & Arg
Exit Sub
errHandler:
MsgBox Err.Number & ":" & Err.Description
End Sub
とりあえずwinXPで Outlook/Outlook Express/thunderbird は動きました。
他環境だったりする場合、ここ
http://jehupc.exblog.jp/9727243/
の情報が参考になると思います。
http://oshiete.goo.ne.jp/qa/5977178.html
こんなんではイケませんか?
この情報のページは既に見ましたが、
「mailto:」を使う方法では
添付ファイルを付けられないんです。
> Arg = "mailto:メールアドレス?" & _
> "subject=件名&" & _
> "body=" & Arg
>
> Shell sPath & Arg
>
とありますが、file= や attach= を追記しても無駄でした。
ここは参考になりませんか?
http://oshiete.goo.ne.jp/qa/5977178.html
あと、ここで聞くのもいいかも
http://www.excel.studio-kazu.jp/kw/20100319143109.html
すみません。全て見たことのある記事です。
また、上記でも言っていますが、「mailto:」プロトコルは既定のメーラーを起動してメール送信ができますが、いかんせん
絶対条件である「添付ファイル」を付けられないのです。NGです。申し訳ない。
ExcelVBAでメールを作成してメーラーを起動するプログラムを作って
http://okwave.jp/qa/q5977178.html
こちらページの回答はどうでしょうか。
http://www.moug.net/tech/acvba/0090045.html
あとはこちらも。
同様に既に見たことがありNGです。。
簡単そうに見えるかもしれませんが、
海外サイトも含めて数時間検索しまくっても見つからないレベルです。
3、送りたいファイルを右クリックして「送る」⇒「メール受信者」(.MAPImail)
既定のメーラにてファイルを添付する機能は OS 付属のコンポーネントである sendmail.dll により実装されていますが、シェル拡張用のコンポーネントである為、通常の、Win32 API に比べ、呼び出し方が少し面倒です。
具体的には、SendMail コンポーネントの IDropTarget インターフェイスを取得し、DragEnter / Drop メソッドを呼び出す必要があります。
ただし、この IDropTarget インターフェイスは、既定の状態では VBA にて使用できない(参照設定が行われていない)為、呼び出す手段を考える必要があります。
方法として考えられるのは、以下にあるような方法かと思います。
<タイプライブラリ化し VBA より呼び出す方法>
■ OLELIB.TLB (tl_ole.zip に内包)
http://www.mvps.org/emorcillo/download/vb6/tl_ole.zip
■ Sending a file to "Mail Recipient" using sendmail.dll
http://www.mvps.org/emorcillo/en/code/vb6/sendmail.shtml
<Win32 API 形式の DLL を作成し、VBA より呼び出す方法>
■ Convert MFC/C++ to VB [Small Code]-VBForums
http://www.vbforums.com/showthread.php?269271-Convert-MFC-C-to-VB-Small-Code
<単体 EXE として実装する方法>
■ SendTo mail recipient - CodeProject
http://www.codeproject.com/Articles/3839/SendTo-mail-recipient
■ SendTo mail recipient
http://www.arstdesign.com/articles/sendtomail.html
■ SendTo mail recipient (part II)
http://www.arstdesign.com/articles/sendto.exe.html
このうち、上記の「タイプライブラリ化し VBA より呼び出す方法」にて紹介しているサンプルコードを動作するのに必要な部分だけを切り出したタイプライブラリ用のソースファイル(oleliblt.odl)を用意してみました。
/* File : oleliblt.odl Compile : midl.exe oleliblt.odl [Enter] */ [ uuid(578a13f1-ad1a-4fa8-8def-25c1b45874de), helpstring("OLELIB Lite"), version(0.01) ] library oleliblt { importlib("stdole2.tlb"); typedef unsigned char BYTE; typedef LONG BOOL; typedef enum HRESULTS { S_OK = 0, S_FALSE = 1 } HRESULTS; typedef enum DROPEFFECTS { DROPEFFECT_NONE = 0, DROPEFFECT_COPY = 1, DROPEFFECT_MOVE = 2, DROPEFFECT_LINK = 4, DROPEFFECT_SCROLL = 0x80000000, } DROPEFFECTS; typedef struct UUID { LONG Data1; SHORT Data2; SHORT Data3; BYTE Data4[8]; } UUID; [ odl, uuid(00000122-0000-0000-C000-000000000046) ] interface IDropTarget : IUnknown { HRESULT DragEnter( [in] IDataObject *pDataObj, [in] LONG grfKeyState, [in] LONG ptX, [in] LONG ptY, [in, out] DROPEFFECTS *pdwEffect); HRESULT DragOver( [in] LONG grfKeyState, [in] LONG ptX, [in] LONG ptY, [in, out] DROPEFFECTS *pdwEffect); HRESULT DragLeave(); HRESULT Drop( [in] IDataObject *pDataObj, [in] LONG grfKeyState, [in] LONG ptX, [in] LONG ptY, [in, out] DROPEFFECTS *pdwEffect); }; typedef enum ESTRRET { STRRET_WSTR = 0, STRRET_OFFSET = 1, STRRET_CSTR = 2 } ESTRRET; typedef struct STRRET { ESTRRET uType; BYTE cStr[260]; } STRRET; typedef enum SHGNO_Flags { SHGDN_NORMAL = 0, SHGDN_INFOLDER = 1, SHGDN_FORADDRESSBAR = 0x4000, SHGDN_FORPARSING = 0x8000, } SHGNO_Flags; typedef enum SHCONTF { SHCONTF_FOLDERS = 0x0020, SHCONTF_NONFOLDERS = 0x0040, SHCONTF_INCLUDEHIDDEN = 0x0080, SHCONTF_INIT_ON_FIRST_NEXT = 0x0100, SHCONTF_NETPRINTERSRCH = 0x0200, SHCONTF_SHAREABLE = 0x0400, SHCONTF_STORAGE = 0x0800, } SHCONTF; [ odl, uuid(000214F2-0000-0000-C000-000000000046) ] interface IEnumIDList : IUnknown { HRESULT Next( [in] LONG celt, [in, out] LONG *rgelt, [out, retval] LONG *pceltFetched); HRESULT Skip( [in] LONG celt); HRESULT Reset(); HRESULT Clone( [out, retval] IEnumIDList **ppenum); }; [ odl, uuid(000214E6-0000-0000-C000-000000000046) ] interface IShellFolder : IUnknown { HRESULT ParseDisplayName( [in] long hwndOwner, [in] long pbcReserved, [in] long lpszDisplayName, [in, out] long* pchEaten, [in, out] long* ppidl, [in, out] long* pdwAttributes); HRESULT EnumObjects( [in] long hwndOwner, [in] SHCONTF grfFlags, [out, retval] IEnumIDList** ppenumIDList); HRESULT BindToObject( [in] long pidl, [in] long pbcReserved, [in, out] UUID *riid, [in, out] long *ppvOut); HRESULT BindToStorage( [in] long pidl, [in] long pbcReserved, [in, out] UUID *riid, [out, retval] IStorage **ppvObj); HRESULT CompareIDs( [in] long lparam, [in] long pidl1, [in] long pidl2); HRESULT CreateViewObject( [in] long hwndOwner, [in, out] UUID* riid, [out, retval] long *ppvOut); HRESULT GetAttributesOf( [in] long cidl, [in, out] long* apidl, [in, out] long* rgfInOut); HRESULT GetUIObjectOf( [in] long hwndOwner, [in] long cidl, [in, out] long *apidl, [in, out] UUID *riid, [in, out] long *prgfInOut, [out, retval] long *ppvOut); HRESULT GetDisplayNameOf( [in] long pidl, [in] SHGNO_Flags uFlags, [in, out] STRRET* lpName); HRESULT SetNameOf( [in] long hwndOwner, [in] long pidl, [in] long lpszName, [in] SHGNO_Flags uFlags, [out, retval] long* ppidlOut); }; [ dllname("OLE32.DLL") ] module ole32 { [entry("CLSIDFromString")] HRESULT CLSIDFromString( [in] LPWSTR lpszProgID, [in, out] UUID *lpclsid); [entry("CoCreateInstance")] LONG CoCreateInstance( [in] UUID *CLSID, [in] stdole.IUnknown *pUnkOuter, [in] CLSCTX dwClsContext, [in] UUID *IID, [out] void *ppv); [entry("CoTaskMemFree")] LONG CoTaskMemFree( [in] LONG Ptr); } [ dllname("KERNEL32.DLL") ] module kernel32 { [entry("RtlMoveMemory")] void MoveMemory( [in] void *pDest, [in] void *pSource, [in] LONG ByteLen); } [ dllname("SHELL32.DLL") ] module shell32 { [entry("SHGetDesktopFolder")] HRESULT SHGetDesktopFolder( [out, retval] IShellFolder **ppshf); } [ dllname("dummy") ] module constants { const LPSTR IIDSTR_IShellFolder = "{000214E6-0000-0000-C000-000000000046}"; } };
<使用方法> 1. MIDL コンパイラ(Visual C++ or Windows SDK 付属ツール)によりコンパイルを実施 C:\work\oleliblt> midl.exe oleliblt.odl [Enter] → 上記のコンパイルにより「oleliblt.tlb」が作成されます。 2. VBE の [ツール]-[参照設定] により「oleliblt.tlb」を選択。 → IDataObject / IDropTarget 等が参照できるようになります。 3. 以下のサイトにあるサンプルコードを入力します。 ■ Sending a file to "Mail Recipient" using sendmail.dll http://www.mvps.org/emorcillo/en/code/vb6/sendmail.shtml 4. テストコードを作成します。 Sub MailTest() Call SendToMailRecipient("C:\work\mailtest\test.txt") End Sub 5. テストコードを実行し、既定のメーラにてファイルが添付されることを確認します。
この方式にて、Windows 2000 + Excel 2000 環境で動作すること確認しました。
難点としては、特定のパスでタイプライブラリの参照を行った後、他の端末に
Excel ファイルを持って行った場合に「参照不可(MISSING)」となってしまう点でしょうか。
プログラムにより、動的に参照設定を行う方法はありますが、「参照不可」と、なってしまった場合、手動で再設定するしか無いようようです。
(この問題を回避する方法としては「毎回、Excel ブックオープン時にプログラムで参照設定を行い、クローズするときに、参照設定を解除する」という方法があるようです。)
<参考情報>
■ Office TANAKA - Excel VBA Tips[マクロで参照設定を操作する]
http://officetanaka.net/excel/vba/tips/tips100.htm
コンパイル済みのタイプライブラリファイルは↓以下にアップしておきました。
http://cx20.main.jp/hatena/file/upload/hatena_1364994425_oleliblt.zip
ありがとうございます。試してみます。
コンパイル済みのタイプライブラリファイルは↓以下にアップしておきました。
2013/04/10 23:26:02http://cx20.main.jp/hatena/file/upload/hatena_1364994425_oleliblt.zip
ありがとうございます。試してみます。
2013/04/14 21:12:17