[[20110606151528]] 『Dictionaryに配列を格納』(まー) ページの最後に飛ぶ

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

 

『Dictionaryに配列を格納』(まー)
 下記のようにDictionaryに配列を格納して、itemをインデックス番号で取り出すようにしたいのですが、下の構文で型が一致しませんとでます。
 w(i, 1) = myDic(ws.Range("F" & i + 1).Value)(0)
 どうすればよいのかご教授願います。素人なので根本的に間違っているかもしれないので詳しく教えていただけると幸いです。

 Sub test2()
 Dim las As Long, myr As Long, i As Long
 Dim ws As Worksheet
 Dim myDic As Object
 Dim w() As String
 Set ws = Sheets("Sheet1")
 myr = ws.Range("B" & Rows.Count).End(xlUp).Row
 With Sheets("Sheet2")
     las = .Range("A" & Rows.Count).End(xlUp).Row
     Set myDic = CreateObject("scripting.dictionary")
     For i = 2 To las
         If Not myDic.exists(.Range("CR" & i)) Then
            myDic(.Range("CR" & i).Value) = Array(.Range("AP" & i), .Range("DA" & i), .Range("DB" & i))
         End If
     Next
     ReDim w(1 To myr - 1, 1 To 3)
     For i = 1 To UBound(w, 1)
         w(i, 1) = myDic(ws.Range("F" & i + 1).Value)(0)
         w(i, 2) = myDic(ws.Range("F" & i + 1).Value)(1)
         w(i, 3) = myDic(ws.Range("F" & i + 1).Value)(2)
     Next
     Sheets("A").Range("A1").Resize(UBound(w, 1), 3) = w
 End With
 End Sub


取りあえず、最後の代入の For 文内を下記のようにして確認してみてはどうでしょうか。
    If Not myDic.exists(ws.Range("F" & i + 1).Value) Then
         MsgBox "[" & ws.Range("F" & i + 1).Value & "]がDictionary に登録されていません。"
    Else
         w(i, 1) = myDic(ws.Range("F" & i + 1).Value)(0)
         w(i, 2) = myDic(ws.Range("F" & i + 1).Value)(1)
         w(i, 3) = myDic(ws.Range("F" & i + 1).Value)(2)
    End If
 (Mook)


 現在のコードでエラーが出ますか?
 Dictionary を使用して Range Objectの値を参照する場合は、必ず .Value Propertyを
 記述しないとエラーの元ですけど。
 (seiya)

 w(i, 1) = myDic(ws.Range("F" & i + 1).Value)(0)
 これは、myDicのなかで、キーがws.Range("F" & i + 1).Valueであるものを取り出す。
 で、あれば、先にセットしているような一次元配列が取得できるけど、キーがなければ
 空白のVariant型データがかえってくる。なので、かえってきたもの(0) なんてやると
 配列じゃないからだめということになる。

 そもそもが、myDicへのセットはSheet2のセルの値をキーにしているのに、
 ws.と、Sheet1のセルの値をキーにして取り出そうとしている。
 なので、当然、未登録(このキーでは書きもまれていない)が発生する。
 myDic に登録されているかどうかは myDIc.Exists(キー) で判定可能(True/Flaseがかえってくる)
 未登録の場合は、それなりの対処が必要。(スキップするのか、あるいは、何か省略値で処理するのか)

 ところで、

 w(i, 1) = myDic(ws.Range("F" & i + 1).Value)(0)
 w(i, 2) = myDic(ws.Range("F" & i + 1).Value)(1)
 w(i, 3) = myDic(ws.Range("F" & i + 1).Value)(2)

 こうしてもいいけど、myDicへのアクセス、ws.Range("F" & i + 1) へのアクセスが、それぞれ3回発生。
 Variant型の変数を規定しておいて(たとえば Dim vvv As Variant) vvv = myDic(ws.Range("F" & i + 1).Value) と1回だけ取得して

 w(i, 1) = vvv(0)
 w(i, 2) = vvv(1)
 w(i, 3) = vvv(2)

 とやるほうが、効率がいい。

 ぶらっと立ち寄り


 追伸

 seiyaさんの指摘はきわめて重要。
 Dictionaryに限らず、たとえばVariant型変数に Array(セルRange,セルRange) なんてやると
 格納された要素は値ではなく、Rage Object。だから、あとで値として取りだそうとすると不具合がでる。
 これに限らず、プロパティは、省略せず、かならず明記!

 ぶらっと立ち寄り

 いま、思い出した。
 myDic(.Range("CR" & i).Value) = Array(.Range("AP" & i), .Range("DA" & i), .Range("DB" & i))
 この記述、私自身が、「ま」さんのQにサンプルとしてアップしたコードに記載した表記だったような・・・

 >これに限らず、プロパティは、省略せず、かならず明記!

 この指導文は、自分自身に向けて!

 ぶらっと立ち寄り@めちゃくちゃ懺悔

(まー)
みなさんありがとうございます。
 おっしゃるとおり、Valueプロパティを入れたら動きました。
 初心者ですいません。
 もう一つ質問です。

 上記のDictionaryのItemに配列を入れる件ですが、Arrayに入れる個数が不規則な場合です。

 例えばA列にA1からAのn行までをArrey関数に入れる場合

 Dim i as Long , n as Long
 Dim v as String
 Dim vvv as Variant
 With ActiveSheet
      n=.Range("A" & Rows.Count).end(xlup).Row
      v=.Cells(1,1).value
      For i = 1 to n
          v=v & "," & .Cells(i,1)
      Next
      vvv=Array(v)
 End With
 
 としてmyDicのアイテムとして格納しmyDic(★)(0)とすると、v が取り出されてしまいます。
 どのようにしたらよいですか?   

 vvv=Array(v)) → vvv=Split(v,",")
 HelpでSplit関数
 (seiya)

seiyaさんありがとうございます。できました。

 次々に質問するのではなく1つづつ解決していきませんか?

[[20110530155910]] 『Dictionaryについて』(まー)

[[20110529220102]] 『Rangeでの配列』(まー)

[[20110525000008]] 『outlookのメール本文にセルの内容を貼り付けたい』(まー)

[[20110517093650]] 『関数の参照先について』(まー)

 (放置新聞)

[[20110530155910]] 『Dictionaryについて』(まー) は確かに私ですが、他は違います。
同じHNの人がいるというこことですね。
次から名前変えます。まー

コメント返信:

[ 一覧(最新更新順) ]


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