[[20170417102019]] 『ユーザーフォームでリストボックス検索から更新ま』(けんとくん) ページの最後に飛ぶ

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

 

『ユーザーフォームでリストボックス検索から更新まで』(けんとくん)

初めまして。
リストボックスに検索結果が出るようにし、リストを選択すると下のテキストボックスに表示するようにしましたが、そこから追加で書き込みする方法が分からない為質問させて頂きます。

Private Sub CommandButton1_Click()
Dim i As Long, r As Range, fAddr As String
ListBox1.Clear
With ActiveSheet.Cells
Set r = .Find(what:=TextBox1.Value, LookIn:=xlValues, lookat:=xlPart)
If Not r Is Nothing Then
fAddr = r.Address
i = 0
Do
ListBox1.AddItem r.Value
ListBox1.List(i, 1) = r.Address
i = i + 1
Set r = .FindNext(r)
Loop While Not r Is Nothing And r.Address <> fAddr
End If
End With
End Sub

Private Sub ListBox1_Click()
With ListBox1
If .ListCount < 1 Then Exit Sub
If .ListIndex < 0 Then Exit Sub
ActiveSheet.Range(.List(.ListIndex, 1)).Select
End With

  Dim i As Long
    With Worksheets("広島市まとめ")
        i = ActiveCell.Row
        Me.TextBox2.Text = .Cells(i, 1)
        Me.TextBox3.Text = .Cells(i, 2)
        Me.TextBox4.Text = .Cells(i, 3)
        Me.TextBox5.Text = .Cells(i, 4)
        Me.TextBox6.Text = .Cells(i, 5)
        Me.TextBox7.Text = .Cells(i, 6)
        Me.TextBox8.Text = .Cells(i, 7)
        Me.TextBox9.Text = .Cells(i, 8)      
        Me.TextBox10.Text = .Cells(i, 9)    
        Me.TextBox11.Text = .Cells(i, 10)
        Me.TextBox12.Text = .Cells(i, 11)
    End With
End Sub

ネット上にころがっている情報から作ったもので、私自身知識が乏しいもので大変恐縮ではございますが教授の程お願い致します。

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


ご自身のコードの中に答えがあるのですが、
 ListBox1.AddItem r.Value
 ListBox1.List(i, 1) = r.Address 

この部分が、値とセルのアドレスを追加していますね。応用してみてください。
(???) 2017/04/17(月) 12:13


 テーマそのものは、???さんのアドバイスで、早晩、解決ということになると思いますので
 ちょっと 別のことを。

 ●ListBox1_Click

  文字通り ListBox1 の中のデータをクリックすると発生するイベントです。
 ということは 『クリックできた』ということですね。もちろん。

 もし、ListBox1 が空っぽなら、クリックそのものができません。
 クリックできたということは ListCount は 1以上ということになります。
 したがって If .ListCount < 1 Then Exit Sub は不要です。

 また、クリックした ということは 選んだわけですから、必ず、ListIndex に選ばれたものが
 入っています。 選ばれていない状態、-1 は、ありえません。
 したがって If .ListIndex < 0 Then Exit Sub これも不要です。

 ●CommandButton1_Click

 まず、 

 With なんとか

    .xxxx として なんとか.xxxx を参照

 End With

 Withでくくった記述は コードがすっきりし、また 参照効率もよろしいのですが、一般的には以下のようにいわれています。

 1) With と End With の間は、適度に短いほうがいい。ここがやたらと長い(間に多くのコードが記述されている)場合
  逆に、その中の .xxxx が 何を参照しているんだろうということが見えにくくなる。
 2) 何度も .xxxx や .yyyy が出てくる場合にきわめて有効。
  今回の場合は、たった2か所。FindメソッドとFindNextメソッドのオブジェクト、つまり検索領域。
  であれば、With と End With で囲まなくても、直接 Cells.Find とか Cells.FIndNext と記述したほうが
  すっきりしてわかりやすいと思います。
  なお、ユーザーフォームモジュールですからシート修飾がないと ActiveSheet とみなされます。
  したがって、ActiveSheet.Cells とかかず 単に Cells でOKです。
 3) この検索領域、Cells ですけど、本当に、シート上、すべてが検索対象なんですか?
  どこか特定の列 ということではないのですか?
  もし、どこか特定の列 ということなら Columns("F").Find とか Columns("F").FindNext というように
  検索領域を絞ったほうが安全ですよ。

 ●インデント

  コード記述は、しっかりとインデントを付けたほうが見やすいです。
  これは、けんとくん さん自身のためです。

  ListBox1_Click のほうは 少しインデントを付けておられますが、それでも中途半端ですね。
  少なくとも、繰り返し制御構造の CommandButton1_Click は 以下のように記述したほうが
  見やすいでしょ?(コードの中身は変えていません。そのままにしてあります)

 Private Sub CommandButton1_Click()
    Dim i As Long, r As Range, fAddr As String
    ListBox1.Clear
    With ActiveSheet.Cells
        Set r = .Find(what:=TextBox1.Value, LookIn:=xlValues, lookat:=xlPart)
        If Not r Is Nothing Then
            fAddr = r.Address
            i = 0
            Do
                ListBox1.AddItem r.Value
                ListBox1.List(i, 1) = r.Address
                i = i + 1
                Set r = .FindNext(r)
            Loop While Not r Is Nothing And r.Address <> fAddr
        End If
    End With
 End Sub

( β) 2017/04/18(火) 08:42


 テーマと関係のない書きこみ連投でいやがられるかもしれませんが、ついでに。

 >ネット上にころがっている情報から作ったもの

 ネット上にはたくさんの有益な情報がありますね。
 でも、とんでもない、間違い情報もあります。
 天下のMSですら、間違いコード例を堂々と掲載したりしています。

 たとえば Loop While Not r Is Nothing And r.Address <> fAddr 

 もしかしたら、

https://msdn.microsoft.com/ja-jp/library/office/ff839746.aspx

 こんなMSのページを参照されたのかもしれません。
 このページのコード、

 Loop While Not c Is Nothing And c.Address <> firstAddress 

 これは、大昔から MSが堂々と掲載していて、しかも、いまだになおしていない有名なバグコードです。

 1つには、無駄なチェックをしている。(特殊なケースで無駄ではないということもありえますーー後述)
 つまり、このループは、最初に検索値が見つかった場合にのみ実行されます。Find->FindNext で、領域を一回りしたあと
 また、検索済みのものを抽出します。なので、見つかったセルのアドレスと最初に見つかったセルのアドレスを比較して
 ひとまわりしたかどうかのチェックを行い、一回りしていたら繰り返し終了 という制御なんですが、
 そもそも、最初に見つかっているわけですから、見つかったものを変更したり削除したりしない限り、Nothing になることは
 ありえない。(例外はあります)

 ですから、結果が Nothing かどうかを判定すること自体がナンセンス。

 ふつうは、Loop While r.Address <> fAddr だけですますことができますね。

 ★特殊な例外

 検索領域に検索値が 1つだけしかなく、かつ、そのセルが結合セルだった場合、最初は見つかりますが
 FindNext をかけると Nothing になります。
(ふつうだったら一回りして最初に見つかったセルが取得されるところですが)

 次に このコードは 「論理的に間違っている」コードだということです。
 前述の 特殊な例 も考慮して、Nothing になることがありえるとしましょう。

 そうすると、Loop While Not r Is Nothing And r.Address <> fAddr 
 And による条件判定は、途中で打ち切らず、最後まで、律儀に(?)記述された条件を判定します。

 r が Nothing だとします。Not r Is Nothing これはいいですね。問題ありません。
 次の r.Address <> fAddr 、r は Nothing です。そうすると Nothing の Address というものを
 判定することになりますから、ここで実行時エラーになります。

 Nothing 判定も行う ということなら

        Set r = .FindNext(r)
        If r Is Nothing Then Exit Do
    Loop While r.Address <> fAddr

 こんな記述にしなければいけませんね。

( β) 2017/04/18(火) 09:57


コメント返信:

[ 一覧(最新更新順) ]


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