Excel VBA質問箱 IV

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

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


14783 / 76738 ←次へ | 前へ→

【67443】Re:重複したデータにしるしをつける
発言  kanabun  - 10/12/3(金) 20:30 -

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

>VBAが使えない私は非常に複雑で解読不能でした。。

>Dictionaryオブジェクトで重複チェック

について、少し踏み込んで コードの解説してみます。

シートのB列に 以下のようなデータがあるとします。
  [B]
[1] key
[2] ●
[3] ▲
[4] ●
[5] ■
[6] ●
[7] ▲

B列の2行目から、なのでプログラムの先頭定数宣言を
 Const COL1 = 2  '検索対象列
 Const ROW1 = 2  '検索する最初の行
と宣言します。

さて、
>  '↓検索範囲データを(文字列にして)配列にコピーする
>  With Columns(COL1).Cells
>    v = Application.Text(Excel.Range _
>      (.Item(ROW1), .Item(.Count).End(xlUp)), "@")
>  End With
を実行すると、
配列v は以下のようにB列の処理対象範囲のデータが格納されます。
※シートの2行目からですが、配列の1番目の要素は[1]です。

v(1,1) = "●"
v(2,1) = "▲"
v(3,1) = "●"
v(4,1) = "■"
v(5,1) = "●"
v(6,1) = "▲"

さて、その次に Dictionaryオブジェクトを宣言し、
> '↓Dicionaryを使って重複チェック
> Set dic = CreateObject("Scripting.Dictionary")
この配列(縦ベクトル)を上から順に格納していきます。

Dictioanryとは いってみれば バケツの集合のような
ものです。ただこのバケツにはすべてラベルが付いていて、
各バケツに付けられたラベルは他のバケツと重複しない
ことがDictionaryバケツの特長です。

それでは、
> ReDim dup(1 To UBound(v), 0)
により、検索配列v と同じ大きさの結果出力用の配列dup を
用意したあとのLoop処理を、いま配列v に格納されている
データ(これをDictionaryでは keyといいます) を順に処理
するLoop過程を↓
>  For i = 1 To UBound(v)
>    If dic.Exists(v(i, 1)) Then 'すでにこのキーが辞書にあれば
>      n = dic(v(i, 1)) 'このキーがどの行で出現したかを得る
>      If n > 0 Then
>        dup(n, 0) = "重複" '直前の出現行に「重複」書き込み
>        dic(v(i, 1)) = 0
>      End If
>      dup(i, 0) = "重複"     'この行に「重複」書き込み
>    Else
>      dic(v(i, 1)) = i '行のデータを出現行とともに辞書に入れる
>    End If
>  Next
実際にやってみましょう。

-------------------
i = 1 のとき v(i,1) は "●"です。
>    If dic.Exists(v(i, 1)) Then 'すでにこのキーが辞書にあれば
のIf文では、「"●" というラベルのバケツがDictionaryにすでに
存在していたら...」という判断をしています。
最初どんなラベルのバケツも存在しないので、
>    Else
>      dic(v(i, 1)) = i '行のデータを出現行とともに辞書に入れる
へジャンプします。
いま i=1 なので、上の文は具体的には
>     dic("●") = 1 '行のデータを出現行とともに辞書に入れる
という意味になります。つまり、
「Dictionaryに "●"というラベルの付いたバケツを用意し、
  そのバケツの中に 数値の1を入れる」
という意味になります。

-------------------
i = 2のときも、同様です。
"▲"というラベルのバケツはまだ存在しませんから、
>      dic(v(i, 1)) = i '行のデータを出現行とともに辞書に入れる
へジャンプして、
    dic("▲") = 2
により、「"▲"というラベルのバケツを用意し、その中に数値2 を入れる」
処理をします。

-------------------
i = 3 v(3,1)="●"のときには、これまでとちがう流れになります:
>    If dic.Exists(v(i, 1)) Then 'すでにこのキーが辞書にあれば
の判断で 「"●"というラベルのバケツはすでに存在する」となりますので
プログラムの実行は If文のすぐ下に↓ 移り、
>      n = dic(v(i, 1)) 'このキーがどの行で出現したかを得る
で、    n = dic("●")  つまり、
「"●"という名のバケツの中に入っている内容物」を n に取り出し
ています。「"●"という名のバケツの中」には i = 1 のときに 1 が
放りこまれていましたね(^^
 たから ここで n は 1 となります。
>      If n > 0 Then
>        dup(n, 0) = "重複" '直前の出現行に「重複」書き込み
>        dic(v(i, 1)) = 0
>      End If
のIf n > 0 だったときの処理は、
     結果の配列dupの n行目(つまり1行目)に "重複"と書き込み、
     さらに、"●"というラベルのバケツ内を 0 にする
という処理をしています。0 を入れるというのは バケツを空にする
ということです。つまり"●"というラベルのバケツは存在し続けるけど、
中身が「空」になる、ということです。
で、直後の処理↓で
>      dup(i, 0) = "重複"     'この行に「重複」書き込み
結果の配列dup 内の現在の行(3)にも "重複"を書き入れます。

i = 1 〜 3 までの処理で 配列の内容と Dictionary内のバケツは
このようになっています:
v(1,1) = "●"   dup(1,0) = "重複"
v(2,1) = "▲"   dup(2,0) = Empty
v(3,1) = "●"   dup(3,0) = "重複"

dic("●") = 0
dic("▲") = 2

-------------------
さて、この調子でつづけると、
i = 4, v(i,1) = "■" のときそういうラベルのバケツはまだ
  存在しませんから dic("■") = 4 の処理が実行され、
  "■"というラベルのバケツが用意されそのなかに4が
  収まります。
-------------------
i = 5, v(i,1) ="●"のときには、すでにある"●"という名の
  バケツの内容物を取り出しますが、中は「0」です。
  つまり、直前の"●"が出現した行にはすでに"重複"は書きこ
  まれている、ということです。
  よって、If文内の処理はせず、ただdupの5番目の要素に
  "重複"を書き込む処理だけをします。
-------------------
i = 6, v(6,1) ="▲"のときは、"▲"というラベルのバケツは
  すでにあり、その中身を調べる n = dic("▲") と n = 2
  が入っているので、dupの2番目に"重複"を書き込み、
  処理済みということで バケツ"▲"のなかを 0 にします
       dic("▲") = 0

-------------------
このようにして最終的に dupは
●  dup(1,0) ="重複"
▲  dup(2,0) ="重複"
●  dup(3,0) ="重複"
■  dup(4,0) =Empty
●  dup(5,0) ="重複"
▲  dup(6,0) ="重複"

となりますので、
これを 指定の列に貼りつければ ↓
> ' COL2 列に結果を書き出す
> Cells(ROW1, COL2).Resize(UBound(dup)).Value = dup

処理は完了、ということです。

いかがですか?
Dictioanryについて、多少はご理解いただけましたか?
0 hits

【67407】重複したデータにしるしをつける まりな 10/12/1(水) 16:59 質問
【67409】Re:重複したデータにしるしをつける Jaka 10/12/1(水) 17:08 発言
【67410】Re:重複したデータにしるしをつける kanabun 10/12/1(水) 18:27 発言
【67411】Re:重複したデータにしるしをつける UO3 10/12/1(水) 20:01 回答
【67441】Re:重複したデータにしるしをつける まりな 10/12/3(金) 16:31 質問
【67442】Re:重複したデータにしるしをつける kanabun 10/12/3(金) 17:42 発言
【67443】Re:重複したデータにしるしをつける kanabun 10/12/3(金) 20:30 発言
【67444】Re:重複したデータにしるしをつける kanabun 10/12/3(金) 20:52 発言
【67472】Re:重複したデータにしるしをつける まりな 10/12/8(水) 11:48 質問
【67526】Re:重複したデータにしるしをつける kanabun 10/12/10(金) 17:12 発言
【67524】Re:重複したデータにしるしをつける まりな 10/12/10(金) 16:22 質問
【67527】Re:重複したデータにしるしをつける kanabun 10/12/10(金) 20:24 発言
【67528】Re:重複したデータにしるしをつける kanabun 10/12/10(金) 20:33 発言
【67557】Re:重複したデータにしるしをつける まりな 10/12/13(月) 14:42 お礼
【67572】Re:重複したデータにしるしをつける まりな 10/12/14(火) 15:11 質問
【67574】Re:重複したデータにしるしをつける kanabun 10/12/14(火) 16:57 発言
【67581】Re:重複したデータにしるしをつける まりな 10/12/15(水) 16:52 お礼

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