• 締切済み

2次元のdictionary

こんにちは。 recordsetの結果をDictionaryにいれたいと思っています。 環境はWindows Vista、vbScriptで書いています。 set dc = createobject("scripting.dictionary") Set rs = Server.CreateObject("ADODB.Recordset") rs.open (sql文), con  for i = 0 to rs.recordcount -1 for j = 0 to rs.fields.count - 1 dc.add rs.fields(j).name, rs.fields(j).value next next ちょっとイメージっぽく書きましたが(このままではエラーでます)、要は複数のフィールドを持つ複数のレコードを入れられないかということです。 色々調べたりしてみたのですがわかりません。 できないのかな?と思いました。 もしできるなら書き方をご教授頂けたらと思います。 よろしくお願いします。

みんなの回答

  • end-u
  • ベストアンサー率79% (496/625)
回答No.8

>>dc(i) = rs.GetRows(1, adBookmarkCurrent) >これが理想なのですが、dc(i)という書き方はエラーになってしまいます。 >オブジェクトにindexがつけられればいいのですが。 "C:\temp\test.xls"のSheet1に適当な65535件のデータでテストしたコードを載せておきます。 特にエラーは出ないので、データもしくは環境のせいでしょうか。 >dc(i) = rs.GetRows(1, adBookmarkCurrent) とは、 dc.Add i, rs.GetRows(1, adBookmarkCurrent) と一緒で、i を index としています。 Const adBookmarkCurrent = 0 Const adOpenStatic = 3 Const wkName = "C:\temp\test.xls" Dim con Dim rs Dim sql Dim dc Dim i 'On Error Resume Next Set con = CreateObject("ADODB.Connection") With con   .Provider = "Microsoft.Jet.OLEDB.4.0"   .Properties("Extended Properties") = "Excel 8.0"   .Properties("Data Source") = wkName   .Open End With sql = "SELECT * FROM [Sheet1$]" Set rs = CreateObject("ADODB.Recordset") Set dc = CreateObject("scripting.dictionary") rs.Open sql, con, adOpenStatic Stop For i = 1 To rs.RecordCount   dc(i) = rs.GetRows(1, adBookmarkCurrent) Next rs.Close con.Close Stop MsgBox dc(1)(0, 0) & vbTab & dc(1)(1, 0) & vbTab & dc(1)(2, 0) MsgBox dc(2)(0, 0) & vbTab & dc(2)(1, 0) & vbTab & dc(2)(2, 0) MsgBox dc(dc.Count)(0, 0) & vbTab & dc(dc.Count)(1, 0) & vbTab & dc(dc.Count)(2, 0) Set dc = Nothing Set rs = Nothing Set con = Nothing If Err.Number <> 0 Then   MsgBox Err.Number & vbLf & Err.Description Else   MsgBox "end" End If #修正なしでVBAでも試せます。

  • rivoisu
  • ベストアンサー率36% (97/264)
回答No.7

いろいろ回答はあるけれど、結局どのようなデータを持ってどのように取り出すかがわからないとうろうろするばかりではないでしょうか。 私はキーを連結して1つのキーにしてしまえばと書いたけど 取り出すときに取り出すキーが二つともわかっていればこれでいいでしょう。 でも最初のキーで取り出したデータの中に2番目のキーがあるような場合はお手上げです。 正直連想配列の必要も無い場合もあるのではないかとも思っています。 どのようなデータを「どのように取り出したいか提示してもらえると回答も正解に塚づくのではないでしょうか、

  • end-u
  • ベストアンサー率79% (496/625)
回答No.6

Recordsetの結果をDictionaryに入れる時、何か別のkeyでレコード単位で入れるのですか? それともfields.Nameをkeyにしてフィールド単位で入れるのですか? GetRowsを使ってレコード単位で入れるなら Const adBookmarkCurrent = 0 Const adOpenStatic = 3 ': rs.Open sql, con, adOpenStatic Stop For i = 1 To rs.RecordCount   dc(i) = rs.GetRows(1, adBookmarkCurrent) Next rs.Close con.Close Stop MsgBox dc(1)(0, 0) & vbTab & dc(1)(1, 0) & vbTab & dc(1)(2, 0) MsgBox dc(2)(0, 0) & vbTab & dc(2)(1, 0) & vbTab & dc(2)(2, 0) こんな感じになるかと。 フィールド単位で、LoopでField別に配列を作ってもそんなに時間かかりますか? Dim v, w, x ': rs.Open sql, con Stop v = rs.GetRows ReDim w(UBound(v, 2)) For i = 0 To UBound(v, 1)   For j = 0 To UBound(v, 2)     w(j) = v(i, j)   Next   dc(rs.fields(i).Name) = w Next rs.Close con.Close Stop x = dc.keys MsgBox x(0) & vbTab & dc(x(0))(0) & vbTab & dc(x(0))(1) & vbTab & dc(x(0))(2) MsgBox x(1) & vbTab & dc(x(1))(0) & vbTab & dc(x(1))(1) & vbTab & dc(x(1))(2) Dictionaryに格納した後どうやって利用するかなのだと思いますが、 v = rs.GetRows ただ単に配列で保持しておくっていう意味じゃないんですよね?

harelip
質問者

補足

お返事ありがとうございます。 >dc(i) = rs.GetRows(1, adBookmarkCurrent) これが理想なのですが、dc(i)という書き方はエラーになってしまいます。 オブジェクトにindexがつけられればいいのですが。 >フィールド単位で、LoopでField別に配列を作ってもそんなに時間かかりますか? 処理件数によっては遅くなるのでは?という古い考えがありました; 経験言語の違う数名で話していたのですが、たとえばPHP経験者は連想配列で渡してもらいたい、他の者はオブジェクトで渡すべきだ(recordsetかDictionary)、などと色々意見がでまして。 私はVB経験者としてrecordsetかgetrowsでの配列渡しを提案したのですが、Rubyなどのように1行でできないか?と言われまして試行錯誤していました。 (つまり共通ライブラリの関数にsqlを渡すと接続・実行・切断を行って結果をもらいたい、と) recordsetはcloneが作れますが、さすがにコネクト切断すると中身も失われてしまいます。 格納後の処理の利便性ではなく、そういった経緯で悩んでいました。

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.5

#2&3です。 VBSでcollectionは使えないのですね、失礼しました。それでは、下記の様なのは如何でしょうか。安定して動くかどうかは定かでありません。珍奇な思いつきかも... Sub test3() Dim dic As Object, tempDic As Object Dim i As Long Set dic = CreateObject("Scripting.Dictionary") For i = 1 To 2 Set tempDic = CreateObject("Scripting.Dictionary") tempDic.Add "field_a", i tempDic.Add "field_b", "code" & Format(i, "00") dic.Add CStr(i), tempDic Set tempDic = Nothing Next i For i = 1 To 2 Debug.Print dic.Item(CStr(i)).Item("field_a") Debug.Print dic.Item(CStr(i)).Item("field_b") Next i End Sub #2が二次元配列で可能かどうかはお試し下さい。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.4

普通と違うやり方をしたいなら、この前に、何がしたいのか質問に書くべきでしょう。アイデアが横道にそれていませんか。 質問者の珍奇な思いつきに、つき合わされるのはかなわない。 他に普通のやり方があるのではないか。

harelip
質問者

補足

お返事ありがとうございます。 目的は、1つの関数でOpen Find Closeをしてデータを返せないか?というものです。 recordsetで返すと、その後別処理でCloseしないといけないので、 dc = Find(sql) みたいな感じで1行でできないかと思いました。

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.3

#2です。ちょっとピント外れでしたか。 下記の様なのは如何でしょうか。"a","b"のところをフィールド名にします。これなら、異なる型のフィールドのデータが入れられます。 Sub test2() Dim dic As Object Dim myKey As String Dim tempCollection As Collection Set dic = CreateObject("Scripting.Dictionary") Set tempCollection = New Collection myKey = "1" tempCollection.Add Item:=123, key:="a" tempCollection.Add Item:="ABC", key:="b" dic.Add myKey, tempCollection 'dictionaryにセット後、消してしまっても、dictionaryの中味は保持されている Set tempCollection = Nothing Debug.Print dic.Item(myKey)("a") Debug.Print dic.Item(myKey)("b") End Sub

harelip
質問者

お礼

お返事ありがとうございます。 Collectionを調べてみたのですが、VBScriptではCollectionが使えないようです;; 参考になりました。ありがとうございます!

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.2

dictionaryに配列を入れるコードをみたことがあります。 試しにやってみたら、下記の通りできました。VBAですが、ご参考まで。 Sub test() Dim dic As Object Dim myKey As String Dim i As Long Set dic = CreateObject("Scripting.Dictionary") myKey = "1" dic.Add myKey, Array(1, 2, 3, 4, 5) For i = 0 To UBound(dic.Item(myKey)) Debug.Print dic.Item(myKey)(i) Next i End Sub

harelip
質問者

補足

お返事ありがとうございます。 dic.Add myKey, Array(1, 2, 3, 4, 5) のArrayは1次元配列じゃないとやっぱりだめでしょうか? Getrowsを指定できれば使えるな~と思いました。 もし1次元配列で指定しなければいけないのなら、ループでField別に配列を作らないといけないので、処理時間をくってしまいそうなので、おとなしくrecordsetにしようと思います。

  • rivoisu
  • ベストアンサー率36% (97/264)
回答No.1

どのように取り出すのかが分かりませんが、二つのfieldを連結したものをキーにすれば一応連想配列はできると思います。

harelip
質問者

補足

お返事ありがとうございます。 >二つのfieldを連結したものをキー というのは具体的にはどういった手法なのでしょうか?

関連するQ&A

  • 二次元のDictionary

    ASPは全くの初心者です。 今回、二次元のDictionaryを使って値を表示させたいのですが 行き詰ってしまいました。 以下のコードをどのように変換すれば良いですか? <%@ LANGUAGE = VBSCRIPT %> <% call dictionary_create() Sub dictionary_create() Dim objParent Dim objChild dim x Set objParent = CreateObject("Scripting.Dictionary") For x=0 to 9 Set objChild = CreateObject("Scripting.Dictionary") objChild.Add "kaigi", "会議名"&i objChild.Add "Id", "0"&i objParent.Add x, objChild Set objChild = Nothing Response.Write objParent.Item("ConfName") Next end sub %>

  • adoのループについて カレントレコードについて

    adoのFor i = 1 To rs.RecordCountについて質問があります。 Sub test() Dim i As Long Dim MyFileName As String Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset MyFileName = CurrentProject.FullName cn.Open "Provider = Microsoft.ACE.OLEDB.12.0;" & "Data Source= " & MyFileName rs.Open "Tテーブル", cn, adOpenKeyset, adLockOptimistic For i = 1 To rs.RecordCount Debug.Print rs.Fields(0).Value rs.MoveNext Next rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub これを実行した時に、テーブルには、1,2,3・・・という値が入っていて、 イミディエイドウインドウにも1,2,3・・・と順番に取得されるのですが、 For i = 1 To rs.RecordCountを実行した時は、強制的にrs.MoveFirstされるのでしょうか? For i = 1 To rs.RecordCount rs.MoveFirst Debug.Print rs.Fields(0).Value rs.MoveNext Next これと同じ意味なのでしょうか? RecordCount プロパティ (ADO) のヘルプを見ましたが、この件に関する記述は探せませんでした。 ご回答よろしくお願いします。

  • EXCEL「Dictionaryオブジェクト」宣言

    EXCEL VBAにて Dictionaryオブジェクトを利用しようと思い ネット検索して調べていると・・・ 1)Dim MyDic As Object Set MyDic=CreateObject("Scripting.Dictionary") 2) Dim MyDic As Scripting.Dictionary Set MyDic = New Scripting.Dictionary 3) Dim MyDic Set MyDic=CreateObject("Scripting.Dictionary") 4) Dim myDic As New Scripting.Dictionary 上記の4パターンが出てきました。 いずれも「連想配列」を使うものなのですが、 オブジェクト型、バリアント型、Newキーワードで宣言・・・ 4つの違いがイマイチ理解できません。 違いを教えてください。

  • VBAのdictionaryでAddの使い方

    VBAでつぎのコードを実行すると、a,A1.1の後、a,A2.2と表示します。 dicには、a,A2.2の設定をしていないのになぜこうなるのでしょうか? どなたか教えてください。 Sub sample() Dim dic As Object Dim subDic As Object Set dic = CreateObject("Scripting.Dictionary") Set subDic = CreateObject("Scripting.Dictionary") subDic.Add "A1", 1 dic.Add "a", subDic subDic.Add "A2", 2 '結果表示 Dim key1 As Variant Dim key2 As Variant For Each key1 In dic.keys For Each key2 In dic(key1).keys MsgBox key1 & "," & key2 & ". " & dic(key1)(key2) Next Next End Sub

  • なぜrs.Move i ではダメなのでしょうか?

    access2003です。 テーブル1には、 フィールド1 あ い う え お が入っています。 Sub test() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim i As Long Set cn = CurrentProject.Connection rs.Open "テーブル1", cn, adOpenKeyset, adLockOptimistic For i = 0 To rs.RecordCount rs.Move i Debug.Print rs.Fields(0).Value Next rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub をすると、 あ い え とイミディエイトウインドウに表示されるのですが Debug.Print rs.Fields(0).Value の部分で 「実行時エラー'3021' BOFとEOFのいずれかTRUEになっていか、または現在のレコードが削除されています。 要求された操作には、現在のレコードが必要です。」 となります。 その時のiの値は、3です。 rs.MoveFirst For i = 1 To rs.RecordCount Debug.Print rs.Fields(0).Value rs.MoveNext Next にすると、 あ い う え お が取得されます。 なぜrs.Move i ではダメなのでしょうか? 理由を教えてください。

  • Dictionaryについてその2

    CreateObject("Scripting.Dictionary")でセットしたオブジェクトは関数の戻り値として取得できますか? 例) --------------------------------------------- Dim RetObj Dim RecValue RetObj = CreateRec() RecValue = RetObj.Item("1") Response.Write(recValue) Private Function CreateRec() Dim RecSet Set RecSet = CreateObject("Scripting.Dictionary") RecSet.Add "1","山田" CreateRec = RecSet Exit Function End Function ------------------------------------------------- 現在のエラー状況 ●エラー タイプ Microsoft VBScript 実行時エラー (0x800A01C2) 引数の数が一致していません。または不正なプロパティを指定しています。 (余談)セットしたオブジェクトを引数渡しは出来るのに戻り値としてとれないのは・・・知識不足ですが不思議です。。 ご教授をお願いいたします

  • Dictionaryの使用に先立って・・・

    いつもお世話になっています。 CreateObject("Scripting.Dictionary")を使用して、 DBから取得したレコードを格納したいのですが、VBのようにコレクションのプロパティを使用することは出来ないのでしょうか? ------------------------------------------------- 例) レコード取得一覧: Filds("ID"),Filds("NAME") 処理を行いたい構想: Dim AAA 'コレクション Dim gRst 'レコードセットオブジェクト Set AAA = CreateObject("Scripting.Dictionary") Do Until gRst.EOF   AAA.ID = gRst.Filds("ID")   AAA.NAME = gRst.Filds("NAME")   '次のレコード  gRst.MoveNext Loop ------------------------------------------------ 大変お手数ですが、ご教授をお願いいたします。

  • Dictionaryについて3

    簡単に作ったソースなのですが、 以下の構文でエラーが発生します。 Dictionaryで作成したオブジェクトの束を配列として 格納させ、更にその配列を復帰値として取得し、メインルーチンにて展開させようと思っています。 以下のソースで考えられることございますか? 色々調べているのですが、述べ2日ハマっています。 ---------------------------------------------- Dim AAA,BBB(),CCC Set CCC=TEST 'CCCオブジェクトを展開し、値を画面に表示させる ’(未着手) private function TEST() Set AAA = CreateObject("Scripting.Dictionary") AAA.Add "1","111" ReDim Preserve BBB(0) Set BBB(0) = AAA Set TEST=BBB ←エラー個所 Exit Function End Function --------------------------------------------- エラー タイプ Microsoft VBScript 実行時エラー (0x800A01A8) オブジェクトがありません。

  • Excelマクロ

    お世話になります。 Excelマクロについて、ざっくりとした質問なのですが、 以下のマクロを実行した時に、オブジェクトXXXには、 どのようなものを格納できるのでしょうか。 Dim XXX As Object Set XXX = CreateObject("Scripting.Dictionary") 「CreateObject」と「Scripting.Dictionary」の使い方を調べてはみたのですが、 それぞれの使い方が今ひとつ分かりません。 お力添えいただきたいと思います。 よろしくお願いいたします。 以上

  • DictionaryオブジェクトのItemの型は?

    このコードの○○○には何を書けばよいのでしょうか?  (下から2行目です) コードの間は適当に省略しています。 Sub test() Set Dic = CreateObject("Scripting.Dictionary") Items = Dic.Items   j = Func2(Items(k)) End Sub Function Func2(a As ○○○) End Function

専門家に質問してみよう