0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

駅すぱあと VBA SDKを使って、経費精算用に経路探索を行うデモを作りました

Posted at

本記事はヴァル研究所の支援として作成された記事です

今回は、以前作成した「駅すぱあと API」をExcel VBAから利用して、経費精算用に経路探索を行う #経路検索 - Qiitaの内容を、VBA SDKを使って書き直してみました。

普段Excelで経費精算の作業を行なっている場合、駅すぱあと VBA SDKを使うことで簡単に経路情報や運賃を算出することができます。

EkispertAPIMania/VBA-SDK: Excel VBAなどで動作する駅すぱあと VBA SDKです(Windowsのみ)の実践的な使い方として、参考にしてください。

コードについて

今回のデモコードはVBA-SDK/demo at main · EkispertAPIMania/VBA-SDKの中に Route.xlsm として保存してあります。実装時の参考にしてください。

利用している機能

このデモでは、SDKの以下の機能を使っています。

image1.png

セットアップ

Releases · EkispertAPIMania/VBA-SDKにて公開しているExcelファイルをダウンロードするか、リポジトリをクローンした上でvbaidiot/ariawaseを使ってコンパイルします。

git clone https://github.com/vbaidiot/ariawase.git
cd ariawase
mkdir src

この src の中にSDKのリポジトリをクローンします。名前は Ekispert.xlsm です。

git clone https://github.com/EkispertAPIMania/VBA-SDK.git Ekispert.xlsm

そして、ariawase ディレクトリに移動して、以下のコマンドを実行します。

cd ..
cscript vbac.wsf combine

そうすると bin ディレクトリの中に Ekispert.xlsm が生成されます。このファイルの中に、SDKのコードが入っています。

Excelファイルの作成とSDKのインストール

新しいExcelファイルをマクロの有効なファイルとして作成します(.xlsmファイルになります)。開発メニューを開いて、Visual Basicを選択します。

image5.png

一緒に、先ほど作成した(またはダウンロードした)SDKのExcelファイルを開きます。標準モジュール、クラスモジュールをすべてコピー(ドラッグ&ドロップ)してください。

image3.png

これで、ExcelファイルにSDKが組み込まれました。

シートの準備

今回は以下の2つのシートを利用します。

  • 経路入力
  • データ

経路入力シート

経路入力 シートには、以下のように入力欄を作成します。

A B
出発駅
経由駅1
経由駅2
到着駅

データシート

データ シートには、以下のように入力欄を作成します。

出発駅名 出発駅コード 経由1駅名 経由1コード 経由2駅名 経由2コード 到着駅名 到着駅コード

APIキーの設定

新しい標準モジュールを作成して、以下のコードを貼り付けます。 YOUR_API_KEY の部分を、取得した駅すぱあと APIのAPIキーに置き換えてください。

Public Const ApiKey As String = "YOUR_API_KEY"

入力された値を使って、駅名を検索してドロップダウンを作成する

駅名を入力して、確定されたら 駅簡易情報 検索を実行します。処理は Private Sub Worksheet_Change(ByVal Target As Range) にて実行します。

Private Sub Worksheet_Change(ByVal Target As Range)
  ' ここに処理を書く
End Sub

処理対象がない場合は、何もせず処理を終了します。

If Intersect(Target, Range("B1:B4")) Is Nothing Then
    Exit Sub
End If

SDKの初期化

まず、SDKを初期化します。

Dim Client As Ekispert
Set Client = New Ekispert
Client.ApiKey = ApiKey

過去の入力補完データを削除

データ シートにある過去の入力データをクリアします。

Dim i As Integer
Dim RowIndex As Integer
RowIndex = Target.Row
Dim RowName As String
RowName = Left(Cells(1, (RowIndex * 2) - 1).Address(False, False), 1)
Dim sheet As Worksheet
Set sheet = Worksheets("データ") ' シート
Dim LastRow As Integer
LastRow = sheet.Cells(sheet.Rows.Count, 1).End(xlUp).Row
If LastRow = 1 Then ' 何もデータがない場合
    LastRow = 2
End If
If Not sheet.Range(RowName & "2:" & RowName & LastRow).Find(Target.value) Is Nothing Then
    ' 選択された場合
    Exit Sub
End If
' 範囲をクリア
If Target.value = "" Then
    ' 入力選択解除
    Target.Validation.Delete
    sheet.Range(sheet.Cells(2, (RowIndex * 2) - 1), sheet.Cells(LastRow, (RowIndex * 2))).Clear
    Exit Sub
End If
sheet.Range(sheet.Cells(2, (RowIndex * 2) - 1), sheet.Cells(LastRow, (RowIndex * 2))).Clear

駅名検索を実行する

駅簡易情報 検索を実行します。これは StationLightQuery を使います。

Dim Query As StationLightQuery
Set Query = Client.StationLightQuery()
Dim Result As ResultSet
Query.Name = Target.value ' 入力された駅名
Query.NameMatchType = Partial ' 部分一致
Result = Query.Find
' エラーチェック
If Result.Success = False Then
    MsgBox Result.Error.Message
    Exit Sub
End If

結果を描画する

検索がうまくいったら、それを データ シートに書き込みます。検索結果の構造は駅簡易情報のレスポンスを参照してください。プロパティ名が複数形になっているものは、配列になります。

' 結果を描画する
For i = 0 To UBound(Result.Points)
    sheet.Cells(i + 2, (RowIndex * 2) - 1).value = Result.Points(i).Station.Name ' 駅名
    sheet.Cells(i + 2, (RowIndex * 2)).value = Result.Points(i).Station.Code     ' 駅コード
Next i

結果範囲をリストにする

データ シートに出力した内容に合わせて、経路入力 シートのセルにリストを作成します。

' その範囲をリスト入力にする
With Target.Validation
    .Add Type:=xlValidateList, AlertStyle:=xlValidAlertInformation, _
        Operator:=xlBetween, Formula1:="=データ!$" & RowName & "$2:$" & RowName & "$" & UBound(Result.Points) + 1
    .IgnoreBlank = True
    .InCellDropdown = True
    .InputTitle = ""
    .ErrorTitle = ""
    .InputMessage = ""
    .ErrorMessage = ""
    .IMEMode = xlIMEModeNoControl
    .ShowInput = True
    .ShowError = True
End With

これで、駅名を入力すると、その駅名に一致する駅コードがリストに表示されるようになります。

経路探索を実行する

経路入力 シートに入力された値を使って、経路探索を実行します。まず、関数の名前だけ作っておきます。

Sub SearchRoute()
  ' ここに処理を書く
End Sub

そして、 経路入力 シートにボタンを配置し、そのボタンをクリックしたときに SearchRoute が実行されるようにします。

image4.png

SDKの初期化

先ほどと同じく、SDKを初期化します。

Dim Client As Ekispert
Set Client = New Ekispert
Client.ApiKey = ApiKey

駅コードの取得

指定されている駅名から、 データ シートにある駅コードを取得します。

Dim InputSheet As Worksheet
Set InputSheet = Worksheets("経路入力") ' 経路入力
Dim Codes() As String
Dim i As Integer
Dim Code As String
Dim Name As String
Dim BoardingName As String
Dim DestinationName As String

For i = 1 To 4
    Name = InputSheet.Cells(i, 2).value
    ' コードを探す
    If Name = "" Then
        ' エラーチェック
        If i = 1 Or i = 4 Then
            MsgBox ("出発駅、到着駅は必須です")
            Exit Sub
        End If
        GoTo Continue
    End If
    
    If i = 1 Then
        BoardingName = Name
    End If
    
    If i = 4 Then
        DestinationName = Name
    End If
    
    If (Not Codes) = -1 Then
        ReDim Codes(0) As String
    Else
        ReDim Preserve Codes(UBound(Codes) + 1) As String
    End If
    Code = GetCode((i * 2) - 1, Name)
    If Code = "" Then
        MsgBox (i & "行目の名前が見つかりません(" & Name & ")")
        Exit Sub
    End If
    Codes(UBound(Codes)) = Code
Continue: ' 駅名が入っていない場合
Next i

GetCode は、 データ シートにある駅名から駅コードを取得する関数です。

Function GetCode(ColumnIndex As Integer, Name As String) As String
    Dim DataSheet As Worksheet
    Set DataSheet = Worksheets("データ")
    Dim LastRow As Integer
    LastRow = DataSheet.Cells(DataSheet.Rows.Count, 1).End(xlUp).Row
    If LastRow = 1 Then
        LastRow = 2
    End If
    
    Dim Range As Range
    Set Range = DataSheet.Range(DataSheet.Cells(2, ColumnIndex), DataSheet.Cells(LastRow, ColumnIndex)).Find(Name, LookAt:=xlWhole)
    If Range Is Nothing Then
        GetCode = ""
    Else
        GetCode = DataSheet.Cells(Range.Row, Range.Column + 1).value
    End If
End Function

経路探索を実行する

経路探索を実行します。これは CourseExtremeQuery を使います。

Dim Course As Course
Dim Point As Point

Dim Query As CourseExtremeQuery
Set Query = Client.CourseExtremeQuery
Query.ViaList(0) = Join(Codes, ":")
Query.SearchType = Plain
Dim Result As ResultSet
Result = Query.Find
If Result.Success = False Then
    MsgBox Result.Error.Message
    Exit Sub
End If

結果を出力する

探索結果を出力します。新しいシートを作成し、その中に結果を出力します。

' 新しいシートを作成する
Dim ResultSheet As Worksheet
Set ResultSheet = Worksheets.Add
ResultSheet.Name = BoardingName & "から" & DestinationName

結果を出力します。結果の構造は経路探索のレスポンスを参照してください。

Dim RowIndex As Long
Dim ColumnIndex As Long
ColumnIndex = 1
For i = 0 To UBound(Result.Courses)
    Course = Result.Courses(i)
    
    RowIndex = 1
    ResultSheet.Cells(RowIndex, ColumnIndex).value = "ルート" & i + 1
    RowIndex = RowIndex + 1
    ResultSheet.Cells(RowIndex, ColumnIndex).value = "合計" & GetPrice(Course.Prices) & "円"
    RowIndex = RowIndex + 2
    ResultSheet.Cells(RowIndex, ColumnIndex).value = "乗車駅"
    ResultSheet.Cells(RowIndex, ColumnIndex + 1).value = "路線名"
    ResultSheet.Cells(RowIndex, ColumnIndex + 2).value = "降車駅"
    RowIndex = RowIndex + 1
    
    Dim j As Long
    For j = 0 To UBound(Course.Route.Lines)
        ResultSheet.Cells(RowIndex, ColumnIndex).value = Course.Route.Points(j).Station.Name
        ResultSheet.Cells(RowIndex, ColumnIndex + 1).value = Course.Route.Lines(j).Name
        ResultSheet.Cells(RowIndex, ColumnIndex + 2).value = Course.Route.Points(j + 1).Station.Name
        RowIndex = RowIndex + 1
    Next j
    ColumnIndex = ColumnIndex + 4
Next i

GetPrice は、経路探索の結果から、通常料金 FareSummary を取得する関数です。

Function GetPrice(Prices() As Price) As Long
    Dim Price As Price
    Dim i As Long
    For i = 0 To UBound(Prices)
        Price = Prices(i)
        If Price.Kind = "FareSummary" Then
            GetPrice = Val(Price.Oneway)
            Exit Function
        End If
    Next i
    GetPrice = 0
End Function

image2.png

まとめ

今回は駅簡易情報と経路探索を使って、VBA SDKから駅名情報の検索と、経路探索を行う方法を紹介しました。SDKを使うことで、簡単に駅すぱあとAPIを利用することができます。ぜひ、実際に使ってみてください。

駅すぱあと API Documents 駅データ・経路検索のWebAPI

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?