プロが教える店舗&オフィスのセキュリティ対策術

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の配列の抜き出し方を
知っている方はお願い致します。

A 回答 (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でも解消されていません。
バグを避けたコードのほうが良いと思いますよ。
    • good
    • 0

本筋とちょっとハズれるけど、実験コード。



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

意外と面白い結果です。
文字列の配列を指定した時だけ
ヘルプ通り『追加済みのリストを指定したときは、このメソッドは無効になります。』

#失礼。ぷち情報でした。
    • good
    • 0
この回答へのお礼

おー!
Rangeオブジェクトの重複登録はエラーになって、
文字列配列の場合は無効でスルーされるんですね。

登録時に
If Application.GetCustomListNum(DataList1) = 0 Then
'登録
End If
としているので、エラーは発生しないでしょうけど。
Valueをとってあげたほうがよさそうですね。
ありがとうございます!!!!!

お礼日時:2009/12/22 16:49

こんばんは。



すでに、#2のend-uさんがご指摘のように、CustomList は、特に、配列にする必要はないはずです。単に、Range の範囲だけではいると思います。Helpには、「文字列の配列または Range オブジェクトを指定します。」となっています。

Application.AddCustomList Range("A1:A3")

もし、入らないなら、それは、すでにCustomList に存在しているかものだったりするはずです。通常、マクロの場合は、Sort と組み合わせて使うし、後で、Application.DeleteCustomList i(←CustomListCountで数を取る) で、削除します。
    • good
    • 1
この回答へのお礼

わざわざRangeやRange().ValueをArrayに突っ込んでいたからいけなかったのですね。

ありがとうございます。

インデックスは
Application.GetCustomListNum(Listarray:=DataList1)
というふうに取り出しているのですが

インデックスをインクリメントしないと
ソートのCustomOrderに使用できないエラーは
office2007だと直ってたりするんでしょうか?

2003と2007が両方使う環境で使用するもので・・・

お礼日時:2009/12/22 16:42

配列経由しなくてもできますが、あえて、なのですよね?


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)
    • good
    • 0
この回答へのお礼

あえて、ではありません
知らなかったのです・・・・。

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

ありがとうございました!

お礼日時:2009/12/22 16:36

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

とかできませでしょうか。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

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

お礼日時:2009/12/22 16:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!