[[20181025152828]] 『文字列検索を予測候補で行いたい』(あらじぃ) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『文字列検索を予測候補で行いたい』(あらじぃ)

お知恵を拝借します。
2列しかないのですが、行は数千行あるシートがあり、その数千行のセルにはすべて違う文字列が入っています。実際には顧客名のリストです。
ユーザーは毎回、そのシート上でCtrl+Fを入力して顧客名の一部を入力して検索し、参照したい行を見に行っています。
このシート上に検索専用のセルを1つ設けて、そこに顧客名の名称を頭から入れて行くと、順次候補が出て来て、入力文字数を増やすとだんだん選択肢が減って行き、最後はその残った候補リストから選択すると目的の行にたどり着くようなものは作れないでしょうか。
(候補予測機能とでも言うのでしょうか)

例えば
"ABC株式会社"
"ABCD株式会社"
"ABCDE株式会社"
が存在するとして、最終的にABCD株式会社を検索したい場合、
"A"を入れた瞬間に候補としてABC株式会社,ABCD株式会社,ABCDE株式会社がでて、ABCDまで入れると候補がABCD株式会社,ABCDE株式会社に減り,
その時点でユーザーが候補からABCD株式会社をクリックすると
ABCD株式会社の行に飛ぶ、といった感じです。

そもそもEXECELにこのような機能があるのか知らずにお尋ねしております。

< 使用 Excel:Excel2016、使用 OS:Windows10 >


インテリセンス機能とか呼ばれる動作ですね。 お考えの通り、標準機能にはありません。

それっぽく作ってみましょう。 シートにActiveXのコンボボックスコントロールを1つ貼ってください。
そして、シートモジュールのコードに以下を貼ってください。

 Dim cpOld As String
 Dim ipFlag As Long

 Private Sub Worksheet_Activate()
    ipFlag = 0
    cpOld = ""
    Call sComboMake
 End Sub

 Private Sub ComboBox1_Change()
    Dim i As Long

    If 0 < ipFlag Then Exit Sub

    With ComboBox1
        If .Text <> cpOld Then
            ipFlag = 1
            If (.Text <> "") Or (Len(.Text) < Len(cpOld)) Then
                cpOld = .Text
                Call sComboMake
                .Text = cpOld
            End If
            cpOld = .Text
            For i = .ListCount - 1 To 0 Step -1
                If Not .List(i) Like .Text & "*" Then
                    .RemoveItem i
                End If
            Next i
            ipFlag = 0
        End If
    End With
 End Sub

 Private Sub ComboBox1_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 9 Then 'TAB
        With ComboBox1
            If 0 < .ListCount Then
                ipFlag = 2
                ComboBox1.Text = ComboBox1.List(0)
                ipFlag = 0
            End If
        End With
    End If
 End Sub

 Sub sComboMake()
    With ComboBox1
        .Clear
        .AddItem "ABC株式会社"
        .AddItem "ABCD株式会社"
        .AddItem "ABCDE株式会社"
    End With
 End Sub

例えば、コンボボックスに「ABCD」まで入力してから▼を押すと、候補が2つだけ表示されるので、ここから1つ選択します。 または、「ABCD」まで入力後にTABキーを押すと、該当する候補の先頭のものが表示されます。

サンプルなので、選択肢は決め打ちしていますが、sComboMakeサブプロシジャを変更し、どこかのシートにでも文字列と行番号の対応表でも用意しておき、そこから文字列を拾ったり、付加情報を得るようにすると良いでしょう。

(???) 2018/10/25(木) 17:42


 >EXECELにこのような機能があるのか知らず

 そのものズバリはないです。自作するしかないです。

 >2列しかないのですが、

 顧客名はどっちの列にあるんですか?(両方?) 
 2列って、A列とB列ですか?

 >入力文字数を増やすとだんだん選択肢が減って行き、

 必ず頭から入れていくんですか?

 株式会社ABCD なんてのもあるハズなんですけども・・

 >最後はその残った候補リストから選択すると
 >目的の行にたどり着くようなものは作れないでしょうか。 

 辿り着いたあと、何をやるんでしょうか?

 わさわざ現地に行かないでも、目的行の修正なんかは1行目辺りでやっちゃえばいいと思うんですけども。

(半平太) 2018/10/25(木) 20:01


顧客名はA列です。実際には"株式会社"の表記は省いたデータです。辿り着いた先にはその会社の担当者名があり、それを参照するのが目的です。ですのでその後のデータ更新はありません。
(???)さんの例ですと、その何千行もの社名をあらかじめ.AddItemのあとに入れてコードを作っておくしかないのですね。EXCELでやるのはやはり現実的ではないということですね。
でも、ありがとうございました。
(あらじぃ) 2018/10/26(金) 10:28

コード中に会社名を直書きしたのは動作サンプルだからであり、本来はセルから代入するのですよ?
とはいえ、何千社もあるので、おそらく動きが遅くなりそうです。現在の文字列に一致する候補だけを一覧にするというのは、それだけ面倒だという事です。

ところで、そんなものを作らなくとも、オートフィルタさえ設定しておけば、オートフィルタ自体がワイルドカード指定できる機能を持っているので、「*ABC*」とか入力すれば、一致する行だけが表示されます。 皆さんにオートフィルタの使い方を指導するだけで目的が達成できたりしませんかね?
(???) 2018/10/26(金) 11:47


ありがとうございます。
もし可能でしたら"本来はセルから代入するのですよ?"の部分を教えていただけないでしょうか。かなり面倒なことのようですので、今回は見切りをつけてオートフィルターで案内しておこうと思ってはいます。

(あらじぃ) 2018/10/29(月) 11:48


マクロでセルの値を得る、という部分だけでも自力作成できないようならば、マクロ案は無いかもですねぇ。 コンボだと絞った結果をいちいち▼を押して確認しないと判らないのですが、応用してテキストボックスとリストボックスに作り替えれば、入力と同時に候補が絞られる様を見られたりするのですけど。

とりあえず、会社名が列挙されているシート名が「Sheet2」だった場合の例なぞ。

 Sub sComboMake()
    Dim wk As Worksheet
    Dim i As Long

    Set wk = Sheets("Sheet2")
    With ComboBox1
        .Clear
        For i = 1 To wk.Cells(wk.Rows.Count, "A").End(xlUp).Row
            .AddItem wk.Cells(i, "A").Value
        Next i
    End With
 End Sub
(???) 2018/10/29(月) 12:57

 >会社の担当者名があり、それを参照するのが目的です。

 その目的なら、ピッタリ1つに絞る必要もないですよね。

 操作手順から先に説明します。(事前準備の説明は後述します)

 1.先ず、D2セルに会社名の先頭文字を入力する。

   ※1文字が普通だが、2文字以上入られるならそれに越したことはない。
     それだけ目的達成までの時間が短くなる。

 2.すると、E3:E11に連番が表示される。
   その連番の中で会社名の文字数と一致するか、少な目の数を右クリックで指定する。

   ※ピッタリの文字数をクリックするのが一番いいが、正確に文字数を数えるのも面倒なので
    テキトーに少な目の文字数にする。(なお、多目の文字数をクリックするのは厳禁)

 3.上記2で右クリックすると、直後にG列とH列に該当データが自動的に表示される。

 多分、この作業1回で目的は達する。

 もし絞り切れていない場合は、もっと大きな連番を再度右クリックする。 または
 D2セルの文字を増やして(1文字入れて実施したなら、2文字まで入れる)、上記手順を繰り返す

 ーーーーーーーー事前準備は以下の手順で行うーーーーーーーー
 (1)タイトル
   A1:B1にはタイトルが在るものとします(会社名・担当者名など)

 (2)数式の入力
   F2セル =D2&REPT("?",MAX(0,E2-LEN(D2)))&"*"
  E3セル =E2+1
   E3の数式はE11セルまでコピーする

 (3)マクロの貼り付け
   データシートの「シート見出し」を右クリックして、「コードの表示(V)」を選ぶ。
   画面中央に白いエリアに後記マクロをコピぺする。

   貼り付けたら、ALT+F11 でエクセルに戻って準備完了です。

 ’シートモジュールに貼り付けるマクロ (標準モジュールに貼り付けではない←重要)

 Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
     If Target.CountLarge > 1 Then Exit Sub
     If Len(Range("D2").Value) = 0 Then Exit Sub

     If Not Intersect(Range("E3:E11"), Target) Is Nothing Then
         Cancel = True
         Range("D1").Value = "先頭文字"
         Range("E1").Value = "文字数"

         Range("F1").Value = Range("A1").Value
         Range("F2").FormulaR1C1Local = "=RC[-2]&REPT(""?"",MAX(0,RC[-1]-LEN(RC[-2])))&""*"""
         Range("E3:E11").FormulaR1C1Local = "=R[-1]C+1"

         Range("E2").Value = Target.Value

     End If

     Columns("G:I").ClearContents

     Columns("A:B").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range( _
         "F1:F2"), CopyToRange:=Columns("G:H"), Unique:=False
 End Sub

(半平太) 2018/10/30(火) 11:08


  実際にやってみたら、連続照会の場合、文字数が1から表示されていないとやりにくいので
  以下に変更してください。

 > Range("E3:E11").FormulaR1C1Local = "=R[-1]C+1"
           ↓変更
    Range("E3:E11").Value = [row(1:9)]

(半平太) 2018/10/30(火) 16:38


わかりやすく書いていただいたので、私でもできました!
ありがとうございます。
この方法か、ワイルドカードでのオートフィルターどちらかで考えます。
(あらじぃ) 2018/10/30(火) 18:05

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.