VBA Dowhileで動的配列を判断条件に使う時の注意点

このQ&Aのポイント
  • VBAのDowhileループを使用する場合、動的配列を判断条件に使用する場合には注意が必要です。
  • 動的配列を使用すると、配列の要素が全て空の場合に無限ループが発生する可能性があります。
  • この問題を回避するためには、動的配列を使用する前に配列の要素数を十分に初期化するか、別のループ構造を使用することが推奨されます。
回答を見る
  • ベストアンサー

VBA Dowhile 判断条件に動的配列を使う

Dim i As Long Dim A() As String '何かの処理で配列全部に文字列を入れる。 i=1 Do while Len(A(i))>0 '何かの処理 i=i+1 Loop 配列の全部の要素に文字列が入ってると、最後のiでエラーになります。静的配列を使う場合は、要素数に余裕を持たせて宣言するので問題無かったのですが、動的配列を使うようになりエラーが出ました。 動的配列では条件判断に配列を使わない方がいいのでしょうか?というよりDowhile自体使わない方がいいのでしょうか。 勿論やりようで使える筈です。例えば要素数を1個追加して空""にするとか。常識的な方法はあるのでしょうか。例えばFor nextとか。

質問者が選んだベストアンサー

  • ベストアンサー
  • keithin
  • ベストアンサー率66% (5278/7940)
回答No.1

ご相談のマクロでは、脱出条件としてA(i)が「存在する」ことが前提になってるのですから、つまりはロジックの組み方が間違ってます。 >常識的な方法 一般には option base 1 for i = 1 to ubound(a) ’if len(a(i)) = 0 then exit for ’必要なら  何かの処理 a(i) next i のようにしとくのが、ご相談の状況では一番簡単確実に見えます。 #もちろん例えばdo loopの中で動的配列の上限を操作する可能性があってそういう事をしているのかもしれませんが、そこはご相談の範疇じゃないので割愛します。

over_the_galaxy
質問者

お礼

ありがとうございます。 Uboundが 一番良さそうですね。

その他の回答 (4)

回答No.5

こんばんは。 >Dowhile自体使わない方がいいのでしょうか。 Do While  というのは、一般的に、数的な終了条件を求められない時に使うものです。 だから、VBAの実務では、外部ファイルのテキストファイルのEOF などの制御コードの時に用います。 数的に捉えられるものは、For 初期値 To 最終値 のほうが便利で早いです。 今回は、あくまでも、初級の練習だと解釈するしかありません。 また、ふつう、動的配列というものは、配列の添字の最大値が予め分からない場合に用いることであって、元はどういう構造になっているのか見せられていませんから、なんとも言えません。 以下のサンプルコードの場合は、本来は、動的配列は不要です。 (サンプルコードとは違うとかいうレスはしないでください。違うのだったら、元のコードを見せてください。) 常識的に、動的に配列に入れたなら、動的配列に使った、カウンター数か、UBoundで、Loopから抜ければよいだけではないでしょうか? >最後のiでエラーになります。 Loopで戻った後に、配列の添字の上限以上の数を入れるわけですから、配列にない添字を入れたわけですから、エラーになります。 Do a = a & Ar(i) '一例 i = i + 1 Loop While i <= UBound(Ar) Or Trim(Ar(i - 1)) = "" あえて、2つの条件をあわせるなら、こうなります。 '// Sub TestArray()  Dim i As Long  Dim j As Long  Dim k As Long  Dim Ar() As String  Dim a As String    Const sABC As String = "abcdefghijklmnopqrstuvwxyz"  For i = 1 To Len(sABC)   ReDim Preserve Ar(j)   Ar(j) = Mid(sABC, i, 1)   j = j + 1 'ここで、カウンター数を取得  Next i  Do   'If Trim(Ar(k)) = "" Then Exit Do 'もし空白条件を入れるなら。   a = a & Ar(k)   k = k + 1  Loop While k < j 'While k <= UBound(Ar) '下に入れる  Stop End Sub '// こういうスタイルの場合は、最初に、予め配列の添字の上限を決めてしまうのが通例です。 空白で、Len(Ar(i))=0 というのは、Ar()が文字型ですから、「""」で十分ですが、あえて、Trimを使いました。

over_the_galaxy
質問者

お礼

ありがとうございます。 Dowhileは数値では用いない、了解です。その様にします。 〉サンプルコードとは違うとかいうレスはしないでください 前回質問のやり取りを意識しての事と思いますが、それを言われてしまうと私としても「質問外の事を書かないでくれ」としか返事出来ません。ソースコードもありませんし、あったとしてもおそらく開示出来ません。ここに質問する時は、変えるとか必要部分のみ書いてます。 Trim これは知りませんでした。調べてみます。

  • kkkkkm
  • ベストアンサー率65% (1617/2456)
回答No.4

Do While i <= UBound(A) '何かの処理 i = i + 1 Loop でいけそうですがどうでしょう。

over_the_galaxy
質問者

お礼

ありがとうございます。 この方法でも出来ますね。ここまで来るとForNextに近いですね。

  • watabe007
  • ベストアンサー率62% (476/760)
回答No.3

参考に Do while Len(A(i))>0   '何かの処理   i = i + 1   If i > UBound(A) Then Exit Do Loop >例えばFor nextとか。 For i = LBound(A) To UBound(A)   '何かの処理 Next

over_the_galaxy
質問者

お礼

ありがとうございます。 i=i+1の後で判定すればDowhileも使えますね。

  • t-aka
  • ベストアンサー率36% (114/314)
回答No.2

UBoundで配列の数を取得しておいて、For~Nextを使用すれば対応できると思います。 --- Dim A() As String '何かの処理で配列全部に文字列を入れる。 Dim i As Long i = 1 Dim arrayMax As Long arrayMax = UBound(A) For i = 0 To arrayMax '何かの処理 If Len(A(i)) = 0 Then Exit For Next i --- といった感じではないでしょうか。

over_the_galaxy
質問者

お礼

ありがとうございます。 Uboundが一番良さそうですね。

関連するQ&A

  • VBAで配列に文字列が入らない?

    以下のように配列を設定し、A(ix)の配列にdo untilでそれぞれに文字列を入れようとしておりますが、うまくいきません。 dountil の一回目では代入ができているようですが、2回目ができずに止まってしまいます。 おかしな点がありましたらご指摘いただけませんでしょうか。 Dim A() As String Dim ix As Long ix = 0 ReDim Preserve A(ix) Dim tate As Long tate = 1 Do Until tate = 8 A(ix) = ws.Cells(tate, 1) tate = tate + 1 ix = ix + 1 Loop Doの初回A(0)に文字列は入りますが、 Doの二回目以降A(1)に文字列を入れる作業ができずに止まってしまいます。 よろしくお願いします。

  • 配列について

    配列の要素数をinteger型にいれたいのですがどうしたらいいですか? 例   Dim A() As String   Dim B AS Integer       A = "あ","い","う" Aの要素数3をBに入れたいのです。 この配列の作りかたもあっているか分かりませんがよろしくお願いします。

  • ExcelVBAで配列に一気にデータを入れる

    かすかな記憶で申し訳ありませんが、変数をVariant型で宣言しておくと、","で区切られた文字列は、一気に配列として代入出来ると聞いた気がしています。色々と試してみたのですが、よくわかりません。よろしくお願いいたします。 Dim a as Variant dim myText as string myText = "月曜,火曜,水曜,木曜,金曜,土曜,日曜" のような感じで(実際のカンマで区切られた文字列は100個ぐらい要素があります)一気に代入して、aを配列として扱いたいのです。 よろしくお願いいたします。

  • 配列

    String型の配列の中の文字列の文字数を数える方法で困っています。 問題は、int型の変数lenで与えられた数字よりも大きい文字数の文字列はいくつあるか調べます。 例) stringsLongerThan({"a","ab","abc"}, 0) 3つ全ての文字列の文字数は0より大きいので3を返す stringsLongerThan({"a","ab","abc"}, 2) "abc"の文字数が2より大きいので1を返す stringsLongerThan({"a","ab","abc","abcd","abcde","abcdef","abcdefg"}, 3) "abcd","abcde","abcdef","abcdefg"の4つが文字数3より大きいので4を返す 途中まで組んだのですが、配列array[]の中の文字列の文字数を数えるにはどうしたらよいのでしょうか? public int stringsLongerthan(String[] array, int len){       int result=0;      for(int i=0;i<array.length;i++){        //ここで配列array[i]の文字列の文字数を数える       int count=文字数;       if(cont>len)        result++;     }      return result; } 宜しくお願いします。

    • ベストアンサー
    • Java
  • VBAの配列について

    初めまして、VBAの配列の入力方法について質問させてください。 大量のデータの処理を高速化するため、配列を使用して以下のVBAを入力しました。 インターネットで調べ、見よう見まねで入力してみたものです…(T_T) 内容は、シート「資料」のC列とシート「Sheet1」のG列の文字列が同じ かつ、シート「資料」のL列から最終列(そのときによって変化します) とシート「Sheet1」のE列の文字列が同じ場合、 シート「資料」のA列~D列及びL列から最終列で文字列の一致したセルを 着色するというものです。 変数「アイス」と「チョコ」にそれぞれシート「資料」のデータと シート「Sheet1」のデータを格納したつもりなのですが、 実行したところ「配列がありません。」というエラーメッセージが 表示されました。 どうやらデータを配列として格納できていないときに表示される エラーメッセージのようなのですが、変数の型を変更してみたり、 配列をアイス(2)にしてみたりと、色々方法を変えて試してみたものの、 処理は成功しませんでした(T_T) 一体何が原因で処理が成功しないのか、どなたかご教授いただけると とても嬉しいです…!よろしくお願いいたします。 ちなみに、配列を使用しない場合の処理は、時間が15分ほどと かなりかかりますが、成功しています。 Application.ScreenUpdating = True Dim アイス, チョコ As Long Dim i As Integer, j As Integer, k As Integer アイス = Sheets("資料").Cells(Rows.Count, 1).End(xlUp).Row チョコ = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row For i = 3 To Sheets("資料").Cells(Rows.Count, 1).End(xlUp).Row For j = 12 To Sheets("資料").Cells(i, 12).End(xlToRight).Column For k = 2 To Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row If アイス(i, 3).Value = チョコ(k, 7).Value And アイス(i, j).Value = チョコ(k, 5).Value Then Sheets("資料").Range("A" & i & ":D" & i).Interior.ColorIndex = 22 アイス(i, j).Interior.ColorIndex = 22 End If Next k Next j Next i

  • VBAの動的配列について

    いつもお世話になっております。 エクセルVBAを学習中の者です。 動的配列についてお伺いします。 添付資料を見て頂きたいのですが、 シート名1~4に同一レイアウトの表があります。 これらの表をを2次元配列に格納し、その後、同一レイアウトのシートに一括転記したいと考えています。 転記の事を考えて、条件としては、 シート1から2行目以降のデータを配列『data』に格納、変数『dataCnt』が転記先の行番号と同じになるように考えています。 当初は、配列の定義を『Dim data(100,3) As Variant』と、多めに要素数を定義して、コードを記述していました。 正直、凄く気持ちが悪い感じでした・・・ 最近、動的配列を学習しまして、 シートごとにデータの行数を変数『lastRow』に格納して、配列を再定義して【データ数=要素数】とならないか? と思い、下記のようなコードを書いてみました。 が、『ReDim Preserve~』で実行エラーが発生してしまいます。 原因がなぜかわかりません! そもそも、動的配列はこのような使い方は出来ないのでしょうか? Sub テスト() Dim data() As Variant Dim x As Long Dim i As Long Dim ii As Long Dim lastRow As Long Dim dataCnt As Long dataCnt = 2 For x = 2 To 5 Worksheets(x).Activate lastRow = Cells(Rows.Count, 1).End(xlUp).Row If x = 2 Then ReDim data(2 To lastRow, 3) Else ReDim Preserve data(2 To dataCnt + lastRow - 1, 3) End If For i = 2 To lastRow For ii = 1 To 3 data(dataCnt, ii) = Cells(i, ii) Next ii dataCnt = dataCnt + 1 Next i Next x End Sub どなたかご指導をよろしくお願いいたします。

  • VB.net 引数で配列変数を渡す際の要素数

    VB.net 2010 の質問です。 配列変数を他のプロシージャに引数で渡す際の、配列変数の要素数をあらかじめ宣言していないとエラーになります。 Dim Hairetsu() As String ' ←エラー Dim Hairetsu(100) As String ' ←正常 Public Sub aaa(ByRef Hairetsu() As String) Hairetsu(0) = "Test" '←正常の場合と、エラーの場合 End Sub Hairetsu(100) のように、要素数を宣言していると、エラーにならないのですが、 プログラム中、要素数がどこまで増加するか、分かりません。 Hairetsu()のように、要素数未確定の配列変数を渡すことは出来ないのでしょうか。 ご存知の方がいらっしゃいましたら、なにとぞアドバイスの程、よろしくお願いいたします。

  • vbaで配列に値を格納する場合

    vbaで配列に値を格納する場合 変数の宣言はどちらを使った方が良いのでしょうか? Sub Sample1() Dim i As Long Dim myStr As String Dim tmp() As String myStr = "a,i,u,e,o" tmp = Split(myStr, ",") End Sub か Sub Sample1() Dim i As Long Dim myStr As String Dim tmp As Variant myStr = "a,i,u,e,o" tmp = Split(myStr, ",") End Sub でも問題なく動くのですが、 Variant型での宣言はあまりしない方が良いですか? あと Dim tmp() As String ならエラーにならないのですが Dim tmp As String だとエラーになってしまう理由がよくわからないので教えて頂けますか?

  • 配列に関してです。

    Dim a(,) As Integer a= New Integer(,) {0,300,400,400,500,600,700,800}  {400,500,700,800,1000,1200,1300,1500}   {700,1000,1300,1600,2000,2000,2000,2000}   {1300,2000,2000,2000,2000,2000,2000,2000} ローカルレベルでこのように配列を宣言したのですが ・配列初期化子の次元が少なすぎます。 ・構文エラーです。 とエラーが出てしまいます。 この宣言、初期化の仕方のどこがおかしいのでしょうか?

  • Excel VBA での動的配列の宣言の仕方

    Excel VBA で動的配列を宣言したところ,上手く行きません。何が悪いのでしょうか? Dim A() As Integer MsgBox LBound(A()) として実行すると,LBound(A())のインデックスが有効範囲にありませんというエラーが出ます いったい何が悪いのでしょうか?動的配列の定義に失敗しているものと思いますが,動的配列の宣言の仕方をお教えください。よろしくお願いします。

専門家に質問してみよう