配列を判定するには?

解決


よし  2011-05-22 05:57:45  No: 102924

windows xp sp3
vb6 sp6

初心者のよしです。
早速ですが、

フォームにラベル  Label1、Label2  コマンドボタン  Command1  を張り付けて、Label2のプロパティIndexに0を設定して、下記を実行すると
”配列ではないオブジェクトです”エラーがでます。Label1のIndexにも数値
を設定した場合にはエラーはでません。
Indexに数値が設定されているのみ下記の処理が実行できるようにしたいのですが?

 If IsArray(cControl.Index) Thenにしてもエラーとなります。
ご教授よろしくお願いします。

Private Sub Command1_Click()
    Dim cControl As Control
    For Each cControl In Me.Controls
        If TypeOf cControl Is Label Then
           Debug.Print cControl.Name & "(" & cControl.Index & ")"
        End If
    Next cControl
End Sub


58  2011-05-22 08:43:31  No: 102925

>If IsArray(cControl.Index) Thenにしてもエラーとなります。
IsArray関数の使い方が正しくありません。

ウォッチリストでLabel1のIndexプロパティを見ると、確かに「<配列ではないオブジェクトです。>」と表示されます。しかし、コントロールにIndexプロパティを指定した場合に配列として扱われるのはコントロールの変数であり、Indexプロパティではありません。つまり、IsArray(cControl)とするべきです。

が、しかし、VB6での、Indexプロパティの指定により配列化したコントロールは、IsArray関数での配列判定が出来ません。何故かは知りませんが。
試しに、以下のコードを実行してみて下さい。

Call MsgBox(CStr(IsArray(Label2)))

Indexプロパティにより配列化したはずのLabel2ですが、Falseが返ります。

ですので、これはもはや「On Error」ステートメントを使うしかないでしょう。

---------------- 以下、ソースコード ----------------

Option Explicit

Private Sub Command1_Click()
    Dim cControl As Control
    For Each cControl In Me.Controls
        If TypeOf cControl Is Label Then
        
            '******** 追加 ********

            On Error Resume Next   'エラー無視

            Dim strIndex As String
            strIndex = "(" & cControl.Index & ")"

            If Err.Number <> 0 Then

                If Err.Number = 343 Then   '"配列ではないオブジェクトです"
                    strIndex = ""
                Else
                    GoTo Err_Trap   '予期しないエラーの場合は終了
                End If
            End If

            On Error GoTo 0   'エラー無視の終了

            '******** 追加 ********
           
            Debug.Print cControl.Name & strIndex
        End If
    Next cControl
Exit Sub
'予期しないエラーが発生した場合のエラートラップ
Err_Trap:
    Call MsgBox(Err.Description, vbOKOnly Or vbCritical)
End Sub

---------------- 以上、ソースコード ----------------

他にも解決策はあるかもしれませんが、それが見つかるまではこの方法でやって見てはいかがでしょうか。


魔界の仮面弁士  2011-05-23 01:57:37  No: 102926

コントロール配列かどうかを確認するには、以下のようにします。

    Dim cControl As VB.Control
    For Each cControl In Me
        If TypeOf cControl Is Label Then
            If TypeOf Me(cControl.Name) Is VB.Control Then
                Debug.Print cControl.Name
            Else
                Debug.Print cControl.Name & "(" & cControl.Index & ")"
            End If
        End If
    Next

コントロール配列にしていない Label1 と
コントロール配列として作った Label2(0) があるとします。

この場合の Label2 は、実はコントロールではありません。

Debug.Print TypeName(Label1)     'Label と表示される
Debug.Print TypeName(Label2)     'Label ではない!
Debug.Print TypeName(Label2(0))  'Label と表示される

ですから、Me.Controls("Label2") のデータ型を調べてみて、
それが Label や Control 型では無かった場合、それは
コントロール配列であるという事がわかるというワケです。

> If IsArray(cControl.Index) Thenにしてもエラーとなります。
そもそも、Index にアクセスできないのですから、これでは駄目でしょう。

それに、Index プロパティの戻り値は Integer 型であり、
どちらにせよ配列ではありません。

> ”配列ではないオブジェクトです”エラーがでます。
コントロール配列と呼ばれるものは、実際にはその名前に反して
配列ではありません。そのため、IsArray では判定できません。

「コントロール配列」ではなく「コントロールの配列」ならば
判定できますけれどね。

Dim c(1) As VB.Control
Set c(0) = Label1
Set c(1) = Command1
Debug.Print IsArray(c)   'True

コントロール配列というものは、実際にはコレクションの一種です。

コントロール配列にすると、Index プロパティが使われるという点の他、
御存知のようにイベントの管理単位やイベント引数も変わってきますし、
  Debug.Print Label2.Count
といった、コレクションならではのメソッドが追加されるきたりもします。


よし  2011-05-23 11:38:07  No: 102927

エラートラップでの判定、またデータ型での判定

>If TypeOf Me(cControl.Name) Is VB.Control Then

>Me.Controls("Label2") のデータ型を調べてみて、
>それが Label や Control 型では無かった場合、それは
>コントロール配列であるという事がわかるというワケです。

非常に勉強になりました。

58さん、魔界の仮面弁士さん  解りやすくご説明していただき、感謝しております。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加