Excel VBA質問箱 IV

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

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


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

【48104】Scripting.Dictionaryで教えて下さい。 質問(煮詰まった) 07/4/3(火) 21:10 質問[未読]
【48106】Re:Scripting.Dictionaryで教えて下さい。 neptune 07/4/3(火) 21:56 回答[未読]
【48109】Re:Scripting.Dictionaryで教えて下さい。 kobasan 07/4/3(火) 23:44 発言[未読]
【48118】Re:Scripting.Dictionaryで教えて下さい。 neptune 07/4/4(水) 11:34 発言[未読]
【48131】Re:Scripting.Dictionaryで教えて下さい。 kobasan 07/4/4(水) 21:54 発言[未読]
【48134】Re:Scripting.Dictionaryで教えて下さい。 ichinose 07/4/5(木) 0:19 発言[未読]
【48150】Re:Scripting.Dictionaryで教えて下さい。 neptune 07/4/5(木) 11:09 発言[未読]
【48130】Re:Scripting.Dictionaryで教えて下さい。 kobasan 07/4/4(水) 21:22 発言[未読]
【48220】Re:Scripting.Dictionaryで教えて下さい。 質問(煮詰まった) 07/4/9(月) 9:05 お礼[未読]

【48104】Scripting.Dictionaryで教えて下さい。
質問  質問(煮詰まった)  - 07/4/3(火) 21:10 -

引用なし
パスワード
   以下の内容で処理しているのですが
出力ファイルに284行目以降出力
されないのですが、これは何か
不具合なのでしょうか、それとも
メモリーないでの編集個数が多すぎるでしょうか?
お手数ですが、教えて下さい。


Dim vnt, a
  Dim dic As Object
  
  '
  With Sheets("作業3")
    vnt = .Range("M2", .Range("A65536").End(xlUp)).Value
  End With
  '
  Set dic = CreateObject("Scripting.Dictionary")
  For i = 1 To UBound(vnt, 1)
  
    If Not dic.exists(vnt(i, 7)) Then
      ReDim a(12)
      a(0) = vnt(i, 1)
      a(1) = vnt(i, 2)
      a(2) = vnt(i, 3)
      a(3) = vnt(i, 4)
      a(4) = vnt(i, 5)
      a(5) = vnt(i, 6)
      a(6) = vnt(i, 7)
      a(7) = vnt(i, 8)
      a(8) = vnt(i, 9)
      a(9) = vnt(i, 10)
      a(10) = vnt(i, 11)
      a(11) = vnt(i, 12)
      a(12) = vnt(i, 13)
       If vnt(i, 1) = "2" Then
         a(12) = a(12) + vnt(i, 9)
       End If
      
    Else
      a = dic(vnt(i, 7))
      a(8) = a(8) + vnt(i, 9)
            
       If vnt(i, 1) = "2" Then
         a(12) = a(12) + vnt(i, 9)
       End If
      
    End If
    '  a(8) = a(8) + vnt(i, 9)
    dic(vnt(i, 7)) = a
  
   Next i
  
  '-----結果出力
  With Sheets("作業4")
    .Cells.ClearContents
    .Range("A1").Resize(, 13).Value = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13")
  
    .Range("A2").Resize(dic.Count, 13).Value = Application _
          .Transpose(Application.Transpose(dic.items))
    .Select
  End With
  
  Erase vnt
  Set dic = Nothing

【48106】Re:Scripting.Dictionaryで教えて下さい。
回答  neptune  - 07/4/3(火) 21:56 -

引用なし
パスワード
   こんにちは

>メモリーないでの編集個数が多すぎるでしょうか?
そういう問題ではなく、
Excelの関数にはデータ数に制限があったと思います。
Transposeにも数千といったレベルであったと思います。
過去ログを検索してみてはどうですか?

質問には関係ないですが、なぜdictionaryなんでしょう??
重複回避をしているのは理解できますが。。

itemを確保(add)してないのに
dic(vnt(i, 7)) = a
とやると・・・エラーは出ないようですが・・・

【48109】Re:Scripting.Dictionaryで教えて下さい。
発言  kobasan  - 07/4/3(火) 23:44 -

引用なし
パスワード
   ▼neptune さん 今晩は。

>itemを確保(add)してないのに
>dic(vnt(i, 7)) = a
>とやると・・・エラーは出ないようですが・・・

これヘルプに次のような解説があるんです。

dictionary の Item プロパティ  Helpより
機能
Dictionary オブジェクトにある指定されたキーと関連付ける項目を設定します。
コレクションの場合、指定されたキーを基に項目を返します。値の取得も可能です。

構文

object.Item(key) [= newitem]

Item プロパティの構文は、次の指定項目から構成されます。
指定項目 内容
Object 必ず指定します。Dictionary オブジェクトの名前を指定します。
Key 必ず指定します。取得または追加する項目と関連付けるキーを指定します。
Newitem 省略可能です。引数 key で指定した値と関連付ける新しい項目を指定します。

解説
項目を変更するときに引数 key の値が見つからない場合は、
引数 newitem で指定された項目と関連付けられた新しいキーが作成されます。

既にある項目を取得しようとするときに引数 key の値が見つからない場合は、
新しいキーが作成され、関連付けられる項目は空の状態になります。


横から失礼しました。

【48118】Re:Scripting.Dictionaryで教えて下さい。
発言  neptune  - 07/4/4(水) 11:34 -

引用なし
パスワード
   こんにちは

kobasanさん、ありがとうございます。

>dic(vnt(i, 7)) = a
なので、itemsしか頭に浮かびませんでした。

VBのHelpに書いてありましたね。Scripting ランタイム ライブラリのHelpしか
見ていませんでしたのでItemsしか見てませんでした。
こちらにはそこまで親切に書いてませんね。

・・・やはり省略せずにキッチリaddしたほうが可読性はよくなりますね。

どうもありがとうございました。

ついでに書くと、配列をItemに格納するならdictionaryでは格納できないみたい
だからCollectionでなければ意味ないと思うし。

何故にdictionaryなのか?これは未だにわかりません。
尤も判断材料はUPされたソースだけですが。。。

【48130】Re:Scripting.Dictionaryで教えて下さい。
発言  kobasan  - 07/4/4(水) 21:22 -

引用なし
パスワード
   ▼質問(煮詰まった) さん 今晩は。

>出力ファイルに284行目以降出力
>されないのですが、これは何か
>不具合なのでしょうか、それとも

私のExcel2002,XPでは、8000行でもうまく出力できます。
ひょっとして、A列のデータが283行あたりで止まっていませんか。
確認してみてください。

【48131】Re:Scripting.Dictionaryで教えて下さい。
発言  kobasan  - 07/4/4(水) 21:54 -

引用なし
パスワード
   ▼neptune さん 今晩は。

>・・・やはり省略せずにキッチリaddしたほうが可読性はよくなりますね。

このあたりは、作る人の好み次第と思いますが。

a(i)=b
dic(K)=b
のような感じで、初心者には直感的で分かりやすいのかもしれませんね。

>ついでに書くと、配列をItemに格納するならdictionaryでは格納できないみたい
>だからCollectionでなければ意味ないと思うし。

今回のコードでは、配列aを格納しながら、ユニークリストの集計をしています。
この点では1次元配列をItemに格納して、dic.Itemsで二次元配列をつくりあげ、一気に結果を出力にしていますね。


>何故にdictionaryなのか?これは未だにわかりません。

この手の集計をdictionaryでやっているのはよく見るのですが。
もちろん、Collectionでもできますが、比較したらdictionaryの方が扱いやすいと思っています。

【48134】Re:Scripting.Dictionaryで教えて下さい。
発言  ichinose  - 07/4/5(木) 0:19 -

引用なし
パスワード
   ▼neptune さん:
こんばんは。
>ついでに書くと、配列をItemに格納するならdictionaryでは格納できないみたい
>だからCollectionでなければ意味ないと思うし。
>
>何故にdictionaryなのか?これは未だにわかりません。
私は逆にCollectionでなければならない理由がしりたいですねえ!!

実は、ちょっと話がずれる箇所もあるのですが・・・。

以前、

HTTP://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/modcore/html/deconthedictionaryobject.asp


の中の

>Dictionary オブジェクトより Collection オブジェクトのほうが役に立つ場合もあります。

と記述されている理由、具体例についての質問を目にし、また、
私なりの投稿をした覚えがあります。

でも、未だに私もすっきりしていません。
ちょっと優れているかなあ と思う点は、

For Each Obj In 文のObjにItemに適した型が指定できる。

インデックス番号が使える

なんてことは思いつきましたが、Dictionaryと比較して
もっと決定的な利点があるなら
知りたいと思っていました。

是非、ご意見を聞かせてください。

【48150】Re:Scripting.Dictionaryで教えて下さい。
発言  neptune  - 07/4/5(木) 11:09 -

引用なし
パスワード
   kobasanさん、ichinose さん:
こんにちは

先ず、知らなかったことがあります。
これは私が、dictionaryをいわゆる辞書としてしか使ったことがない事が
原因で、配列をItemの要素として、格納できることを知りませんでした。
kobasanさんのご指摘で検証してみて納得しました。
Sub test2()
   Dim dic
   Dim I As Long
   Dim a(5) As Long, b(5) As Long, c(5) As Long
  
   Set dic = CreateObject("Scripting.Dictionary")

  For I = 0 To 4
    a(I) = I
    b(I) = I + 1
    c(I) = I + 2
  Next I
  
  dic(0) = a
  dic(1) = b
  dic(2) = c
  
  For I = 0 To 4
    Debug.Print "a=" & dic(0)(I) & " ; b=" & dic(1)(I) & " ; c=" & dic(2)(I)
  Next I
End Sub

>私は逆にCollectionでなければならない理由がしりたいですねえ!!
に付いては上記の「知らなかった」のが原因です。従って、このケースの
場合Collectionでなければならない事はありません。

collectionに関してですが、決定的な違いはdictionaryにはObjectへの参照を
格納できないと思っていたのですが、
ichinose さんの
>是非、ご意見を聞かせてください。
で、ざっと検証してみました。結果できるようですね。
'UserFormにTextBox,ListBox,ComboBoxを各1個ずつ配置
Sub test2()
  Dim dic
  Dim I As Long
  Dim a As Object
  Dim b As Object
  Dim c As Object
  
  Set dic = CreateObject("Scripting.Dictionary")
  
  Set a = UserForm1.TextBox1
  a.Text = "TextBox1Sample"
  
  Set b = UserForm1.ListBox1
  b.AddItem "ListBox1Sample"
  b.ListIndex = 0
  
  Set c = UserForm1.ComboBox1
  c.AddItem "ComboBox1Sample"
  c.ListIndex = 0
  
  Set dic(0) = a
  Set dic(1) = b
  Set dic(2) = c

  Debug.Print "a:" & dic(0).Text & " b:" & dic(1).Text & " c:" & dic(2).Text
End Sub

以上の結果を踏まえると、
「カスタム オブジェクト モデルを作成する場合、Collection オブジェクトを使用して
カスタム コレクションへの参照を保存することができますがDictionary オブジェクトではこの操作は行えません」
は手間がかかるので検証してませんが、ここまで可能ならカスタム オブジェクト ・・・
以外には「もっと決定的な利点」は知りません。

ただ、やはり、私はobjectにはcollection、辞書的機能にはdictionaryを使うと思います。
(なじみの問題とcollection、dictionaryと言う言葉がわかり易いからですが^ ^;)
今思ったんですが、Classに子Classを持たせる際はカスタムオブジェクトだからやはり、
Collection しか使えないのかな???

kobasanさん、ichinose さんのご指摘、ご指導には感謝いたします。
自分で検証をした事でDictionary に対する理解が少しは深まったように思います。

kobasanさんの
>>・・・やはり省略せずにキッチリaddしたほうが可読性はよくなりますね。
>このあたりは、作る人の好み次第と思いますが。
それはそのとおりなのですが、やはり、入れるところを確保せずに入力するのは
作法から外れるようで抵抗がありますね。
これも個人的な好み、感覚ですが、規定のプロパティを省略したり、暗黙の参照などが嫌いなのと同じです。
好みなら、そうですかとしかいえませんけどね。


質問(煮詰まった) さん>
横道にずれてごめんなさい。で、肝心の問題はどうなったんですかね?
せっかく詳しい方が、訪れているので聞いた方がいいですよ。

【48220】Re:Scripting.Dictionaryで教えて下さい。
お礼  質問(煮詰まった)  - 07/4/9(月) 9:05 -

引用なし
パスワード
   確認してみます。
アドバイスありがとうございました。

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