Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


5223 / 13646 ツリー ←次へ | 前へ→

【51451】重複を無くすコードについて Misako 07/9/18(火) 21:55 質問[未読]
【51452】Re:重複を無くすコードについて ichinose 07/9/18(火) 23:19 発言[未読]
【51458】Re:重複を無くすコードについて Misako 07/9/19(水) 20:42 お礼[未読]
【51460】Re:重複を無くすコードについて ichinose 07/9/19(水) 21:57 発言[未読]
【51485】Re:重複を無くすコードについて Misako 07/9/20(木) 22:17 お礼[未読]
【51530】Re:重複を無くすコードについて ichinose 07/9/21(金) 19:42 発言[未読]
【51534】Re:重複を無くすコードについて 多摩川 07/9/22(土) 0:02 お礼[未読]
【52052】Re:重複を無くすコードについて Misako 07/10/17(水) 22:59 お礼[未読]

【51451】重複を無くすコードについて
質問  Misako  - 07/9/18(火) 21:55 -

引用なし
パスワード
   このサイトで、下のコードの「重複を除く」コードを記録させていただき、
活用させていただいています。私にとって大切なコードです。
今は、理屈も分からず丸暗記です。
しかし、今になっても、コードが理解できません。
特にComboBox1.List(i)の理解が出来ません。
何故重複した場合にList(i)のところで吸収して
動作するのかも理解できません。
理屈が分かるほうが・・・といつも思っていました。
Debug.Printでは結果が出て、結果だけは判るのですが・・・
解説をしていただければありがたいのですが、よろしくお願いします。

Private Sub UserForm_Initialize()
Dim k As Long
Dim i As Long
For k = 6 To Range("A65536").End(xlUp).Row
  For i = 0 To ComboBox1.ListCount - 1 
    If Cells(k, 1).Value = ComboBox1.List(i) Then
       Exit For
    End If
  Next i
  If i = ComboBox1.ListCount Then
    ComboBox1.AddItem Cells(k, 1).Value
  End If
Next k
End Sub

【51452】Re:重複を無くすコードについて
発言  ichinose  - 07/9/18(火) 23:19 -

引用なし
パスワード
   ▼Misako さん:
こんばんは。

>このサイトで、下のコードの「重複を除く」コードを記録させていただき、
>活用させていただいています。私にとって大切なコードです。
下記のコードは、出力としてコンボボックスにA列のデータを重複なしで登録するコードですよね?

つまり、コンボボックスCombobox1には、重複するデータは登録されていないのです。


>
>Private Sub UserForm_Initialize()
>Dim k As Long
>Dim i As Long
>For k = 6 To Range("A65536").End(xlUp).Row

'****************************************************************
>  For i = 0 To ComboBox1.ListCount - 1 
>    If Cells(k, 1).Value = ComboBox1.List(i) Then
>       Exit For
>    End If
>  Next i
'****************************************************************
'この中のコードは、セルの値(A6から始まる)とCombobox1に登録されている値の全て
'と等しいか否かの比較をしています。

'セルの値とCombobox1に登録されているメンバの中で等しいメンバがあれば、そのセルの
'値は、Combobox1に登録しません(重複は、含まないのですから)。

'そのセルがCombobox1に登録されているメンバの中のどれとも等しくなければ、
'そのセルをCombobox1に登録します。

'その判断が↓このIf文で行っています。これがちょっとわかりにくいですね!!
'iがComboBox1.ListCount と等しいということは、Combobox1のメンバと全て比較し、
'等しくなかったということです。つまり、新たにCombobox1にそのセルの値は登録されます。
'反対に、等しくない場合は、そのセルの値が、Combobox1のメンバに既に存在することを意味します。
'よって、そのセルの値は、Combobox1に登録しません

>  If i = ComboBox1.ListCount Then
>    ComboBox1.AddItem Cells(k, 1).Value
>  End If
>Next k
>End Sub

これでいかがですか?


Private Sub UserForm_Initialize()
Dim k As Long
Dim i As Long
For k = 6 To Range("A65536").End(xlUp).Row
  For i = 0 To ComboBox1.ListCount - 1
    If Cells(k, 1).Value = ComboBox1.List(i) Then
      Debug.Print Cells(k, 1).Row & " の " & Cells(k, 1).Value & " は既に存在します"
       Exit For
    End If
  Next i
  If i = ComboBox1.ListCount Then
    ComboBox1.AddItem Cells(k, 1).Value
  End If
Next k
End Sub

尚、上記のようにDebug.Printを入れて、見直してみてください

【51458】Re:重複を無くすコードについて
お礼  Misako  - 07/9/19(水) 20:42 -

引用なし
パスワード
   ▼ichinose さん:

今晩は、
丁寧なご説明感謝しています。
ありがとうございました。
大枠は理解できましたが、変数のiが0,1,2の動きが気になり
そこを見ていたものですから・・・理解が進みませんでした。

でも何故iの変数が0〜2の動きなのでしょうかね?
もう少しじっくりと勉強します。
先ずは御礼まで。
また、この続きを質問させていただくかも知れません。
その折にはまたよろしくお願いします。

【51460】Re:重複を無くすコードについて
発言  ichinose  - 07/9/19(水) 21:57 -

引用なし
パスワード
   ▼Misako さん:
こんばんは。
>でも何故iの変数が0〜2の動きなのでしょうかね?
ん? iが0〜2というような変化することが疑問に思う事の真意がちょっと
わかりませんが・・・。

Combobx1のメンバーはList()という配列に格納されています。
List()の最初の添え字が0なのですよ!!

例えば、上記のCombobox1にメンバとして、あ、い、う、え、お という5文字が
登録されているとすると・・・、

Combobox1.List(0)   ------> あ

Combobox1.List(1)   ------> い

Combobox1.List(2)   ------> う

Combobox1.List(3)   ------> え

Combobox1.List(4)   ------> お

となります。このListという配列の添え字としてiは使われています。

ですから、iは、0,1,2という変化をFor文によって制御され、
Combobox1のメンバを全て取得することが出来るのです。

これでいかがですか?

投稿ついでに、

提示されたコンボボックスに重複なしデータの登録処理コードは、
データによっては、重複なしデータになりません。


新規ブックにて確認してください。

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

このUserform1には、コンボボックス(Combobox1)を一つだけ配置してください。


このUserform1のモジュールには、提示されたコードをそのまま記述します。

'=================================
Private Sub UserForm_Initialize()
Dim k As Long
Dim i As Long
For k = 6 To Range("A65536").End(xlUp).Row
  For i = 0 To ComboBox1.ListCount - 1 
    If Cells(k, 1).Value = ComboBox1.List(i) Then
       Exit For
    End If
  Next i
  If i = ComboBox1.ListCount Then
    ComboBox1.AddItem Cells(k, 1).Value
  End If
Next k
End Sub

標準モジュールに
'===============================================================
Sub main()
  With ActiveSheet.Range("a6:a20")
    .Value = [{1;2;3;4;5;5;5;6;7;8;9;10;9;9;9}]
    MsgBox "A列にサンプルデータ作成しました。" & vbCrLf & _
       "これから、ユーザフォームのコンボボックスに重複なし登録します"
       
    End With
  UserForm1.Show
End Sub

としてmainを実行してみてください。

本来なら、コンボボックスには、
1,2,3,4,5,6,7,8,9,10 というメンバが登録されなければならないのに

数字が重複して登録されていませんか?

どこかにバグがありますから、考えてみてください。

【51485】Re:重複を無くすコードについて
お礼  Misako  - 07/9/20(木) 22:17 -

引用なし
パスワード
   ▼ichinose さん:

今晩は。
貴重な時間を割いて、解説頂きありがとうございました。
やっと分かりました。理解できました。
感謝、感謝です。
わだかまりが無くなくなりました。

それからサンプルを頂き、びっくりしました。
素晴らしいコードを頂き大切に残しておきたく思っています。

でも、バグがどこに?有るのか・・・と
その前に、以前数字でこの「重複」を無くすテストをしていて、
あっ…これは「数字」は対象外だなんて、勝手に決め付けており
ました。だからバグ?っとは、今の今まで思っていませんでした。

今の理解ではList()の添え字がこのケースでは0〜9まで使われていて、listの
中で制御できないのでしょうか?多分これでは無いかと判断しました。
つまり添え字の数字と重複を無くす数字の区別がつかないのでは。
と判断しました。これで正解でしょうか?。

本当に勉強になりました。もう少しまた勉強します。

【51530】Re:重複を無くすコードについて
発言  ichinose  - 07/9/21(金) 19:42 -

引用なし
パスワード
   こんばんは。

>でも、バグがどこに?有るのか・・・と
>その前に、以前数字でこの「重複」を無くすテストをしていて、
>あっ…これは「数字」は対象外だなんて、勝手に決め付けており
>ました。だからバグ?っとは、今の今まで思っていませんでした。
なるほど・・・。

>今の理解ではList()の添え字がこのケースでは0〜9まで使われていて、listの
>中で制御できないのでしょうか?多分これでは無いかと判断しました。
>つまり添え字の数字と重複を無くす数字の区別がつかないのでは。

添え字の数字iは直接は関係ありません。
でも、言い回しが違っているだけで 本質のところはお分かりなのかもね!!


では・・・。

新規ブック(あくまでも新規ブックですよ)の標準モジュールに
'=========================================================
Sub main()
  Dim g0 As Long
  Dim com As Variant
  Dim vardat1 As Variant
  Dim vardat2 As Variant
  Dim strdat As String
  Dim lngdat As Long
  Dim mes As String
  vardat1 = "123"
  vardat2 = 123
  strdat = "123"
  lngdat = 123
  With Range("a1:a5")
    .Value = Evaluate("{""vardat1----Variant  """"123"""""";" & _
          """vardat2----Variant  123""; " & _
          """strdat ----String  """"123"""""";" & _
          """lngdat ----Long   123"";" & _
          """これらの変数と定数で比較します""}")
  
    .Rows.AutoFit
    .Columns.AutoFit
    End With
  MsgBox "ready ?"
  If vardat1 = vardat2 Then
    mes = "vardat1 と vardat2は、等しい"
  Else
    mes = "vardat1 と vardat2は、等しくない"
    End If
  Cells(1, 3).Value = mes
  If vardat1 = lngdat Then
    mes = "vardat1 と lngdatは、等しい"
  Else
    mes = "vardat1 と lngdatは、等しくない"
    End If
  Cells(2, 3).Value = mes
  If vardat2 = strdat Then
    mes = "vardat2 と strdatは、等しい"
  Else
    mes = "vardat2 と strdatは、等しくない"
    End If
  Cells(3, 3).Value = mes
  If vardat1 = 123 Then
    mes = "vardat1 と 123は、等しい"
  Else
    mes = "vardat1 と 123は、等しくない"
    End If
  Cells(4, 3).Value = mes
  If vardat2 = "123" Then
    mes = "vardat2 と 文字列""123""は、等しい"
  Else
    mes = "vardat2 と 文字列""123""は、等しくない"
    End If
  Cells(5, 3).Value = mes
  With Range("c1:c4")
    .Columns.AutoFit
    End With
End Sub

mainを実行して見てください。

A列に入力された変数の型と変数の中身と

C列に入力された比較結果をよく見てみてください。

If文での比較では、

最初のVariant型の変数同士であるVardat1とVardat2を比較した結果以外は、

等しいという結果を出しています。

数値と文字列でもVariant型同士の比較でなければ、等しい という結果です。

では、元のコードに戻ると・・・、

Private Sub UserForm_Initialize()
Dim k As Long
Dim i As Long
For k = 6 To Range("A65536").End(xlUp).Row
  For i = 0 To ComboBox1.ListCount - 1 
    If Cells(k, 1).Value = ComboBox1.List(i) Then '★
'     このCells(k, 1).Value Variant型の数値であり、
'     ComboBox1.List(i) は、Variant型の文字列になります。
'     よって、セルに入っている5とList()に格納されている"5"は
'     決して等しくなりません。
'     つまり、このExit Forが実行されないので
'     同じ5が追加されてしまいます。
      Exit For
    End If
  Next i
  If i = ComboBox1.ListCount Then
    ComboBox1.AddItem Cells(k, 1).Value
  End If
Next k
End Sub

修正は、Variant型とVariant型の変数の比較にしなければ良いのですから、
★の行を

    If cstr(Cells(k, 1).Value) = ComboBox1.List(i) Then

と修正して再度確認してみてください。

今度は、数字も正しく重複なしで登録されると思いますよ!!


尚、重複なしのデータを取得する方法は、他にもいくつかあります

提示されたコードが悪いわけではありません。
が、もう少し簡単で処理の速い方法がここの過去ログにも
ありますから、調べてみてください。
(Dictionary または、AdvancedFilter 等をキーに検索してみてください)

【51534】Re:重複を無くすコードについて
お礼  多摩川  - 07/9/22(土) 0:02 -

引用なし
パスワード
   ▼ichinose さん:
横から失礼します。
勉強中の身としては非常に興味がある内容であり、ichinose さんの回答を待っていました。

Dim h As Long
h = Cells(k, 1).Value
とした場合、重複がなくなり、

Dim h As Long
h = ComboBox1.List(i)
とした場合も、重複がなくなり、

数値と文字を比較しているため、重複すると思っていました。
Cells(k, 1).Value はエクセル上では数値として認識されているため、
勝手に整数型になるものだと思い込んでいました。
なので、ComboBox1.List(i)は文字を返すのかと勝手に思ってしまいました。
Variant型になるんですね!
しかも、Variant型同士の比較はだめなのですね!!
勉強になりました。

【52052】Re:重複を無くすコードについて
お礼  Misako  - 07/10/17(水) 22:59 -

引用なし
パスワード
   ▼ichinose さん:

今晩は。
お礼が遅くなりました。
色々とサンプルの提示などご親切に教えていただき感謝しています。
コードは美味く動きました。
ただ、未だ理解がすすんでおりません。
勉強させていただきます。

お礼が本当に遅くなりましたことをお詫びいたします。
これからもよろしくお願いいたします。

5223 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free