- ベストアンサー
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 ちなみにエラーは「型が一致しません」です。 どこを直したらいいか教えてください。
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
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 があった方がいいです。
その他の回答 (7)
ちょっと、踏み込んでいいですか? 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 まあ、定年間際のおじさんのおせっかいです。 お礼など必要ありません。 ちょっと、先の回答を参考にされるとすれば問題の多い書き方でしたので補足した次第です。
お礼
非常にユニークな考え方ですね。 長年の経験がひしひしと伝わってきます。 今回は流用はできませんが、次回以降の開発の参考にしてみます。 あと、ここに書く形になって申し訳ないですが、 今までご回答していただいたかた、誠にありがとうございました。 最初の解答からだいぶ目的が変わってきましたので、 一旦ここで閉め、改めて質問します。
ANo3の補足+ANo6の補足だけですと、一切、コードを変更する必要はないです。 配列の形でCheck1が増えようとも、それは For Each のループ回数が3つ増えるだけですよ。 そして、その都度にそれぞれの増えたチェックボックスのプロパティが設定されます。 コード変更は無用という理由です。
お礼
あ、そうですねぇ。 ちょっと別プログラムで合成してたらとばしたのでその部分を取り払って動きを見てみます。 ありがとうございました。
ズブの素人ですが、横から失礼! 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 を設定しなきゃ。 なお、コマンドボタンはグラフィックスにしておかないと背景色の指定は無視されます。
- redfox63
- ベストアンサー率71% (1325/1856)
For Eachの場合 Nextは単独にしないといけません Next ctlのctlを削除しましょう
お礼
削除しました。
- redfox63
- ベストアンサー率71% (1325/1856)
プロパティの種類が統一されていないので難しいように思いますよ たとえば 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
お礼
テキストボックス・チェックボタン・コマンドボタンが一個ずつあります。 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 を実行してみましたが、うまくいきませんでした (修飾子が不正です)。
No.1です。 お礼欄のQに関しては。 その場合は一括でオブジェクト型で受けるもよし。 または別途それぞれに配列型各オブジェクト変数を用意し、画面上の 位置情報のみ別の構造体配列かクラスで持てばいいかと思います。 オブジェクト変数は何にでもなれ「すぎる」ので、なれ「すぎない」 ほうがオブジェクト指向には合った考え方だと思います。 また複数コントロールが介在する場合は、「お前はテキスト ボックス?」とカレントオブジェクト自身を判定させれば いいはずです。 各コントロールは、自分が「何」かプロパティをもっていたかと。 ちなみに。 複数コントロールが動的に画面に現れるクラスってのがイマイチ イメージつかないのですが? ソフトウェアの機能概要はなんでしょうか? 通常はフォーム概念で「業務クラス」になるような気がしますが。 (一部は郵便番号コントロールとか、独立オブジェクトになる はずですけどね)
んー。 ちょっとタッチが違うように思いますね。 VB6はなんだかんだ言われても一応オブジェクト指向できますので。 まず、 1.Dim obj(9) As Object ではなく、Dim oText(9) AS TextBox ではないかと。 テキストクラスの入れ子ですよね? 2.変数領域が確保できたら、newでインスタンスを作成する 必要がありますよね? 3.変数代入は今まで通り、oText(index).Text = "あいうえ"と なるのでは?と思います。 ADODB.commandとか、Recordsetを利用するのと同じ形にすれば いいんじゃないでしょうか? これでいいんじゃないでしょうか?
お礼
質問のところにしっかり書いてなかったのですが、 実はDim obj(9) As Object には、テキストボックス以外に、コンボボックス、ラジオボタン、チェックボックスなども入ってくる可能性があります。 その場合はどうなるのでしょうかね。
お礼
ありがとうございます。 僕の思っていた仕様が上記となります。 上記の考えをヒントにして、 本ツールを作ってみたいと思います。 それで、ちょっと踏み込みたいのですが、 チェックボックス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にした方がいいですか?