郵便番号⇔住所

郵便番号を入力するれば、住所が表示される。住所を入力すれば、郵便番号が表示される。マクロの作成に挑戦します。
まず、郵便番号のデータベースをダウンロードしましょう。ここをクリックしてください。
お好きな都道府県をダウンロードしてください。
圧縮ファイルですので、解凍してください。解凍ソフトが必要な場合は、ここからダウンロードしてください。
ダウンロードしたファイルはcsv形式になっていますので、いったんエクセルで開いてxls形式で保存してください。ここでは、兵庫県のファイルを使用します。




UserFormの作成
次のようなUserFormを作成してください。




@TextBox1に郵便番号を入力すると、住所が表示されるコードの記述

郵便番号のデータを見ると、C列に「郵便番号」・H,I列に「住所」が入っています。マクロの記録で郵便番号による検索を記録すると次のようになります。
Sub Macro1()
Range("C1").Select
Cells.Find(What:="6580051", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False).Activate
End Sub

Findメソッドが出てきました。これについて、調べてみます。


Find メソッド

指定されたセル範囲の中で特定の情報を検索し、情報が見つかった最初のセル (Range オブジェクト) を返します。検索の条件にあてはまるセルが見つからなかった場合は、Nothing を返します。選択状態やアクティブ セルに影響はありません。

構文

expression.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte)

expression   必ず指定します。対象となる Range オブジェクトを表すオブジェクト式を指定します。

What   必ず指定します。バリアント型 (Variant) の値を使用します。対象セル範囲内で検索するデータです。文字列など、セル内のデータに該当する値を指定します。

After   省略可能です。バリアント型 (Variant) の値を使用します。指定したセルの次から検索が開始されます。この引数で指定するセルは、コードからではなく、通常の画面上で検索を行う場合のアクティブ セルに該当します。対象セル範囲の中の、単一セルでなければなりません。検索は指定したセルの次から始まるので、指定したセル自体は、検索が範囲全体を一度検索して戻ってくるまで検索されません。この引数を省略すると、対象セル範囲の左上端のセルが検索の開始点となります。

LookIn   省略可能です。バリアント型 (Variant) の値を使用します。使用できる定数は、XlFindLookIn クラスの xlFormulas(数式)xlValues(値(文字列、数値))xlComments(コメント) のいずれかです。

LookAt   省略可能です。バリアント型 (Variant) の値を使用します。使用できる定数は、XlLookAt クラスの xlPart(検索文字列を含む) または xlWhole(完全一致のセル) です。

SearchOrder   省略可能です。バリアント型 (Variant) の値を使用します。使用できる定数は、XlSearchOrder クラスの xlByColumns(列方向) または xlByRows(行方向) です。

SearchDirection   省略可能です。バリアント型 (Variant) の値を使用します。使用できる定数は、XlSearchDirection クラスの xlNext(後方検索) または xlPrevious(前方検) です。既定の定数は xlNext です。

MatchCase   省略可能です。バリアント型 (Variant) の値を使用します。大文字と小文字を区別するには、True を指定します。既定値は False です。

MatchByte   省略可能です。バリアント型 (Variant) の値を使用します。この引数は、2 バイト (全角) 文字の言語サポートが選択またはインストールされているときだけ使用できます。半角と全角を区別するには、True を指定します。区別しないようにするには、False を指定します。

解説

引数 LookInLookAtSearchOrder、および MatchByte の設定は、このメソッドが使われるたびに保存されます。次にこのメソッドを使うときに、これらの引数の指定を省略すると、保存された設定が使われます。これらの引数の設定を変更すると、[検索] ダイアログ ボックスに表示される設定が変わります。また、[検索] ダイアログ ボックスで設定を変更すると、保存されている設定が変わります。このような設定の変更によって生じる問題を避けるためには、Find メソッドを使うたびに、これらの引数を明示的に指定します。

検索は指定された範囲の最後に達すると、範囲の最初に戻って検索を繰り返します。同じ範囲を繰り返して検索しないようにするには、最初に検索内容が見つかったセルの位置を保存しておき、次のセルが見つかるたびに、そのセルの位置と保存しておいたセルの位置を比較するようにします。

複雑なパターンの検索を行うには Like 演算子と For Each...Next ステートメントを使います。たとえば、次の例はセル範囲 A1:C5 でフォント名の先頭が "Cour" であるセルを検索し、見つかったセルのフォントを "MS Pゴシック" に変更します。

For Each c In [A1:C5]
    If c.Font.Name Like "Cour*" Then
        c.Font.Name = "MS Pゴシック"
    End If
Next



@のサンプルコード
CommandButton1をダブルクリックして、その中にコードを記述しよう。サンプルコードは下記のとおりです。変数の宣言は、最後にします。

Private Sub CommandButton1_Click()
a = ActiveSheet.UsedRange.Rows.Count
b = TextBox1.Value
On Error GoTo Shori1
Range("C1", "C" & a).Find(What:=b, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:= _
False, MatchByte:=False).Select
c = Selection.Cells.Row
Label3.Caption = Range("H" & c).Text & _
Range("I" & c).Text
Label9.Caption = b
TextBox1.Value = ""
TextBox1.SetFocus
Exit Sub


Shori1:
Select Case Err.Number
Case 91
MsgBox "該当する住所はありません。"
Case Else
End Select
TextBox1.Value = ""
TextBox1.SetFocus
End Sub

アクティブシートで使用している行数をaに代入します。
TextBox1の値をbに代入します。
エラーの場合、処理1にいきます。
C列1行からC列a行の範囲でbといっしょの数値を検索し、
そのセルを選択します。


選択したセルの行数をcに代入します。
Label3にH列c行の文字とI列c行の文字を表示します。

Label9にbの値を表示します。
TextBox1の数値をクリアします。
TextBox1にカーソルを持っていきます。
プロシージャの終了

エラー時の処理1
エラーには番号があります。番号によって処理をします。
エラー番号91の場合は、
MsgBoxで「該当する住所はありません」を表示します。
その他の場合は、何も表示しません。
Select の終了
TextBox1の数値をクリアします。
TextBox1にカーソルを持っていきます。
Subの終了

On Error ステートメントで注意しなければならないのは、エラーが発生しなくても「Shori1」が実行されるということです。つまり、Case91以外のエラーナンバーが発生した場合には、MsgBoxはこのプログラムでは表示されないということになります。したがって、赤字も部分を記入しておくと処理がより正確になります。




Select Case ステートメント

条件式の値に従って、複数のステートメント ブロックのいずれかを実行させるフロー制御ステートメントです。

構文

Select Case testexpression
[Case expressionlist-n
[statements-n]] ...
[Case Else
[elsestatements]]

End Select

Select Case ステートメントの構文は、次の指定項目から構成されます。

指定項目 内容
testexpression 必ず指定します。任意の数式または文字列式を指定します。
expressionlist-n Case 節がある場合は、必ず指定します。次の形式で指定します。また、複数指定するときは、カンマ (,) で区切ります。

expression

expression To expression

Is comparisonoperator expression

引数 expression には数式または文字列を、引数 comparisonoperator には比較演算子を指定します。キーワード To は、値の範囲を指定するキーワードです。キーワード To を使って値の範囲を指定するときは、小さい方の値を先 (左側) に指定し、大きい方の値を後(右側)に指定します。キーワード Is は、値の範囲を意味するキーワードで、Is 演算子と Like 演算子以外の比較演算子と共に使われます。キーワード Is は指定しなくても自動的に設定されます。

statements-n 省略可能です。引数 testexpression が引数 expressionlist-n のいずれかと一致するとき、一致した引数 statements-n のステートメントが実行されます。
elsestatements 省略可能です。引数 testexpressionCase 節のいずれとも一致しないとき、引数 elsestatements のステートメントが実行されます。

解説

引数 testexpressionCase 節の引数 expressionlist のいずれかの式に一致すると、Case 節の次のステートメントがその次の Case 節まで実行されます。Case 節が最後の節の場合は、End Select まで実行されます。ブロックの実行が終わると、制御は End Select の次のステートメントに移ります。引数 testexpression が複数の Case 節に一致するときは、最初に一致した Case 節に続くステートメントだけが実行されます。

Case Else 節を使用して引数 testexpression がどの Case 節の引数 expressionlist にも一致しなかったときに実行する引数 elsestatements を指定します。Case Else ステートメントは必ずしも必要ではありませんが、予測できない引数 testexpression の値を処理するために、Select Case ブロックに Case Else ステートメントを記述することをお勧めします。どの Case 節の引数 expressionlist も引数 testexpression と一致しない場合に Case Else ステートメントが存在しないと、End Select の次のステートメントまで実行が継続します。

Case 節には複数の式や範囲を指定できます。たとえば、次の行は有効なステートメントです。

Case 1 To 4, 7 To 9, 11, 13, Is > MaxNumber

メモ 比較演算子 IsSelect Case ステートメントで使われるキーワード Is は、同じものではありません。

また、文字列の範囲や複数の文字列式を指定することもできます。次に示す Case 節では、"everything" と、アルファベット順に並んだ "nuts" から "soup" の間にある文字列、TestItem の現在の値のいずれかに等しい文字列が一致します。

Case "everything", "nuts" To "soup", TestItem

Select Case ステートメントはネスト (入れ子) 構造にすることができます。このとき、各 Select Case ステートメントには、それぞれ対応する End Select ステートメントが必要です。





Count プロパティ

コレクションに含まれる要素の数を返します。値の取得のみ可能です。長整数型 (Long) の値を使用します。





ATextBox2、3に住所を入力すると、郵便番号が表示されるコードの記述

サンプルコード
CommandButton2をダブルクリックして、その中にコードを記述しよう。サンプルコードは下記のとおりです。変数の宣言は、最後にします。
Private Sub CommandButton2_Click()
Label3 = ""
Label9 = ""
a = ActiveSheet.UsedRange.Rows.Count
z = TextBox2.Text
y = TextBox3.Text
On Error GoTo Shori2
Range("H1", "H" & a).Find(What:=z, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:= _
False, MatchByte:=False).Select
w = Selection.Cells.Row
i = w
Do While Range("H" & i).Text = z
i = i + 1
Loop

Range("I" & w, "I" & i - 1).Find(What:=y, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:= _
False, MatchByte:=False).Select
u = Selection.Cells.Row
Label9 .Caption= Range("C" & u).Value
Label3 .Caption= z & y
TextBox2.Text = ""
TextBox3.Text = ""
TextBox2.SetFocus
Exit sub

Shori2:
Select Case Err.Number
Case 91
If w <> Empty Then
Label9.Caption = Range("C" & w)
Label3.Caption= z & y
MsgBox Range("C" & w).Value & "は、掲載がない地区のため
  住所を再確認してください。"
Else
MsgBox "住所1および住所2の入力誤りです。"
End If
Case Else
End Select
TextBox2.Text = ""
TextBox3.Text = ""
TextBox2.SetFocus
End Sub

Label3を空白にします。
Label9を空白にします。
アクティブシートで使用している行数をaに代入します。
TextBox2の文字をzに代入します。
TextBox3の文字をyに代入します。
エラーの場合、処理2にいきます。
H列1行からH列a行の範囲でzといっしょの文字を検索し、
そのセルを選択します。



選択したセルの行数をwに代入します。
iにwを代入します。
H列i行の文字がzの間ループします。
(市区の中で町名を探すため同じ市区の行数を求めます。

I列w列からI列(i-1)行の範囲でyといっしょの文字を検索し、
そのセルを選択します。


選択したセルの行数をuに代入します。
C列u行の数字をLabel9に表示します。
zとyの文字をLabel3に表示します。
TextBox2の文字をクリアします。
TextBox3の文字をクリアします。
TextBox2にカーソルを持っていきます。
プロシージャの終了

エラー時の処理2
エラーには番号があります。番号によって処理をします。
エラー番号91の場合で、
wがEmptyでない場合は、
C列u行の数字をLabel9に表示します。
zとyの文字をLabel3に表示します。
MsgBoxで「C列w行の数字は、掲載がない地区のため
  住所を再確認してください。」を表示します。
他の場合は、
MsgBoxで「住所1および住所2の入力誤りです。」を表示します。
If文の終了
他のケースの場合は、何もしません。
Selectの終了
TextBox2の文字をクリアします。
TextBox3の文字をクリアします。
TextBox2にカーソルを持っていきます。
Subの終了


終了プログラムの作成

Private Sub CommandButton3_Click()
End
End Sub


変数の宣言

GeneralのDeclarationsで宣言します。
Dimの宣言は下記のようにお願いします。図は間違っています。

Dim a As Integer, b As Integer
Dim c As Integer, d As Integer
Dim i As Integer, j As Integer
Dim k As Integer, u As Integer
Dim w As Integer
Dim sheetcnt As Integer, Chiku As Integer
Dim z As String, y As String


これで、郵便⇔郵便番号のマクロができました。

次回は、これをさらに発展させていきたいと思います。




リストボックスを利用して、都道府県を選択し検索できるマクロの作成

どのようなものを作成するか。
〇都道府県をダウンロードしシートに貼り付けると、リストボックスにその都道府県が表示され、検索したい都道府県を選択することができるものを作成します。


リストボックスに各シート名を代入するサンプルコード
Private Sub UserForm_Initialize()
sheetcnt = Application.Worksheets.Count
For j = 1 To sheetcnt
sheetname = Worksheets(j).Name
With UserForm1.ListBox1
.AddItem sheetname
.Selected(0) = True
End With
Next j
Worksheets(1).Activate
End Sub
UserFormが表示される前に実行
 シート数をsheetcntに代入します。
 次のことをシート数だけ繰り返します。
シート名をsheetnameに代入します。

リストにsheetnameを代入していきます。
最初のシートを選択状態にします。


ワークシートの1枚目をアクティブにします。




Initializeとは
UserFormが表示される前に「Initialize」内に書かれたプロシージャが実行されされます。したがって、UserFormのあるマクロの起動時の一番初めに実行したい場合に利用します。




Worksheets プロパティ
Application オブジェクトでは、作業中のブックのすべてのワークシートを表す Sheets コレクションを返します。値の取得のみ可能です。

Workbook オブジェクトでは、指定されたブックのすべてのワークシートを表す Sheets コレクションを返します。値の取得のみ可能です。

コレクションのメンバを取得する方法は、たとえば、コレクションからオブジェクトを返す Item プロパティを使います。次の使用例は、Workbook オブジェクトのブック 1 を表す変数 firstBook を設定します。

Set firstBook = Workbooks.Item(1)

Item プロパティおよび、Item メソッドは、多くのコレクションの既定のプロパティとメソッドとなっているため、既定の Item というキーワードを省略し、ステートメントをより正確に記述することができます。

Set firstBook = Workbooks(1)

名前付きオブジェクト

ほとんどの Item プロパティでは整数値を指定できますが、オブジェクト名で指定する方が便利な場合があります。このような場合は、プロパティを使用する前にオブジェクトに名前を付ける必要があります。通常、名前を付けるときはオブジェクトの Name プロパティを設定します。次の使用例は、作業中のブックに名前付きのワークシートを作成して、そのワークシートを名前で参照します。

ActiveWorkbook.Worksheets.Add.Name = "新規"
With Worksheets("新規")
    .Range("a5:a10").Formula = "=rand()"
End With

定義済みのインデックス値

いくつかのコレクションには定義済みのインデックス値が含まれていて、この値を使用してオブジェクトを取得できます。定義済みインデックス値は、それぞれ定数で表すことができます。たとえば、Borders コレクションに対して XlBordersIndex クラスの定数を指定した Item プロパティを使用して、単一の境界線を取得できます。

次の使用例は、シート 1 のセル範囲 A1:G1 までの下の境界線を二重線に設定します。

Worksheets("Sheet1").Range("a1:g1"). _
    Borders.Item(xlEdgeBottom).LineStyle = xlDouble




AddItem メソッド

単一行のテキストの取得と表示が設定されているリスト ボックスまたはコンボ ボックスの場合は、リストに項目を追加します。複数行のテキストの取得と表示が設定されているリスト ボックスまたはコンボ ボックスの場合は、一覧に行を追加します。sheetnameには、AddItemメソッドで組み込んだ時に、自動的に「0」から始まる番号が付けられます。「1」から始まるのではないので、気をつけてください。

構文

Variant = object.AddItem [ item [, varIndex]]

AddItem メソッドの構文は、次の指定項目から構成されます。

指定項目 内容
object 必ず指定します。オブジェクトの名前を指定します。
item 省略可能です。追加する項目または行を指定します。1 番目の項目または行には 0 を、2 番目の項目または行には 1 を指定します。以下同様に続きます。
varIndex 省略可能です。新しい項目または行を挿入するオブジェクトの位置を示す整数値を指定します。





Selected プロパティ

リスト ボックス (ListBox) コントロールにおける各項目の選択状況を設定します。値の取得も可能です。

構文

object.Selected( index ) [= Boolean]

Selected プロパティの構文は、次の指定項目から構成されます。

指定項目 内容
object 必ず指定します。オブジェクトの名前を指定します。
index 必ず指定します。0 以上で、リスト内の項目数から 1 を引いた数以下の範囲の整数値を指定します。
Boolean 省略可能です。項目が選択されているかどうかを示します。

設定値

引数 Boolean の設定値は次のとおりです。

内容
True 項目は選択されています。
False 項目は選択されていません。

解説

Selected プロパティは、複数選択を許可しているときに使用します。このプロパティを使うと、複数の列があるリスト ボックスにおいてどの行が選択されているかを調べることができます。また、行の選択/選択解除をコードを通じて操作するときにもこのプロパティを使用します。

このプロパティの既定値は、リスト ボックス (ListBox) コントロールの現在の選択状況に依存します。

単一項目を選択するリスト ボックスの場合、Value プロパティまたは ListIndex プロパティを使うことをお勧めします。ListIndex プロパティは、選択されている項目のインデックスを返しますが、複数選択が許可されている場合は、実際に選択されているかどうかにかかわらず、フォーカスがある行のインデックスを返します。

リスト ボックス (ListBox) コントロールの MultiSelect プロパティに fmMultiSelectSingle が設定されている場合、Selected プロパティに真 (True) を設定できる行は、1 つに限られます。

有効なインデックス以外の値を指定してもエラー メッセージは表示されませんが、そのプロパティの指定値は無視されます。





ListIndex プロパティ

リスト ボックス (ListBox) コントロールまたはコンボ ボックス (ComboBox) コントロールで、現在選択されている項目を返します。

構文

object.ListIndex [= Variant]

ListIndex プロパティの構文は、次の指定項目から構成されます。

指定項目 内容
object 必ず指定します。オブジェクトの名前を指定します。
Variant 省略可能です。コントロールで、現在選択されている項目を示します。

解説

ListIndex プロパティは、リストの中で現在選択されている行のインデックスを示します。ListIndex プロパティの値の範囲は、-1 以上で、リスト内の全行数から 1 を引いた数 (ListCount プロパティ -1) 以下です。どの行も選択されていない場合、ListIndex プロパティは -1 を返します。リスト ボックス (ListBox) コントロールまたはコンボ ボックス (ComboBox) コントロールでいずれかの行を選択すると、そのインデックス番号が ListIndex プロパティに設定されます。たとえば、リストの 1 行目を選択すると、ListIndex プロパティには 0 が設定され、2 行目を選択すると 1 が設定されます。




リストボックス1で選択したシートをアクティブにするサンプルコード

Private Sub ListBox1_Click()
For k = 0 To sheetcnt
Chiku = UserForm1.ListBox1.ListIndex
Select Case Chiku
Case k
shtname = Worksheets(k + 1).Name
End Select
Next k
Worksheets(shtname).Activate
UserForm1.TextBox1.SetFocus
End Sub
ListBox1をクリックしたときのイベント
0からsheetcntまで繰り返します。
ListBox1のインデックス番号をChikuに代入します。
インデックス番号とワークシート番号は1番違いですので、
これを利用して、シート名を取得します。



取得したシート名のシートをアクティブにします。
UserForm1のTextBox1をSetFocusします。


これで、リストボックスで選択した都道府県の「郵便番号⇔住所」を利用できます。
最後に、これまでのすべてのサンプルソースを記述します。





Dim a As Integer, b As Integer, c As Integer, d As Integer
Dim i As Integer, j As Integer, k As Integer, u As Integer , w As Integer
Dim sheetcnt As Integer, Chiku As Integer
Dim z As String, y As String


Private Sub CommandButton1_Click()
a = ActiveSheet.UsedRange.Rows.Count
b = TextBox1.Value
On Error GoTo Shori1
Range("C1", "C" & a).Find(What:=b, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:= _
False, MatchByte:=False).Select
c = Selection.Cells.Row
Label3.Caption = Range("H" & c).Text & _
Range("I" & c).Text
Label9.Caption = b
TextBox1.Value = ""
TextBox1.SetFocus
Exit Sub
Shori1:
Select Case Err.Number
Case 91
MsgBox "該当する住所はありません。"
Case Else
End Select
TextBox1.Value = ""
TextBox1.SetFocus
End Sub


Private Sub CommandButton2_Click()
Label3 = ""
Label9 = ""
a = ActiveSheet.UsedRange.Rows.Count
z = TextBox2.Text
y = TextBox3.Text
On Error GoTo Shori2
Range("H1", "H" & a).Find(What:=z, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:= _
False, MatchByte:=False).Select
w = Selection.Cells.Row
i = w
Do While Range("H" & i).Text = z
i = i + 1
Loop

Range("I" & w, "I" & i - 1).Find(What:=y, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:= _
False, MatchByte:=False).Select
u = Selection.Cells.Row
Label9.Caption = Range("c" & u).Value
Label3.Caption = z & y
TextBox2.Text = ""
TextBox3.Text = ""
TextBox2.SetFocus
Exit Sub

Shori2:
Select Case Err.Number
Case 91
If w <> Empty Then
Label9.Caption = Range("C" & w)
Label3.Caption = z & y
MsgBox Range("C" & w).Value & "は、掲載がない地区のため住所を再確認してください。"
Else
MsgBox "住所1および住所2の入力誤りです。"
End If
Case Else
End Select
TextBox2.Text = ""
TextBox3.Text = ""
TextBox2.SetFocus
End Sub


Private Sub CommandButton3_Click()
'Application.Visible = True
End

End Sub


Private Sub UserForm_Initialize()
sheetcnt = Application.Worksheets.Count
For j = 1 To sheetcnt
sheetname = Worksheets(j).Name
With UserForm1.ListBox1
.AddItem sheetname
.Selected(0) = True
End With
Next j
Worksheets(1).Activate
'Application.Visible = False
End Sub


Private Sub ListBox1_Click()
For k = 0 To sheetcnt
Chiku = UserForm1.ListBox1.ListIndex
Select Case Chiku
Case k
shtname = Worksheets(k + 1).Name
End Select
Next k
Worksheets(shtname).Activate
UserForm1.TextBox1.SetFocus
End Sub