こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

VB6-オブジェクトを配列にセット

質問用に、本来作りたいものではなく、機能に絞った質問をします。
ちなみにNo.2567628とは違います。

テキストボックスが10個あり、Text1、Text2、…Text10というオブジェクト名となります(説明の便宜上以上の名前になっているが実際はtxt○○で、○○の規則は無い)。仕様の都合上、text(1)、text(2)…の配列は使用できません。(配列のタイプはNo.2567628)

上記の仕様で、全てのテキストボックスをvbnullstringに割り当てたいのですが、
Private Sub Form_Load()
Dim i As Integer
Dim obj(9) As Object
Set obj(0) = Text1
Set obj(1) = Text2
Set obj(2) = Text3
Set obj(3) = Text4
    …
Set obj(9) = Text10

For i = 0 To 10
obj(i).text = vbnullstring
Doevents
Next i
End Sub

で、本来出来るのですが、
Set obj(0) = Text1 の右辺がStringで定義したい場合ができません。

つまり
Set obj(0) = "Text1"
という感じです。
(本来のシステムなら"Text1"にあたる所が"strData"とかになる)

Private Sub Form_Load()
Dim i As Integer
Dim obj(9) As Object
Set obj(0) = "Text1"  'ここでエラー
Set obj(1) = "Text2"
Set obj(2) = "Text3"
Set obj(3) = "Text4"
Set obj(4) = "Text5"
Set obj(5) = "Text6"
Set obj(6) = "Text7"
Set obj(7) = "Text8"
Set obj(8) = "Text9"
Set obj(9) = "Text10"

For i = 0 To 9
obj(i).Text = vbNullString
DoEvents
Next i

End Sub
ちなみにエラーは「型が一致しません」です。

どこを直したらいいか教えてください。

投稿日時 - 2007-07-31 00:00:00

QNo.3213956

すぐに回答ほしいです

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

Private Sub Command1_Click()
  Dim I   As Integer
  Dim ctl  As Control
  Dim obj(2) As String
  
  obj(0) = "Text1"
  obj(1) = "Check1"
  obj(2) = "Command1"
  For Each ctl In Me.Controls
    For I = 0 To 2
      If ctl.Name = obj(I) Then
        ctl.BackColor = vbYellow
        Exit For
      End If
    Next I
  Next ctl
End Sub

Exit For があった方がいいです。

投稿日時 - 2007-07-31 13:40:52

お礼

ありがとうございます。
僕の思っていた仕様が上記となります。

上記の考えをヒントにして、
本ツールを作ってみたいと思います。

それで、ちょっと踏み込みたいのですが、
チェックボックスcheck1のみ
check1(0)~check1(3)の4つがある場合、

dim J as integer
(中略)
      If ctl.Name = obj(I) Then

        if オブジェクトが配列の場合 = true ther
         for J = 0 to UBOUND(ctl.Name)
         ctl(J).BackColor = vbYellow
         next
Exit For
        Else
ctl.BackColor = vbYellow
end if
      End If
 ・・・
の用にしたらだめですが、For Each ~ Inにした方がいいですか?

投稿日時 - 2007-07-31 15:52:54

このQ&Aは役に立ちましたか?

4人が「このQ&Aが役に立った」と投票しています

回答(8)

ちょっと、踏み込んでいいですか?

Const conCTLNAME = "Text1/Check1/Command1"

Private Sub Command1_Click()
  Dim ctl As Control
  
  For Each ctl In Me.Controls
    If InStr(1, conCTLNAME, ctl.Name, vbTextCompare) Then
      ctl.BackColor = vbYellow
    End If
  Next ctl
End Sub

先の回答は、このようにも書けますよね。
違いは、プログラムコード自体から"Text1/Check1/Command1"を追放していることです。
コード内に埋め込まれた特定の数字や文字列は’マジックナンバー’と呼ばれています。
このマジックナンバーのあるコードはメンテナンスが非常に困難とされています。
ですから、[記号定数]を利用して特定のデータはコード内から追放することが推奨されています。

さて、「それじゃ、ctl がText1かCheck1なのかが判らない」という不具合も発生します。
これも、記号定数に規則性を持たせることで解決します。
Instr で検索して10番目からが Text1である、20番目はCheck1であるとすれば良い訳です。

'               ----+----1----+----2----+----3----+----4
Const conCTLNAME = "---------Text1/----Check1/---Command1"

Private Sub Command1_Click()
  Dim P  As Integer
  Dim ctl As Control
 
  For Each ctl In Me.Controls
    P = InStr(1, conCTLNAME, ctl.Name, vbTextCompare)
    If P > 0 Then
      Select Case P
        Case 10 ' Text1
          ctl.BackColor = vbYellow
        Case 20 ' Check1
          ctl.BackColor = &H8000000F
        Case 30 ' Command1
          If ctl.Style = 1 Then
            ctl.BackColor = vbYellow
          End If
        Case Else
      End Select
    End If
  Next ctl
End Sub

まあ、定年間際のおじさんのおせっかいです。
お礼など必要ありません。
ちょっと、先の回答を参考にされるとすれば問題の多い書き方でしたので補足した次第です。

投稿日時 - 2007-08-01 08:43:15

お礼

非常にユニークな考え方ですね。
長年の経験がひしひしと伝わってきます。
今回は流用はできませんが、次回以降の開発の参考にしてみます。

あと、ここに書く形になって申し訳ないですが、
今までご回答していただいたかた、誠にありがとうございました。

最初の解答からだいぶ目的が変わってきましたので、
一旦ここで閉め、改めて質問します。

投稿日時 - 2007-08-01 09:05:36

ANo3の補足+ANo6の補足だけですと、一切、コードを変更する必要はないです。
配列の形でCheck1が増えようとも、それは For Each のループ回数が3つ増えるだけですよ。
そして、その都度にそれぞれの増えたチェックボックスのプロパティが設定されます。
コード変更は無用という理由です。

投稿日時 - 2007-07-31 17:06:16

お礼

あ、そうですねぇ。

ちょっと別プログラムで合成してたらとばしたのでその部分を取り払って動きを見てみます。
ありがとうございました。

投稿日時 - 2007-07-31 18:12:10

ズブの素人ですが、横から失礼!

Private Sub Command1_Click()
  Dim I   As Integer
  Dim ctl  As Control
  Dim obj(2) As String
  
  obj(0) = "Text1"
  obj(1) = "Check1"
  obj(2) = "Command1"
  For Each ctl In Me.Controls
    For I = 0 To 2
      If ctl.Name = obj(I) Then
        ctl.BackColor = vbYellow
      End If
    Next I
  Next ctl
End Sub

obj() は、オブジェクトでも何でもないですよね。
単に ctl を比較テストするための文字列データ。
ctl.BackColor を設定しなきゃ。

なお、コマンドボタンはグラフィックスにしておかないと背景色の指定は無視されます。

投稿日時 - 2007-07-31 13:36:01

ANo.4

For Eachの場合 Nextは単独にしないといけません
Next ctlのctlを削除しましょう

投稿日時 - 2007-07-31 11:54:49

お礼

削除しました。

投稿日時 - 2007-08-01 09:06:28

ANo.3

プロパティの種類が統一されていないので難しいように思いますよ
たとえば LabelはCaptionが表示文字列TextBoxはTextといった具合に

でご希望の処理をしようとするなら
obj配列は String型で
フォームのContolsコレクションを舐めてNameプロパティと比較
個別の処理
といった具合かと

for each ctl in Me.controls
  for n=0 to 9
    if ctl.Name = obj(n) then
      ' 何かの処理
    end if
  next
Next

投稿日時 - 2007-07-31 01:14:17

お礼

テキストボックス・チェックボタン・コマンドボタンが一個ずつあります。

Dim n As Integer
Dim ctl
Dim obj(2) As String

obj(0) = "Text1"
obj(1) = "Check1"
obj(2) = "Command1"
For Each ctl In Me.Controls
If ctl.Name = obj(n) Then
obj(n).BackColor = vbYellow
End If
Next ctl

を実行してみましたが、うまくいきませんでした
(修飾子が不正です)。

投稿日時 - 2007-07-31 11:20:24

ANo.2

No.1です。

お礼欄のQに関しては。
その場合は一括でオブジェクト型で受けるもよし。
または別途それぞれに配列型各オブジェクト変数を用意し、画面上の
位置情報のみ別の構造体配列かクラスで持てばいいかと思います。

オブジェクト変数は何にでもなれ「すぎる」ので、なれ「すぎない」
ほうがオブジェクト指向には合った考え方だと思います。

また複数コントロールが介在する場合は、「お前はテキスト
ボックス?」とカレントオブジェクト自身を判定させれば
いいはずです。

各コントロールは、自分が「何」かプロパティをもっていたかと。

ちなみに。
複数コントロールが動的に画面に現れるクラスってのがイマイチ
イメージつかないのですが?
ソフトウェアの機能概要はなんでしょうか?

通常はフォーム概念で「業務クラス」になるような気がしますが。
(一部は郵便番号コントロールとか、独立オブジェクトになる
 はずですけどね)

投稿日時 - 2007-07-31 00:35:12

ANo.1

んー。

ちょっとタッチが違うように思いますね。
VB6はなんだかんだ言われても一応オブジェクト指向できますので。

まず、
1.Dim obj(9) As Object ではなく、Dim oText(9) AS TextBox
  ではないかと。
  テキストクラスの入れ子ですよね?
2.変数領域が確保できたら、newでインスタンスを作成する
  必要がありますよね?
3.変数代入は今まで通り、oText(index).Text = "あいうえ"と
  なるのでは?と思います。

ADODB.commandとか、Recordsetを利用するのと同じ形にすれば
いいんじゃないでしょうか?
これでいいんじゃないでしょうか?

投稿日時 - 2007-07-31 00:12:35

お礼

質問のところにしっかり書いてなかったのですが、
実はDim obj(9) As Object
には、テキストボックス以外に、コンボボックス、ラジオボタン、チェックボックスなども入ってくる可能性があります。

その場合はどうなるのでしょうかね。

投稿日時 - 2007-07-31 00:16:23

あなたにオススメの質問