[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『VBAのDictionaryを使って、特定の文字があった場合にカウントしたい』(VBA初心者ひば)
countifを使用する場合のコードは理解できたのですが、
勉強中のDictionaryを使った場合のコードをネットで調べても、
よく理解出来なかったため質問します。
下記のようにA列の2行目から約70000行まで、
空欄または"あああ"が入っている行が混在しています。
A列に"あああ"と入っている行数を数えるVBAのコードを教えてください。
(下の場合は4とMsgboxに出るようにしたいです)
A列
2行目 あああ
3行目
4行目 あああ
5行目 あああ
6行目
・
・
・
70000行目 あああ
< 使用 Excel:Office365、使用 OS:Windows10 >
こんなので行けないかな?
Sub Sample() Const strFixed As String = "あああ" Dim dicT As Object Dim aCell As Range
Set dicT = CreateObject("Scripting.Dictionary")
For Each aCell In Range("A2", Cells(Rows.Count, "A").End(xlUp)) If aCell = strFixed Then dicT(strFixed) = dicT(strFixed) + 1 End If Next
MsgBox dicT(strFixed) End Sub
(半平太) 2022/03/16(水) 17:19
蛇足ですが。
複数候補について出現個数を集計する例にすると、 Dictionaryを使う有難みがより明確になるかもしれません。 (まあ、それ言い出したら、COUNTIFじゃないか等々、収拾がつかなくなります。 マクロの練習という意味で考えます)
Sub test() Dim dic As Object Dim r As Range Dim v As Variant
Set dic = CreateObject("Scripting.Dictionary") dic("aa") = 0 '一例です。要修正 dic("bb") = 0
For Each r In Range("A1", Cells(Rows.Count, "A").End(xlUp)) v = r.Value If dic.Exists(v) Then dic(v) = dic(v) + 1 End If Next [D1].Resize(dic.Count, 1) = Application.Transpose(dic.keys) [E1].Resize(dic.Count, 1) = Application.Transpose(dic.items) End Sub
なお、数値(1)と数字("1")を同一視したい場合は、 vを文字列型変数にするとよいと思います。
(γ) 2022/03/16(水) 20:01
例えばA列の飛び飛びセルに、あああ いいい あああ ううう ううう おおお あああ
とあるとして、重複を除いた数(この場合なら、4)を出したい場合も半平太様のDictionaryのやり方で出来たりしますか?
それとも違うやり方になりますか?
(便乗) 2022/03/19(土) 09:09
当初の質問は「あああ」が何個あるかです。
「あああ」限定なんて、Dictionaryの使い方としては極めて稀です。 Dictionaryの出番さえないケースです。
普通は、「あああ」「いい」・・がそれぞれ何個あるかを知りたい、なんて時でしょう。
さて、便乗質問に関しては、「あああ」「いい」・・の種類の数ですから、 それよりずーっと簡単で、Dictionaryのプリミティブな使い方と言えますね。
Sub Sample() Dim dicT As Object Dim aCell As Range
Set dicT = CreateObject("Scripting.Dictionary")
For Each aCell In Range("A2", Cells(Rows.Count, "A").End(xlUp)) If aCell <> "" Then dicT(aCell.Value) = Empty '「.Value」は省略してはならない End If Next
MsgBox dicT.Count End Sub
(半平太) 2022/03/19(土) 09:53
Emptyを格納するとはどう言う事なのかが調べても分からず、、
すみません、教えて下さい。
(便乗) 2022/03/19(土) 12:30
>Emptyを格納するとはどう言う事なのかが調べても分からず、
Emptyに限定した話ではありません。 "A"でもいいし、100でもいいです。何だっていいんです。
目的は、重複のない(当然ですけど)キーが幾つあるかを調べることであって、 対応するItemが何かは無関係です。
そう言う場合、便乗さんは何を格納させますか?(彼女の名前?)
(半平太) 2022/03/19(土) 12:58
すでにコメントいただいたとおりですが、 つらつら書いてしまったので。
(1)
重複を排除した要素の種類だけを得たいといった場合は、 Emptyを itemに明示的にセットすることで、 値は使わずKeyのほうにだけ興味があることを、 コードを読む人(他人もしくは将来の自分)に明示的に示せます。
また値を使う場合でも、 そもそもEmptyとは、 ・文字列としては""と同等、 ・数値としては0と同等になる 特別のキーワードなので汎用性はあります。
ただし、個数をカウントしたい、などという場合は、 dic("a") = 0 などとすると意図は明確になると思います。
(2)
一般的な話として、テキストではdic.Addを使う例が多いですが、 実務的にはdic("A") = "B"といった書き方をすることが多いです。
そして、本来Existsを使わないといけない場面で、 If dic("A") = "" Then のように、(キーを作っていないのに)値を取得しようとすると、 その行為によってkeyを"A"としたdictionaryのペアが作成されてしまうので、 注意が必要です。
以下を試してみます。 Sub test() Dim dic As Object Set dic = CreateObject("Scripting.Dictionary")
If dic("a") = 0 Then Debug.Print "間違った使い方" Debug.Print dic("a"), TypeName(dic("a")) '(*) End Sub などとすると、(*)はエラーにならず、dic("a")が参照できてしまうことがわかります。
その際、TypeNameは Emptyを返すので、 ・itemは初期化されていないと解釈するのか、 ・Empty値が自動的にセットされているとみるか は自信がありませんが、明示的にEmptyとしていないので、 たぶん前者の解釈になるのかなとは思いますが。
(γ) 2022/03/19(土) 14:11
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.