[[20140607155449]] 『ListBox間でリストの値を移動』(やさもん) ページの最後に飛ぶ

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

 

『ListBox間でリストの値を移動』(やさもん)

お世話になります。

ListBox1に複数列セルの内容を表示させております。
これを・・・
ListBox1で複数選択したリストを
ListBox2に転記させたいと考えております。

単列の転記はできたのですが
見よう見まねで、作成した複数列のリスト転記が分からず困っております。
すみません・・・^^;
アドバイスの程よろしくお願いします。

'2つのListBoxを連動させる(ListBox1の選択内容をListBox2へ表示)

'単列の転記
Private Sub CommandButton1_Click()

  Dim i As Integer

  If ListBox1.ListIndex = -1 Then Exit Sub
    For i = 0 To ListBox1.ListCount - 1
    If ListBox1.Selected(i) Then
       ListBox2.AddItem ListBox1.List(i)
    End If
  Next i

End Sub

'複数列の転記
Sub CommandButton2_Click()

  Dim i As Integer
  Dim n As Integer

    n = 2 '開始行
  For i = 0 To ListBox1.ListCount - 1
    '選択されているかチェック
    If ListBox1.Selected(i) = True Then
      ListBox2.List(i, 0).Value = ListBox1.List(i, 0)
      ListBox2.List(i, 1).Value = ListBox1.List(i, 1)
      ListBox2.List(i, 2).Value = ListBox1.List(i, 2)
    n = n + 1
  End If
  Next i
End Sub

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


これで出来ました。
 ↓

質問をお願いします^^;

重複項目は移動できないようにしたいのですがどのようにすればよろしいのでしょうか?

アドバイスの程よろしくお願いします。

'ListBox間移動(追記)
'※移動元のリストを切り取って転記
Private Sub CommandButton1_Click()
Dim i As Integer

    If ListBox1.ListIndex = -1 Then Exit Sub

    For i = ListBox1.ListCount - 1 To 0 Step -1

    If ListBox1.Selected(i) Then

        With ListBox2
            .AddItem ListBox1.List(i, 0), .ListCount
            .List(.ListCount - 1, 1) = ListBox1.List(i, 1)
        End With
            ListBox1.RemoveItem i

    End If
    Next i

End Sub

(やさもん) 2014/06/07(土) 17:00


 >重複項目は移動できない

 ListBox1で既にListBox2に移動済みの項目は、再度選択され、ボタンクリック時に移動処理を行ってもその行は、移動しないという事ですか?

 方法1

 最初に ListBox2.Clear を行い、ListBox2は、常に何もないところから登録を始める

 最初に何もないのですから、重複することはありません。

 但し、一つだけ選択して追加移動ということはできませんが・・・。

 方法2

 ListBox1にメンバ設定時に実際に登録する複数列以外にもう一つ列を追加し、そこに連番を入れます。

 ListBox2に移行時にもその連番も移行します。

 登録時には、この連番列に同じ番号があるかないかのチェックを行います。
 あれば、未登録 なければ、登録 という手順でコードを書きます。

 尚、連番として、List列を追加しても表示はさせないように設定します(ColumnsCount)。

(ichinose) 2014/06/07(土) 17:52


ichinose さん

ありがとうございます。

ListBox内に重複項目があった場合削除するコードを
ネットで探しましたが、分かりませんでした。

もしよろしければ、もう少しアドバイスいただけますでしょうか?

よろしくお願いします。
(やさもん) 2014/06/07(土) 19:11


 前投稿は、撤回です。
 重複の意味を間違えていました。というより、重複の意味がわかりません。

 私とやさもんさんが 同じブックを見るようにしましょう。

 新規ブックにて、

 ユーザーフォームを一つ作成してください(UserForm1)

 このUserForm1に以下の順序でコントロールを作成してください。
 コントロールの位置や大きさは、適当でよいです(コードで調整します)。

 リストボックス(ListBox1)
 コマンドボタン(CommandButton1)
 リストボックス(ListBox2)

 UserForm1のモジュールに

 '======================================================================
 Option Explicit
 Private Sub CommandButton1_Click()
    Dim idx As Long
    If ListBox1.ListIndex = 0 Then Exit Sub
    For idx = ListBox1.ListCount - 1 To 0 Step -1
        If ListBox1.Selected(idx) Then
           With ListBox2
               .AddItem ListBox1.List(idx, 0), .ListCount
               .List(.ListCount - 1, 1) = ListBox1.List(idx, 1)
               .List(.ListCount - 1, 2) = ListBox1.List(idx, 2)
           End With
           ListBox1.RemoveItem idx
        End If
    Next idx
 End Sub
 '=================================================================================
 Private Sub UserForm_Initialize()
    With Me
       .Width = 568
       .Height = 190
    End With
    With ListBox1
       .Left = 18
       .Top = 24
       .Width = 210
       .Height = 75
       .ColumnCount = 3
       .MultiSelect = fmMultiSelectMulti
       .ColumnWidths = "50;30;50"
       .List() = Evaluate("{""磯野波平"",54,""磯野家の大黒柱"";""磯野フネ"",53,""旧姓 石田"";" & _
              """フグ田サザエ"",24,""実写版の初代は、江利チエミ"";""フグ田マスオ"",28,""早稲田大学卒業"";" & _
              """磯野カツオ"",11,""想像通り B型"";""磯野ワカメ"",9,""実写版の初代は、松島トモ子"";" & _
              """フグ田タラオ"",3,""太陽にほえろ と関係が深い""}")

    End With
    With ListBox2
       .Left = 330
       .Top = 24
       .Width = 210
       .Height = 75
       .ColumnCount = 3
       .ColumnWidths = "50;30;50"
    End With
    With CommandButton1
       .Left = 252
       .Top = 50
       .Width = 54
       .Height = 24
       .Caption = ">>"
    End With
 End Sub

 標準モジュールに

 Option Explicit
 Sub main()
    UserForm1.Show
 End Sub

 以上です。

 mainを実行してみてください。UserForm1が表示され、

 ListBox1には、サザエさん一家の名前が表示されています。

 ListBox1の中から、フグ田姓のみ選択して、[>>]ボタンをクリックしてください。

 選択したフグ田姓の方だけがListBox2に移動し、ListBox1からは、削除されています。

 さて、この例だと

 >重複項目は移動できない

 どのようなことなのでしょうか?

(ichinose) 2014/06/08(日) 11:06


ichinose さん

丁寧に解説ありがとうございます。

ListBox1からListBox2へ値を移動する際は、解説と同じように
ListBox1から削除するようにしております。

選択→移動(ListBox1の選択したList削除)

If ListBox1.Selected(i) Then
   ↓
(転記処理)
   ↓

'ListBox1で選んだ値をリストから削除
ListBox1.RemoveItem i

そして、質問の意図ですが

(申し訳ありません・・・説明不足で・・・^^;)

※仕様上の問題もあると思いますが目をつぶってください。

ListBox1へのリスト読み込みは、複数シートの内容読み込むように
シート分のコマンドボタンを用意してListBoxに読み込んでおります。

※各sheetには、同じ名前の人が登録されていることがあります。
※各sheetを読み込む際には、ListBox1の内容を一旦クリアにして新規に読み込む形をとっております。
 
結果
sheet1の内容を選択しListBox2へ転記させる際に、各sheetの内容を
「読み込み→転記→読み込み→転記・・・」としていると
同じ名前の人がいることに気づかずに、ListBox2へ転記してしまうのです。

そのため
ListBox1の内容を読み込みを行う際に
ListBox2の中にあるリストに「重複データ」があれば、除外(削除)する処理方法
を考えているところです。

すみませんよろしくお願いします。

(やさもん) 2014/06/08(日) 14:07


追記

(1)

「ListBox1の内容を」ListBox2へ読み込みを行う際に

ListBox2の中にあるリストに「重複データ」があれば、除外(削除)する処理方法

(2)

ListBox1に「シートの内容を」読み込みを行う際に

ListBox2の中にあるリストに「重複データ」があれば、除外(削除)する処理方法

ネットで探すと(2)の方法のほうが圧倒的に多いようです。

ListBox1にシートの内容を読み込む際に
  ↓
ListBox2に転記してあるデータに重複がないかチェック
  ↓
ListBox2のリストとシートの内容に重複があればシートの重複内容を除いてListBox1へセット

(やさもん) 2014/06/08(日) 14:27


 Listbox2に登録されていたら、Listbox1に登録しないという仕様なら、
 Listbox2のListプロパティを使って対象メンバがあるかないかを調べればよいと思います。

 サザエさんのデータで言えば、

 以下のようなデータ設定がされているんですよね?

 前投稿と同じブックの標準モジュールに

 '==================================================================================
 Sub データ設定()
    With Worksheets("sheet1")
       .Range("a1:c8").Value = Evaluate("{""氏名"",""年齢"",""備考"";" & _
                      """磯野波平"",54,""磯野家の大黒柱"";""磯野フネ"",53,""旧姓 石田"";" & _
                      """フグ田サザエ"",24,""実写版の初代は、江利チエミ"";""フグ田マスオ"",28,""早稲田大学卒業"";" & _
                      """磯野カツオ"",11,""想像通り B型"";""磯野ワカメ"",9,""実写版の初代は、松島トモ子"";" & _
                      """フグ田タラオ"",3,""太陽にほえろ と関係が深い""}")
    End With
    With Worksheets("sheet2")
       .Range("a1:c5").Value = Evaluate("{""氏名"",""年齢"",""備考"";" & _
                      """波野ノリスケ"",24,""サザエのいとこ"";" & _
                      """波野タイ子"",22,""ノリスケの妻"";" & _
                      """波野イクラ"",1,""原作と外見の差が大きい"";" & _
                      """フグ田タラオ"",3,""太陽にほえろとの関係が深い""}")
    End With

 End Sub

 Sheet1とSheet2というシート名は用意しておいてください。

 データ設定を実行すると、Sheet1 Sheet2にデータが設定されます。

 先のUserform1のモジュールは 以下のように変更してください

 '========================================================================
 Option Explicit
 Private Sub CommandButton1_Click()
    Dim idx As Long
    If ListBox1.ListIndex = 0 Then Exit Sub
    For idx = ListBox1.ListCount - 1 To 0 Step -1
        If ListBox1.Selected(idx) Then
           With ListBox2
               .AddItem ListBox1.List(idx, 0), .ListCount
               .List(.ListCount - 1, 1) = ListBox1.List(idx, 1)
               .List(.ListCount - 1, 2) = ListBox1.List(idx, 2)
           End With
           ListBox1.RemoveItem idx
        End If
    Next idx
 End Sub
 Private Sub UserForm_Initialize()
    With Me
       .Width = 568
       .Height = 190
    End With
    With ListBox1
       .Left = 18
       .Top = 24
       .Width = 210
       .Height = 75
       .ColumnCount = 3
       .MultiSelect = fmMultiSelectMulti
       .ColumnWidths = "50;30;50"
    End With
    With ListBox2
       .Left = 330
       .Top = 24
       .Width = 210
       .Height = 75
       .ColumnCount = 3
       .ColumnWidths = "50;30;50"
    End With
    With CommandButton1
       .Left = 252
       .Top = 50
       .Width = 54
       .Height = 24
       .Caption = ">>"
    End With
 End Sub

 更に標準モジュールに

 '===================================================================
 Sub フォーム表示()
    Dim rng As Range
    Dim crng As Range
    With UserForm1
       .ListBox1.Clear
    End With
    With ActiveSheet
       Set rng = .Range("a2", .Cells(.Rows.Count, "a").End(xlUp))
    End With
    If rng.Row > 1 Then
       For Each crng In rng
          If Not chk_listbox2(crng.Value) Then
             With UserForm1.ListBox1
                 .AddItem crng.Value
                 .List(.ListCount - 1, 1) = crng.Offset(0, 1).Value
                 .List(.ListCount - 1, 2) = crng.Offset(0, 2).Value
             End With
          End If
       Next
    End If
    UserForm1.Show vbModeless
 End Sub
 Function chk_listbox2(ByVal c_val As Variant) As Boolean
    Dim g0 As Long
    chk_listbox2 = False
    With UserForm1.ListBox2
       For g0 = 0 To .ListCount - 1
          If .List(g0, 0) = c_val Then
             chk_listbox2 = True
             Exit For
          End If
       Next
    End With
 End Function

 これで Sheet1をアクティブにして、「フォーム表示」を実行してリストボックスを操作した後、

 Userform1を表示した状態でSheet2をアクティブにして再度、「フォーム表示」を実行してください。

 Listbox2に名前がある登場人物は、削除されてListbox1に登録されるはずです。
 登録するか否かのチェック方法は他にも方法がありますが、基本的な方法を提示しました。
(ichinose) 2014/06/09(月) 00:44

ichinose さん

ありがとうございます。
試した所、確かにListBox2に名前がある人は、ListBox1に重複して読み込まないようになっていました。

実際のファイルで、試してみます。
(やさもん) 2014/06/09(月) 08:12


ichinose さん

リストを新たに読み込む際に、ListBox2に名前がある人は
ListBox1に読み込まないようにする方法は下記コードが判断しているのでしょうか?

比較の方法は・・・
「セル1列目」と「ListBox2の1列目」でかつ「文字列」の場合は削除されるようです。

 ※数値の場合はダメでした。

例えば・・・

1.検索値が、文字列ではなく数値(ID番号)だった場合

2.セルの2列目にID番号があり
  ListBox1とListBox2には、ID番号が1列目の場合

色々数値を替えてやってみましたが、理解できず、書き込みさせてもらいました。

 Function chk_listbox2(ByVal c_val As Variant) As Boolean
    Dim g0 As Long

    chk_listbox2 = False

    With UserForm2.ListBox2

       For g0 = 0 To .ListCount - 1

          If .List(g0, 0) = c_val Then

             chk_listbox2 = True

             Exit For

          End If

       Next

    End With

 End Function

すみません、よろしくお願いします。
(やさもん) 2014/06/09(月) 21:45


 >色々数値を替えてやってみましたが、理解できず、書き込みさせてもらいました。 

 そのやったコードを見せてください。
 >ListBox1に読み込まないようにする方法は下記コードが判断しているのでしょうか? 
 そうです、この chk_listbox2というFunctionプロシジャーです。

 そのコードを以下のように訂正してください。

 Function chk_listbox2(ByVal c_val As Variant) As Boolean
    Dim g0 As Long
    Dim wkstr As String
    chk_listbox2 = False
    With UserForm1.ListBox2
       For g0 = 0 To .ListCount - 1
          wkstr = .List(g0, 0)
          If wkstr = c_val Then
             chk_listbox2 = True
             Exit For
          End If
       Next
    End With
 End Function

 まだこれは、サザエさん登場人物名で重複をチェックしているコードです。

 サザエさんの年齢を25にしてください。

 これで年齢にダブりがなくなりますから、この年齢をIDに見立てることができますよね?

 これで、年齢がダブらないように比較するには、どこを変更すればよいか?

 考えてみてください。

 年齢で チェックできれば、元のデータでも行けると思います。

(ichinose) 2014/06/10(火) 09:14


ichinose さん

ありがとうございました。
おかげさまで、アドバイス通りやってみたところできました。

あとバグがないか探ってみます。

解決です(^^)
(やさもん) 2014/06/12(木) 12:17


コメント返信:

[ 一覧(最新更新順) ]


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