• 締切済み

セル範囲から一次元配列の生成

VBAで動的に一次元配列を作成しようと思っています。 Dim DataList01 DataList01 = Array("項目01", "項目02", "項目03") のような配列を DataList01 = Array(Range("A1:A3").Value) などという方法で作成することはできないでしょうか? 動的に作成したArrayを、ユーザー設定リストに登録し、 ソートを行おうと考えていますが DataList01 = Array(Range("A1:A3").Value) Application.AddCustomList Listarray:=DataList01 で行うと、登録時点でエラーが発生します。 (実行時エラー '13':型が一致しません。) 行や列の情報を除外した、RangeからValueの配列の抜き出し方を 知っている方はお願い致します。

みんなの回答

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

>インデックスをインクリメントしないと >ソートのCustomOrderに使用できないエラーは >office2007だと直ってたりするんでしょうか? 直っていません。 2007では新たにSortオブジェクトが追加されていて その[SortFields.Add メソッド]の引数[CustomOrder]ではListarrayそのものを指定するように変更されているようです。 でも2003と2007互換を保とうとするなら従来のSortメソッドを使う事になるでしょう。 2007でも従来のSortメソッドが使えます。 その場合http://support.microsoft.com/kb/134913/jaこのバグは解消されていません。 これは、試してもらえばすぐわかる事ですよね? 『2003と2007が両方使う環境で使用するもの』であれば、両方の環境でテストする必要があります。 もし貴方が他の人に使ってもらうマクロを提供している立場で、稼働環境を限定できないのなら その辺りのテストの手間を省いてはいけないのではないですか? 掲示板で訊くのもいいかもしれませんけど、その場合はせめてテストコードを提示するべきだと思います。 Option Explicit Sub Custom_SortTest()   Dim iListIndex As Long   Dim vSort   vSort = Array("b", "c", "a")   Application.AddCustomList ListArray:=vSort   iListIndex = Application.GetCustomListNum(vSort)   With Sheets.Add.Range("A1:A3")     .Value = [{"c";"b";"a"}]     .Sort Key1:=.Cells, _        Header:=xlNo, _        OrderCustom:=iListIndex     Debug.Print "1", Join(Application.Transpose(.Value))     .Sort Key1:=.Cells, _        Header:=xlNo, _        OrderCustom:=iListIndex + 1     Debug.Print "2", Join(Application.Transpose(.Value))   End With   Application.DeleteCustomList (iListIndex) End Sub あと、また余談ですが >Valueをとってあげたほうがよさそうですね。 というのは配列にとったほうが良いという意味でしょうか。 それともValueプロパティを抜いてRangeで指定したほうが良いという意味? (前者だとは思いましたが念のため) セル範囲を指定した場合エラーが出るのはバグですし、 http://support.microsoft.com/kb/211811/ja 2007でも解消されていません。 バグを避けたコードのほうが良いと思いますよ。

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

本筋とちょっとハズれるけど、実験コード。 Sub test()   Dim ws As Worksheet   Dim v, DataList01      v = [{"aaa";"bbb";"ccc"}]   Set ws = Sheets.Add   ws.Range("A1:A3").Value = v   ws.Range("B1:B3").Value = v   DataList01 = Array(ws.Range("A1:A3").Value)   On Error Resume Next   With Application     .AddCustomList ListArray:=DataList01     MsgBox "ご質問状況" & vbLf & Err().Number & ":" & Err().Description     Err().Clear     .AddCustomList ListArray:=ws.Range("A1:A3")     MsgBox "追加1-1 " & .CustomListCount     .AddCustomList ListArray:=ws.Range("B1:B3") 'ws.Range("A1:A3")     MsgBox "追加1-2 " & .CustomListCount     MsgBox "重複登録の場合" & vbLf & Err().Number & ":" & Err().Description     .DeleteCustomList (.GetCustomListNum(v))     MsgBox "削除後 " & .CustomListCount     Err().Clear          .AddCustomList ListArray:=ws.Range("A1:A3").Value     MsgBox "余談ですが" & vbLf & "追加2-1 " & .CustomListCount     .AddCustomList ListArray:=ws.Range("A1:A3").Value     MsgBox "追加2-2 " & .CustomListCount     MsgBox "余談コードのエラー" & vbLf & Err().Number & ":" & Err().Description     .DeleteCustomList (.GetCustomListNum(v))     MsgBox "削除後 " & .CustomListCount   End With   Set ws = Nothing End Sub 意外と面白い結果です。 文字列の配列を指定した時だけ ヘルプ通り『追加済みのリストを指定したときは、このメソッドは無効になります。』 #失礼。ぷち情報でした。

potluckker
質問者

お礼

おー! Rangeオブジェクトの重複登録はエラーになって、 文字列配列の場合は無効でスルーされるんですね。 登録時に If Application.GetCustomListNum(DataList1) = 0 Then '登録 End If としているので、エラーは発生しないでしょうけど。 Valueをとってあげたほうがよさそうですね。 ありがとうございます!!!!!

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.3

こんばんは。 すでに、#2のend-uさんがご指摘のように、CustomList は、特に、配列にする必要はないはずです。単に、Range の範囲だけではいると思います。Helpには、「文字列の配列または Range オブジェクトを指定します。」となっています。 Application.AddCustomList Range("A1:A3") もし、入らないなら、それは、すでにCustomList に存在しているかものだったりするはずです。通常、マクロの場合は、Sort と組み合わせて使うし、後で、Application.DeleteCustomList i(←CustomListCountで数を取る) で、削除します。

potluckker
質問者

お礼

わざわざRangeやRange().ValueをArrayに突っ込んでいたからいけなかったのですね。 ありがとうございます。 インデックスは Application.GetCustomListNum(Listarray:=DataList1) というふうに取り出しているのですが インデックスをインクリメントしないと ソートのCustomOrderに使用できないエラーは office2007だと直ってたりするんでしょうか? 2003と2007が両方使う環境で使用するもので・・・

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

配列経由しなくてもできますが、あえて、なのですよね? Application.AddCustomList Listarray:=Range("A1:A3").Value >行や列の情報を除外した、RangeからValueの配列の抜き出し方を DataList01がVariant型なので DataList01 = Range("A1:A3").Value Application.AddCustomList Listarray:=DataList01 とすれば良いです。 DataList01は二次元配列になります。 一次元配列にしたいならTranspose関数を使います。 DataList01 = Application.Transpose(Range("A1:A3").Value)

potluckker
質問者

お礼

あえて、ではありません 知らなかったのです・・・・。 ありがとうございます。 Transposeか!すっかり忘れていました。 でも、そのままつっこむだけで勝手にリストにしてくれるようなので そのまま使いたいと思います。 ありがとうございました!

  • kmetu
  • ベストアンサー率41% (562/1346)
回答No.1

Dim buf As Variant buf = Range("A1:A3").Value で二次元配列 buf(n,1) にデータを格納できます。 DataList01 = Array(buf(1,1),buf(2,1),buf(3,1)) Application.AddCustomList Listarray:=DataList01 とかできませでしょうか。

potluckker
質問者

お礼

回答ありがとうございます。 二次元配列のものにアクセスして、一次元データをとるのですね。 その場合配列が長いと、Loopしなければいけなくなってしまいますので。 ちょっとためらわれます。

関連するQ&A