[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2006/02/10(Fri) 10:44
投稿者名:gt
URL :
タイトル:
動的に2次元配列
お世話になっています。gtです。

動的に2次元配列についてお伺いします。
1次元動的に配列ができていますが、
2次元配列ほうがどう宣言すればいいでしょうか。
よろしくお願いします。

環境:Win2000 VB6.0

投稿時間:2006/02/10(Fri) 11:07
投稿者名:これ
URL :
タイトル:
Re: 動的に2次元配列
> 動的に2次元配列についてお伺いします。
> 1次元動的に配列ができていますが、
> 2次元配列ほうがどう宣言すればいいでしょうか。

同じですよ。
MSDN は持ってませんか?Webの方は.NETになってしまってるので
参考にならないかもしれませんが
VBScriptの方で検索すると
hhttp://tryasp.winscom.co.jp/document/vbscript/569.htm

Dim ステートメントで空のかっこを使うと、動的配列を宣言できます。
宣言した後で、動的配列の次元と要素の数をプロシージャ内で定義するには
ReDim ステートメントを使います。
ということなので 次元数もReDimでできます。
当サイト管理人の花ちゃんさんもよく書かれていますが
まず自分で検索してみることをお勧めします。

投稿時間:2006/02/10(Fri) 11:57
投稿者名:gt
URL :
タイトル:
Re^2: 動的に2次元配列
> MSDN は持ってませんか?Webの方は.NETになってしまってるので
> 参考にならないかもしれませんが
> VBScriptの方で検索すると
> hhttp://tryasp.winscom.co.jp/document/vbscript/569.htm
>
> Dim ステートメントで空のかっこを使うと、動的配列を宣言できます。
> 宣言した後で、動的配列の次元と要素の数をプロシージャ内で定義するには
> ReDim ステートメントを使います。
> ということなので 次元数もReDimでできます。
> 当サイト管理人の花ちゃんさんもよく書かれていますが
> まず自分で検索してみることをお勧めします。
返事ありがとう。
例を示す
Dim arr() As Variant
Dim i As Integer

ReDim arr(2, 0)
arr(0, 0) = "a"
arr(1, 0) = "b"
arr(2, 0) = "c"

ReDim Preserve arr(2, 3)  'エラーが起きない
For i = 0 To 3
   arr(0, i) = "a" & i
   arr(1, i) = "b" & i
   arr(2, i) = "c" & i
Next
   ReDim Preserve arr(2, 5)  'エラーが起きない
For i = 0 To 5
   arr(0, i) = "a" & i
   arr(1, i) = "b" & i
   arr(2, i) = "c" & i
Next
  ReDim Preserve arr(10, 5)  'エラーです

Preserve は配列の最後の次元の要素数を変更する場合に使用する(Helpに書いてある)
配列の第一要素を変換したい場合
arr(10, 5)
どうしたらいいでしょうか。

よろしくお願いします.

投稿時間:2006/02/10(Fri) 12:43
投稿者名:demontaki
URL :
タイトル:
Re^3: 動的に2次元配列
> Preserve は配列の最後の次元の要素数を変更する場合に使用する(Helpに書いてある)
> 配列の第一要素を変換したい場合
> arr(10, 5)
> どうしたらいいでしょうか。
> よろしくお願いします.

どうもdemontakiです。
この場合にはReDimで単純に処理することはできません
その理由としてはヘルプに以下のように書かれているためです。

--ヘルプより引用
キーワード Preserve を指定した場合、変更できるのは、動的配列の最後の次元のサイズに限られま
す。また、次元数は変更できません。
引用終わり--

上記の記述により2次元配列であれば1次元目のサイズを変更することはできません
したがってこの場合の対処として下記のような方法が考えられます。
なお、ソースはgtさんのものを流用させていただきます。

Dim arr()       As Variant
Dim arr_Conv()  As Variant 'コンバート用の配列を用意します。
Dim i           As Integer

    ReDim arr(2, 0)
    arr(0, 0) = "a"
    arr(1, 0) = "b"
    arr(2, 0) = "c"
    ReDim Preserve arr(2, 3) 'エラーが起きない
    For i = 0 To 3
        arr(0, i) = "a" & i
        arr(1, i) = "b" & i
        arr(2, i) = "c" & i
    Next
    ReDim Preserve arr(2, 5) 'エラーが起きない
    For i = 0 To 5
        arr(0, i) = "a" & i
        arr(1, i) = "b" & i
        arr(2, i) = "c" & i
    Next
    ReDim arr_Conv(10, 5) 'コンバート用の配列を目的のサイズに設定します。
    arr_Conv() = arr()   '基となる配列をコンバート用の配列に移動させます。
    ReDim arr(10, 5)    'キーワード Preserveを付けていないため目的のサイズに変更できます。
    arr() = arr_Conv()    'コンバート用の配列から基の配列にデータを戻します。

といった感じでしょうかね?
ポイントしてはPreserveを使用せずにサイズを変更するということです。
これで解決できますよね?

以上

投稿時間:2006/02/10(Fri) 12:49
投稿者名:demontaki
URL :
タイトル:
Re^4: 動的に2次元配列
ごめんなさい
さっきの投稿は間違いでした

投稿時間:2006/02/10(Fri) 12:54
投稿者名:demontaki
URL :
タイトル:
Re^5: 動的に2次元配列
> ごめんなさい
> さっきの投稿は間違いでした

ごめんなさい
こちらが正解でした

Dim arr()       As Variant
Dim arr_Conv()  As Variant
Dim i           As Integer

    ReDim arr(2, 0)
    arr(0, 0) = "a"
    arr(1, 0) = "b"
    arr(2, 0) = "c"
    ReDim Preserve arr(2, 3) 'エラーが起きない
    For i = 0 To 3
        arr(0, i) = "a" & i
        arr(1, i) = "b" & i
        arr(2, i) = "c" & i
    Next
    ReDim Preserve arr(2, 5) 'エラーが起きない
    For i = 0 To 5
        arr(0, i) = "a" & i
        arr(1, i) = "b" & i
        arr(2, i) = "c" & i
    Next
    ReDim arr_Conv(10, 5)
    For i = 0 To 5
        arr_Conv(0, i) = arr(0, i)
        arr_Conv(1, i) = arr(1, i)
        arr_Conv(2, i) = arr(2, i)
    Next
    
    arr() = arr_Conv() '配列自体のコピーをしますのでarr()のサイズも変わります。

投稿時間:2006/02/10(Fri) 13:43
投稿者名:gt
URL :
タイトル:
Re^6: 動的に2次元配列
demontakiさん、ご回答ありがとう。

>ReDim arr(10, 5)
>For i = 0 To 5
> arr_Conv(0, i) = arr(0, i)
> arr_Conv(1, i) = arr(1, i)
> arr_Conv(2, i) = arr(2, i)
>Next
>arr() = arr_Conv()

なるほど、そういうやり方ですか。
試したのですが、うまくできました。

もう一つ質問があります、
配列同士一括コピーは同じサイズでしょうか。
この例というと
arr(10,5) <== arr_Conv(10, 5)  一括コピー可

arr_Conv(10,5) <==  arr_Conv(2, 5)  一括コピー不可
そのために解決策としては配列の個別にコピーすることですね。
>For i = 0 To 5
> arr_Conv(0, i) = arr(0, i)
> arr_Conv(1, i) = arr(1, i)
> arr_Conv(2, i) = arr(2, i)
>Next

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

投稿時間:2006/02/10(Fri) 20:15
投稿者名:demontaki
Eメール:
URL :
タイトル:
Re^7: 動的に2次元配列
どうもdemontakiです。
返信が遅くなってごめんね

下記の質問についてですが、もう御分かりになっているようですから
これ以上の補足は必要無いとも考えたのですが暇ですから書いてしまいます。
長文だけど勘弁してね

>配列同士一括コピーは同じサイズでしょうか。
この答えですが、配列同士をコピーする場合、
左辺のサイズは必ず右辺のサイズとなります。
(これがNo.5764が間違いであるという理由になります。)

つまり例として挙げられていた
>arr(10,5) <== arr_Conv(10, 5) 一括コピー可
結果はarr()がarr_Conv()と同じ(10,5)となりコピー可能となります。

>arr_Conv(10,5) <== arr_Conv(2, 5) 一括コピー不可
↑多分、arr(10,5) <== arr_Conv(2, 5)のことだと思うのですが
この場合も上記と同じくarr_Conv()がarr()に設定されますので
arr()がarr_Conv()と同じ(2,5)となり、一括コピーは可能となっています。

さらに解説するとNo.5764の誤りとしては
>ReDim arr_Conv(10, 5)
>arr_Conv() = arr()   
>ReDim arr(10, 5)
>arr() = arr_Conv()

最初に配列が(10,5)となりますが右辺に(2,5)のサイズを設定したため
(10,5)から(2,5)にサイズが小さくなってしまいます。
その後、配列を(10,5)としても
再度、(2,5)の配列を右辺に持ってきているわけですから
元の(2,5)に戻ってしまうということになります。

この点を改善したのがNo.5766なっています。
>ReDim arr_Conv(10, 5)
>For i = 0 To 5
>arr_Conv(0, i) = arr(0, i)
>arr_Conv(1, i) = arr(1, i)
>arr_Conv(2, i) = arr(2, i)
>Next
>arr() = arr_Conv()
最初に配列を再定義して(10,5)にしておくのは同じなのですが
その後に一括コピーしていたのを単項目ごとに設定するように変更しています。
これによって、(10,5)のサイズを小さくしないで基となる配列の値を設定しています。
最後に右辺に(10,5)の配列を持ってくることで
arr()のサイズを大きくして値を設定できるわけですね。

以上、長くなってゴメンネ

投稿時間:2006/02/11(Sat) 12:22
投稿者名:gt
URL :
タイトル:
Re^8: 動的に2次元配列
ご返事ありがとう。

> 左辺のサイズは必ず右辺のサイズとなります。
わかりました。

> >arr_Conv(10,5) <== arr_Conv(2, 5) 一括コピー不可
> ↑多分、arr(10,5) <== arr_Conv(2, 5)のことだと思うのですが
すみませんでした、書き方ミスです。その通りです。

> さらに解説するとNo.5764の誤りとしては
> >ReDim arr_Conv(10, 5)
> >arr_Conv() = arr()
   arr(2,5)==>arr_Conv(2,5) '小さくなった、コピー前arr_Conv(10,5)だった。
> >ReDim arr(10, 5)
> >arr() = arr_Conv()
    arr_Conv(2,5)==>arr(2,5) ’小さくなった、そのときarr_Conv(2,5)だった。


配列のことはっきりわかりました。
丁寧な説明ほんとにありがとうございました。

投稿時間:2006/02/11(Sat) 12:50
投稿者名:
Eメール:
URL :
タイトル:
Re^9: 動的に2次元配列
枯れた方法ですが、
・二次元配列ではなく、ユーザ定義型の配列を使う
というものがあります。

例えば
Option Explicit
'hoge型の宣言
Private Type hoge
    itm() As Variant
End Type
'hoge型の配列
Private itm() As hoge

Private Sub Form_Load()
    Dim i As Long
    'hoge型の配列の確保
    ReDim itm(2)
    'hoge型の配列の要素.itm()の確保
    For i = 0 To 2
        ReDim itm(i).itm(0)
    Next
    
    '使ってみる
    itm(1).itm(0) = "a"
    'hoge型の配列の拡張
    Debug.Print itm(1).itm(0)
    '拡張後、要素が残っているか確かめる
    ReDim Preserve itm(10)
    Debug.Print itm(1).itm(0)
End Sub

の様に使えます。
まぁ、2次元配列ではなくなりますが…

投稿時間:2006/02/13(Mon) 08:47
投稿者名:gt
URL :
タイトル:
Re^10: 動的に2次元配列
ご返事ありがとう。

> 例えば
> Option Explicit
> 'hoge型の宣言
> Private Type hoge
>     itm() As Variant
> End Type
> 'hoge型の配列
> Private itm() As hoge
>
構造体宣言ことですね。

>     '使ってみる
>     itm(1).itm(0) = "a"
>     'hoge型の配列の拡張
>     Debug.Print itm(1).itm(0)
>     '拡張後、要素が残っているか確かめる
>     ReDim Preserve itm(10)
>     Debug.Print itm(1).itm(0)
下記のようにテストしました。
    '拡張後、要素が残っているか確かめる
    ReDim Preserve itm(10)
    For i = 0 To 9
        Debug.Print itm(i).itm(0)
    Next i
i=3時、エラーが出ました。
実行時エラー9
インデックスが有効範囲にありません。

実際に拡張していないようですね、
   ReDim Preserve itm(10)を宣言したのに、
実際はitm(2)ままになっているようです。

よろしくおねがいします。

投稿時間:2006/02/13(Mon) 12:02
投稿者名:
Eメール:
URL :
タイトル:
Re^11: 動的に2次元配列
ちょっとわからなかったので、もう一度ソースを書いてみます。
Option Explicit
'hoge型の宣言
Private Type hoge
    itm()       As Variant
End Type
'hoge型の配列

Private Sub Form_Load()
    Dim i       As Long
    Dim itm()   As hoge
    'hoge型の配列の確保
    RedimPreserve_hogeAry itm, 2, 10
    
    '使ってみる
    itm(1).itm(1) = "a"
    Debug.Print itm(1).itm(1)
    'hoge型の配列の拡張
    RedimPreserve_hogeAry itm, 10, 10
    '拡張後、要素が残っているか確かめる
    Debug.Print itm(1).itm(1)
    itm(8).itm(2)="b"
    Debug.Print itm(8).itm(2)
End Sub

Private Sub RedimPreserve_hogeAry(ByRef h() As hoge, ByVal s1 As Long, ByVal s2 As Long)
    'itmを内容を保持して再確保
    Dim i       As Long
    ReDim Preserve h(1 To s1)
    For i = 1 To s1
        ReDim Preserve h(i).itm(1 To s2)
    Next
End Sub

※hoge型の要素itmの再確保方法も書いてるし、hoge型の配列itmの再確保方法も書いてるし…
 何か問題あったのかな…

投稿時間:2006/02/13(Mon) 12:56
投稿者名:demontaki
URL :
タイトル:
Re^12: 動的に2次元配列
お久しぶりです。
demontakiです。

おせっかいとも思いましたが、
返信させていただきます。

まず、gtさんのコメントについてですが
>実際に拡張していないようですね、
>ReDim Preserve itm(10)を宣言したのに、
>実際はitm(2)ままになっているようです。
構造体宣言されたものを再定義する場合、
一次元目のみを再定義すると一次元目の要素数は10となっているにもかかわらず
増加した要素(この場合3〜10のこと)の二次元目には何も設定されていない状態となります。
UBound(itm())・・・10となる
UBound(itm(2).itm())・・・0となる
UBound(itm(10).itm())・・・エラーとなる
このため二次元目を再定義して、増加した要素にも二次元目の設定をしてあげる必要があります。

もさんのコメントについてですが
> ※hoge型の要素itmの再確保方法も書いてるし、hoge型の配列itmの再確保方法も書いてるし…
>  何か問題あったのかな…
gtさんが間違われた点としては
hoge型の配列の拡張の記述の後に一次元目の記述しかなかったからではないでしょうか?
たしかに記述されたソースを私も最初は確認のためソースをそのまま使用しましたが
前半にあるhoge型の配列の確保とhoge型の配列の要素.itm()の確保の記述を見て
気づきましたし、理解力の差もありますし人に教えるのは難しいですね・・・

以上

投稿時間:2006/02/13(Mon) 13:56
投稿者名:gt
URL :
タイトル:
Re^13: 動的に2次元配列
もさん、demontakiさん、
ご回答ありがとう。

もさんのサンプルをテストしました、
うまくできました。
可変長配列(行が可変と列も可変)の作り方、よくわかりました。


ほんとにありがとうございました。

投稿時間:2006/02/13(Mon) 14:27
投稿者名:gt
URL :
タイトル:
Re^14: 動的に2次元配列
補足:
1.配列の開放は ReDim itm(0, 0) ですよね。
2.1次元配列ID_ALL()を追加したいのですが、うまくできませんでした。

'hoge型の宣言
Private Type hoge
    itm()       As Variant
  ID_ALL()    As Integer  //1次元配列
End Type
'hoge型の配列

    'hoge型の配列の確保
    RedimPreserve_hogeAry itm, 2, 10   ’この部分変更していません。
For i = 1 To 2
    itm(i).ID_ALL = i   ’ここで、エラー:配列には割り当てない
    For j = 1 To 2
        itm(i).itm(j) = "a" & i & " ," & j
        Debug.Print "ID_ALL="; itm(i).ID_ALL, "itm(i).itm(j)="; itm(i).it
m(j)
     Next j
Next i

どう解決するのでしょうか。
よろしくお願いします.

投稿時間:2006/02/14(Tue) 09:47
投稿者名:gt
URL :
タイトル:
解決
自分で解決しました。
>Private Type hoge
>itm() As Variant
>  ID_ALL()   As Integer //1次元配列
>End Type

ID_ALL()   As Integer //1次元配列
無理と判断したのですが、新たに宣言しました。
最適と思っていないのですが、一応正常に動くました。

これさん、もさん、demontakiさん、
ありがとうございました。