質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

691閲覧

VBA:配列に入れた要素を抽出したい

krrr

総合スコア1

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

1グッド

0クリップ

投稿2023/12/21 05:59

編集2023/12/21 07:52

実現したいこと

どのようにすれば、Arr(1, 1)やArr(3, 2)など、指定した要素を取り出せるのでしょうか?

発生している問題

Excelシートから必要なセルのみを抽出し、配列を作成しました。
列数は2列と決まっていて、列1が"データ名"、列2が"データ名に対応する数値"です。
行数は元データを検索しながら取得しており、「ii」としています。(つまり、配列のサイズはArr(ii, 2)となります。)

配列の作成まではできたのですが、要素の抽出ができません。
下記のコードでは、配列の行数が最大のときの要素しか残っていないようです。
(i = 10だとすると、Arr(10, 1)の要素は出力できますが、Arr(1, 1)の要素はEmpty値となってしまいます。)

どのようにすれば、Arr(1, 1)やArr(3, 2)など、指定した要素を取り出せるのでしょうか?
初心者のため、初歩的なことをお聞きしているかと思いますが、お答えいただけましたら幸いです。

該当のソースコード

VBA

1'ws = 参照元のExcel 2'i = 参照元のExcelシートの行数 3'y To y + k = 参照元のExcelシートの検索する行数の範囲 4'ii = 配列Arrの行数 5 6ii = 0 7 For i = y To y + k 8 If ws.Cells(i, 1) <> "" Then 9 ii = ii + 1 10 ReDim Arr(ii, 2) 11 Arr(ii, 1) = ws.Cells(i, 1) 'この時点ではArr(1, 1)が取得できている 12 Arr(ii, 2) = ws.Cells(i, 5) 13 End If 14 Next 15'この後でArr(1, 1)などを抽出したいが、できない
tatsu99👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YellowGreen

2023/12/21 07:52 編集

End If が重複していませんか。 A列に空白の行があると 検索する行数と配列の要素の数は、一致しなくなるのですね。 方法としては、 事前に検索範囲のA列の値を検査して空白でないセルの数を保存しておき ReDim Arr(1 To 保存した数, 1 To 2)などとするか、 コレクションに蓄積してから配列に戻すとかでしょうか。
krrr

2023/12/21 07:55

ご回答ありがとうございます。 End If 重複していましたので修正しました。 先に個数を取得する必要があるのですね。個数を取得するコードを書いてみます。ありがとうございます。
krrr

2023/12/21 08:28

こちらの件、解決しました。 基本的には個数を先に取得することでこの問題は解決できること、勉強になりました。 ありがとうございました。
guest

回答2

0

ベストアンサー

ReDim Arr(ii, 2)

  • Preserve キーワードのない ReDim ステートメントを呼び出して動的配列を再定義した場合、各要素に格納されていた値は全て失われる。

  • 次元数が 2 以上である動的配列を Preserve キーワード付きの ReDim ステートメントによって再定義する場合、サイズの変更が可能なのは最後の次元だけである。つまり 2 次元配列の場合、1 次元目のサイズを変更することはできない。

  • その次元における添え字の下限値を指定しなかった場合、その次元の添え字の最小値は 0 となる。

vba

1ii = 0 2For i = y To y + k 3 If ws.Cells(i, 1) <> "" Then 4 ii = ii + 1 5 'ここでは2次元配列の行と列の関係を逆転させる。 6 'また、各次元の添え字の最小値は明示的に 1 とする。 7 ReDim Preserve Arr(1 To 2, 1 To ii) 8 Arr(1, ii) = ws.Cells(i, 1) 9 Arr(2, ii) = ws.Cells(i, 5) 10 End If 11Next 12 13'最後に2次元配列の行列を入れ替える 14Arr = WorksheetFunction.Transpose(Arr)

投稿2023/12/21 07:46

sk.exe

総合スコア1095

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

krrr

2023/12/21 08:00

ご回答いただきありがとうございます。 Preserveキーワードとういうものがあるのですね。大変勉強になります。 すぐに試してみます。ありがとうございます。
krrr

2023/12/21 08:24

こちらの方法を試したところ、解決しました。 誠にありがとうございました。
guest

0

for 文中でRedimで配列を初期化しているからではないでしょうか?
for文の前で、ReDim Arr(k, 2)のように初期化してはどうでしょうか?

投稿2023/12/21 06:35

編集2023/12/21 06:36
sazi

総合スコア25430

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

krrr

2023/12/21 07:50

ご回答いただきありがとうございます。 確かにそれが原因ですね。しかし、For文の前でReDimしてしまうと、"インデックスが有効範囲にありません"のエラーが出てしまいます。 配列の中身の取得と、配列の箱の個数の取得とを同じ繰り返し処理の中で得ようとしていることが間違いでしょうか?
krrr

2023/12/21 08:25

こちらの件、解決しました。 繰り返し処理の中でReDimを使うと毎回初期化されてしまうこと、大変勉強になりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問