こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

Excel VBA tabキーでtextを移動

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

投稿日時 - 2017-05-04 22:13:04

QNo.9325337

困ってます

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

こんにちは。

> 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
' ' 〓〓〓 〓〓〓

投稿日時 - 2017-05-05 09:22:55

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

No.2です。推敲漏れがあって、訂正です。

誤)
For Each oShapeP In Sheet1.Shapes
正)
For Each oShapeP In wsh.Shapes

尚、こちらから補足ですが、
No.2掲載のVBAを実行する場合には、事前の準備として、
シートモジュール等に書かれている既存の記述と、
処理が重複することのないよう、注意してください。

訂正、補足、以上です。失礼しました。

投稿日時 - 2017-05-05 09:47:09

ANo.1

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

投稿日時 - 2017-05-04 23:28:41

お礼

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

投稿日時 - 2017-05-05 21:58:20

あなたにオススメの質問