Excel VBA | ハイブリッド運用の完全版コード(DB+API併用)

VBA
スポンサーリンク

以下は、KEN_ALLベースのローカルDB検索を優先し、未ヒット時にAPI検索+キャッシュ追記、さらにAPI失敗時のリトライ・ログ出力まで含めた「実務向けの完全版VBA」です。A列に郵便番号、B~D列に住所(都道府県・市区町村・町域)を出力する想定です。


構成概要

  • Local DB(ZipDBシート)検索:高速・大量処理向け
  • API検索(zipcloud):未ヒットや最新性補完用
  • キャッシュ追記:API取得結果をZipDBに追加して次回以降はDB参照
  • エラーハンドリング:APIのリトライ(最大3回)、ログ出力

前提

  • ブック内にシート「ZipDB」を用意(列A: 郵便番号、B: 都道府県、C: 市区町村、D: 町域)
  • 住所出力先は「アクティブシート」のB~D列
  • JSON解析に VBA-JSON(JsonConverter.bas)を導入済み
  • 参照設定不要版(CreateObject利用)

コード

Option Explicit

' ========= エントリーポイント =========
Sub ProcessZipHybrid()
    Dim lastRow As Long, i As Long
    Dim zip As String, addrPref As String, addrCity As String, addrTown As String
    Dim found As Boolean
    
    ' データ行(A列)を自動検出
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
    If lastRow < 2 Then
        MsgBox "処理対象の郵便番号がありません。", vbInformation
        Exit Sub
    End If
    
    ' 画面更新停止(高速化)
    Application.ScreenUpdating = False
    
    For i = 2 To lastRow
        zip = NormalizeZip(Cells(i, 1).Value)
        If zip = "" Then
            ' 空行スキップ
            GoTo CONTINUE_NEXT
        End If
        
        ' 1) ローカルDB検索
        found = SearchLocalDB(zip, addrPref, addrCity, addrTown)
        
        If Not found Then
            ' 2) API検索(リトライ&ログ付き)
            found = SearchAPIWithRetry(zip, addrPref, addrCity, addrTown)
            
            ' 3) API成功ならキャッシュ追記
            If found Then
                AppendToLocalDB zip, addrPref, addrCity, addrTown
            End If
        End If
        
        ' 4) 出力
        If found Then
            Cells(i, 2).Value = addrPref
            Cells(i, 3).Value = addrCity
            Cells(i, 4).Value = addrTown
        Else
            Cells(i, 2).Value = "取得失敗"
            Cells(i, 3).Value = ""
            Cells(i, 4).Value = ""
        End If
        
CONTINUE_NEXT:
    Next i
    
    Application.ScreenUpdating = True
    MsgBox "処理が完了しました。", vbInformation
End Sub

' ========= 郵便番号整形 =========
Function NormalizeZip(ByVal raw As String) As String
    Dim z As String
    z = Trim(CStr(raw))
    If z = "" Then
        NormalizeZip = ""
        Exit Function
    End If
    z = Replace(z, "-", "")
    z = Replace(z, "ー", "") ' 長音の誤入力対策例
    ' 7桁のみ許容(先頭ゼロも保持)
    If Len(z) = 7 And IsNumeric(z) Then
        NormalizeZip = z
    Else
        NormalizeZip = ""
    End If
End Function

' ========= ローカルDB検索(ZipDBシート) =========
Function SearchLocalDB(zip As String, _
                       ByRef pref As String, _
                       ByRef city As String, _
                       ByRef town As String) As Boolean
    Dim ws As Worksheet
    Dim rng As Range, foundCell As Range
    
    On Error GoTo ERR_HANDLER
    
    Set ws = ThisWorkbook.Worksheets("ZipDB")
    ' 郵便番号は列Aで検索
    Set rng = ws.Range("A:A")
    Set foundCell = rng.Find(What:=zip, LookIn:=xlValues, LookAt:=xlWhole)
    
    If Not foundCell Is Nothing Then
        pref = ws.Cells(foundCell.Row, 2).Value
        city = ws.Cells(foundCell.Row, 3).Value
        town = ws.Cells(foundCell.Row, 4).Value
        SearchLocalDB = True
    Else
        SearchLocalDB = False
    End If
    
    Exit Function
    
ERR_HANDLER:
    WriteLog "ローカルDB検索エラー: zip=" & zip & " desc=" & Err.Description
    SearchLocalDB = False
End Function

' ========= API検索(zipcloud)+リトライ&ログ =========
Function SearchAPIWithRetry(zip As String, _
                            ByRef pref As String, _
                            ByRef city As String, _
                            ByRef town As String) As Boolean
    Dim url As String, i As Integer
    Dim http As Object
    Dim responseText As String
    Dim JSON As Object, result As Object
    
    On Error GoTo ERR_HANDLER
    
    url = "https://zipcloud.ibsnet.co.jp/api/search?zipcode=" & zip
    
    For i = 1 To 3
        Set http = CreateObject("MSXML2.XMLHTTP")
        http.Open "GET", url, False
        http.Send
        
        If http.Status = 200 Then
            responseText = http.responseText
            Set JSON = JsonConverter.ParseJson(responseText)
            
            If JSON("status") = 200 Then
                ' resultsは配列(0ベースだがVBA-JSONは1ベースのCollection)
                If JSON("results").Count >= 1 Then
                    Set result = JSON("results")(1)
                    pref = NzString(result("address1"))
                    city = NzString(result("address2"))
                    town = NzString(result("address3"))
                    
                    SearchAPIWithRetry = (pref <> "" And city <> "")
                    Exit Function
                End If
            Else
                ' API側の業務エラー(例:不正郵便番号)
                WriteLog "API業務エラー: zip=" & zip & " code=" & JSON("status") & " msg=" & NzString(JSON("message"))
            End If
        Else
            ' 通信失敗(HTTPステータス控え)
            WriteLog "API通信失敗: zip=" & zip & " http=" & http.Status
        End If
        
        ' ウェイト(2秒)
        Application.Wait (Now + TimeValue("0:00:02"))
    Next i
    
    SearchAPIWithRetry = False
    Exit Function
    
ERR_HANDLER:
    WriteLog "API例外: zip=" & zip & " desc=" & Err.Description
    SearchAPIWithRetry = False
End Function

' ========= ローカルDBへキャッシュ追記 =========
Sub AppendToLocalDB(zip As String, pref As String, city As String, town As String)
    Dim ws As Worksheet
    Dim nextRow As Long
    
    On Error GoTo ERR_HANDLER
    
    Set ws = ThisWorkbook.Worksheets("ZipDB")
    nextRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1
    
    ws.Cells(nextRow, 1).Value = zip
    ws.Cells(nextRow, 2).Value = pref
    ws.Cells(nextRow, 3).Value = city
    ws.Cells(nextRow, 4).Value = town
    
    Exit Sub
    
ERR_HANDLER:
    WriteLog "キャッシュ追記エラー: zip=" & zip & " desc=" & Err.Description
End Sub

' ========= 文字列Null対策(Nothing/Null→空文字) =========
Function NzString(v) As String
    On Error Resume Next
    If IsNull(v) Then
        NzString = ""
    Else
        NzString = CStr(v)
    End If
End Function

' ========= ログ出力(テキスト追記) =========
Sub WriteLog(msg As String)
    Dim fso As Object, ts As Object
    Dim logPath As String
    
    logPath = ThisWorkbook.Path & "\ZipHybridLog.txt"
    
    On Error Resume Next
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.OpenTextFile(logPath, 8, True) ' 8=Append
    ts.WriteLine Format(Now, "yyyy/mm/dd hh:nn:ss") & " " & msg
    ts.Close
End Sub
VB

運用のコツ

  • ZipDBはKENA LL.CSVを定期更新しておくとAPIヒット率が下がり、全体の速度が上がります。
  • API結果はキャッシュされるため、同じ郵便番号を再処理すると通信せずにDBから即返却されます。
  • ログファイル(ZipHybridLog.txt)で失敗要因を追跡し、ネットワークやAPI制限の確認に役立ててください。
VBA
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました