- ベストアンサー
Excel VBA tabキーでtextを移動
Excelシート上のテキストボックスやコンボボックスに入力後、TABキーで次のボックスに移動することを考えています。 keycode=9でTABキーを検出し textbox1.activate としてもtextbox1にカーソルが立ちません。 TABキーで移動して即入力できるようなプログラムはできないでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは。 > keycode=9でTABキーを検出し > textbox1.activate としてもtextbox1にカーソルが立ちません。 やり方としては合っていて、通常は正しく遷移しますから、 詳細に原因を探ってみた方が良さそうですが、 実行時エラーに[なる|ならない] とか、 textbox1.activate MsgBox textbox1.Name と並べて実行してみて、狙い通りのオブジェクトを捉えているか みたいに、参照が正しいか確認するとか、 実は、縦細長の"キャレット"が表示されているけれど、 期待している"カーソル"とは違う、という意味、 とか、 旧バージョン固有の(特定状況下の)現象、 とか、 各コントロールに変更を加えたプロパティ設定によって コントロールのフォーカスを無効にしている場合、 とか、 情報量的に、実物ブックを見れば判りそうでも、 ノーヒントで正解出せるほど易しい問題ではないように感じます。 > TABキーで移動して即入力できるようなプログラムはできないでしょうか? Excel VBAの範疇で言えば、UserFormを奨める方が (いづれにしても不足を補う工夫は必要ですが相対的に) 却って簡単になりそうですから、直球回答かな、とは思います。 でも、そういうことは期待してないみたいですね。 プログラムというのも、「Excel VBA以外」という解釈が自然かも知れませんが、 お応え出来ることも限られているので、 昔書いてたVBAから抜粋したものを紹介しておきます(こちらでは動作確認済)。 ひょっとしたら、この中に答えやヒントが見つかることもあるのかも、と。 以下、掲載するスクリプトの説明。 SetEvTxtSh1を実行して、Classのイベントを 起動、または再起動してください。 とりあえず、auto_openで起動する例を添えています。 ※ ThisWorkbook_OpenイベントからCallする必要がある場合は、 ontimeメソッド等でタイミングを遅らせてCallするように 注意して下さい。 Tabキー、Enterキー、↑キー、↓キー、等、 TextBox、ComboBox の UserForm上での TabStopコントロール間移動の挙動に 近付ける意図で書いてあります。 既に設定値のあるボックスに遷移する時は、 テキストを全選択した強調表示になるようにしています。 oleobject.activate を実行する時には、一旦、 Excelに制御を渡した方が動作が安定して、トラブルを減らせる というような仕様が、昔はあったような、、、。 試しにやってみたらマシな挙動にはなります。 (画面がチカチカするのは、どの方法でも避けようがないみたい) activecel.activate oleobject.activate みたいに素直に書くと、oleobjectに渡したキーストロークが シートにも渡って、セル選択が遷移してしまうので、 ontimeメソッドで待機(態と非同期に)してから。 実行させてます。(★ 1~★ 4が呼び出し順) シート上でグループ化されたボックスも対象にします。 遷移する順(TabIndex相当)については 指定が判りませんから仮に配置順です。 例えばこれを、 新規ブック、お使いのブック、双方動作させてみて、 どうなるか確かめるだけでも、 原因特定には繋がることもあるのかな、とは、思います。 ' ' 〓 Module1 〓 Option Explicit Public colClass As New Collection Public oOLE As OLEObject Public cnCls As Long ' ' // Private Sub Auto_Open() SetEvTxtSh1 End Sub ' ' // Public Sub SetEvTxtSh1() SetEvTxtBxes Sheets("Sheet1") ' 要◆シート指定 End Sub ' ' // Private Sub SetEvTxtBxes(wsh As Worksheet) Dim oShapeP As Shape Dim oShape As Shape Dim d If colClass.Count Then Exit Sub For Each oShapeP In Sheet1.Shapes On Error Resume Next d = oShapeP.GroupItems.Count On Error GoTo 0 If d Then For Each oShape In oShapeP.GroupItems If oShape.Type = msoOLEControlObject Then Set oOLE = oShape.DrawingObject If oOLE.progID = "Forms.TextBox.1" Or oOLE.progID = "Forms.ComboBox.1" Then cnCls = cnCls + 1 colClass.Add New Class1, CStr(cnCls) End If End If Next End If Next For Each oOLE In wsh.OLEObjects If oOLE.progID = "Forms.TextBox.1" Or oOLE.progID = "Forms.ComboBox.1" Then cnCls = cnCls + 1 colClass.Add New Class1, CStr(cnCls) End If Next End Sub Public Sub ActOLE(p) ' ★ 3 ActiveCell.Activate colClass(p).Activate End Sub ' ' 〓 〓 ' ' 〓〓〓 Class1 〓〓〓 Option Explicit Private WithEvents TextBox As MSForms.TextBox Private WithEvents ComboBox As MSForms.ComboBox Private myOLE As OLEObject Private nIndex As Long ' ' // Private Sub Class_Initialize() Set myOLE = oOLE Select Case oOLE.progID Case "Forms.TextBox.1": Set TextBox = myOLE.Object Case "Forms.ComboBox.1": Set ComboBox = myOLE.Object End Select nIndex = cnCls Debug.Print nIndex, myOLE.Name, myOLE.Index End Sub Private Sub Class_Terminate() Set myOLE = Nothing: Set TextBox = Nothing: Set ComboBox = Nothing End Sub Private Sub TextBox_Keydown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) Dim nDir As Long Select Case KeyCode Case vbKeyTab, vbKeyReturn: If Shift Then nDir = -1 Else nDir = 1 Case vbKeyDown: nDir = 1 Case vbKeyUp: nDir = -1 End Select If nDir Then ActivateAsync (nDir) ' ★ 1 End Sub Private Sub ComboBox_Keydown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) Dim nDir As Long Select Case KeyCode Case vbKeyTab, vbKeyReturn: If Shift Then nDir = -1 Else nDir = 1 End Select If nDir Then ActivateAsync (nDir) ' ★ 1 End Sub ' ' // Private Function ActivateAsync(nDir As Long) ' ★ 2 Application.OnTime Now, "'ActOLE """ & (nIndex + cnCls + nDir - 1) Mod cnCls + 1 & """'" End Function Public Function Activate() ' ★ 4 myOLE.Activate With myOLE.Object .SelStart = 0 .SelLength = 255 End With End Function ' ' 〓〓〓 〓〓〓
その他の回答 (2)
- real beatin(@realbeatin)
- ベストアンサー率82% (174/211)
No.2です。推敲漏れがあって、訂正です。 誤) For Each oShapeP In Sheet1.Shapes 正) For Each oShapeP In wsh.Shapes 尚、こちらから補足ですが、 No.2掲載のVBAを実行する場合には、事前の準備として、 シートモジュール等に書かれている既存の記述と、 処理が重複することのないよう、注意してください。 訂正、補足、以上です。失礼しました。
- imogasi
- ベストアンサー率27% (4737/17069)
Excelのシートこそ、入力を受け付けるもの・仕組みだ。 なんで、わざわざテキストボックスにデータを入れさせて、たぶんシートのセルに入れる(移す)のか。考え方が個人の趣向に走ってないか。 ユーザーフォームを使う例なら http://www.atmarkit.co.jp/ait/articles/1404/04/news037.html を勉強すること。 エクセルの機能に、データーフォーム https://121ware.com/qasearch/1007/app/servlet/relatedqa?QID=015897 のような仕組みもある。 入力規則の「リスト」利用もある。 これらを知っていて、こういう要求を出すのか? (これらものぞむならVBAコードでも指示できる)
お礼
ご指導ありがとうございます。 Excelシートのセルをそのまま使うことは良いかもしれません。 入力画面には、コンボボックスやオプションボタンがあるため全て移行できるか検討してみます。