Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


5201 / 13646 ツリー ←次へ | 前へ→

【52119】2次元配列について 多摩川 07/10/22(月) 10:39 質問[未読]
【52120】Re:2次元配列について neptune 07/10/22(月) 11:02 回答[未読]
【52123】Re:2次元配列について 多摩川 07/10/22(月) 11:33 質問[未読]
【52126】Re:2次元配列について neptune 07/10/22(月) 14:39 回答[未読]
【52129】Re:2次元配列について 多摩川 07/10/22(月) 18:15 お礼[未読]
【52130】Re:2次元配列について ichinose 07/10/22(月) 19:06 発言[未読]
【52134】Re:2次元配列について 多摩川 07/10/23(火) 9:13 お礼[未読]

【52119】2次元配列について
質問  多摩川  - 07/10/22(月) 10:39 -

引用なし
パスワード
   いつもお世話になっております。
恐れ入りますが、再び、お知恵をお貸し下さい。

テキストデータから番号リストとデータを読み取り、シート1のA列にあるリスト番号と照らし合わせ、番号が一致する時にデータをB列に記入する操作を行うコードを考えています。
その際、ReDimステートメントを使用しているのですが、「インデックスが有効範囲にありません。」と
実行時エラー9が発生しました。

そこで、原因を探ろうと下記のように簡単なコードで試してみたのですが、はやり同じエラーが発生してしまいました。
どのように改善したらよろしいのでしょうか?

Sub macro()
  Dim ws1 As Worksheet, ws2 As Worksheet
  Dim i As Long, j As Long, Cnt As Long
  Dim id() As Long
  Set ws1 = ThisWorkbook.Sheets(1)
  Set ws2 = ThisWorkbook.Sheets(2)
  Cnt = ws1.Range("A1").End(xlDown).Row
  For i = 1 To 3
    For j = 1 To Cnt
      ReDim Preserve id(j, i): id(j, i) = ws1.Cells(j, i)
    Next j
  Next i
  For i = 1 To 3
    For j = 1 To Cnt
      ws2.Cells(j, i) = id(j, i)
    Next j
  Next i
  Set ws1 = Nothing
  Set ws2 = Nothing
End Sub

【52120】Re:2次元配列について
回答  neptune  - 07/10/22(月) 11:02 -

引用なし
パスワード
   こんにちは

redimを複数配列の再使用するときは最後の次元しか変更することは出来ません。
Helpに書いていますから、ご精読下さい。

【52123】Re:2次元配列について
質問  多摩川  - 07/10/22(月) 11:33 -

引用なし
パスワード
   ▼neptune さん:
回答ありがとうございます。

>redimを複数配列の再使用するときは最後の次元しか変更することは出来ません。
>Helpに書いていますから、ご精読下さい。
質問の前に一応Helpは読みました。確かに「最後のただ 1 つの次元」と書いてありましたが、
id(x) から
Redim Preserve id(x ,y)
と次元を変更することがNGだと思っていました。
意味が違うようなのですね。

Redim Preserve id(A, 1) とした場合、最後の次元とは "1" のことで、A は A = A + 1 と変化しても "1" は変更がダメとなるのでしょうか?
この場合、Redim Preserve id(x, 2)ならば、A×2 の配列はせいりつするのか?ならば、Redim Preserve id(x, 1)はいつ宣言するのか?
等々、疑問がたくさんあります。
恐れ入りますが「最後の次元」について、ご説明をいただけないでしょうか?

【52126】Re:2次元配列について
回答  neptune  - 07/10/22(月) 14:39 -

引用なし
パスワード
   ▼多摩川 さん:
こんにちは


>Redim Preserve id(A, 1) とした場合、最後の次元とは "1" のことで、A は A = A + 1 と変化しても "1" は変更がダメとなるのでしょうか?
その通りです。A=A+1の時点で駄目です。

>この場合、Redim Preserve id(x, 2)ならば、A×2 の配列はせいりつするのか?ならば、Redim Preserve id(x, 1)はいつ宣言するのか?
1次元目は変えられません。従って、最初です。
dim id(10,1) as hoge
のように宣言しておいて、2次元目即ちこの場合1を
redim preserve id(10,2) as hoge
のようになら変更できます。

>恐れ入りますが「最後の次元」について、ご説明をいただけないでしょうか?
色々ご自分でいろんなケースを考えて実験するとよく解りますよ。
大して時間はかかりません。

【52129】Re:2次元配列について
お礼  多摩川  - 07/10/22(月) 18:15 -

引用なし
パスワード
   ▼neptune さん:
>▼多摩川 さん:
>こんにちは
>
>
>>Redim Preserve id(A, 1) とした場合、最後の次元とは "1" のことで、A は A = A + 1 と変化しても "1" は変更がダメとなるのでしょうか?
>その通りです。A=A+1の時点で駄目です。
>
>>この場合、Redim Preserve id(x, 2)ならば、A×2 の配列はせいりつするのか?ならば、Redim Preserve id(x, 1)はいつ宣言するのか?
>1次元目は変えられません。従って、最初です。
>dim id(10,1) as hoge
>のように宣言しておいて、2次元目即ちこの場合1を
>redim preserve id(10,2) as hoge
>のようになら変更できます。
>
>>恐れ入りますが「最後の次元」について、ご説明をいただけないでしょうか?
>色々ご自分でいろんなケースを考えて実験するとよく解りますよ。
>大して時間はかかりません。

何となく概要は分かりました。
後は色々実験してみて確認してみます。
誠にありがとうございました。

【52130】Re:2次元配列について
発言  ichinose  - 07/10/22(月) 19:06 -

引用なし
パスワード
   ▼多摩川 さん:
こんばんは。
>テキストデータから番号リストとデータを読み取り、シート1のA列にあるリスト番号と照らし合わせ、番号が一致する時にデータをB列に記入する操作を行うコードを考えています。
>その際、ReDimステートメントを使用しているのですが、「インデックスが有効範囲にありません。」と
>実行時エラー9が発生しました。
原因は、neptuneさんの投稿のとおりだと思います。
例えば、

Dim 配列(1 to 5,1 to 10)
この↑2次元配列って、内部でシートイメージでデータが入るわけではありません。

Dim 配列(1 to 5,1 to 4, 1 to 3)
ましてやこれは内部で↑3次元空間にデータが配置されるわけでもありません。

内部では、すべて一次元の配列です。これを踏まえると、
上記のエラーも仕方が無いかなあ なんて思います。

シートに

  A   B   C
1  1   2    3
2  4   5    6
3  7   8    9
4  10  11    12


とあるデータを
2次元配列では、
dim 配列(1 to 3,1 to 4) と配置し、

1  4  7  10
2  5  8  11
3  6  9  12

上記のようにデータを配置して運用すれば移行が可能です。


新規ブックの標準モジュールに
'==========================================================
Sub macro()
  Dim ws1 As Worksheet, ws2 As Worksheet
  Dim i As Long, j As Long, Cnt As Long
  Dim id() As Long
  Set ws1 = ThisWorkbook.Sheets(1)
  Set ws2 = ThisWorkbook.Sheets(2)
  With ws1.Range("a1:c30")
    .Formula = "=int(rand()*10000)+1"
    .Value = .Value
    .Activate
    End With
  MsgBox "サンプルデータ 作成"
  Cnt = ws1.Range("A1").End(xlDown).Row
  For i = 1 To Cnt
    ReDim Preserve id(1 To 3, 1 To i)
    For j = 1 To 3
      id(j, i) = ws1.Cells(i, j)
    Next j
  Next i
  MsgBox "配列に格納完了 別シートに移行します"
  For i = 1 To Cnt
    For j = 1 To 3
      ws2.Cells(i, j) = id(j, i)
    Next j
  Next i
  Set ws1 = Nothing
  Set ws2 = Nothing
End Sub

上記を実行して結果とコードを見比べてみてください。

【52134】Re:2次元配列について
お礼  多摩川  - 07/10/23(火) 9:13 -

引用なし
パスワード
   ▼ichinose さん:
詳しく説明して頂き、本当にありがとうございました。
作成中のマクロにも反映できました。

初め、ReDim Preserve id(j, i) は j の値が増えるたびに
id(1,1), id(1,2), id(1,3), ・・・
id(2,1), id(2,2), id(1,3), ・・・
と変数が作られるとイメージしていました。
ですが、j = j + 1 と増分させても、初めが j = 1 だとこれが最後の次元となってしまうわけですね。
従って初めから、
ReDim Preserve id(1 To n, 1 To i)と言葉が適切ではないかもしれませんが枠を設定してやればいいのですね!

大変勉強になりました。
ありがとうございました。

5201 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free