- 締切済み
セル範囲から一次元配列の生成
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の配列の抜き出し方を 知っている方はお願い致します。
- みんなの回答 (5)
- 専門家の回答
みんなの回答
- end-u
- ベストアンサー率79% (496/625)
>インデックスをインクリメントしないと >ソートの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)
本筋とちょっとハズれるけど、実験コード。 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 意外と面白い結果です。 文字列の配列を指定した時だけ ヘルプ通り『追加済みのリストを指定したときは、このメソッドは無効になります。』 #失礼。ぷち情報でした。
- Wendy02
- ベストアンサー率57% (3570/6232)
こんばんは。 すでに、#2のend-uさんがご指摘のように、CustomList は、特に、配列にする必要はないはずです。単に、Range の範囲だけではいると思います。Helpには、「文字列の配列または Range オブジェクトを指定します。」となっています。 Application.AddCustomList Range("A1:A3") もし、入らないなら、それは、すでにCustomList に存在しているかものだったりするはずです。通常、マクロの場合は、Sort と組み合わせて使うし、後で、Application.DeleteCustomList i(←CustomListCountで数を取る) で、削除します。
お礼
わざわざRangeやRange().ValueをArrayに突っ込んでいたからいけなかったのですね。 ありがとうございます。 インデックスは Application.GetCustomListNum(Listarray:=DataList1) というふうに取り出しているのですが インデックスをインクリメントしないと ソートのCustomOrderに使用できないエラーは office2007だと直ってたりするんでしょうか? 2003と2007が両方使う環境で使用するもので・・・
- end-u
- ベストアンサー率79% (496/625)
配列経由しなくてもできますが、あえて、なのですよね? 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)
お礼
あえて、ではありません 知らなかったのです・・・・。 ありがとうございます。 Transposeか!すっかり忘れていました。 でも、そのままつっこむだけで勝手にリストにしてくれるようなので そのまま使いたいと思います。 ありがとうございました!
- kmetu
- ベストアンサー率41% (562/1346)
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 とかできませでしょうか。
お礼
回答ありがとうございます。 二次元配列のものにアクセスして、一次元データをとるのですね。 その場合配列が長いと、Loopしなければいけなくなってしまいますので。 ちょっとためらわれます。
お礼
おー! Rangeオブジェクトの重複登録はエラーになって、 文字列配列の場合は無効でスルーされるんですね。 登録時に If Application.GetCustomListNum(DataList1) = 0 Then '登録 End If としているので、エラーは発生しないでしょうけど。 Valueをとってあげたほうがよさそうですね。 ありがとうございます!!!!!