[VC2005] 郵便番号を検索するアプリケーションを作成する方法

◆概要

 日本郵便が無償で公開しているCSV形式の郵便番号データを使って、図1のような郵便番号を検索するアプリケーションを作成する方法を紹介します。


 この郵便番号データに関して、日本郵便は著作権を主張していません。従って、アプリケーションに同梱することができます。たとえば、住所録などにつかうとよいでしょう。


 コードに関してはコメントをつけていますので解説はしませんが、フォームのロードで都道府県名を直接追加しています。これは決まった47都道府県しかありませんし、CSVファイルから検索すると時間がかかるため、この方法を採用しています。

◆詳細

 フォームに下図のようにコントロールを配置してください。statusStripのコントロール名はstatusStrip1です。


図1
フォームの設計


 また、日本郵便の郵便番号のダウンロードページから「全国一括」というデータをダウンロードしてください。配布ファイルはLZH形式で圧縮されています。解凍ソフトを使って解凍(展開)し,KEN_ALL.CSVというファイルを取り出し、Cドライブのルートに置いてください。


リスト1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;            //for StreamReader
using System.Diagnostics;   //for Stopwatch


namespace GetAddress
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        string sken;
        string strCity;
        string strTown;
        string Address;

        private void Form1_Load(object sender, EventArgs e)
        {
            listBox1.Items.Add("北海道");
            listBox1.Items.Add("青森県");
            listBox1.Items.Add("岩手県");
            listBox1.Items.Add("宮城県");
            listBox1.Items.Add("秋田県");
            listBox1.Items.Add("山形県");
            listBox1.Items.Add("福島県");
            listBox1.Items.Add("茨城県");
            listBox1.Items.Add("栃木県");
            listBox1.Items.Add("群馬県");
            listBox1.Items.Add("埼玉県");
            listBox1.Items.Add("千葉県");
            listBox1.Items.Add("東京都");
            listBox1.Items.Add("神奈川県");
            listBox1.Items.Add("新潟県");
            listBox1.Items.Add("富山県");
            listBox1.Items.Add("石川県");
            listBox1.Items.Add("福井県");
            listBox1.Items.Add("山梨県");
            listBox1.Items.Add("長野県");
            listBox1.Items.Add("岐阜県");
            listBox1.Items.Add("静岡県");
            listBox1.Items.Add("愛知県");
            listBox1.Items.Add("三重県");
            listBox1.Items.Add("滋賀県");
            listBox1.Items.Add("京都府");
            listBox1.Items.Add("大阪府");
            listBox1.Items.Add("兵庫県");
            listBox1.Items.Add("奈良県");
            listBox1.Items.Add("和歌山県");
            listBox1.Items.Add("鳥取県");
            listBox1.Items.Add("島根県");
            listBox1.Items.Add("岡山県");
            listBox1.Items.Add("広島県");
            listBox1.Items.Add("岡山県");
            listBox1.Items.Add("山口県");
            listBox1.Items.Add("徳島県");
            listBox1.Items.Add("香川県");
            listBox1.Items.Add("愛媛県");
            listBox1.Items.Add("高知県");
            listBox1.Items.Add("福岡県");
            listBox1.Items.Add("佐賀県");
            listBox1.Items.Add("長崎県");
            listBox1.Items.Add("熊本県");
            listBox1.Items.Add("大分県");
            listBox1.Items.Add("宮崎県");
            listBox1.Items.Add("鹿児島県");
            listBox1.Items.Add("沖縄県");
        }

        private void listBox1_SelectedIndexChanged(
                                object sender, EventArgs e)
        {            
            //選択されている項目のテキストを取得する
            sken = listBox1.Text;
            //ラベルに住所を表示
            lblAddress.Text = sken;
            //lblZipCodeをクリア
            lblZipCode.Text = "";
            string sCity;
            //listBox2とlistBox3をクリア
            listBox2.Items.Clear();
            listBox3.Items.Clear();
            try
            {
                //StreamReaderオブジェクトの作成
                StreamReader sr = new StreamReader("C:\\KEN_ALL.CSV",
                                                Encoding.Default);
                //1行ずつ読み込み
                string dat;
                string tempCity = "";
                while ((dat = sr.ReadLine()) != null)
                {
                    string tmpZip;

                    //カンマで区切られた文字列を取得
                    string[] sbuf = dat.Split(',');
                    //配列の7番目が都道府県名
                    tmpZip = sbuf[6].Trim('"');

                    //選択された都道府県名と比較
                    if (sken == tmpZip)
                    {

                        //Skenと一致する市区町村名をlistBox2に追加
                        //配列の8番目が郵便番号
                        sCity = sbuf[7].Trim('"');
                        if (tempCity != sCity)
                        {
                            listBox2.Items.Add(sbuf[7].Trim('"'));
                        }
                        tempCity = sCity;
                    }
                    Application.DoEvents();
                }

                //ファイルを閉じる
                sr.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }            
        }

        private void listBox2_SelectedIndexChanged(
                                object sender, EventArgs e)
        {
            //選択されている項目のテキストを取得する
            strCity = listBox2.Text;
            Address = sken+strCity;//都道府県名+市区町村名            
            //ラベルに住所を表示
            lblAddress.Text = Address;
            //lblZipCodeをクリア
            lblZipCode.Text = "";
            //listBox3をクリア

            listBox3.Items.Clear();
            try
            {
                //StreamReaderオブジェクトの作成
                StreamReader sr = new StreamReader("C:\\KEN_ALL.CSV",
                                                Encoding.Default);
                //1行ずつ読み込み
                string dat;                
                while ((dat = sr.ReadLine()) != null)
                {
                    string tmpZip;
                    
                    //カンマで区切られた文字列を取得
                    string[] sbuf = dat.Split(',');
                    //配列の都道府県名+市区町村名
                    tmpZip = sbuf[6].Trim('"')+sbuf[7].Trim('"');

                    //選択された都道府県名と比較
                    if (Address == tmpZip)
                    {
                        //リストで選択された都道府県名+市区町村名(Address)と
                        //配列から作成した都道府県名+市区町村名(tmpZip)とが
                        //一致する町域名をlistBox3に追加
                        //配列の9番目が市区町村名
                        strCity = sbuf[8].Trim('"');
                        listBox3.Items.Add(strCity);
                    }
                    Application.DoEvents();
                }

                //ファイルを閉じる
                sr.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

        }

        private void listBox3_SelectedIndexChanged(
                                    object sender, EventArgs e)
        {
            //処理時間を計測
            Stopwatch sw = new Stopwatch();
            //処理時間計測開始
            sw.Start();

            //リストボックスで選択されている住所
            //AddressにはlistBox1とlistBox1をせんたくすることによって
            //都道府県名+市区町村名がすでに格納されているので
            //これにlistBox3で選択された町域名をプラスすれば
            //郵便番号を検索できる
            strTown = listBox3.Text;
            Address = listBox1.Text+listBox2.Text + strTown;
            //ラベルに住所を表示
            lblAddress.Text = Address;
            //lblZipCodeをクリア
            lblZipCode.Text = "";
            try
            {
                //StreamReaderオブジェクトの作成
                StreamReader sr = new StreamReader("C:\\KEN_ALL.CSV",
                                                Encoding.Default);
                //1行ずつ読み込み
                string dat;
                while ((dat = sr.ReadLine()) != null)
                {
                    string tmpZip;

                    //カンマで区切られた文字列を取得
                    string[] sbuf = dat.Split(',');
                    //配列の都道府県名+市区町村名+町域名
                    tmpZip = sbuf[6].Trim('"') 
                           + sbuf[7].Trim('"') 
                           + sbuf[8].Trim('"');
                    
                    //選択された住所と比較
                    if (Address == tmpZip)
                    {
                        //配列の3番目が7桁郵便番号
                        string strZipCode = sbuf[2].Trim('"');
                        //ハイフォン(-)を入れる
                        strZipCode = strZipCode.Substring(0, 3) 
                                   + "-" 
                                   + strZipCode.Substring(3);
                        //ラベルに郵便番号を表示
                        lblZipCode.Text = strZipCode;

                        // 処理時間をTimeSpan構造体で書式付き表示
                        TimeSpan ts = sw.Elapsed;
                        // 出力例:00:00:00.9984668
                        toolStripStatusLabel1.Text = ts.ToString(); 

                    }
                    Application.DoEvents();
                }

                //ファイルを閉じる
                sr.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
        }
    }
}

◆実行結果

 listBox1で都道府県名を選択すると、listBox2に市区町村名が表示されます。続けて、市区町村名を選択するとlistBox3に町域名が表示されます。さらに町域名を選択するとラベルに住所と郵便番号が表示されます。また、ステータスバーにはlistBox3で町域名を選択してから郵便番号が表示されるまでの時間が表示されます(図2)。


 処理時間に関してはデバッグモードでは遅いので、必ずプロジェクトの実行形式ファイルを作成して、それを使ってアプリケーションを実行してください。Pentium4 2.53MHz 1.5GB RAMでは0.8秒程度で表示できます(図では0.28秒)。

図2

実行結果

◆補足

 フォームのロードで都道府県名を直接追加するところは、AddRengeメソッドを使って次のようにすると高速化できます。

            this.listBox1.Items.AddRange(new object[]{
                                                       "北海道",
                                                       "青森県",
                                                       "岩手県",
                                                       "宮城県",
                                                       "秋田県",
                                                       "山形県",
                                                       "福島県",
                                                       "茨城県",
                                                       "栃木県",
                                                       "群馬県",
                                                       "埼玉県",
                                                       "千葉県",
                                                       "東京都",
                                                       "神奈川県",
                                                       "新潟県",
                                                       "富山県",
                                                       "石川県",
                                                       "福井県",
                                                       "山梨県",
                                                       "長野県",
                                                       "岐阜県",
                                                       "静岡県",
                                                       "愛知県",
                                                       "三重県",
                                                       "滋賀県",
                                                       "京都府",
                                                       "大阪府",
                                                       "兵庫県",
                                                       "奈良県",
                                                       "和歌山県",
                                                       "鳥取県",
                                                       "島根県",
                                                       "岡山県",
                                                       "広島県",
                                                       "山口県",
                                                       "徳島県",
                                                       "香川県",
                                                       "愛媛県",
                                                       "高知県",
                                                       "福岡県",
                                                       "佐賀県",
                                                       "長崎県",
                                                       "熊本県",
                                                       "大分県",
                                                       "宮崎県",
                                                       "鹿児島県",
                                                       "沖縄県"});

◆機能アップ

 このアプリケーションでは、都道府県を選択してから市区町村名が表示されるまで若干のタイムラグがあります。これは12万件ある全国一括のデータから検索しているためです。県ごとのデータを使用するとスピードアップすることができます。県ごとのデータも日本郵便の郵便番号データダウンロードページからダウンロードできます。このときは、ListBox1で選択した都道府県によりStreamReaderに読み込むファイルをSwitch文で変更することが必要です。


また、ListBox2やListBox3に追加するときに画面がちらつきます。これを防止するには、リストに追加するところの前後に、 再描画を回避するためにBeginUpdateメソッドとEndUpdateメソッドを追加します。たとえば、listBox1をクリックしたときに呼び出される、listBox1_SelectedIndexChangedイベントハンドラを次のように修正します。

            listBox2.BeginUpdate();
            try
            {
                //省略
            }
            catch(exception e)
            {
                //省略
            }
            listBox2.EndUpdate();

 なお、DownLoadページに自作の郵便番号検索ソフト「郵太」を公開しています。



▼ページトップへ