CodeZine(コードジン)

特集ページ一覧

データ最新化まで含めた総合ソリューション型 住所検索コンポーネント「JPAddress for .NET 1.0」

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2013/01/16 14:00

 郵便番号といえば郵便だけに使うものではありません。たとえメール主体になったとしても物理的なモノを送付するには住所が必要ですし、住所の入力を省力化する標準的な手法として郵便番号からの住所検索の需要は益々増えています。しかし、郵便番号をコード系として捉えた場合に、2つの大きな問題を抱えてしまうことになります。

  1. 住所の統廃合や新設に伴うコードマスタ更新方法の確立
  2. 郵便番号の公式データが正規化されていないために生じるデータ変換

 この2つの問題を一気に解決するのが、今回ご紹介する「JPAddress for .NET 1.0J」です。JPAddressは単純な郵便番号-住所検索コンポーネントではありません。なぜなら郵便番号を使ったときに生じる問題の解決まで視野に入れた総合ソリューション型コンポーネントだからです。

 また、JPAddressは郵便番号データと検索エンジンの組み合わせなので、Windowsフォームアプリ、WPFアプリ、ASP.NETアプリというマルチ環境で利用できます。どのような環境でも同じ開発方法がとれるというのは、開発効率性、同じ郵便番号データを使える点、など優位な点が多々あります。

準備

「JPAddress for .NET 1.0J」インストール

 「SPREAD for WPF 1.0J」もそうでしたが、新しいインストーラのデザインはかなりお気に入りです。

図1 「JPAddress for .NET 1.0J」のインストール
図1 「JPAddress for .NET 1.0J」のインストール

 今回もデフォルト指定のインストール先ではなく「C:\Program Files (x86)\GrapeCity」フォルダに変更しましたが、自動的にサブフォルダとしての製品フォルダが指定できるので非常に便利です。

Windowsフォームアプリで使用する

ツールボックスへの追加

 JPAddressに限ったことではありませんが、コンポーネントをVisual Studioで使うためにはツールボックスへ登録しておくのが便利です。そのためには、1度だけツールボックスへの登録操作を行わなければなりません。1度登録してしまえば次回以降にこの操作は必要ありません。

 ツールボックスへの登録を行うには、まず、Visual Studioを起動してWindowsフォームアプリケーションの新規作成を行います。

 はじめにツールボックスを右クリックして[タブの追加]を選択し、「GrapeCity Win」タブを追加します。次に、「GrapeCity Win」タブの下を右クリックして[アイテムの選択]をクリックしてダイアログを表示します。

図2 ツールボックスへの追加
図2 ツールボックスへの追加

 一覧で「GrapeCity.Win.JPAddress」をチェックして[OK]ボタンをクリックすれば、ツールボックスに追加できます。ここでVisual Studioを再起動しておくとよいでしょう。

ウィンドウデザイナでの作業

 Windowsフォームアプリケーションの新規作成では、Form1というWindowsフォームが1つだけあるプロジェクトが生成されます。「Form1」では味気ないので、「MainForm」と名前を変更してから作業を進めたいと思います。名前の変更は、ソリューションエクスプローラーで「Form1」を右クリックして[名前の変更]メニューから行いましょう。

 次にツールボックスにある「GcJPAddress」アイコンを、デザイナ上のウィンドウにドラッグ&ドロップします。

図3 GcJPAddressを配置
図3 GcJPAddressを配置

 JPAddressはUIのあるコンポーネントではないので、フォームデザイナでは非表示コントロールが配置される領域に配置されます。同時に、JPAddressを開発環境で動作させるのに必要なライセンスファイルがプロジェクトに追加されます。

図4 ライセンスファイル
図4 ライセンスファイル

ロジックコードの記述

 せっかくフォームデザイナに配置したJPAddressですが、今回のサンプルではデザインとロジックを分離したいので、さくっとフォームデザイナ上からアイコンを削除して、ロジック記述用のJPAddressModel.vbを作成して、そこでコードを使ってJPAddressを使ってみたいと思います。

 Visual StudioのソリューションエクスプローラーでModelsフォルダを作成し、Modelsフォルダを右クリックして[追加]‐[クラス]メニューでクラスファイルを追加します。

 クラスファイルには次のようなコードを記述します。

リスト1 JPAddressModel.vb
Imports GrapeCity.Win.JPAddress
Imports System.ComponentModel

Public Class JPAddressModel
    Implements INotifyPropertyChanged

    Private _Address As List(Of AddressInfo)
    Public Property Address As List(Of AddressInfo)
        Get
            Return Me._Address
        End Get
        Set(value As List(Of AddressInfo))
            Me._Address = value
            Call NotifyPropertyChanged("Address")
        End Set
    End Property

    Public Sub GetAddress(postCode As String)
        Me.Address = (New GcJPAddress).GetAddress(postCode, True).ToList
    End Sub

    Public Event PropertyChanged(sender As Object,
                     e As PropertyChangedEventArgs) _
                 Implements INotifyPropertyChanged.PropertyChanged

    Private Sub NotifyPropertyChanged(ByVal propertyName As String)
        RaiseEvent PropertyChanged(Me,
                                   New PropertyChangedEventArgs(propertyName))
    End Sub
End Class

 JPAddressの使い方は非常に簡単で、実際に郵便番号から住所を検索しているのは、GetAddressメソッドの中の次の1行です。

Me.Address = (New GcJPAddress).GetAddress(postCode, True).ToList

 これでAddressプロパティに住所が設定されることになります。郵便番号から住所を検索したとき、複数の結果が返ってくる場合があります。そのためJPAddressでの検索結果もIEnumerable型になっています。ここでは画面との連結を考えてToListを使ってListに変換しています。

 それでは次に、Addressプロパティを画面に連結するためのクラスをつくりましょう。

画面連結用クラスの作成

 ソリューションエクスプローラーでViewModelsフォルダを作成し、フォルダ上で右クリックをして[追加]‐[クラス]メニューを選択して、MainViewModelクラスファイルを作成します。JPAddressModelのPublicなプロパティ、メソッド、イベントをそのままPublicで公開すればいいのでコードは次のようになります。

リスト2 MainViewModel.vb
Imports System.ComponentModel
Imports GrapeCity.Win.JPAddress

Public Class MainViewModel
    Implements INotifyPropertyChanged

    Private WithEvents VmModel As New JPAddressModel

    Public ReadOnly Property Address As List(Of AddressInfo)
        Get
            Return Me.VmModel.Address
        End Get
    End Property

    Public Sub GetAddress(postCode)
        Call Me.VmModel.GetAddress(postCode)
    End Sub

    Public Event PropertyChanged(sender As Object,
                 e As PropertyChangedEventArgs) _
             Implements INotifyPropertyChanged.PropertyChanged

    Private Sub VmModel_PropertyChanged(sender As Object,
                                        e As PropertyChangedEventArgs) _
                                    Handles VmModel.PropertyChanged
        RaiseEvent PropertyChanged(Me,
                                   New PropertyChangedEventArgs(e.PropertyName))
    End Sub
End Class

画面の作成

 今回のサンプルでは、郵便番号欄、検索ボタン、検索結果一覧という画面構成にします。

図5 画面構成
図5 画面構成

 一覧部分はDataGridViewを採用し、Columnsに表示したい要素を事前に設定しておきます。

画面コードの作成

 最後に画面に連結するためのコードをMainForm.vbに記述しましょう。

リスト3 MainForm.vb
Public Class MainForm
    Private ViewModel As New MainViewModel
    Private Me_BindingSource As New BindingSource

    Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles Me.Load
        Me.Result_DataGridView.AutoGenerateColumns = False
        Me.Me_BindingSource.DataSource = ViewModel
        Me.Result_DataGridView.DataSource = Me.Me_BindingSource
        Me.Result_DataGridView.DataMember = "Address"
    End Sub

    Private Sub Search_Button_Click(sender As Object,
                                    e As EventArgs) _
                                Handles Search_Button.Click
        Call Me.ViewModel.GetAddress(Me.PostCode_TextBox.Text)
    End Sub
End Class

 DataGridViewのAutoGenerateColumnsプロパティは、なぜかプロパティウィンドウで設定できませんが、このプロパティをFalseにしておかないと、事前に設定したColumnsが無視されてデータが表示されてしまうので注意してください。なお、AutoGenerateColumnsプロパティは逆転の発想で最初はTrueにしておいて、どのようなフィールド名でデータが格納しているかを一気に調べることに使うという手もあります。

実行

 それでは完成したプロジェクトのプロジェクト構成を確認してみましょう。

図6 プロジェクト構成
図6 プロジェクト構成

 クラスを用途別のフォルダに分けることで、かなりすっきりした構成になっていると思います。ビルドでエラーがでないようであればさっそく実行してみましょう。

 デフォルトで郵便番号を設定していますので、画面が表示されたら[住所検索]ボタンをクリックしてみてください。

図7 画面構成
図7 画面構成

 グレープシティ本社の住所が表示できれば正常に動作しています。

WPFアプリで使用する

ツールボックスへの追加

 Visual Studioのツールボックスは、タブや登録済コントロールの表示をWindowsフォームアプリとWPFアプリで別になるように制御しています。

 そのため、例えばWindowsフォームアプリのプロジェクトでツールボックスに「GrapeCity Win」というタブを作っても、WPFアプリのプロジェクトではそのタブは表示されません。しかしWPF側で「GrapeCity Win」という名前でタブを登録しようとしても、既存チェックにひっかかりタブを作ることができません。

 そこで、ツールボックスを右クリックして[タブの追加]を選択し、「GrapeCity WPF」タブを追加します。そして、「GrapeCity WPF」タブの下を右クリックして[アイテムの選択]を選択してダイアログを表示します。

図8 ツールボックスへの追加
図8 ツールボックスへの追加

 一覧で「GrapeCity.Windows.JPAddress」をチェックして[OK]ボタンをクリックすれば、ツールボックスに追加できます。ここで、Visual Studioを再起動しておくとよいでしょう。

ウィンドウデザイナでの作業

 WPFアプリでもWindowsフォームアプリと同じように、ツールボックスにある「GcJPAddress」アイコンをデザイナ上のウィンドウにドラッグ&ドロップします。

図9 GcJPAddressを配置
図9 GcJPAddressを配置

 しかしこのまま実行すると、ライセンスファイルがないというエラーになってしまいます。

図10 エラー表示
図10 エラー表示

 理由はWindowsフォームアプリのときとは異なり、自動的にライセンスファイルが追加されません。

図11 ライセンスファイルが追加されない
図11 ライセンスファイルが追加されない

 WPFアプリの場合、手動で追加しなければならないので、先ほどWindowsフォームアプリで自動作成されたものをMy Projectフォルダにコピーしてからソリューションエクスプローラーで[プロジェクトに含む]メニューで取り込みましょう。

図12 ライセンスファイルの取り込み
図12 ライセンスファイルの取り込み

 この作業を行っているときにちょっとひらめいたのですが、Windowsフォームアプリで追加されたライセンスファイルには「GrapeCity.Win.JPAddress.GcJPAddress」のライセンスが記述されているので、本来はこれをWPF用にする必要があります。しかし、WPFアプリの場合も、UIとロジックを分離してWPF上ではなく裏側でJPAddressを使うので、ライセンスファイルをそのままに参照するライブラリを「GrapeCity.Win.JPAddress.GcJPAddress」にしてみたらどうなるでしょうか。

図13 参照の追加
図13 参照の追加

 興味が湧いてきたのでこの方法で実装してみたいと思います。もちろんこれはメーカー非推奨なので、うまくいったとしても利用は自己責任の世界になります。

ロジックコードの記述

 Visual StudioのソリューションエクスプローラーでModelsフォルダを作成します。ここで新たにクラスファイルを作成してもいいのですが、Windowsフォームアプリで作ったJPAddressModel.vbを取り込んで使ってみましょう。Modelsフォルダを右クリックして[追加]‐[既存の項目]メニューでクラスファイルを追加します。

画面連結用クラスの作成

 画面連結用クラスについても同様にWindowsフォームアプリで作成したものを取り込みます。取り込んだものにWPF特有のCommandバインディング用のコードを追加します。

リスト4 MainViewModel.vb
Imports System.ComponentModel
Imports GrapeCity.Win.JPAddress

Public Class MainViewModel
    Implements INotifyPropertyChanged
        :
        (略)
        :
    'Public Sub GetAddress(postCode)
    '    Call Me.VmModel.GetAddress(postCode)
    'End Sub

    Private _getAddressCommand As ICommand
    Public ReadOnly Property GetAddress As ICommand
        Get
            If Me._getAddressCommand Is Nothing Then
                Me._getAddressCommand = New GetAddressCommand(Me)
            End If
            Return Me._getAddressCommand
        End Get
    End Property

    Private Class GetAddressCommand
        Implements ICommand

        Private _viewModel As MainViewModel

        Public Sub New(viewModel As MainViewModel)
            _viewModel = viewModel
            AddHandler _viewModel.PropertyChanged, AddressOf ViewModel_Changed
        End Sub

        Public Function CanExecute(parameter As Object) As Boolean _
            Implements ICommand.CanExecute
            Return (String.IsNullOrEmpty(Nothing))
        End Function

        Public Event CanExecuteChanged(sender As Object,
                                       e As EventArgs) _
                                   Implements ICommand.CanExecuteChanged

        Private Sub ViewModel_Changed(sender As Object, e As EventArgs)
            RaiseEvent CanExecuteChanged(sender, e)
        End Sub

        Public Sub Execute(parameter As Object) Implements ICommand.Execute
            Dim postcode As String = parameter.ToString.Replace("-", "")
            Me._viewModel.VmModel.GetAddress(postcode)
        End Sub
    End Class
End Class

画面の作成

 今回のサンプルでは、郵便番号欄、検索ボタン、検索結果一覧という画面構成にします。

図14 画面構成
図14 画面構成
リスト5 MainWindow.xaml
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="MainWindow"
    Title="JPAddress Sample" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="0" Grid.Row="0" 
                 x:Name="PostCode_TextBox" Text="981-3205" Margin="10" />
        <Button Grid.Column="1" Grid.Row="0" 
                Content="住所検索" Margin="10" 
                Command="{Binding GetAddress}"
                CommandParameter="{Binding Text, ElementName=PostCode_TextBox}"/>
        <DataGrid Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="3" 
                  AutoGenerateColumns="False" IsReadOnly="True"
                  ItemsSource="{Binding Address}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Prefecture}" Header="都道府県" />
                <DataGridTextColumn Binding="{Binding City}" Header="市区町村" />
                <DataGridTextColumn Binding="{Binding Town}" Header="町" />
                <DataGridTextColumn Binding="{Binding Area}" Header="町域" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid> 
</Window>

画面コードの作成

 最後に画面に連結するためのコードをMainForm.vbに記述しましょう。

リスト6 MainWindow.xaml.vb
Class MainWindow 
    Private ViewModel As New MainViewModel

    Public Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        Me.DataContext = Me.ViewModel
    End Sub
End Class

 DataGridViewのAutoGenerateColumnsプロパティは、なぜかプロパティウィンドウで設定できませんが、このプロパティをFalseにしておかないと事前に設定したColumnsが無視されてデータが表示されてしまうので注意してください。なお、AutoGenerateColumnsプロパティは逆転の発想で最初はTrueにしておいてどのようなフィールド名でデータが格納しているかを一気に調べることに使うという手もあります。

実行

 デフォルトで郵便番号を設定していますので、画面が表示されたら[住所検索]ボタンをクリックしてみてください。

図15 画面構成
図15 画面構成

 グレープシティ本社の住所が表示できます。

 もちろん本来であればWPF用の方を使うのが正しい組み合わせなので、

  • 参照設定
  • Importsステートメント
  • ライセンスファイル

の「GrapeCity.Win.JPAddress.dll」を「GrapeCity.Windows.JPAddress.dll」に変更してWPF用に切り替えておきましょう。

住所の更新

 ここまで紹介した機能だけでみると、JPAddressは単なる住所検索コンポーネントでしかありません。もちろん郵便番号だけでなく、地区コードからの検索などまだ紹介していない検索機能もありますが、それ以上にJPAddressがその他の住所検索コンポーネントと違うのは辞書更新サービスの存在です。

 JPAddressのUpdateメソッドを使えば、httpを利用してグレープシティ辞書更新サービスサーバーから最新の辞書を取得して辞書データを更新することができるのです。もちろん、Proxyサーバーにも対応しており、IEでインターネットに接続できるように設定してあれば、グレープシティ辞書更新サービスサーバーへの接続もその情報を使って接続可能です。

 それでは、Updateメソッドの使い方をみてみましょう。

リスト7 辞書更新機能付きのJPAddressModel.vbの例
Imports GrapeCity.Win.JPAddress
Imports System.ComponentModel

Public Class JPAddressModel
    Implements INotifyPropertyChanged
    Private Jpa As New GcJPAddress

    Public Sub New()
        Call Update()
    End Sub

    Private Sub Update()
        Jpa.Proxy = System.Net.WebRequest.GetSystemWebProxy()
        Jpa.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials
        ' 「vwvyz」には認証IDを設定します。 
        Jpa.Update("vwvyz ")
    End Sub
    :
    (略)
    :
End Class

  このように非常に簡単なコードで実装が可能です。Updateメソッドはダウンロードと辞書更新が完了するまで処理待ち状態になるため、更新中のアプリの挙動についても考慮する必要はありません。

 このサービスは年間契約の有償サービスのため利用するには別途申し込みが必要です。ただし、トライアル版では利用できませんが、製品購入後であれば認証IDにプロダクトキーを指定することで90日間のテスト利用ができます。

まとめ

 今回のサンプルでは自動的に更新を行っていましたが、承認プロセスをアプリに取り入れ、確認用端末を更新してテスト結果がOKであれば、例えばDBなどに承認OKのフラグを立てて各端末やWebサーバーでUpdateメソッドをアプリの内部で自動的に呼び出すという流れも作ることができます。

 住所検索部分であれば、郵便局の郵便番号データダウンロードからデータをダウンロードして使いやすいように加工をしてアプリに組み込めば自作できます。しかし、定期的に更新される郵便番号データダウンロードを毎回使いやすいように加工して配布するという手間を自社要員で実施する必要はないと思います。リソースの最適化という視点やデータ生成結果の品質ということを考えても、複数の取引先にデータ配信しているところにアウトソーシングするのがよいのではないでしょうか。

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 初音玲(ハツネアキラ)

     国内SIerのSEでパッケージ製品開発を主に行っており、最近は、空間認識や音声認識などを応用した製品を手掛けています。  個人的には、仕事の内容をさらに拡張したHoloLensなどのMRを中心に活動しています。  Microsoft MVP for Windows Development...

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5