• ベストアンサー

Excel VBA tabキーでtextを移動

Excelシート上のテキストボックスやコンボボックスに入力後、TABキーで次のボックスに移動することを考えています。 keycode=9でTABキーを検出し textbox1.activate としてもtextbox1にカーソルが立ちません。 TABキーで移動して即入力できるようなプログラムはできないでしょうか?

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

  • ベストアンサー
回答No.2

こんにちは。 > 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)

回答No.3

No.2です。推敲漏れがあって、訂正です。 誤) For Each oShapeP In Sheet1.Shapes 正) For Each oShapeP In wsh.Shapes 尚、こちらから補足ですが、 No.2掲載のVBAを実行する場合には、事前の準備として、 シートモジュール等に書かれている既存の記述と、 処理が重複することのないよう、注意してください。 訂正、補足、以上です。失礼しました。

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

Excelのシートこそ、入力を受け付けるもの・仕組みだ。 なんで、わざわざテキストボックスにデータを入れさせて、たぶんシートのセルに入れる(移す)のか。考え方が個人の趣向に走ってないか。 ユーザーフォームを使う例なら http://www.atmarkit.co.jp/ait/articles/1404/04/news037.html を勉強すること。 エクセルの機能に、データーフォーム https://121ware.com/qasearch/1007/app/servlet/relatedqa?QID=015897 のような仕組みもある。 入力規則の「リスト」利用もある。 これらを知っていて、こういう要求を出すのか? (これらものぞむならVBAコードでも指示できる)

ken-nosuke
質問者

お礼

ご指導ありがとうございます。 Excelシートのセルをそのまま使うことは良いかもしれません。 入力画面には、コンボボックスやオプションボタンがあるため全て移行できるか検討してみます。

関連するQ&A