- ベストアンサー
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 ちなみにエラーは「型が一致しません」です。 どこを直したらいいか教えてください。
- tocci_pc
- お礼率81% (301/370)
- Visual Basic
- 回答数8
- ありがとう数10
- みんなの回答 (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 には、テキストボックス以外に、コンボボックス、ラジオボタン、チェックボックスなども入ってくる可能性があります。 その場合はどうなるのでしょうかね。
関連するQ&A
- VB添削
このプログラムは 例えば3 3 4とテキストボックスに数字が打ち込まれると 3×3行列が4個分 のテキストボックスがでてきます。 ここに数字を打ち込んでいき、ボタン2を押すと3×3のテキスト トボックスが出てくると同時に足し算した結果が出てくるようにしたいです。 以下のプログラムはできたところまで作成しています。 どこを直せばよいのでしょうか。 Public Class Form1 Private number As Integer Private rows As Integer Private columns As Integer Private Sub Form11_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load For i As Integer = 1 To 3 AddHandler Me.Controls("TextBox" & i).TextChanged, AddressOf TextBox_TextChanged Next End Sub Private Sub TextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) If System.Text.RegularExpressions.Regex.IsMatch(CType(sender, TextBox).Text, "[^0-9]") Then MessageBox.Show("数字で入力してください", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error) With CType(sender, TextBox) .Text = .Text.Substring(0, .Text.Length - 1) .SelectionStart = .Text.Length End With End If Dim cnt1 As Integer Dim cnt2 As Integer Dim cnt3 As Integer If Integer.TryParse(TextBox1.Text, cnt1) And Integer.TryParse(TextBox2.Text, cnt2) And Integer.TryParse(TextBox3.Text, cnt3) Then For k = 1 To cnt3 For i = 1 To cnt1 For j = 1 To cnt2 Dim tb As TextBox = New TextBox() tb.Name = "tb" + i.ToString() Me.Controls.Add(tb) tb.Top = (i - 1) * 28 + 55 tb.Left = (j - 1) * 30 + 40 * (cnt2 * (k - 1)) + 10 tb.Width = 25 Next Next Next End If End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.Bounds = New Rectangle(10, 10, 1350, 800) Me.AutoScroll = True End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim sum As Double Dim cnt As Integer = 0 For i As Integer = 1 To rows For j As Integer = 1 To columns Dim tb As TextBox = New TextBox() cnt += 1 : If cnt > rows * columns Then cnt = 1 tb.Name = "tb" + cnt.ToString Me.Controls.Add(tb) tb.Top = (i - 1) * 30 + (80 + 40 * rows) tb.Left = (j - 1) * 60 + 10 tb.Width = 40 sum = 0 For k As Integer = 1 To number sum += Double.Parse(CType(Me.Controls("tb" + (cnt + (rows * columns * (k - 1))).ToString()), TextBox).Text) Next tb.Text = sum.ToString() Next Next End Sub Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged End Sub Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged End Sub Private Sub TextBox3_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox3.TextChanged End Sub End Class
- 締切済み
- Visual Basic
- Excel VBA でExecuteExcel4Macro("GET.OBJECT(48,
エクセル2000です。 以前、ワークシートに配置したフォームツールのラベルの参照元を取得するマクロをご教示いただき、以下のTest01は問題なく作動しています。 Sub test01() Dim obj As Object Dim i As Integer Dim obj_n As String 'オブジェクトの名前 With ActiveSheet For Each obj In .Labels i = i + 1 .Cells(i, 2) = obj.Name: obj_n = obj.Name .Cells(i, 3) = obj.TopLeftCell.Address 'GET.OBJECT で、リンクがないものを取ると、False になる .Cells(i, 5) = ExecuteExcel4Macro("GET.OBJECT(48,""" & obj_n & """)") .Cells(i, 6) = obj.OnAction Next End With End Sub 今回、同一シートではなく別シートに表示させようと以下のTest02を書いたのですが、やってみると .Cells(i, 5) はすべて#VALUE!エラーになってしまいました。 ExecuteExcel4Macro("GET.OBJECT(48~がどのようなものかわからずやっているので応用がききません。(そもそも48って?) どのようになおしたらよいのかご教示いただければ幸いです。 Sub test02() Dim obj As Object Dim i As Integer Dim obj_n As String Dim ws As Worksheet, ns As Worksheet Set ws = ActiveSheet Set ns = Worksheets.Add With ns For Each obj In ws.Labels i = i + 1 .Cells(i, 2) = obj.Name: obj_n = obj.Name .Cells(i, 3) = obj.TopLeftCell.Address .Cells(i, 5) = ExecuteExcel4Macro("GET.OBJECT(48,""" & obj_n & """)") .Cells(i, 6) = obj.OnAction Next End With End Sub
- ベストアンサー
- オフィス系ソフト
- Formオブジェクトについて
Formオブジェクトに関する質問です。 ある関数にフォームオブジェクトを引数として渡してやりたいのですが、何かよい方法はありますでしょうか? 例) Private Sub cmdTest_Click(Index as Integer) Dim frm as Form If Index = 0 then Load_Test(Form 2) Else Load_Test(Form 3) End if End Sub Private Sub Load_Test(frm as Form) frm.Show frm.Label1.Caption = "TEST” End Sub
- ベストアンサー
- Visual Basic
- VBで入力された値をワード文書に表示(OLEオートメーション)
VBより名前と年齢を入力し、登録ボタンを押すと ワードにデータが登録されるようにしたいのですが、 実行時エラーが表示されます。 Dim x As Object Private Sub Command1_Click() x.Insert.Into Text1.Text & ":" & Text2.Text & Chr(10) ---(1) End Sub Private Sub Form_Load() Set x = CreateObject("Word.Basic") End Sub Private Sub Form_Unload(Cancel As Integer) Set x = Nothing End Sub (1)で 実行時エラー'509'「Insert,文書ウィンドウが選択されていないためコマンドは使用できません」 が表示されます。 考えられる原因はなにか教えてください! VB6.0/WindowsXP SP2/Office 2000 です
- ベストアンサー
- Visual Basic
- VBで倍数を出したい
VBで倍数を出したい よろしくお願いします。 おそらく基本なんだと思うのですが、さっぱりわかりません。 TextBox Label Buttonと並んでいて、 TextBoxに入った整数に対し、 Buttonを1度押すたびに、 Labelに倍数が表記されていく、 という趣旨なのですが。 まず、前段階として下記を作らされました。 Public Class Form1 Dim i As Integer Dim m As Integer Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click i = TextBox1.Text lblmessage.Text = i + m m = lblmessage.Text End Sub End Class このように、labelの数字がどんどん変わっていくのはできたのですが、問題は、 Text…10 Label…10 20 30 40 50 60 70 80 90 100 となり、しかも一度に出るのではなく、Buttonひと押しにつき一つの解が出ね 次の一押しで改行され解が出る。 かつ、100で打ち止めにすること…だそうです。 いちおうめちゃくちゃですが、みんな風に作りました。 Public Class Form1 Dim a As Integer Dim b As Integer Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim b As Integer = 10 a = TextBox1.Text lblMessage.Text = a & ControlChars.CrLf & a + b End Sub End Class どうかヒントだけでもお願いします。
- ベストアンサー
- オフィス系ソフト
- SetとNothingの存在意味?
数値とオブジェクトの変数セットはそれぞれ、 Dim num as integer num = 5 Dim obj as Object set obj = new From set obj = Nothing ですが、 オブジェクトの場合でインスタンスを生成しない、単なる参照?別名? の場合はNothingは不要でしょうか? Dim obj as Object For x = 1 to 10 set obj = Form2 ' newとインスタンスを生成するのではなく、単なる参照 obj.Caption = str(x) & "回目" 'set obj = nothingは不要? Next x
- ベストアンサー
- Visual Basic
- VB、教えてください。
VB、教えてください。 5つのラベルが縦に並んでいます。 label0 label1 label2 label3 label4 あらかじめ、 Dim m as integer=0 を宣言し、 どうにかして "label"という文字列とmという数字をくっつけ、 label0 label1… という風にできないでしょうか。 そして label"m".text=10*m というような表示を作りたいのですが。 下記のようなイメージです。分かりにくかったらごめんなさい。 Public Class Form1 Dim m As Integer = 0 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click lblmessage(+("m").Text = 10*m m = m + 1 End Sub End Class
- ベストアンサー
- オフィス系ソフト
- VB6→VS2005アップグレード後
いつもお世話になっております。 VBを勉強中です。 VB6→2005にアップグレード後、下記のエラーが発生しました。 "オブジェクト参照がオブジェクト インスタンスに設定されていません。" 以前もこちらでアドバイスをいただき、 デザインの中でADDされているかどうかを確認し、解決に結びついたので 今回も同様かと思い、色々と行ったのですが解決しません。 frmapli_S3のデザイナ内に下記が存在しましたが 原因はここでしょうか? CType(Me.Frame1, System.ComponentModel.ISupportInitialize).EndInit() 以下はVB6での正常稼動時のソースです。 Public Sub ShowPermValue() Dim Textbox As Textbox Dim i As Long: Dim j As Long: Dim k As Long For i = 0 To 19 For j = 1 To 8 k = i * 10 + j Set Textbox = frmapli_S3.Controls("text" & k) Textbox.Text = PermValue(k) Next Next End Sub Public Sub SetPermValue() Dim Textbox As Textbox Dim i As Long: Dim j As Long: Dim k As Long For i = 0 To 19 For j = 1 To 8 k = i * 10 + j Set Textbox = frmapli_S3.Controls("text" & k) PermValue(k) = Textbox.Text Next Next 下記はVB2005アップグレード時のソースです。 Public Sub ShowPermValue() Dim Textbox As TextBox Dim i, j, k As Integer For i = 0 To 19 For j = 1 To 8 k = i * 10 + j Textbox = CType(frmapli_S3.Controls("text" & k), TextBox) TextBox.Text = PermValue(k) Next Next End Sub Public Sub SetPermValue() Dim Textbox As TextBox Dim i, j, k As Integer For i = 0 To 19 For j = 1 To 8 k = i * 10 + j Textbox = CType(frmapli_S3.Controls("text" & k), TextBox) PermValue(k) = Textbox.Text ←ここでエラー Next Next End Sub
- 締切済み
- Visual Basic
- 配列を引数で渡したりするには?
初心者なので困っています。配列をほかのサブルーチンへ渡して、その中で配列の値を書き換えて、上層のルーチンへ渡すにはどうしたらよいのでしょうか? 初心者なので、みなまさまのお知恵を拝借させてください。よろしくお願いします。 Private Sub Print() Dim C_ALL(3) As Integer Dim D_ALL(3) As Integer Data_Set(C_ALL(), D_ALL()) MsgBox(C_ALL() & " " & D_ALL()) '配列内容すべて表示 End Sub Private Sub Data_set(ByRef C_ALL As Integer, ByRef D_ALL As Integer) Dim i As Integer For i = 0 To 4 C_ALL(i) += i D_ALL(i) += i i += 1 Next End Sub
- 締切済み
- Visual Basic
- VB6のwinsockでconnectできない
socketでconnectすると、sckclosingとなって通信できない。 機械との通信プログラムをつくるため、インターネットから以下のようなサンプルを取って、同一コンピュータ、または異なるコンピュータ間で通信しようとした(一部省略、改変)が、stateが8となってしまいます。socketを使うのは初めてで、皆目見当がつきません。よろしくお願いします。 サーバー側 Private Sub Form_Load() Winsock1.LocalPort = 1001 Winsock1.Listen -------- End Sub Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) Dim dat As String, ans As String Dim n As Integer Winsock1.GetData dat Text1.Text = dat Winsock1.SendData "わかりません" End Sub Private Sub Form_Load() Text1.Text = "abc" (正しいコンピュータ名を入れた) Winsock1.Close LabCon.Caption = "Closed": LabCon.BackColor = vbWhite End Sub クライアント側 Private Sub Command1_Click() Winsock1.Close Winsock1.RemoteHost = Text1.Text Winsock1.RemotePort = 1001 'ポート番号設定 Winsock1.Connect Do While (Winsock1.State <> sckConnected) LabCon.Caption = Winsock1.State DoEvents Loop End Sub クライアントでcommand1ボタンをクリックすると最初はstateが0、ループに入ると8となって出られません。WindowsXP、Vista共に同じ結果でした。
- ベストアンサー
- Visual Basic
お礼
ありがとうございます。 僕の思っていた仕様が上記となります。 上記の考えをヒントにして、 本ツールを作ってみたいと思います。 それで、ちょっと踏み込みたいのですが、 チェックボックス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にした方がいいですか?