• ベストアンサー

エクセルマクロのイベントプロシージャについて

 こにんちは。仕事で使う表をもっと便利にするため、独学でマクロを勉強、作成している者です。  さて、今回、ユーザーフォーム上に5つのテキストボックスを配置して(Textbox1~Textbox5)、Textbox1に入力した内容によってカーソルの移動先を変えるマクロを作成したいのですが、うまくいきません。  私の作成したコードは以下の通りです(今回、質問するにあたって、かなり省略しています)。 Private Sub TextBox1_AfterUpdate() Select Case TextBox1.Value Case 1 TextBox1.SetFocus Case 2 TextBox2.SetFocus Case 3 TextBox3.SetFocus Case 4 TextBox4.SetFocus Case Is >= 5 TextBox5.SetFocus End Select End Sub  そこで、いろいろ試したり調べたりしたのですが、どうもイベントプロシージャそのものに対する基本的な認識ができていない気がしてきました。  と言いますのも、上記プログラムを走らせると、1、2を入力した際はタブオーダーに従い?Textbox2へカーソルが移動しますが、3以上の数値を入力すると、4でも5でもTextbox3へ移動します。  何をやってもタブオーダー通りにしか移動しないのならともかく、なぜこのような変な動きになるのか、分かりやすく説明していただくことは可能でしょうか。  また、もちろんどうすれば目的通り動かせるのかも教えていただきたく思います。  もちろん一番の目的はそれなのですが、今後の理解のため、イベントのタイミング等について教えていただければ幸いです。  なお、各イベントの意味については、下記のページを見て理解はできたつもりなのですが・・・。  http://home.att.ne.jp/zeta/gen/excel/c04p30.htm

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

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.3

#2 の修正です。 データ型を単純に i をInteger 型してしたので、エラーが発生するようです。 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)  Dim i As Variant   If KeyCode <> 13 Then Exit Sub   If Not IsNumeric(i) Then Exit Sub   i = TextBox1.Value   If i = 1 Then KeyCode = 0   If i > 1 Then   If i > 5 Then i = 5     Me.Controls("TextBox" & i).SetFocus   End If   'TextBox1.Value = "" '入力した数値を消す End Sub テキストボックスに入力したら、TextBox1 に戻る Private Sub TextBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   If KeyCode = 13 Then     TextBox1.SetFocus   End If End Sub

slowdancer
質問者

お礼

ご回答いただき、ありがとうございます。 昨日、1回目にいただいたコードでエラーが出たため、ない知恵を絞って、その原因をあれこれ考えていました。素直にお聞きすればよかったですね(笑)。 やってみたら、思っている動きができました!ありがとうございます。 今後のため、このコードの中身を少しでも理解できるよう、この後、じっくり考えさせていただきますが、パッとみてひとつだけ疑問点があります。13で区切っているのは、何か理由があるのですか?

その他の回答 (5)

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.6

#4です。 すみません。 >>TextBox1に入力する数字が2桁以上だと、 >>まったく違う話になりますので、 >>別途質問を立て直した方いいと思います。 二重に間違えました。 #1へのコメントを読んで、Enter押さないオーダーと勘違いしてました。 失礼なこと書いてごめんなさい。 それと、#8のソースが、数字入力1桁のみに対応、というのも間違いです。 2から19の数字入力でフォーカス移動します。 重ね重ね、失礼しました。

slowdancer
質問者

お礼

再度コメントいただきまして、ありがとうございます。 >#1へのコメントを読んで、Enter押さないオーダーと勘違いしてました。 とのことですが、こちらこそ分かりにくい文章で申し訳ありませんでした。 今後もみなさんからいただいたご回答とコードを見て、勉強していきたいと思っています。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.5

こんにちは。 #2,#3で書いた者です。 >13で区切っているのは、何か理由があるのですか? 13というのは、"Enter" の意味ですが、Enter を入れるまで待つということです。 「1」を入れたけれども、間違いで、「2」というときは、BackSpace で訂正が効きます。Change イベントだと入力した時点で稼動してしまいますので、私は使いません。また、2桁以上でも可能です。 If i = 1 Then KeyCode = 0 これは、入力しても、そのコントロールのフォーカスを移動させないということを意味しています。 なお、KeyDown は、私が良く使う方法です。

slowdancer
質問者

お礼

再度のご回答、ありがとうございました。 KeyCodeのことを理解してなかったため、最初はなぜ13?と思ったのですが、ご説明いただいたおかげでようやく分かりました。 ご回答者様のkeydownを使った方法は、私にも何をやっているのか理解でき、今後も使わせていただけそうです。勉強になりました!

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.4

こんにちは 状況は再現できました。 10キーからIMEオフ状態で数字を1桁だけ入力したらイベント発生、 という条件なら(実際に(Textbox1~Textbox5)なら)、 _Change() イベントが使えるかもしれません。 よく解りませんが、以下のような感じではどうでしょうか。 一応、TextBox1への移動は意味ないので、2~5にフォーカスが移動します。 一応エラー処理も少しだけ加えました。 ' ////// ' 以下をコピペ。必ず!!、UserFormモジュールの先頭行に。 ' Sub TextBox1_Changeが重複する場合は、エラーになります。 Const TextBoxesMin = 1 Const TextBoxesMax = 5 Private Sub TextBox1_Change() PSetF TextBox1.Value End Sub Sub PSetF(v) If Val(v) < 2 Then Exit Sub v = CInt(v) If v > TextBoxesMax Then v = TextBoxesMax Me.Controls("TextBox" & v).SetFocus End Sub ' Excel2000、2003で動作確認済み ' ////// 十分にニーズを把握できないので、説明はご容赦ください。 TextBox1に入力する数字が2桁以上だと、 まったく違う話になりますので、 別途質問を立て直した方いいと思います。 条件に合わないようでしたら、すみません

slowdancer
質問者

お礼

ご回答いただきありがとうございました。 試してみたところ、確かに目的の動きをするのが確認できました。 下の方のお礼にも書きましたが、なんとかその動きを理解できるよう、この後、教えていただいたコードをじっくり解読させていただきます。 ちなみに蛇足ですが、状況を再現できたというのが、ちょっとうれしかったです(笑)。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんにちは。 UserForm は、入門したばかりでなくても、難しいです。というか、私は、苦手で勉強しませんでしたからね。 >3以上の数値を入力すると、4でも5でもTextbox3へ移動します。 詳しいことは分かりませんが、TabOrder の3番目に動くのではないでしょうか。ダメな理由は考えたことがありません。例えば、こんな風にすれば、目的どおりの場所に飛ぶはずです。 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)  Dim i As Integer   i = TextBox1.Value   If KeyCode <> 13 Then Exit Sub   If i = 1 Then KeyCode = 0   If i > 1 Then   If i > 5 Then i = 5     Me.Controls("TextBox" & i).SetFocus   End If   'TextBox1.Value = "" End Sub

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.1

一読して、>Textbox1に入力した内容によってカーソルの移動先を変える・・・ってどういう意味かな。 Excelのシート上の選択セルを変えるということかな。 それではSetFocuでなない。 1つのテキストボックスの情報で、他のテキストボックス群の中の約束(対応)されたテキストボックスを選択状態にするのかな。 あまり省力化にならないし、普通こんなこと考えないと思うが。 直接テキストボックスを選択すれば、済むことだし。 ただ5個の中でどのテキストボックスを選択したか、えり分けるのは 難しいです。 ーーー 初心者は、自分の下手なコードを載せるのは最後に参考程度にして、「やりたいことをはっきり書くこと」。またやりたいことが、質問者のアイデアの入った段階からでなく、素のベルで書いてみてください。コードからは、やりたいことの解読が難しいことが多い。 本件もそう思う。 例えばテキストボックスを使う、というアイデア(構想)そのものが、素人の思いつきになっている(適当でない)場合が多い。 中級の人でも、発想を変えるとコードが短くなり、考えがすっきりして、コードの誤りが少なくなる処理を、こういう公の場に質問した機会を捉え、勉強したいはずです。 ーー 関連して、 TextBoxはそのイベントなどでトリガーを引くより、コマンドボタンを設けて、テキストボックスの入力が終わっときクリックさせて、それをトリガーに刷るほうがよいのでは。

slowdancer
質問者

補足

 ご回答ありがとうございます。私の書き方が悪かったようで申し訳ありません。私のやりたいことは、後者、すなわち、 >1つのテキストボックスの情報で、他のテキストボックス群の中の約束(対応)されたテキストボックスを選択状態にするのかな。 の方です。  確かにご指摘のとおり、わざわざこんなことをしなくても、マウスでクリックすればどのテキストボックスでも選択状態になるのですが、データ入力の効率を出来るだけ上げるため、右手を10キーに添えたままで極力入力が行なえるようにしたいからです。  後でデータに矛盾が生じた際に、一度通り過ぎたテキストボックスへカーソルを自動的に戻るようにしたいときがあるのです。  また、入力不要なテキストボックスに対して、enterキーを空打ちして飛ばすのも、できれば省略したいと考えています。  例えば商品出荷データの入力フォームを作成しているのですが、前者の例でいえば、出荷日と到着日を入力し、その後、出荷先のデータを入力した際、遠方なのに翌日着にしていたらエラーメッセージを出して到着日のテキストボックスにカーソルを移動させます。  後者の例でいえば、特定の商品については、商品コードを入力すると、品名、仕様、色などのテキストボックスに自動的にデータが表示されるため、それらのテキストボックスは飛ばして、すぐに数量のテキストボックスを選択状態にします。  もちろん現状でも十分使えていますが、それらのことが実現できれば、少しだけ使いやすくなるという、「なくても困らない、あったら便利だ」程度のことではあります。  たったそれだけのためにかなりの時間と労力を費やすのなら、さっさと諦めようと思ったのですが、ネットで調べてみたところ、afterupdateというイベントを使えば、比較的簡単にできそうだと感じました。それを試すために作ったのが上記のコードです。  しかし、所詮、基本を知らない素人の浅知恵ですから、うまく動きませんでした。前述のとおり、できなくても別に困りはしないのですが、なぜできないのかがすごく気になったため、また、イベントプロシージャについて勉強する良い機会だと思ったため、こうして質問するにいたったわけです。  よって、やりたいことを述べてそれをコードにしていただくというより、イベントプロシージャの(特に今回はafterupdateイベントの)動きや働きについて、より深く理解できればと思っております。  長文になり、失礼しました。読み返してみると、少し言い訳っぽく見える気がしますが、そういう意味ではなく、何がしたいかを詳しく述べてみたつもりです。  なぜ、afterupdateのイベントでsetfocusはうまく機能しないのでしょうか?

関連するQ&A

  • エクセルユーザーフォームのカーソル位置

    どうしても分からないのでお助け下さい(>_<) エクセルでユーザーフォームを作っています。 TextBox1に品番を入れたら、Label1に品名を表示させています。 このとき、TextBox1に存在しない品番を入力した場合は、 再度入れなおしをさせたいのです。 そこで、カーソルをもう一度TextBox1に持っていきたいのです。 しかし、どうやってもタブオーダーでTextBox1の次にあるTextBox2に カーソルが行ってしまいます。 どうしたらもう一度TextBox1にカーソルを持っていくことができますか? ちなみに品名を表示するモジュールを書いておきます。 このSetFocusが違うということは分かるのですが・・・。 Private Sub TextBox1_AfterUpdate() Dim tmp As Range, a a = Me.TextBox1.Value   Set tmp = Sheets(1).Columns(1).Find(a, , xlWhole)   If tmp Is Nothing Then     Me.Label1.Caption = "品番が誤っています。再度入力して下さい"     Me.TextBox1.SetFocus     Exit Sub   Else     Me.Label1 = tmp.Offset(0, 1)   End If End Sub

  • ユーザーフォームのカーソル移動

    Excelのマクロでカーソル移動の事で教えて下さい。 フォームを表示するとTextBox1にカーソルが表示されます。 TextBox1で入力の判断しNG場合 カーソルを移動せずTextBox1に表示したいのですが CommandButton1に移動してしまいます。 (SetFocusでTextBox1を指定してNG) 【フォームの内容です】 TextBox1が1個 CommandButtonが2個存在します。 TextBox1のTabIndexは 0 CommandButton1のTabIndexは 1 CommandButton2のTabIndexは 2 【プログラムです】 Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean) If TextBox1 = "" Then MsgBox "NG"     TextBox1.SetFocus End If End Sub 宜しくお願い致します。

  • コマンドボタンのEnterイベント後に、フォーカスを移動したい。

    コマンドボタンのEnterイベント後に、フォーカスを移動したい。 フォームに「TextBox1」(TabIndex=0)「TextBox2」(TabIndex=1)「CommandButton1」(TabIndex=2)の3つのコントロールがある場合。 CommandButton1がクリックされた場合も、TextBox2からCommandButton1に、タブキーまたはエンターキーで、フォーカスが移った場合にも、同じ処理を行い、処理結果によってTextBox1やTextBox2にフォーカスを移したいと考えています。 以下のようなサンプルを作成しました。 Private Sub CommandButton1_Enter() CommandButton1_Click End Sub Private Sub CommandButton1_Click() MsgBox ("OK") TextBox2.SetFocus End Sub この場合、CommandButton1_Enterのイベントが起こった場合、CommandButton1_Click()のTextBox2.SetFocusは効きません。 (正確には、CommandButton1_Enterイベントが終わった時点で無効でしょうか。) Enterイベントは、フォーカスが移動する前に発生するため、このイベントが終わった後に、そもそもの動作に戻り、フォーカス移動が発生してしまうからなのだと思っております。 要は、コマンドボタンにタブキーやエンターキーでフォーカスしても、コマンドボタンをクリックしたのと同じ処理を行い、所定の位置にフォーカスを持っていきたいのですが、どのように行えば良いか、わからない状況です。 よろしくお願いいたします。

  • UserFormのSetFocus

    環境はExcel2002です (1)TextBox1に入力された数値を,区切りにする (2)TextBox2を入力不可の状態から入力可能な状態にする (3)TextBox2をSetFocusする という単純なプロシージャなのですが SetFocusされなくて困ってます UserFormタブオーダーの順番はTextBox1,TextBox2の順になっています 考えられる原因はなんでしょうか? ご教示願います 原因が不明でも回避する方法を教えていただいても結構です なんとしてもSetFocusしたい Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean) Me.TextBox1.Text = Format(TextBox1.Text, "#,##0") Me.TextBox2.Enabled = True Me.TextBox2.BackColor = &H80000005 '背景色(白色) Me.TextBox2.SetFocus End Sub

  • エクセル イベントマクロのエラー回避

    イベントマクロを初めて書いてみたのですが A列を全部選択して削除などをするとエラーがて出てしまいます 回避するにはどのようにしたら良いのでしょうか? Private Sub Worksheet_Change(ByVal Target As Range) If Not Intersect(Target, Range("A:A")) Is Nothing Then Select Case Target.Value Case Is = "りんご" cellColor = 3 Case Is = "みかん" cellColor = 6 End Select End If If Not Intersect(Target, Range("B:B")) Is Nothing Then Select Case Target.Value Case Is = "りんご" cellColor = 6 Case Is = "みかん" cellColor = 3 End Select End If Target.Interior.ColorIndex = cellColor End Sub 以上が書いたものです。 皆様の知恵お貸しください 宜しくお願いします。

  • エクセル マクロで教えて下さい。

    入力されたセルの値で、フリーフォーム(図形)の色を変えるマクロを作成しました。 (色々の方のお力をお借りしておりますが。。。) Private Sub Worksheet_Change(ByVal Target As Range) Dim mShp As String, SCol As Integer Select Case Target(1).Address(0, 0) Case "A1": myShp = "フリーフォーム 1" Case "A8": myShp = "フリーフォーム 8" Case "B3": myShp = "フリーフォーム 3" Case Else: Exit Sub End Select Select Case Target(1).Value Case 1: SCol = 10 Case 2: SCol = 13 Case 3: SCol = 12 Case 4: SCol = 11 Case 5: SCol = 15 Case Else: SCol = -1 End Select With Me.Shapes(myShp).Fill If SCol = -1 Then .Visible = msoFalse Else .Visible = msoTrue .ForeColor.SchemeColor = SCol End If End With End Sub A1,A8,B3に直接値を入力すると色が変化しますので、問題ないのですが、VLOOKUP等で別シートの値を、A1,A8、B3に表示させても色が変わらない事がわかりました。 そこで、このマクロでVLOOKUP等で引っ張って来た場合でも対応出来る様に変更する事は可能でしょうか? それが出来ない場合は、別シートのセルを直接参照し色を変化出来る様に変更する事が出来ないでしょうか? これを作成するのに聞いた人間はマクロに詳しい方々ですが、当方は、マクロは素人同然です。 詳しく説明していただければ幸いです。 何卒よろしくお願い致します。

  • Excel VBAのユーザーフォーム

    Textboxや、Comboboxで、2バイト入力した時に、次のTextboxや、Comboboxに移動出来るような制御はありますか?2バイト以上入力出来ないような制御をしたいです。 Private Sub ComboBox1_Change() ComboBox2.SetFocus End Sub も考えたのですが、これだと何バイトでも入力出来るので、宜しくお願いします。

  • TextBoxに連続で入力する方法

    Form1に、TextBox1とTextBox2を配置しています。 TextBox1にKey入力を受け、Enter Keyで取り込む動作を、連続して行うためのプログラムを作ってみましたが、何故かEnter Keyの後、カーソルがTextBox2に移動してしまいます。Enter Keyの後、TextBox1.SetFocusで、カーソルをTextBox1にしているのですが何故が解らず困っています。Enter Kyeの後、カーソルがTextBox1に戻るようにするには、どのようにすれば良いのか教えて下さい。 PC環境は、OS=Win10 Excel=2010 です。作ったプログラムは以下の通りです。よろしくお願いします。 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) If KeyCode = vbKeyReturn Then Sheets("Sheet1").Range("A1") = TextBox1.Value TextBox1 = "" TextBox1.SetFocus End If End Sub

  • エクセル 条件に合わせてマクロを停止させたい

    VBA初心者です。よろしくお願いします。 Sub テスト1() Select Case Cells(ActiveCell.Row, "a").Value Case "○" テスト2 Case "×" ここでマクロを停止させたい End Select End Sub これをループさせているのですが、”a”に”×”がきたときにマクロを停止させる記述方法はありますか?

  • excel vba ジャンプ

    excel2003のUserFormにてtextbox作成しました。 textbox1にページを入力すると指定のページにジャンプする コードを作成したのですが、動作的には目的とする事ができました。 ただ、初心者レベルで作成したので、コード記述が長く、 ページが増えるたびにコードを追記していかなければなりません。 下記に作成したコードを記述します。 もっと簡単に記述する方法はありますか? ---------------------------------------------------------- Private Sub TextBox1_Change() If TextBox1.Value = 1 Then ActiveWindow.ScrollRow = 1 ActiveWindow.ScrollColumn = 1 Range("$A$15").Select End If If TextBox1.Value = 2 Then ActiveWindow.ScrollRow = 38 ActiveWindow.ScrollColumn = 1 Range("$A$38").Select End If If TextBox1.Value = 3 Then ActiveWindow.ScrollRow = 69 ActiveWindow.ScrollColumn = 1 Range("$A$69").Select End If If TextBox1.Value = 4 Then ActiveWindow.ScrollRow = 100 ActiveWindow.ScrollColumn = 1 Range("$A$100").Select End If If TextBox1.Value = 5 Then ActiveWindow.ScrollRow = 131 ActiveWindow.ScrollColumn = 1 Range("$A$131").Select End If End Sub ---------------------------------------------------------- 上記記述で行っていることは、 textbox1に 1 と入力すると1ページ目が表示  キーボードでctrl+Homeの操作をした状態でカーソルがA15選択 textbox1に 2 と入力すると2ページ目が表示  表示の先頭が38行目、カーソルがA38選択 ページの行数が1ページ目だけ37行 2ページ目以降が31行ごとです。 実際は、200ページ以上あるのでなんとかしたいのですが・・・・

専門家に質問してみよう