お仕事の都合で、Excel for Mac 2011(正確には、Visual Basic for Applications)から Web API を呼び出す必要が生じたため、調べたことを備忘録として残しておきます。
MacScript 関数を利用する方法
一番お手軽なのは、VBA の MacScript 関数を使って、AppleScript 経由で curl
コマンドを叩く方法です。
Function getHttp(url As String, query As String) As String
Dim command As String
command = "do shell script ""curl --get -d '" & query & "' " & url & """"
getHttp = MacScript(command)
End Function
上記のコードを Visual Basic Editor1 を開いて、標準モージュール2にコピー&ペーストしてください。
使用例として、OpenWeatherMap から天気情報を取得する手順を紹介します。3
- セル A1 に、天気を調べたい都市名を入力します。例えば、
Fukuoka,jp
と入力します。 - セル A2 に、Web API の URL
http://api.openweathermap.org/data/2.1/forecast/city
を入力します。 - セル A3 に、クエリーパラメーターを組み立てる式
="q=" & A1
を入力します。 - セル A4 に、
=getHttp(A2, A3)
と入力します。
しばらくすると、セル A4 に福岡の天気情報が JSON 形式の文字列で出力されます。
お手軽ではあるんですが、少し反応が鈍いというか、なんとなく遅い感じがしました。わたしのお仕事的には、これで十分だったのですが、もっと良い手はないかと調べてみると、Stack Overflow でベストな解決策がありました。
C ライブラリの popen 関数を利用する方法
Stack Overflow での質問 How do I issue an HTTP GET from Excel VBA for Mac 2011 の Franco Rondini さんの回答がそれです。
使い方は、先ほど紹介したとおりです(先ほどの使用例は、ここで紹介されていた例を使用しました)。ただし、セル A4 に投入する式を =HTTPGet(A2, A3)
に変更してください。
Option Explicit
' execShell() function courtesy of Robert Knight via StackOverflow
' http://stackoverflow.com/questions/6136798/vba-shell-function-in-office-2011-for-mac
Private Declare Function popen Lib "libc.dylib" (ByVal command As String, ByVal mode As String) As Long
Private Declare Function pclose Lib "libc.dylib" (ByVal file As Long) As Long
Private Declare Function fread Lib "libc.dylib" (ByVal outStr As String, ByVal size As Long, ByVal items As Long, ByVal stream As Long) As Long
Private Declare Function feof Lib "libc.dylib" (ByVal file As Long) As Long
Function execShell(command As String, Optional ByRef exitCode As Long) As String
Dim file As Long
file = popen(command, "r")
If file = 0 Then
Exit Function
End If
While feof(file) = 0
Dim chunk As String
Dim read As Long
chunk = Space(50)
read = fread(chunk, 1, Len(chunk) - 1, file)
If read > 0 Then
chunk = Left$(chunk, read)
execShell = execShell & chunk
End If
Wend
exitCode = pclose(file)
End Function
Function HTTPGet(sUrl As String, sQuery As String) As String
Dim sCmd As String
Dim sResult As String
Dim lExitCode As Long
sCmd = "curl --get -d """ & sQuery & """" & " " & sUrl
sResult = execShell(sCmd, lExitCode)
' ToDo check lExitCode
HTTPGet = sResult
End Function
余談
これで、どれくらい早くなったかというと、気持ち早くなったという感じでしょうか。
あと、HTTPGet という関数名とかコードの記法にいまひとつ馴染めなかったので、以下のように書き換えて試しました。また、HTTP POST の方も postHttp という関数を追加して試したりしました。
Function getHttp(url As String, query As String) As String
Dim command As String
Dim result As String
Dim exitCode As Long
command = "curl --get -d """ & query & """" & " " & url
result = execShell(command, exitCode)
' ToDo check exitCode
getHttp = result
End Function
Function postHttp(url As String, query As String) As String
Dim command As String
Dim result As String
Dim exitCode As Long
command = "curl -d """ & query & """" & " " & url
result = execShell(command, exitCode)
' ToDo check exitCode
postHttp = result
End Function
P.S.
個人的には、最初に紹介したお手軽な方で、利用するかなーといった感じです。ベストな解決策がありましたと紹介しておいてアレなんですが . . . (^^;A
-
Excel の [ツール] メニューから [マクロ] -> [Visual Basic Editor] を選択すると、Visual Basic Editor の画面に切り替わります。 ↩
-
標準モジュールがなければ、[挿入] メニューから [標準モジュール] を選択すると、標準モジュール(Module1)が追加されます。 ↩
-
via Stack Overflow での質問 How do I issue an HTTP GET from Excel VBA for Mac 2011 の Franco Rondini さんの回答 ↩