• ベストアンサー

配列について。

Redim した後   For i LBound(配列) To UBound(配列)    作業   Next i をしているのですが、配列の要素数を別プロセスで 計算させる場合、必ずしも要素が存在するとはかぎ りません。 その場合エラーがでるわけですが、このように配列 の中身が存在しない場合はどのように回避できるの でしょうか? VB6&Windows2000です。

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

  • ベストアンサー
  • takasebou
  • ベストアンサー率42% (61/144)
回答No.1

方法はいろいろとあると思いますが、簡単に考えますと 1.配列の要素数を別変数で管理しておき、まず最初にその変数をチェックする。 2.バリアント型にして、isArray関数を使う などが考えられると思います。

wakaranai_kun
質問者

補足

ご回答、どうもありがとうございました。 まだテストできていませんが、チャレンジしてみます。 ところで自分なりに次のように回避しようと思ったのです が・・・ 要素がない場合、Err.Number = 9 が返って来るようで 次のように回避しようとしました。 この場合、i=0の時はErrorLabel1:へ飛べるのですが、 i=1になった場合、ErrorLabel1:へ飛べずにそこで止 まってしまいます。 これは仕様なのでしょうか? Sub ABC() Dim i As Integer, j As Integer Dim oNodList AS Node     For i = 0 to Max -1       oNodList = Get_ChildList() 'ここで配列の取得        On Error Goto ErrorLabel         For j = LBound(oNodList) To UBound(oNodList)            '作業         Next j LabelResume:     Next i          Exit Sub ErrorLabel1:   If Err.Number = 9 Then    GoTo LabelResume   End If    End Sub

その他の回答 (2)

  • takasebou
  • ベストアンサー率42% (61/144)
回答No.3

#1です。 下記の件ですが ErrorLabel1:   If Err.Number = 9 Then    GoTo LabelResume   End If    End Sub ここでエラーをクリアしていないので、再度同じエラーが発生しても今までと同じエラーが発生しただけですので、とびません。   If Err.Number = 9 Then    Err.Clear    GoTo LabelResume   End If にすれば大丈夫だと思います。

wakaranai_kun
質問者

お礼

何度もありがとうございます。 Err.Clearだったんですね。 知りませんでした。 今後、使っていきたいと思います。 いろいろと有効な手段が見つかり助かりました。 また、よろしくお願いします。

  • sam_inoue
  • ベストアンサー率47% (27/57)
回答No.2

' IsArrayチェックでは意味なし Sub TEST1() Dim A() MsgBox IsArray(A) ReDim A(1) MsgBox IsArray(A) End Sub ' IsArrayが有効な例 Sub TEST2() Dim A MsgBox IsArray(A) ReDim A(1) MsgBox IsArray(A) End Sub ' 配列要素数=0を使わない例 Sub TEST3() Dim A() ReDim A(0) MsgBox UBound(A) ReDim A(5) MsgBox UBound(A) End Sub 最初にReDim A(0)としてしまい、 有効要素はIndex=1以降を使うことします。 このままUBound(A)=0なら配列は無効と判断できます。

wakaranai_kun
質問者

お礼

ご回答ありがとうございます。 一つ目二つ目の違いは今はじめて知りました。 参考にさせてもらいました。 三つ目については実はその方法でやっていたの ですがしっくり来なかったので今回、質問させ てもらった次第です。 それで、再度、常に0番から有効値を埋めるに は?と考え次の方法で何とかなることがわかり ました。 配列数は返ってきたRecordeCountで決めています。 Function Test() As String()   Dim RS   Dim i   Dim Hairetsu()     If RS.RecordCount > 0 Then      For i = 0 To RS.RecordCount       ReDim Preserve Hairetsu(i)       Hairetsu(i)="Test" & i      Next i     Else      ReDim Hairetsu(0)      Hairetsu(0) = "No Element"     End If     Test=Hairetsu End Function

関連するQ&A

  • VBの配列 IsNull, IsNuthing, ...? 用途がわかりません。

    以下の場合、(1)で範囲エラーとなります。 redim a(0)とすると、a配列に1個データがあるということで、for文が実行されますが。 Redimしないまま(データが無い意味としたいので)で、このFor文をパスするには、どのように記述すればよいのでしょうか? dim a() as string '----->(2) for i=LBound(a) to UBound(a) '---->(1) msgbox(a(i)) next i

  • メモリの解放について VB6 VBA

    VB6やVBAで動的配列をERASEしたのですが、タスクマネージャーで見ても使っているメモリを解放しているように見えません。 動的配列の内容をMsgBoxで表示させるたびにメモリがどんどん減っていきます。Eraseしても戻りません。 Redim ArryaDat(0)とかでも無理でした。 APIを使って(どんな方法)でも、メモリを解放したいのですが、可能でしょうか? Dim ArrayDat() as String Redim ArrayDat(100) ArrayDat(0) = "なんとか" ArrayDat(1) = "かんとか" ... ArrayDat(100) = "メモリを解放したい" for i = LBound(ArrayDat) to UBound(ArrayDat) MsgBox("どんどんメモリが消費されていく・・ [" & ArrayDat(i) & "]") next i Redim ArrayDat(0) Erase ArrayDat NsgBox("解放したつもり? 誰か教えて") あと、.NETではメモリ解放はどうなっているのでしょうか? まだ使いませんが、頭の片隅に入れておきたいです。

  • 二次元配列のVBA

    二次元配列のVBAの書き方がよくわからないのですが、 私が作ったサンプルプログラムのSub 二次元()において 二次元配列で表すにはどうすればいいのでしょうか? Sub 二次元()では 配列を格納する変数はtmpしか使っていませんが もう一つ配列を格納する用の変数を作ればいいのでしょうか? 数字とアルファベットは別々に取り出したいです。 ----------------------------------------------------- Sub 一次元() Dim myStr As String Dim tmp As Variant Dim i As Long For i = 1 To 5 myStr = myStr & "," & i Next myStr = Mid(myStr, 2) tmp = Split(myStr, ",") For i = LBound(tmp) To UBound(tmp) Debug.Print tmp(i) Next i End Sub Sub 二次元() Dim myStr As String Dim tmp As Variant Dim i As Long For i = 1 To 5 myStr = myStr & "," & i & "と" & Chr(64 + i) Next myStr = Mid(myStr, 2) tmp = Split(myStr, ",") For i = LBound(tmp) To UBound(tmp) Debug.Print tmp(i) Next i End Sub

  • 動的配列の後始末?

    以下のサブルーチンで、lines()と動的配列を定義して、Splitでデータを入れたのですが、このサブルーチンが終了すると、lines()はデータも含めて解放されるのでしょうか? 極端な話、1億回このサブルーチンを呼ぶと、メモリーリークするのでしょうか? それと、VB6やVB.NETでは、For文・For Each文のどちらを使う方が良いのでしょうか? Sub test() Dim lines() As String lines = Split(Data, vbCrLf, -1, vbBinaryCompare) Dim i As Integer For i = LBound(lines) To UBound(lines) MsgBox ("for=[" & lines(i) & "]") Next i Dim s As Variant For Each s In lines MsgBox ("for each=[" & s & "]") Next End Sub

  • 動的配列が存在(要素が有る)か否かを判定できますか?

    VBAで、「For ループが初期化されていません」エラーが発生します。 動的配列が要素0の時に発生するようです。 動的配列の要素が生成された場合だけ、Forループしたいのですが、 どうやって判定すればよいのでしょうか? ------------------------------- Dim 配列() As Integer Dim i As Integer i = 0 If (i < 0) Then ' 本当は真になったり偽になったり ReDim 配列(0 To i) 配列(i) = a + b i = i + 1 End If '' if ★★★ then '' 配列が有るか確認 For Each c In 配列 MsgBox c Next '' end if -------------------------------

  • 2次元配列を返す関数について

    VB6でExcelのMMULTのような関数が欲しかったので作って見ました。 関数内で配列をRedimで確保して戻り値として返すのですが、このような方法でメモリーリークなど発生する心配はないでしょうか? '行列の掛け算 Public Function mtxMult(ByRef mx1() As Double, ByRef mx2() As Double) As Double() Dim r, c, i, r1, c1, r2, c2 Dim res() As Double '行と列の最大値を得る r1 = UBound(mx1, 1) c1 = UBound(mx1, 2) r2 = UBound(mx2, 1) c2 = UBound(mx2, 2) If c1 <> r2 Then Exit Function ReDim res(0 To r1, 0 To c2) '答えの配列を確保 '各要素を掛ける For r = 0 To r1 For c = 0 To c2 res(r, c) = 0 For i = 0 To c1 res(r, c) = res(r, c) + mx1(r, i) * mx2(i, c) Next i Next c Next r mtxMult = res End Function '動作確認 Private Sub Command1_Click() Dim mx1(0 To 1, 0 To 1) As Double Dim mx2(0 To 1, 0 To 1) As Double Dim res() As Double Dim r As Integer List1.Clear mx1(0, 0) = 1 mx1(0, 1) = 2 mx1(1, 0) = 3 mx1(1, 1) = 4 mx2(0, 0) = 5 mx2(0, 1) = 6 mx2(1, 0) = 7 mx2(1, 1) = 8 res = mmult(mx1, mx2) For r = 0 To 1 List1.AddItem res(r, 0) & " , " & res(r, 1) Next r End Sub ところで、質問のソースコードのインデントを保持する方法はないでしょうか?

  • 配列化

    VB2005においてlabel,textboxといったコントロールを配列化したいのですがどうすればいいでしょうか? VB6では下記のコードが成り立ちますが・・・ For i=0 to 3 label(i).caption = str(i) Next このようにコントロール自体を配列化することは出来るのでしょうか?

  • エクセルVBAで配列内に空白データを入れる場合

    エクセル2000です。 ある大きな表のうち、0値を非表示ではなく完全に削除するために以下のようなマクロを書いてみました。 一旦配列に取り込んでいるのは高速化のためです。 これで見た目には目的を達しているのですが、実際には0値が長さ0の文字列に変わっただけで完全な空白にはなっていません。 配列にとりこまず、セルをループして0値のセルをClearすれば解決するのはわかるのですが、ほかにいい方法はないでしょうか? Sub TEST0値() Dim myAr With ActiveSheet x = .Range("A" & Rows.Count).End(xlUp).Row myAr = .Range("A4:AP" & x).Value For i = LBound(myAr, 1) To UBound(myAr, 1) For n = LBound(myAr, 2) To UBound(myAr, 2) If myAr(i, n) = 0 Then myAr(i, n) = "" Next n Next i .Range("A4:AP" & x).Value = myAr End With End Sub

  • ReDim Preserveできなかった配列をUBOUND……

    VBScriptでプログラムを組んでおります。 初心者なので言葉の使い方が間違っているかもしれませんがご容赦ください。 ASPでDBにアクセスして、このときにReDim Preserveを使って配列(str)を動的に拡張しながらDBから項目を抽出しています。 この動的に作った配列の項目を表示する際にどうしても項目数が必要なので UBound(str)で要素数を抜き出して使用しています。 DBにデータがあれば問題ないのですが、DBにデータがない場合はUBound(str)実行時に -------------------------- Microsoft VBScript 実行時エラー (0x800A0009) インデックスが有効範囲にありません。: 'ubound' -------------------------- と表示されてしまいます。 これを回避するにはDBから1つの項目を抽出する度に+1するような変数を作れば事足りるとは思いますが、 そうすると配列内の項目を表示する関数の引数を増やすことになり、少し納得がいきません。 Dim str() において Redim str(1)をしたかしてないかを見分ける方法を教えてくださいませんか。 ……無ければ「無い」と仰ってくれれば助かります。 では失礼します。 お時間があればご協力宜しくお願いします。

  • エクセルVBAで配列の追加

    エクセル2000です。 1行4列のセル範囲のデータを配列に取り込んで、後から別の1行4列のセル範囲のデータを配列に追加し、2次元配列として吐き出そうと思います。 最初の範囲がA1:D1、追加範囲がA4:D4とした場合、こんな不細工なコードになってしまいました。 これでも動きますが、どう修正すべきでしょうか? Sub test() Dim myAr() myAr = Application.Transpose(Range("A1:D1").Value) ReDim Preserve myAr(1 To 4, 1 To 2) For i = 1 To 4 myAr(i, 2) = Cells(4, i) Next i Range("F1").Resize(UBound(myAr, 2), UBound(myAr, 1)).Value = Application.Transpose(myAr) End Sub