情シス仕事の備忘録

自身の備忘録を兼ねて、情シス仕事で役に立ちそうな情報を掲載しています

Excel VBA ⇔ Cloud データ取得・加工(e-Stat API)

Excel VBAでe-Stat APIを使用して、クラウド上にある政府統計データの取得・加工を行う例を紹介します。e-Statは日本の統計を閲覧できる政府統計ポータルサイトで、開発者向けにAPIによるデータ取得機能も提供しています。

・操作環境:Windows 11
・使用プラン:Microsoft 365 Business Premium(※)
※Excelが使用できれば、上記プランでなくても問題ありません

なお、この記事では、VBAの使用許可や開発メニュー表示といった初期設定や、VBAエディタの使い方の説明は割愛いたします。

 

 

e-Stat APIの使用を開始する

e-Stat APIを使用するには、ユーザー登録が必要です。未登録の場合は、画面右上の[新規登録]から登録します。
※e-Statホーム画面:政府統計の総合窓口

 

ログイン後、右上の[マイページ]を選択します。

 

[API機能(アプリケーションID発行)>API機能]を選択し、以下の通り入力し、[発行]を選択します。
・名称:(適宜入力)
・URL:(APIを使用したWebアプリを公開する場合のURL指定します。公開しない場合は、http://test.localhost/とします)
※アプリケーションIDは3個まで発行できます

 

[appId]欄にアプリケーションIDが表示されたら、値を控えておきます。
※取得したアプリケーションIDは複数の統計で使用できます。アプリ公開目的でなければ、一個発行すればそれを流用できます
左上の[トップページ]を選択して、次の工程に進みます。

 

統計データのAPIのURLを取得する

右側の[開発者向け]を選択します。

 

[API機能]を選択します。

 

[機能概要>提供データ]を選択します。

 

提供データのリンクを選択します。

 

[データ種別]が[データベース]となっている統計がAPI機能が提供されているものです。
この例では、統計名のキーワード[サービス]で絞り込み、[サービス産業動向調査]を選択します。

 

画面下部の[統計データ]のリンクを選択します。

 

[データベース]の概要リンクを選択します。

 

この例では、[2013年1月から>月次調査>年次]を選択します。

 

この例では、[表番号]の[00205]の統計データを使用することとし、その行の[API]を選択します。

 

[ファイル形式]は[CSV形式]を選択します。[URLをコピー]を選択してこの値を控えておきます。

 

PostmanでAPIの動作確認を行う(推奨)

いきなりVBAで実装するのではなく、先にAPI開発ツール「Postman」でデータ取得時のデータのやりとりを確認することをおススメします。Postmanの入手方法は以前の記事を参考にしてください。

 

この例におけるPostmanの設定および動作確認の方法を紹介します。

まずは環境を新規作成します。コレクションに直接設定値をベタ打ちもできますが、同じ接続先に色々なリクエストを試したい場合、ここで設定を変数化しておくと便利です。今回のアプリケーションIDのようなセキュアな値はタイプをシークレットにします。
・app_id:工程1で控えたアプリケーションID
※{{xxx}}はxxxという変数として扱われます

 

コレクションにデータ取得用のリクエストを新規作成します。
・メソッド:GET
・URL:工程2で控えたAPIのURL
・パラメーター>appId>値:{{app_id}}
※{{app_id}}は環境の画面で定義した変数app_idです。
設定できたら、[送信]を選択します。

 

送信結果を確認すると、工程2の最後に指定した通り、CSV形式となっています。
この例では28行目までが基本情報、29行目がタイトル行(“tab_code”から始まる行)、30行目以降がデータ行です。なお、統計データにより行数は若干異なります。
このままExcelにコピー&ペーストしても統計データとして使用しにくい状態なので、次の工程のExcel VBAにてAPIからのデータ取得と加工を行います。

 

Excelファイルを用意する

VBAを実行するExcelファイルを用意します(拡張子はxlsm)。
・Menuシート:[データ取得]ボタン(ActiveXコントロール)を押すと、e-Stat APIに接続し(工程2で控えたAPIのURLを使用)、データ取得と加工を行います。

 

・Searchシート:Menuシートの[データ取得]ボタンを押すと、e-Statのデータを取得・加工してシートに出力します。
※統計データとして使用しやすいよう、value列の値は数値(データがない場合はブランク)に変換しています

 

・paramシート:工程1で控えたアプリケーションIDの値を定義しておきます。

 

・VBAプロジェクト:Mainシート上にソースを実装します。画面に表示されているのは、データ取得ボタンクリック時にデータ取得・加工のプロシージャを呼び出すソースと、クリアボタンクリック時にAPIのURLをクリアするソースです。データ取得・加工のプロシージャの中身は次の工程で紹介します。

 

[ツール>参照設定]を選択し、[Microsoft Scripting Runtime]のチェックをオンにします。
これが未実施の場合、API呼び出し時のHTTPリクエストオブジェクトの作成でエラーが発生します。

 

Excel VBAでe-Statのデータを取得・加工する

データ取得・加工のメインとなるプロシージャのソースです。ポイント事項は以下の通りです。

  • API実行時のアプリケーションIDはparamシートから取得し、MainシートのURL(TextBox1)に結合している
  • 検索結果はString型の変数apiResponseで取得し、エラーがあれば詳細情報を表示(エラー発生時は2行目にエラーコード、3行目にエラー内容が格納されるため、これを表示)している
Private Sub getReseachData()

  '変数宣言
  Dim wb As Workbook
  Dim ws As Worksheet
  Dim ws_param As Worksheet
  Dim apiMethod As String
  Dim apiUrl As String
  Dim apiHeaders As New Dictionary
  Dim apiResponse As String
  Dim data_row As Variant 'apiResponseをlf改行で分割格納した変数

  'ワークシートの設定 、データ初期化
  Set wb = ThisWorkbook
  Set ws = wb.Worksheets("Search")
  ws.Rows("1:" & ws.Range("A" & ws.Rows.Count).End(xlUp).Row).Delete
  Set ws_param = wb.Worksheets("param")

  'データ取得
  apiMethod = "GET"
  apiUrl = Left(TextBox1.Text, InStr(TextBox1.Text, "?")) & "appId=" & _
    ws_param.Cells(1, 2).Value & _
    Mid(TextBox1.Value, InStr(TextBox1.Text, "?") + Len("appID=") + 1)
  apiHeaders.RemoveAll
  apiHeaders.Add "Content-type", "application/json"
  apiResponse = callRestApi(apiMethod, apiUrl, apiHeaders) 'API実行
  data_row = Split(apiResponse, vbLf)

  'データ取得でエラーが発生した場合、ダイアログにエラー番号と内容を表示して終了
  If UBound(data_row) < 4 Then
    MsgBox "データ取得でエラーが発生しました。:" & _
    data_row(1) & ":" & data_row(2), vbOKOnly, "データ取得エラー"
    Exit Sub
  End If

  '取得したデータを加工し、searchシートに書き出す
  Call writeSearchData(ws, data_row)

End Sub

 

データ取得・加工のメインプロシージャから呼び出しているサブ関数・プロシージャのソースです(API実行、データ加工・書き出し)。ポイント事項は以下の通りです。

  • この例ではAPIで取得するデータの形式をCSVとしたため、API実行関数の戻り値はJson型ではなくString型としている
  • データ加工・書き出し関数では、"tab_code"で始まる行をタイトル行とし、以降の行をデータ行とし、Searchシートへの書き出し対象としている
  • データ加工・書き出し関数では、各項目データの囲み文字""を除き、value列のデータ行以外は文字列として頭に'をつけている
  • データ加工・書き出し関数では、value列のデータ行は数値として扱い、統計データがない場合(元データは"-"となっている)はブランクに置き換えている
'*****************************************
' callRestApi:API実行(CSVデータ取得)
'*****************************************
Private Function callRestApi(method As String, url As String, headers As Dictionary) As String

  Dim http As Object
  Dim cnt As Long

  'httpリクエストオブジェクトの設定
  Set http = CreateObject("msxml2.xmlhttp") '参照設定でMicrosoft Scripting Runtimeが必要
  http.Open method, url, False

  'httpリクエストヘッダーの設定
  For cnt = 0 To headers.Count - 1
  http.setRequestHeader headers.keys(cnt), headers.Items(cnt)
  Next cnt

  'リクエスト送信
  http.send

  'レスポンスの文字列をそのまま返す
  callRestApi = http.responseText

End Function

'*****************************************
' writeSearchData:取得データのsearchシートへの書き出し
'*****************************************
Private Sub writeSearchData(ws As Worksheet, data_row As Variant)

  Dim data_col As Variant 'data_rowを,で分割格納した変数
  Dim cnt_row As Long
  Dim cnt_col As Long
  Dim start_row As Long 'タイトル行の行番号(行が"tab_code"で始まる)
  Dim value_col As Long 'value列の列番号(タイトルが"value")

  For cnt_row = 0 To UBound(data_row)
    If data_row(cnt_row) Like """tab_code""" & "*" Then
      start_row = cnt_row '"tab_code"で始まる行はタイトル行であり、行番号を格納
    End If
    If cnt_row >= start_row Then 'タイトル行以降を書き出し対象とする
      data_col = Split(data_row(cnt_row), ",")
      For cnt_col = 0 To UBound(data_col)
        If cnt_row = start_row And data_col(cnt_col) = """value""" Then
          value_col = cnt_col 'タイトル行かつvalue列の場合、列番号を格納
        End If
        If cnt_row > start_row And cnt_col = value_col Then 'データ行かつvalue列の場合
          If data_col(cnt_col) <> """-""" Then '値が"-"でない場合、"を除き出力
            ws.Cells(cnt_row - start_row + 1, cnt_col + 1).Value = _
             Replace(data_col(cnt_col), """", "")
          End If
        Else 'データ行でないかvalue列でない場合、先頭に'を付加し、"を除き出力
          ws.Cells(cnt_row - start_row + 1, cnt_col + 1).Value = _
            "'" & Replace(data_col(cnt_col), """", "")
        End If
      Next cnt_col
    End If
  Next cnt_row

End Sub

 

おわりに

この記事で紹介した通り、e-StatのAPIを使ったデータ取得は比較的簡単に実施できます。e-Statは情報量が非常に多く、APIの扱いよりも、欲しいデータに辿りつくまでの方が苦労しそうだと思いました。
情シス担当の仕事としてe-Statのデータを使う機会は少ないかもしれませんが、参考になれば幸いです。