SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

VBAでファイルをダウンロードする

Windows APIを使ってWebからファイルをダウンロードする

配列のメモリアドレスを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です。

動的配列を使ったサンプル1
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
WinInet関数の返り値について
 「vbinet.exe」に含まれる関数宣言のテンプレートでは、InternetReadFile()やInternetCloseHandle()の返り値は整数型(Integer)になっていますが、長整数型(Long)に書き換えた方がよいでしょう。BOOL型の大きさは4バイトだからです。
プロキシを使うには?
 InternetOpen()関数の第2引数lAccessTypeを変更するとプロキシサーバを使うことができます。
 INTERNET_OPEN_TYPE_PRECONFIGを指定すると、Windows(IE)の設定を利用してアクセスします。
 INTERNET_OPEN_TYPE_PROXYを指定すると、第3引数sProxyNameで任意のプロキシを文字列で指定できます。

次のページ
まとめてファイルへ書き込む

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

さなみ(サナミ)

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2149 2008/02/26 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー