2021/01/11

年賀状リスト等の宛名検索と追記




1.背景

年賀状などのために住所録リストを作られている方は多いと思います。私もExcelでリストを作成し宛名印刷用のデータにしています。
リストの項目は各人で工夫されていると思いますが、特に年賀状などは「相手から賀状が来たか否か」も重要な情報であり、図1-1の「賀状着」のような列を作る場合があります。そして「Ctrl+F」または「ホーム」タブ→「編集」グループ→「検索と選択」の「選択」から「検索と置換」のダイアログボックスを表示させ、目的の人を探し、その行の「賀状着」欄にマークを付けます。
検索でデータを探し、マークをつける
図1-1

但し検索する文字列が、氏名・住所・備考などで重複(図1-1のように、姓の「千葉」と住所の「千葉」)していることもあるので、氏名だけに検索対象範囲を絞りたければ、氏名の列をアクティブにしてから検索をすると目的のデータがすぐに見つかります。しかし検索後「賀状着」列のセルにマークを入力しようとセルクリックした瞬間、せっかくの「氏名列アクティブが解除」されてしまい、検索を続ける場合は再度「氏名列をアクティブ」にする手間が発生してしまいます。

今回は、文字列検索をしている最中でも「初期の検索範囲を解除せずに異なる列のセルに追記が可能」なダイアログを紹介します。

2.システム概要

今回のシステムは複数の住所録に対応できるように、図2-1のようにExcelアドインに登録して使用することを意識して作っています。もちろん、住所録のファイル内にマクロを作ってもOKです。

Excel上のボタンから起動するには、「7.アドインとしてExcelにマクロを登録」のところでも紹介するように、事前に今回のシステム(一番下のサンプルファイル)をアドインファイル(拡張子 .xlam)として各PC内に保存します。そして住所録ファイルを開いた上で、図2-1のようにメニューからボタン①をクリックすることで、今回作ったダイアログが起動②します。
なおサンプルファイルでは、アドイン手続きをせずに試行が出来るように、住所録シートの最上部に「ダイアログ表示」ボタンを設置してあります。そのボタンをクリックすることで、ダイアログが表示されるようにしてあります。

またサンプルファイル、及び説明用の図中の住所録は、疑似的に作成(https://hogehoge.tk/personal/を使用)された住所録に対し多少修正を加えたものを使用しています。
そのデータの疑似性を確認するため、いくつかの住所について実在有無を確認してみました。その結果、町名までは実在のものでしたが、丁目・番地以下は架空の番号のようです。但し氏名は実在する可能性はありますので、データの取り扱いにはご注意下さい。

住所録リスト上でダイアログを起動する
図2-1

表示した検索ダイアログ内で図2-2のように、検索ボックス③に検索文字列を入力し、マークを記入する列④をスピンボタンで選択し、記入するマークの文字列を設定⑤します。
検索文字列、追記文字列を決める
図2-2

そして、検索対象範囲(例えば氏名の列)を指定⑥し、ダイアログ上の「次を検索⑦」ボタンを何回かクリックすることで目的のデータ行を見つけ、そこで「文字列挿入⑧」ボタンをクリックすると、指定した列のセルに⑤で指定した文字列が追記(元の文字列の後ろに追加)されます。
目的の行のところで、マークをつける
図2-3

なお、⑥の検索対象を指定しない(単一セルを選択した状態)場合には、シート内の全てのセルが検索対象になります。
また⑦の「次を検索」ボタンはデフォルトボタンにしていますので、ダイアログにフォーカスがあれば「キーボードのリターンキーで次を検索」することができます。この機能により「検索にはリターンキー」「文字列挿入⑧にはマウスクリック」と、2種類の入力手段を使って効率の良い作業が可能となります。
また検索途中で、記入列や記入文字列を変更することは可能です。

なお③の検索文字列が空の時には、空のセルを探しますし、⑤の追加文字列が空の時には空の文字列を追加(=値は変化せず)します。Excelの組込ダイアログと同様に、今回のシステムでは「検索・追加文字列が空か否かのチェックはしない」仕様にしています。

終了するには「閉じる」ボタンをクリックするか、キーボードの「ESCキー」を押すとダイアログが閉じます(Hide)。Hideしただけですので、再度起動ボタン①をクリックすると、前回の検索文字列などを残したままダイアログが起動します。

3.プログラムの流れ

プログラムの主要な流れは図3-1のように、ダイアログ上の「次を検索」ボタンと「文字列挿入」ボタンの2つによって動作します。
プログラムの流れ
図3-1

まず「次を検索」ボタンをクリック①すると、Findメソッド②が実行されます。Findメソッドには複数の引数がありますが、今回はダイアログ上の「検索文字列④」のみを変数として「Findメソッドの引数」としてまとめ③、Findメソッドに渡します。
Findメソッドは、検索が成功した時にはそのセル範囲、失敗(見つからなかった)したときにはNothingを返します。ですのでその戻り値で判別⑤し、成功した時はそのセル位置をActive⑥に、失敗した時にはその旨をメッセージ表示⑦します。

一方検索が成功した後「文字列挿入」ボタンをクリック⑧すると、まず「文字列を書き込むセル位置」を算出します。行位置は、検索されたActiveセル⑥の位置から取得⑩し、列位置はダイアログ上の「記入する列⑫」から取得⑪します。この⑩⑪の行位置・列位置から書き込む位置を特定し、また書き込む文字列はダイアログ上の「記入する文字列⑬」から取得し、特定したセル位置に書込み⑨ます。

4.フォームの作成

今回のフォームは、図4-1のように作成しました。
フォームの作成
図4-1

フォーム上には検索文字列を入力するTextBox1と追加文字列を入力するTextBox2を配置します。また記入する列を設定するSpinButton1とその設定内容(列位置)を表示するLabel1を配置します。
また主なマクロを操作するボタンとして、文字列挿入ボタン(CommandButton1)・検索ボタン(CommandButton2)・終了ボタン(CommandButton3)を置きます。

以上のコントロールのプロパティ(表面の文字列など)は、図6-1のInitializeイベントプロシージャ内で設定します。またその他の説明用のLabelは、フォーム設計時に表示文字列を設定します。

5.標準モジュールのコード

本システムは、図5-1のFind_Startプロシージャからスタートします。
  1. '========== ⇩(1) システムの起動 ====================
  2. Sub Find_Start()
  3.  If ActiveSheet.Type = xlWorksheet Then
  4.   UserForm1.Show 0
  5.  End If
  6. End Sub
図5-1

4行目のShowメソッドでダイアログがモードレス(ダイアログ起動中もシートを操作可能)で起動されますが、検索は「ワークシート上でのみ可能」ですので、アクティブになっているシートがワークシートか否かを3行目で確認しています。
シートの種類は図5-2のように5種類あり、その内の「住所録として使用できるワークシート」のみで動作するようにするためです。
XlSheetTypeのメンバー
名前内容検索が可能
xlChart-4109グラフシート
xlDialogSheet-4116Excel5 ダイアログシート
xlExcel4IntlMacroSheet4Excel4International マクロシート
xlExcel4MacroSheet3Excel4マクロシート
xlWorksheet-4167ワークシート
図5-2

なおExcel4マクロシート(図5-2の3番目,4番目)はワークシート相当みたいで、Excel標準の「検索」も起動できますが、今回は対象外としています。

6.フォームモジュールのコード

6-1.フォーム起動時の初期化

フォームを初回に起動する時に呼び出されるInitializeイベントプロシージャが図6-1です。
  1. '========== ⇩(2) フォーム初回起動時 ====================
  2. Private Sub UserForm_Initialize()
  3.  Me.Caption = "検索と追記"
  4.  Me.CommandButton1.Caption = "文字列挿入"
  5.  Me.CommandButton2.Caption = "次を検索"
  6.  Me.CommandButton3.Caption = "閉じる"
  7.  Me.CommandButton2.Default = True
  8.  Me.CommandButton3.Cancel = True
  9.  Me.SpinButton1.Max = Application.Columns.Count
  10.  Me.SpinButton1.Min = 1
  11. End Sub
図6-1

9行目は、フォームのタイトル部に「検索と追記」という表示をします。
10~12行目は、各ボタンの表面に文字を表示しています。

14行目は「次を検索」ボタンをDefaultボタンに設定しています。Defaultプロパティに設定(=True)できるのは、1つのフォーム内で1つのコマンドボタンだけです。
Defaultボタンに設定すると、そのボタンに対しては「キーボードのEnterキーを押す」=「Defaultボタンをクリックする」ことになります。ただし「フォーム内の他のボタンにフォーカスがある時にEnterキーを押した時」には「Defaultボタンでは無く、フォーカスのあるボタンが押されたことになる」ことには注意が必要そうです。

15行目は「閉じる」ボタンをCancelボタンに設定しています。Cancelプロパティに設定(=True)できるのも、1つのフォーム内で1つのコマンドボタンだけです。
Cancelボタンに設定すると、そのボタンに対しては「キーボードのESCキーを押す」=「Cancelボタンをクリックする」ことになります。他のボタンにフォーカスがあっても、この機能は有効です。

17~18行目は、記入する列を切り替えるスピンボタンの設定です。
今回のスピンボタンは、A列・B列・C列・ … ・XFD列(Excelのバージョンで最終列は異なります)と切り替えをする役目です。その列位置をR1C1参照スタイルのように、第1列・第2列・第3列・ … ・第16384列と数値で表し、MIN値を1、MAX値を16384 と置くことで「実際に存在する列位置のどれかを選ぶ」ことが出来るようにします。
実際に存在する最大の列位置は、17行目のように「Application.Columns.Count」で「そのバージョンに合った最大列位置」が得られますので、それをMax値としています。尚、Min値は1でどのバージョンでも同じなので、18行目でMin値を設定します。

スピンボタンの初期設定値はMin=0、Max=100 で、またスピンボタンの持っている値(Value値)の初期値はValue値=0です。
それを図6-2の右側のように、設定値を変更する必要があります。なお、スピンボタンの値(=初期の書込み列位置)は1(=A列)とすることにします。

スピンボタンの設定値変更
図6-2

変更をする設定項目は「Min値」「Max値」「Value値」の3つですが、設定する順序も考える必要があります。
今回は図6-3のように「Max値」→「Min値」の順序で設定しています。「Value値」は特に設定していませんが、Value値はMin値とMax値の間に必ず居ますので「Min値を0→1に変更する時に、自動的にValue値も押し上げられて0→1に値が変更」されます。

スピンボタン設定値の変更の順序
図6-3

ですので、今回の場合はMin値を変更するだけでValue値をあえて変更する必要はありません。また、Value値が変更されるとスピンボタンのChangeイベントが発生しますが、今回は「Min値を0→1に変更した時点でイベントが発生」することになります。
よって18行目を実行した後、図6-10のSpinButton1_Changeイベントが呼び出され、Label1の「記入列」の表示としては「初期状態のA列」が表示されることになります。

初回起動時は図6-1のInitializeイベントから発生し、フォームを実表示する時には図6-4のActivateイベントプロシージャが呼び出されます。なお、フォームを一度閉じた(=Hideした)後に再度呼び出した場合は、Initializeイベントは経由せずにActivateイベントプロシージャからスタートします。
  1. '========== ⇩(3) フォーム表示時 ====================
  2. Private Sub UserForm_Activate()
  3.  Me.TextBox1.SetFocus
  4. End Sub
図6-4

Activateイベントプロシージャでは、22行目で「検索文字列(TextBox1)」にフォーカスを当てた状態でフォームを起動させています。
これは、起動時に検索ワード部分にフォーカスを当てておくことで、ユーザーがマウスクリックでTextBoxを選択しなくてもワードを入力できるようにしておくためです。また、フォームを閉じる時には「閉じる」ボタンをクリックしますが、Hideした状態のままでは「閉じる」ボタンにフォーカスが当たっていますが、フォーム表示時に「ボタン以外にフォーカスを当てる」ことで、起動直後でもキーボードのEnterキーを押せば検索が開始する効果も狙っています。

6-2.文字列挿入ボタン

図6-6の「次を検索」ボタンで「検索文字列が見つかったセルがActive」になっている状態の時、「文字列挿入」ボタンをクリックした時に動作するイベントプロシージャが図6-5です。
  1. '========== ⇩(4) 文字列挿入ボタンのクリック ====================
  2. Private Sub CommandButton1_Click()
  3.  Dim WriteCell As Range    '文字列を書き込むセル範囲
  4.  Set WriteCell = ActiveSheet.Range(Me.Label1.Caption & ActiveCell.Row)
  5.  WriteCell.Value = WriteCell.Value & Me.TextBox2.Value
  6.  Me.CommandButton2.SetFocus
  7. End Sub
図6-5

28行目は、書き込むセルを特定して変数WriteCellに代入しています。そのセルの位置は以下のようになります。特にセルの位置については、列+行の文字列を結合させて「A1参照スタイル」で指定している形になります。
 ・シート:現在Activeになっているシート = ActiveSheet
 ・行位置:検索してActiveとなったセルの行位置 = ActiveCell.Row
 ・列位置:スピンボタンで選択した列位置 = Me.Label1.Caption(Label1上のA1参照スタイルでの列位置)

30行目は、書き込むセルに記入されていた文字列の後ろに「追加文字列(TextBox2.Value)」をくっつけてから、再度書き込むセルに戻します。

32行目では、フォーカスを「次を検索ボタン(CommandButton2)」に移します。図6-1の14行目のところで説明しましたが、どこか他のボタンにフォーカスが当たっていると「Enterキーを押してもDefaultボタンをクリックした事にならない」ため、「DefaultボタンであるCommandButton2」にフォーカスを当てています。
なお「ボタン以外にフォーカスが当たっていれば良い」ので、32行目を「Me.TextBox1.SetFocus」に置き換えてもOKです。

6-3.検索ボタン

「次を検索」ボタンをクリック、またはフォームがアクティブになっている状態でキーボードのEnterキーを押した時に呼び出されるイベントプロシージャが図6-6です。
  1. '========== ⇩(5) 検索ボタンのクリック ====================
  2. Private Sub CommandButton2_Click()
  3.  Dim SS As Range              '検索するセル範囲
  4.  Dim FoundCell As Range          'Findメソッドの戻り値(セル範囲、またはNothing)
  5.  Dim mySh_Bk As Integer          '検索場所(シート、またはブック)
  6.  Dim myWhat As String            '検索する文字列(Findメソッドの引数)
  7.  Dim myLookIn As Variant          '検索するデータの種類(Findメソッドの引数)
  8.  Dim myLookAt As Variant          '検索の方法(Findメソッドの引数)
  9.  Dim mySearchOrder As Variant       '検索する順序(Findメソッドの引数)
  10.  Dim myMatchCase As Variant        '大文字と小文字の区別(Findメソッドの引数)
  11.  Dim myMatchByte As Variant        '全角・半角の区別(Findメソッドの引数)
  12.  Call myOption(mySh_Bk, myWhat, myLookIn, myLookAt, mySearchOrder, myMatchCase, myMatchByte)
  13.  If Selection.Count = 1 Then '選択している範囲
  14.   Set SS = ActiveSheet.Cells
  15.  Else
  16.   Set SS = Selection
  17.  End If
  18.  Set FoundCell = SS.Find(What:=myWhat, _
  19.                 After:=ActiveCell, _
  20.                 LookIn:=myLookIn, _
  21.                 LookAt:=myLookAt, _
  22.                 SearchOrder:=mySearchOrder, _
  23.                 SearchDirection:=xlNext, _
  24.                 MatchCase:=myMatchCase, _
  25.                 MatchByte:=myMatchByte, _
  26.                 SearchFormat:=False _
  27.                 )
  28.  If FoundCell Is Nothing Then
  29.   MsgBox "検索が失敗しました"
  30.  Else
  31.   FoundCell.Activate
  32.  End If
  33. End Sub
図6-6

36~45行目は、プロシージャ内で使用する変数宣言です。その内40~45行目はFindメソッドの引数です。Findメソッドの引数は、図6-7のように9つあります。
なお一番右の「引数継承」欄で〇になっている引数は、Findメソッドを使用すると保存される引数で、次にFindメソッドを使用する時にこれらの引数を指定しない場合には保存した引数値が使われることになります。(今回のシステムでは、引数の継承は使用していません。)
引数役割データ型定数・値既定値引数継承
What検索データVariant
After検索開始セルVariant範囲の左上端セル
LookIn検索する
データの種類
Variant数式=xlFormulas= -4123
値=xlValues= -4163
コメント=xlComments= -4144
xlFormulas
LookAt検索の方法Variant完全に同一=xlWhole = 1
部分一致=xlPart = 2
xlPart
SearchOrder検索する順序Variant行を先に検索=xlByRows =1
列を先に検索=xlByColumns = 2
xlByRows
SearchDirection検索の方向Long前方検索=xlNext =1
後方検索=xlPrevious =2
xlNext
MatchCase大文字と小文字
の区別
Variant区別する=True
区別しない=False
FALSE
MatchByte全角・半角
の区別
Variant区別する=True
区別しない=False
FALSE
SearchFormat検索の書式Variant書式を検索する=True
書式を検索しない=False
FALSE
図6-7

この9つの引数の中から40~45行目の6つをどうやって選んだかですが、Ctrl+Fで起動する組込ダイアログには図6-8のようにオプションが存在します。ダイアログ右下の「オプション≫」をクリックすると、ダイアログの枠が広がり出現する部分です。
Findメソッドの引数と検索のオプション項目の関係
図6-8

このオプション内の検索場所を除く5つがFindメソッドの引数に対応し、また一番上の「検索する文字列」はWhat引数に対応しています。なお検索場所の項目はFindメソッドの引数にはなっていませんが、ダイアログのオプションで変更可能となった場合を考えて、変数の1つに加えています。
ですので今後、今回のフォームを拡張してオプション設定を可能とした時に対応し易いように、赤字で示した引数+検索場所については変数として設定することにしました。
なおSearchFormat引数は、書式を検索する時にTrueに設定するものですが、Excel上では数多くの書式を設定できますので「書式を検索するためには、書式をある程度絞り込んで設定するツールも必要になる」と考え、今回は対象から外しました。

47行目では「検索場所+6つのFindメソッドの引数」を図6-12のmyOptionプロシージャに渡し、「各変数に値が代入」されて戻ってきます。上でも説明しましたが、このように面倒なやり方をしているのは「フォームを拡張してオプション設定を可能とした時」に、図6-12のコードを修正すれば成立するためです。ですので、検索ダイアログにオプションが存在しない今回の場合に限れば、異なる値が戻ってくる可能性があるのは「myWhat」のみになります。
(なお、検索場所以外の項目はFindメソッドの引数そのものなので、myOptioプロシージャ内の変更だけでOkそうです。しかし検索場所がシート内かブック内かを切替ようとすると、ロジックはかなり複雑になりそうです。)

49~53行目は、シート内での検索範囲を設定しています。
氏名の列とか、住所の列とかを故意的に選択している場合は、「その列の中だけで検索する」ことをユーザーは期待しているはずです。そして、そのように列を選択している時には、複数のセル範囲を選択していることになりますので「Selection.Count」は複数の値を返してきます。
一方、組込ダイアログの検索を使用するときも「シート全体について検索したい時」は、「単一のセルを選択」しているはずです(シートの左上をクリックして、シート全体をActivateにする人もいるとは思いますが)。ですので「Selection.Count = 1」の時は「シート全体に対して検索実行」と判断することにしました。

ということで「Selection.Count = 1」の時は、50行目で「シート全体」を検索範囲(変数SS)に、それ以上の時は52行目で「現在選択している範囲」を検索範囲に設定しています。

55~64行目は1つのコードで、Findメソッドを実行し、その戻り値を変数FoundCellに代入しています。検索範囲については55行目のRangeオブジェクト「SS」で指定しています。
引数は前述したように全部で9つあり、変更される可能性のある引数に対しては「my・・・」という変数名で値を渡しています。
図6-7を見ても分かるように、引数の内「SearchDirection」と「SearchFormat」は既定値のままの値を渡していますので、わざわざ引数を設定をせず省略しても良いのですが、ここでは全引数を説明する意味で引数設定をしています。

Findメソッドは戻り値として、
 ・検索文字列が見つかった時:見つかったセル範囲(Rangeオブジェクト)
 ・見つからなかった時   :Nothing
を返してきます。ですので66~70行目のように、戻り値の代入された変数FoundCellの値を調べることで処理を分岐させています。
すなわち、戻り値がNothingの時は「見つからなかった」ことを意味しますので67行目でメッセージを出し、それ以外(セル位置を返してきた時)はそのセル位置をActiveにします。

なお、Activateの代わりに「Select」としてしまうと、せっかく氏名列などを検索範囲とした場合でもその範囲は解除されてしまいますので、ここでは解除されない「Activate」を使用しています。
(変数FoundCellには、Range型かそれ以外のNothingが入る可能性がありますので、変数FoundCellのデータ型はVariant型の方が正しいと思われるかもしれません。しかしRange型の初期値(セル位置が何も入っていない時)はNothingですので、Range型の宣言で問題はありません。)

6-4.閉じるボタン

ダイアログの「閉じる」ボタンをクリック、またはキーボードのESCキーを押すと呼び出されるイベントプロシージャが図6-9です。
  1. '========== ⇩(6) 閉じるボタンのクリック ====================
  2. Private Sub CommandButton3_Click()
  3.  Me.Hide
  4. End Sub
図6-9

内容としては、75行目で単純にダイアログを隠しているだけです。隠すだけですので、その後図5-1のFind_Startプロシージャを呼び出せば、検索文字列などは閉じた時の状態のまま再表示されることになります。

6-5.スピンボタン

「記入する列」の変更のために、スピンボタンの左矢印・右矢印をクリックしたとき呼び出されるイベントプロシージャが図6-10です。
  1. '========== ⇩(7) スピンボタンの操作 ====================
  2. Private Sub SpinButton1_Change()
  3.  Dim colNo As Long       'スピンボタンの変更後の値(Value値)
  4.  Dim colABC As Variant     'ワークシートの列全体を表す文字列
  5.  colNo = SpinButton1.Value
  6.  colABC = Application.ConvertFormula("c" & colNo, xlR1C1, xlA1, xlRelative)
  7.  Me.Label1.Caption = Split(colABC, ":")(0)
  8. End Sub
図6-10

82行目では、SpinButton1の値(Value値)を取得し、変数colNoに代入しています。この値はR1C1参照スタイルの列位置を指すことになるのですが、標準状態のExcelのワークシートの列位置は「A1参照スタイルの列位置(A列、B列、・・・)で表示」されていますので、84~85行目でA1参照スタイルの列位置に変換をします。

84行目では「ConvertFormulaメソッド」を使って、R1C1参照スタイルからA1参照スタイルへの変換を行っています。
ConvertFormulaメソッドには、図6-11のように5つの引数があります。
引数役割データ型定数・値引数省略の場合必須
/Opt
Formula変換対象の数式
を含む文字列
Variant必須
FromReferenceStyle変換前の
参照形式
XlReferenceStyleA1形式=xlA1 = 1
R1C1形式=xlR1C1 = -4150
xlA1必須
ToReferenceStyle取得する
参照スタイル
VariantA1形式=xlA1 = 1
R1C1形式=xlR1C1 = -4150
FromReferenceStyle
で指定した値が適用
Opt
ToAbsolute変換された
参照型
Variant行:絶対参照+列:絶対参照=xlAbsolute = 1
行:絶対参照+列:相対参照=xlAbsRowRelColumn = 2
行:相対参照+列:相対参照=xlRelative = 3
行:相対参照+列:絶対参照=xlRelRowAbsColumn = 4
参照の種類は
変更されず
Opt
RelativeTo相対参照
の基点
Variant現在Activeに
なっているセル位置
Opt
図6-11

参照スタイル変換の考え方を以下のように考えました。
 ・変換対象である引数Formulaには、列名だけを指定する訳にはいかないので、「列全体」としてのセル範囲を指定する。
 ・列全体をR1C1参照形式で表すには、例えばE列全体とすると「C5:C5」または「C5」と表示できる。
 ・変換後、例えばE列全体は絶対参照では「$E:$E」と表示されるが、相対参照だと「E:E」となる。相対参照の方が加工が簡単そう。
以上の考え方から、84行目の式は「Application.ConvertFormula("c" & colNo, xlR1C1, xlA1, xlRelative)」としました。第1引数のFormulaは、上記の「C5」相当、第4引数のToAbsoluteには相対参照の「xlRelative」を使っています。

このConvertFormulaの戻り値はcolABC変数に代入され、例えばE列全体であれば「E:E」という文字列が入ります。
この文字列は列名と列名の間に「:(コロン)」が入っていますので、85行目のSplit関数で一旦配列に格納し、その1番目(インデックス=0)のデータを取り出して、Label1の表示にしています。
なお、配列の2番目(インデックス=1)の値を使用しても結果は同じです。

なお、図6-1のInitializeイベントの18行目でスピンボタンのMin値を移動した時、同時にValue値も変更(0→1)されることになり、図6-10のSpinButton1_Changeイベントプロシージャが実行されますので、最初にフォームを起動した時には「1列目」である「A」という列名がLabel1に表示されることになります。

6-6.Findメソッドのオプション値生成

図6-6の47行目から呼び出されるのが、図6-12になります。引数として、検索文字列および検索のオプションで指定できる値の変数を受け取り、ユーザーがダイアログ内でどのような設定しているかを調査し、その結果(検索文字列および検索のオプション値)を戻します。
  1. '========== ⇩(8) Findメソッドのオプション値生成 ====================
  2. Private Sub myOption(mySh_Bk As Integer, myWhat As String, myLookIn As Variant, myLookAt As Variant, _
  3.             mySearchOrder As Variant, myMatchCase As Variant, myMatchByte As Variant)
  4.  mySh_Bk = 0              '検索場所(シート=0、ブック=1)
  5.  myWhat = Me.TextBox1.Value    '検索する文字列
  6.  myLookIn = xlFormulas         '検索対象
  7.  myLookAt = xlPart           '完全一致か否か
  8.  mySearchOrder = xlByRows      '検索方向
  9.  myMatchCase = False          '大文字小文字の区別
  10.  myMatchByte = False          '半角全角の区別
  11. End Sub
図6-12

今回システムでは、検索のオプションは選択できない(選択できる仕様にしていない)ため、ほとんど定数のようなものです。
唯一94行目で、「検索文字列(TextBox1)」の値を読み込み、変数myWhatにしています。
95~99行目は、図6-7の既定値(組込ダイアログの検索の初期値)を設定しています。

92行目の変数mySh_Bkの値は、今回のシステムでは全く使っていません。現在のシート上のみで検索をするか、ブック全体を検索対象にするかの変数なのですが、Findメソッドのオブジェクト(Findの親として設定するオブジェクト)は「Rangeオブジェクト」です。
「ブックのオブジェクト」がFindに使えれば、ブック全体を対象として検索することは簡単なのですが、Rangeオブジェクトしか対応していませんので、次々にシートを切り替えて検索していくしか(自動マクロ記録を見ても)方法は無さそうです。
ですのでブック内検索については、別の機会に紹介していきたいと思います。

7.アドインとしてExcelにマクロを登録

「住所録ファイル」と「検索システムファイル」が異なる場合は、2つ同時に開けば検索可能にはなりますが、あまり使い勝手は良くありません。そこで「検索システムファイル」をExcelの機能の1つに登録し、Excel上部のリボンのボタンを押せばシステムを起動できるようにしてみます。

まず、図7-1のように、検索システムのファイル(サンプルファイルであれば、it-047.xlsm)をアドインとしてPC内に保存します。
アドインとしてファイルを保存する
図7-1

アドインファイル(拡張子 .xlam)がPC内に保存されたら、次に図7-2の手順で保存したアドインファイルを有効にします。
アドインとしてファイルを保存
図7-2

次に、スタートするプロシージャ(サンプルファイルであれば、Find_Start)をボタン化します。
まずExcel上部のリボンの部分で右クリックし、「リボンのユーザー設定」を選択します。すると図7-3のようなダイアログが現れますので、新しいタブ・新しいグループを作成し、マクロを追加します。
なお、既存のユーザー用タブ・グループを流用する場合は、⑨⑩を飛ばして「ボタンを追加するグループを選択状態」にしてから手順を続けます。
アドインとしてファイルを保存する
図7-3

マクロが登録⑭されたら、図7-4のように「マクロ名をユーザーに分かり易い名前に変更」します。この作業は必須ではありませんが、省略すると元のプロシージャ名そのものになります。
アドインとしてファイルを保存する
図7-4

最後に⑲OKボタンをクリックすれば、図7-5のように「ユーザー専用のマクロボタンが完成」します。
なお、タブやグループの名前についても変更は可能です。
アドインとしてファイルを保存する
図7-5

Excelへのアドインの方法については、下記も参照下さい。ファイル名が異なるだけで手順は同じです。
西暦・和暦対照表」「セルの罫線を矢印キーで引く

8.最後に

住所録にチェックをする作業は、どなたにも経験があると思います。追記しようとマウスクリックすると検索範囲が解除されてしまい、イライラしたことのある方も多いのではないでしょうか(私もその一人です)。今回のアプリでは、そのイライラを少しでも解消できるのではないかと思います。

今回のアプリは、アクティブにしたシート上のみで動くもので、ブック全体を検索できるものではありません。住所録は個人レベルで言えば1つのシート上で作られる場合が多いと思いますので、今回仕様でもほどほど使えると思います。
しかし会社レベルであれば、多くのシートに取引会社別・あいうえお別などで住所録を作っている場合も考えられます。ですので「ブック内検索」は必要になると思い、現在ロジックを練っているところです。近いうちに紹介できるよう頑張ります。

2021.01.23追記
今回省略したブック内検索について、一応完成しました。
詳細は「年賀状リスト等の宛名検索(ブック内検索可)」を参照下さい。


年賀状リスト等の宛名検索と追記(it-047.xlsm)

セキュリティ向上を目的として「インターネット経由でダウンロードしたOfficeファイル(Excel等)のマクロは、既定でブロック」されるようにOfficeアプリケーションの既定動作が変更になりました。(2022年4月より切替開始)
解除の方法については「ダウンロードファイルのブロック解除方法」を参照下さい。