[[20160831222846]] 『VBA Listboxの値を並び替え』(さんちゃん) ページの最後に飛ぶ

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

 

『VBA Listboxの値を並び替え』(さんちゃん)

お世話になっております。
userform上にListboxを配置しています。
リストは20000ほどありますが重複データで多くても20程度でよいと思っています、シートのデータをそのままリストとしてListboxへ表示させても使い物になりません。

問題
1.リストをフィルターを掛けて並び替えたデータをListboxへ表示する。
※シートへ書き込み並び替えてListboxへ表示する方法で出来ますが、それでは面白くなく勉強になりません。


1.Listboxへ重複データにフィルターを掛け並び替える部分は出来ています。このデータをListboxへ並び替えたデータを表示する部分でつまずいております、Webでいろいろ調べ多少手を加えたものです。※前項で20程度とありますがtestなので6としております。
並べ替えたデータをListBoxに表示するにはどのような構文が必要でしょうか?

Private Sub UserForm_Initialize()

途中抜粋

    Dim swap As String
    Dim data(5) As String
    Dim v As Long
    Dim w As Long

   w = UserForm1.ListBox1.ListCount - 1
    For v = 0 To w
        data(v) = ListBox1.List(v)
    Next v
    For w = 0 To 5
      For g = 5 To w Step -1
         If data(w) > data(g) Then
           swap = data(w)
             data(w) = data(g)
               data(g) = swap
         End If
       Next g
    Next w
ローカルウインドウで見るとdata(0)"",data(1)"",data(3)"AA1",data(4)"AA2",data(5)"AA3"
のように並び替えは出来ています。
表示する部分ご教授お願いいたします。

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


 >>※シートへ書き込み並び替えてListboxへ表示する方法で出来ますが、それでは面白くなく勉強になりません。

 いやぁ、立派な方法ですよ。というより、ゴリゴリ、自前コードを書いても、エクセル標準機能のパフォーマンスには
 到底かないません。使えるものはどんどん使いましょう。

 (アップされたコード内で配列ソートがありますね。でも、エクセルの並び替えよりパフォーマンスはぐっと落ちるはずです)

 ただ、今回のテーマなら並び替えというより 重複削除機能でしょうね。並び順にかかわらず一発で必要なキーで
 重複が削除され一意のリストになりますよ。

(β) 2016/09/01(木) 00:42


 当処理にエクセル標準機能を活用するか、ゴリゴリ 自分でコードを書くかは別にして。

 1.もともとのListBox1 へのデータの格納部分が見えませんが、プロパティ RowSource で指定していますか?
   それとも、元ネタがあるシートのデータを配列に取り込み Listに格納、ないしは AddItem で 1行ずつ追加していますか?
 2.ローカルウィンドウで調べた結果、ご自身でも確認されていますけど、このコードでは 空白が 先頭にきます。
   もし、空白が多ければ、表示されたListBox1 は 空っぽのように見え、実際のリストは、下のほうにずずずっとスクロールして初めて
   でてきます。 これでいいのですか?
 3.そもそも、空白データもリストに入っていることがおかしいんですが、このListBox1 の内容、列数は1つですか
   複数列ですか?
 4.複数列だとして、並び替えや重複削除のための列は、どの列ですか?

 いずれにしても、仕様が不明なんですが、アップされたコード、なんだかおかしいですねぇ。
 0 〜 5 って データの行数分のループ処理ですかね? 0 〜 w は 列数分のループ処理?
 何をやりたいのか、コードと説明文が食い違っているような気がします。

(β) 2016/09/01(木) 06:50


答えを書いてしまうと、それこそ面白くなくて勉強にならないかもですが…。

 Private Sub CommandButton1_Click()
    Dim i As Long
    Dim cw As String

    With CreateObject("System.Collections.ArrayList")
        For i = 0 To ListBox1.ListCount - 1
            cw = ListBox1.List(i)
            If cw <> "" And Not .Contains(cw) Then
                .Add cw
            End If
        Next i
        .Sort
        ListBox1.Clear
        For i = 0 To .Count - 1
            ListBox1.AddItem .Item(i)
        Next i
    End With
 End Sub
(???) 2016/09/01(木) 09:29

 本来は、そもそも、ListBox1にListを登録する際に、重複削除と並び替えを行えばいいと思いますが
 既にListBox1に登録されているとして。

 ???さんのコードと基本同じですが、List内にあると思われる空白も削除します。
 (とりあえず1列のリストだという前提です。複数列なら別コードになります)

 Private Sub UserForm_Initialize()
    Dim d As Variant
    Dim w As Variant
    Dim al As Object

    w = ListBox1.List

    With CreateObject("System.Collections.ArrayList")

        For Each d In w
            If d <> "" Then
                If Not .contains(d) Then .Add d
            End If
        Next

        .Sort
        ListBox1.RowSource = "" '念のため
        ListBox1.List = .toarray

    End With

 End Sub

(β) 2016/09/01(木) 11:10


(β様)(???様)お世話になります。
いろいろありがとうございます。以前は仕事上でここには大変お世話になっているものです。VBAも独学で、最近?でもないんですが、会社も変わり、あまりVBAには触れていません。何より、本で独学、同じものを作っても勉強にはならない、知識や構造が理解できていんです。でも、やる方法はあるにもかかわらず、webを見ると、やれそうな感じで・・・これでは、ダメなんでしょうが、専門知識や実力がないんです、β様???様のように手を差し伸べて頂ける方に、助けを頂ける事が何よりです。
仕事上、今日は実務に回され何もできていませんが、まずは回答のお礼を申し上げます。

「コード内で配列ソート」実はこれも動作が遅く、Sortが使えそうですが、2重の質問なので、もうしばらく悩んでみます。
問い合わせ(回答になるかわかりませんが)
1.[データの格納部分]は現在、For NextでAddItem で 1行ずつ追加しています。
2.[空白が 先頭にきます。]まさに、悩みの1つです。いろいろの質問はルール違反なので・・・空白は避けたいです。
3.[列数は1つですか]はい、1つです。基本的には空白は無いのですが、避ける方法も勉強したいです。
4.[複数列]1列です。
他、アップされたコード「0〜5」test用にしています。実際は20程度を予測しています。ですから空白が入ってしまします。本来は Dim data(5) As Stringがdata(20)としておくことで全てを拾えると考えています、実はdata(変数)←この変数をListboxデータ数とする事で、空白が無くなるのですが、いろいろやってみたのですが、 Dim data(5) As Stringとするとローカルウインドウでdata 0 to 5となりループ回数が指定されると考えています、また変数にして(w)としたいのですがエラーとなります。今は今後の課題としています。空白も予想して頂いて、さすがです。

とりあえず、ありがとうございます。頂いた物を勉強します。今後ともよろしくお願いいたします。

(さんちゃん) 2016/09/01(木) 21:32


(β様)(???様)大変ありがとうございました。
うまくいきました。CreateObject("System.Collections.ArrayList")これは、勉強の仕方かもしれませんが、これは出てきません(;;)。System.Collections.ArrayList私の場合、一列すべてのデータを一旦Listboxにすべて取り込んでいます、これがSystem.Collections.ArrayListとなっている?と思うのですが、この後、Comboboxには、2万前後の種類200以上のデータを取り込みます。非常に時間がかかります、Listboxに一旦取り込む事が無駄で、並び替えにFoe Nextを使っている事で時間が掛っている(これは昔の定番手法のようですが)直接データ域を.SortしCreateObjectの対象にすればよいのではないかと考えています。
 .Add cwこの辺もすっかり忘れていました。
  ListBox1.List = .toarray これは(.toarray)は、ググっても内容が理解できませんでした、また勉強します。
考えは大きくズレていないと思いますが?少しずつスピードアップできるようにやってみます。ご指導ありがとうございました。今後ともよろしくお願いいたします。
(さんちゃん) 2016/09/01(木) 23:40

現在、最初に全てListBoxに代入している箇所を、直接ArrayListオブジェクトにAddすると良いでしょうね。

System.Collections.ArrayList で探せば、情報が得られるでしょう。
これはExcel標準の機能ではなく、OSの追加機能である .Net Framework1.1で追加されたものを利用しているのですよ。
(windows10ならば、OSの標準機能に含まれます)

とりあえずは、こんなコードで重複チェックや空白チェックし、ソートまでできるんだなぁ、くらいの理解で良いです。
数年後、同じ仕様説明を読むと、理解できるようになっているかも?、くらいの難しさですから。
(???) 2016/09/02(金) 10:32


(???様)重ねてお礼を申し上げます。
「ListBoxに代入している箇所を、直接ArrayListオブジェクトにAddする」なるほど、
なんとなくですが、理解できそうです。
「System.Collections.ArrayList で探せば」わかりました。勉強します。
「難しさですから。 」ですよね、本を買ってその本を全てできるわけでもなく、今回の様な使い方を解説する本は持っていないですし、あっても「まず理解できない」です。
(???さん)(βさん)のように、貴重な時間を割いて、回答して頂ける方々に、ご指導頂ける事が、本当に励みになります。
(???さん)(βさん)本当にありがとうございます。m(..)m今後とも、ご指導よろしくお願いいたします。
(さんちゃん) 2016/09/02(金) 21:22

コメント返信:

[ 一覧(最新更新順) ]


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