MS Access Tips/Sample and VBA and Blog customize etc...

ボタンクリックでテキストボックスに文字入力 その1

フォーム上にボタンを配置して、マウスクリックでテキストボックスに入力したい。

今回は、このような希望をなるべくシンプルに実現する方法を考察してみます。

サンプルとして、テンキーをクリックして数式を入力して計算結果を表示する電卓を作成します。

電卓フォーム

ボタンクリックによる文字入力以外に、イベントの処理の共通化などのテクニックも参考になると思います。

難易度:

ボタンクリック

ボタンクリックで文字入力と言うことなので、コマンドボタンを利用するのが普通の考えですが、コマンドボタンだとクリック時にフォーカスがボタンに移動してしまいます。クリックしたら、すぐテキストボックスにフォーカスを戻せばいいのですが、フォーカスが行ったり来たりするのでちらついたりします。

そこで、ラベルをボタン代わりに使います。ラベルならクリックしてもフォーカスは移動しません。ラベルの「立体表示」を「浮き出し」にしておきます。

フォーム上にテキストボックス「Txt1」、ラベル「ラベル2」を配置します。

上記のコードで、テキストボックスのカーソル位置に"1"が挿入されます。SelTextに代入することで、カーソルが先頭へ移動してしまいますので、カーソル位置を覚えておいて、代入後に次の位置に移動させてます。

このままだとクリックしてもボタンらしくないので、マウスボタンクリック時に「くぼみ」にして、真数ボタン解放時に浮き出しに戻すとボタンらしく見えます。 さらに上余白で標題を下げるとさらにそれらくしなります。

イベント処理の共通化

ラベル一つではテンキーにならないので必要数分ラベルを追加して、ラベルの数だけ上記のイベントプロシージャを記述すればいいわけですが、同じようなコードを繰り返し記述するのも無駄な気がしますね。

共通化する方法として、「クラスモジュールを使う」または、「関数(Function)を使う」というのが考えられますが、前者はかなり高度で難易度が高いので、今回は、後者の方法を使います。

フォーム上にラベルを追加して、全部で10個配置します。標題は、それぞれ、0 ~ 9 までつけます。

上記のイベントプロシージャを下記のように、Functionに書きかえます。

ラベル2のプロパティシートのイベントタブの各イベント欄を下記のように設定します。

プロパティ 設定値
クリック時  =lbl_Click([ラベル2]) 
マウスボタンクリック時   =lbl_MouseDown([ラベル2]) 
マウスボタン解放時  =lbl_MouseUp([ラベル2])

他のラベルも同様に設定します。関数内の[]の中はもちろん自分自身の名前にします。

これで、ラベルボタンをクリックするとテキストボックスに標題の文字が入力されます。

FrmTenkey0.gif

今回は、ここまで。次回で、数式電卓を完成させます。

18 Comments

名無し says...""

超初心者です。
大変参考になりました。
ひとつ質問です。

Private Sub ラベル2_Click()

Dim p As Integer

With Me.txt1

p = .SelStart

.SelText = "1"

.SelStart = p + 1

End With

End Sub

のWith Me.txt1 のコードをボタンと連動させるにはどうしたらよいのか教えてください。
例えば、txt1ボタン・txt2ボタン・txt3ボタンの様に入力欄を変えたいのです。
よろしくお願いいたします。

2010.03.02 18:18 | URL | #- [edit]
hatena says..."関連付け"

上記、記事の「イベント処理の共通化」の部分は読まれましたか。

その通りにすれば、ボタンとテキストボックスの関連付けができますが、
どのあたりで躓いているのでしょうか。

2010.03.02 20:49 | URL | #- [edit]
西田 says..."最高です! できれば一つ教えてください。"

タブレット端末でユーザに数字入力させる方法で悩んでいましたが、
見事な解決です! コードも短く素晴らしいと思います。
ひとつ質問にお答えください。 初心者なものでtxt1のデータを呼び出し元のフィールドへ返す方法がわかりません。 「=」キーを押した時の処理で[Forms]![TBL01]![残高]= Me.txt1 などとすれば渡せますが、この方法だとフィールドの数だけテンキーフォームが必要になってしまいます。 呼び出し元からテンキーフォームを開く時にフィールド名を変数として渡したいのですが・・。

2014.06.17 13:01 | URL | #- [edit]
hatena says..."re:最高です! できれば一つ教えてください。"

> ひとつ質問にお答えください。 初心者なものでtxt1のデータを呼び出し元のフィールドへ返す方法がわかりません。 「=」キーを押した時の処理で[Forms]![TBL01]![残高]= Me.txt1 などとすれば渡せますが、この方法だとフィールドの数だけテンキーフォームが必要になってしまいます。 呼び出し元からテンキーフォームを開く時にフィールド名を変数として渡したいのですが・・。

事前に入力したいテキストボックスにフォーカス移動しておきます。
電卓フォームは、ダイアログモードで呼び出します。
電卓をフォームを閉じるときに、フォームを非表示にすると、
呼び出したフォームのテキストボックスがアクティブになります。
アクティブなコントロールに代入します。
アクティブなコントロールはScreen.ActiveControlで取得出来ます。


具体的なコードは、下記のベージの「サンプルコード2」が参考になるでしょう。

http://hatenachips.blog34.fc2.com/blog-entry-39.html
入力ダイアログフォームの設計 - hatena chips

2014.06.17 18:16 | URL | #5uE6dEgY [edit]
西田 says..."できました!(^_^)v"

アドバイスどおりにしたら完璧に要求を満たすことができました。
とても嬉しいです。
すばやい回答といい、
本当にありがとうございました。

2014.06.17 22:06 | URL | #- [edit]
西田 says..."呼び出し元のコントロール名も取得したい"

欲張って申し訳ないですがもう一つ、教えてください。
実際にユーザに使わせて見たところ、電卓フォームでの入力は快適なのですが、入力中にどのフィールドに入力しているのか不安になるようです。
電卓フォームに呼び出し元のコントロール名またはそのラベルを表示させることができれば、ユーザの不安を解消できるのですが何か良い方法 あるでしょうか?

2014.06.19 02:17 | URL | #- [edit]
hatena says..."re:呼び出し元のコントロール名も取得したい"

電卓フォームの開くときのイベントプロシージャで、
Screen.ActiveControl.Name で呼び出し元のコントロール名が取得出来ます。
関連付けられたラベルは、そのコントロールの子コントロールになってますので、
Screen.ActiveControl.Controls(0) で取得出来ます。


コード例

電卓フォームのモジュール

Option Compare Database
Option Explicit
Dim TargetCtl As Control

'開くとき
Private Sub Form_Open(Cancel As Integer)
  Set TargetCtl = Screen.ActiveControl
  Me.Caption = "入力先: " & TargetCtl.Controls(0).Caption
End Sub


'入力コマンドボタンのクリック時
Private Sub cmdInput_Click()
  TargetCtl = Me.txtInput
  DoCmd.Close acForm, Me.Name
End Sub

2014.06.19 11:54 | URL | #5uE6dEgY [edit]
西田 says..."重ね重ねありがとうございました。"

お蔭様で全て解決できました。

タブレット端末では CApution の文字は小さすぎて見えないとのことでしたのでテキストボックスを新設して対応しました。

的確で素早いアドバイスに大変 感謝しております。
どうもありがとうございました。 <(_ _)>

2014.06.19 22:57 | URL | #- [edit]
西田 says..."完璧を期したいのでついでに教えてください。"

質問ばかりでハナハダ恐縮ですが、もう一つ教えてください。

「テンキーフォーム」で「入力キー」を押下すると目的フォームのアクティブフィールドにデータが代入されるようになりました。
この時、フォーカスは値が代入されたフィールドに残ったままです。
ユーザの操作を省くために、値を代入した後は、自動的に次のタブへフォーカスを移動したいと思います。
「コントロールの移動」マクロでできないかと思って試行錯誤してみましたが、うまく行きません。

お手までなかったらで結構ですが、次の目的フィールドでもテンキーを表示させて「テンキーフォーム」の「入力キー」を押下する度に値を代入しながら次々にタブを移動していく動作を可能にする方法についてアドバイスお願いします。

2014.06.21 09:02 | URL | #- [edit]
hatena says..."re:完璧を期したいのでついでに教えてください。"

いろいろ方法は考えられるますが、
次のコントロールがどこかを取得するのが面倒なので、
とりあえず一番簡単なSendkyes で Tabキーを送る方法。

テンキーフォームのモジュール

Option Compare Database
Option Explicit
Dim TargetCtl As Control

'開くとき
Private Sub Form_Open(Cancel As Integer)
  Set TargetCtl = Screen.ActiveControl
  Me.Caption = "入力先: " & TargetCtl.Controls(0).Caption
End Sub


'入力ラベルのクリック時
Private Sub cmdInput_Click()
  TargetCtl = Me.txtInput
  Me.txtInput = Null
  ctl.Parent.SetFocus
  SendKeys "{tab}", True
  Set TargetCtl = Screen.ActiveControl
  Me.SetFocus
End Sub

2014.06.22 21:52 | URL | #5uE6dEgY [edit]
西田 says..."コンパイルエラーになるのですが・・"

せっかく教えて頂いたのに理解不足ですみません。

ctl.Parent.SetFocus  のところでどうしてもコンパイルエラーになります。
ctlを反転表示して「変数が定義されていません」と表示されます。
Dim ctl As Controlのような定義が必要なのでしょうか?
そもそも ctl.Parent って何をさしているのでしょうか?


2014.06.23 00:16 | URL | #- [edit]
hatena says..."re:コンパイルエラーになるのですが・・"

> ctl.Parent.SetFocus  のところでどうしてもコンパイルエラーになります。
> ctlを反転表示して「変数が定義されていません」と表示されます。

タイプミスでした。
下記に修正してください。

TargetCtl.Parent.SetFocus


Parent とは親という意味ですが、対象コントロールの親、つまり対象コントロールのあるフォームになります。

2014.06.23 00:22 | URL | #5uE6dEgY [edit]
西田 says..."コンパイルエラーなくなりました。(^_^)v"

ありがとうございます。
エラーは出なくなりました。
コードの書き方にミスがあるのかまだ思ったようには動作しませんが、今しばらく研究してみたいと思います。
(フォーカスが次のタブへ移動してくれないし、2回目の値転送もしてくれません)
ありがとうございました。

2014.06.24 02:14 | URL | #- [edit]
hatena says..."re:コンパイルエラーなくなりました。(^_^)v"

テンキーフォームの「ポップアップ」を「はい」、「作業ウィンドウ固定」は「いいえ」にしてください。

テンキーフォームを呼び出すときは、ダイアログモードにしないでください。

Docmd.OpenForm "テンキーフォーム", , , , , acDialog

となっていたら、下記に修正してください。

Docmd.OpenForm "テンキーフォーム"



上記のうまくいかなければ、
私の主催する下記の掲示板へ移動しましょう。

hatena の Microsoft Access 掲示板
http://hatena-access.progoo.com/bbs/

そちらですと、画像やファイルもアップロードできますので。

2014.06.24 03:01 | URL | #5uE6dEgY [edit]
西田 says..."誘ってくださってありがとうございます。"

ありがとうございます。

2度目の値 代入はできるようになりましたが、タブの移動はできていません。
以後、掲示板へ移動させていただきます。
よろしくお願いします。

2014.06.24 10:44 | URL | #- [edit]
Time says..."時間の入力"

ボタンクリックによる文字入力を活用させて頂いています。
時刻をボタンクリックで入力したく、テキストボックスのプロパティを以下のように設定しています。
定型入力 00:00;0; (1109と入力し11:09と表示したい)
書式 hh:nn
自動タブ はい

イベントプロパティに指定した式 クリック時でエラーが発生しました。入力された値はこのフィールドに設定されている定型入力 00:00;0; に従っていません。のエラーメッセージが表示されます。エラーを回避する方法があれば教えてください。

2019.06.13 11:10 | URL | #wB.5Ivk. [edit]
hatena says..."re:時間の入力"

定型入力はキーボードから入力が前提の機能ですので、VBAでテキストを書き換えるとエラーになります。
lbl_Clickのコードを下記のように書き換えてください。

Private Function lbl_Click(ctl As Control)
  SendKeys ctl.Caption
End Function

SendKeysでキーボード入力をシミュレートしてます。

2019.06.13 19:51 | URL | #ofj98f56 [edit]
Time says..."re:時間の入力(解決済)"

> SendKeysでキーボード入力をシミュレートしてます。
迅速かつ的確なアドバイスありがとうございます。
問題がすぐに解決できました。また何かございましたら宜しくお願い致します。

2019.06.14 10:44 | URL | #wB.5Ivk. [edit]

Leave a reply






Trackbacks

trackback URL
https://hatenachips.blog.fc2.com/tb.php/7-025ed2a3
該当の記事は見つかりませんでした。