配列のメモリアドレスをAPI関数に渡す
VBAでバイナリデータを扱う場合、バイト型(Byte)配列を使うのが最も簡単な方法です。
バイト型(Byte)配列のメモリアドレスをAPI関数に渡す場合、ポイントになるのは配列の先頭要素を参照渡しすると配列の全体のメモリアドレスが関数に渡されるということです。例えば、「Dim a(1 To 100) As Byte」と宣言された長さ100の配列aがある場合、a(1)を参照渡しすると配列a全体のメモリアドレスを関数は受け取ります。
DeclareステートメントでAPI関数を宣言するときは、配列を渡したい引数をバイト型(Byte)の参照渡しにしておきます。
動的配列を使ってデータをダウンロードする
では、具体的なサンプルを紹介したいと思います。CodeZineのバナー画像(http://codezine.jp/img/banner/forlink/lbanner_l.gif)をダウロードしファイルへ保存するExcel VBAです。
Option Explicit '標準モジュールに以下のDeclare ステートメントを追加 'InternetOpen()用 Public Const INTERNET_OPEN_TYPE_PRECONFIG = 0 Public Const INTERNET_OPEN_TYPE_DIRECT = 1 Public Const INTERNET_OPEN_TYPE_PROXY = 3 'InternetOpenUrl()用 Public Const INTERNET_FLAG_RELOAD = &H80000000 Public Declare Function InternetOpen Lib "wininet.dll" _ Alias "InternetOpenA" (ByVal sAgent As String, _ ByVal lAccessType As Long, _ ByVal sProxyName As String, _ ByVal sProxyBypass As String, _ ByVal lFlags As Long) As Long Public Declare Function InternetOpenUrl Lib "wininet.dll" _ Alias "InternetOpenUrlA" (ByVal hInternetSession As Long, _ ByVal sUrl As String, _ ByVal sHeaders As String, _ ByVal lHeadersLength As Long, _ ByVal lFlags As Long, _ ByVal lContext As Long) As Long '第2引数をバイト型 (Byte)の参照渡しにしておく Public Declare Function InternetReadFile Lib "wininet.dll" (_ ByVal hFile As Long, _ sBuffer As Byte, _ ByVal lNumBytesToRead As Long, _ lNumberOfBytesRead As Long) As Long Public Declare Function InternetCloseHandle Lib "wininet.dll" (_ ByVal hInet As Long) As Long Sub バナーのダウンロード1() 'バナー画像のURL Const URL = "http://codezine.jp/img/banner/forlink/lbanner_l.gif" Dim s As String Dim FileName As String Dim FileNumber As Integer Dim hOpen As Long Dim hConnect As Long Dim buf() As Byte '動的配列 Dim dwSize As Long '保存する.gifファイルのパスを取得 'マクロ含むExcelファイルと同じフォルダに保存する s = ThisWorkbook.FullName FileName = Left(s, InStrRev(s, "\", , vbBinaryCompare)) & _ "banner1.gif" '保存用にファイルを開く FileNumber = FreeFile Open FileName For Binary Access Write As #FileNumber 'WinInetを初期化 hOpen = InternetOpen("Excel VBA", INTERNET_OPEN_TYPE_DIRECT, _ vbNullString, vbNullString, 0) 'URLを開く hConnect = InternetOpenUrl(hOpen, URL, vbNullString, 0, _ INTERNET_FLAG_RELOAD, 0) Do '1024バイトずつデータを取得しファイルへ書き込む '動的配列の大きさを定義 ReDim buf(1 To 1024) '配列の先頭要素を渡す InternetReadFile hConnect, buf(1), 1024, dwSize 'データ取得サイズが0になったら終了 If dwSize = 0 Then Exit Do Else '動的配列の大きさを再定義 'Preserve を指定してデータが消えないようにする ReDim Preserve buf(1 To dwSize) 'ファイルへ書き込み Put #FileNumber, , buf End If '配列を消去 Erase buf Loop 'ハンドルを開放 InternetCloseHandle hConnect InternetCloseHandle hOpen 'ファイルを閉じる Close #FileNumber End Sub
INTERNET_OPEN_TYPE_PRECONFIGを指定すると、Windows(IE)の設定を利用してアクセスします。
INTERNET_OPEN_TYPE_PROXYを指定すると、第3引数sProxyNameで任意のプロキシを文字列で指定できます。
