- ベストアンサー
〔ExcelVBA〕ユーザーフォームテキスト
ユーザーフォームから値の入力を受け付けるようにしています。 このとき、テキストボックスに入力された数値が3桁区切りで表示されるように出来ないでしょうか?数値を入力するボックスなので。 100万円以上の数値を入力するときに見づらくて困っています。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは、再度の登場です。(^^; リアルタイムならWendy02さんの仰るとおりChangeイベントだろうと思います。 -------------------------------------------------- Private Sub TextBox1_Change() TextBox1.Text = Format(TextBox1.Text, "#,###") End Sub ----------------------------------------------------- それから電卓のように右端から入力されていくようにするだけなら、MaskEdBoxコントロールを使えば出来ますが・・・・ 今回の場合とはちょと目的が違います。 一応後学のためにヘルプを覗いてみることをお勧めします。 以上です。
その他の回答 (5)
- KenKen_SP
- ベストアンサー率62% (785/1258)
> 簡単に言うとどのような利用の仕方をするものなのでしょうか? クラス化する最大のメリットはインスタンスが可能であること。 と言うと難しい話のように聞こえますが、実は単純な話です。今回の事例 で説明すると...電卓の入力動作には2種の制御が必要です。 1. 入力をリアルタイムで桁区切りの数値にフォーマットする -->他ご回答にあるとおり、Change イベントで実現します 2. 入力時に数値しか入力できない -->KeyDown イベントで実現します 通常ですと、以上のように2つのイベントプログラムを書くことになりますね。 では、この動作を100個のテキストボックスに適用するとしたらどうしますか? 必要イベント2×100個のテキストボックス = 200 で 200 のイベントプログラムを書きますか? では1000個なら? 全く同じ動作なのに効率が悪いですよね。そういう時にクラスが非常に 役立ちます。今回の場合、例え 100個のテキストボックスであろうとも Private NumCtrl(1 To 100) As New NumTextbox Private Sub UserForm_Initialize() For i = 1 To 100 Set NumCtrl(i).Bind = Me.Controls("TextBox" & Cstr(i)) Next i End Sub これだけです。仮にテキストボックスが 1000 でも 2000 でもこの方法なら どれだけ増えても簡単です。 同じ機能を複製して使いたいとき...そんな時にクラスが使われます。 2次的なメリットは機能のカプセル化です。 クラスでは決められたプロパティーを設定したり、機能を呼び出すだけで ひとかたまりの処理がなされます。この時、クラス内のコードを理解して 使う必要はありません。 身近な例で言えば、Excel ワークシートや ThisWorkbook モジュール、 フォームは実は全てクラスなんですよ。 例えば、フォームのタイトルを変えるには Userform1.Caption = "SAMPLE FORM" なんてコードを書きます。Caption プロパティーを設定するだけで、ウインドウ のタイトルが変わるんです。これは実際にはフォームクラスが裏で複雑な 処理をして Windows に数多くのメッセージを送って、Windows から返って きたメッセージを解析して、やっと書き換わるものなのですが、ユーザーは その煩雑な部分を意識することはありません。 Userform1.Caption = "SAMPLE FORM" これだけ書けば、ちょろっと書き換わるんです。今回の NumTextbox クラス も利用するのに必要なコードは、 NumCtrl(1).Bind = Textbox1 といった単純なコードです。 本当はものすごく複雑なことをやってるのだけれども、それをユーザーが 意識することなく、このように単純な手続きのみで処理ができる... これがカプセル化です。 クラス...と聞いて腰が引ける人が多いのですが、上述のとおりコードを書く 人は、普段からクラスを使っているのです。意識してないだけなんですよね。 もちろんクラスを書くにはそれなりの知識が必要なのですが、コツさえ掴んで しまえばそれほど難しくもなく、クラスを利用するに至っては非常に簡単な ことなのです。
お礼
ありがとうございます。 効率よくコードを記述するためにも、将来的には心得たいですね。 でも、クラスの意味するところのイメージはできました。
- KenKen_SP
- ベストアンサー率62% (785/1258)
こんにちは。KenKen_SP です。 電卓のような入力...ということでクラスを作ってみました。取り合えず、 サンプルとして手順説明通り試してみて下さい。なお、クラスを他ブックに インポートし、Form_Initialize イベントにクラス関連付けのコードを追加 するだけで、他案件でも簡単に使いまわせます。 長いソースですが、慣れると簡単な作業です。 注) クラスとフォームと2つのソースがあります。 ' ソース1 の貼り付け手順 ' 1. VBE [挿入]-[フォーム] をクリック ' 2. 1. で挿入したフォームに次のコントロールを配置 ' Textbox1 ' Textbox2 ' CommandButton1 ' 3. ソース1 をフォームモジュールへコピペ ' ソース1 Option Explicit ' 冒頭で NumTextbox クラスを使うことを宣言します ' 今回は2つのテキストボックスを使うので(1 TO 2) Private NumCtrl(1 To 2) As New NumTextbox Private Sub UserForm_Initialize() ' 数値用テキストボックスにそれぞれ NumTextbox クラスを関連付けます Set NumCtrl(1).Bind = Me.TextBox1 Set NumCtrl(2).Bind = Me.TextBox2 End Sub Private Sub CommandButton1_Click() On Error GoTo ERROR_HANDLER MsgBox "合計:" & CStr(CCur(TextBox1.Value) + CCur(TextBox2.Value)) Exit Sub ERROR_HANDLER: If Err.Number = 6 Then MsgBox "テキストボックスの値は文字列なので整数部29桁まで" & vbLf _ & "入力可能ですが、計算時はオバーフロー対策が必要です。", _ vbCritical, "注意事項" End If End Sub ' ソース2 の貼り付け手順 ' 1. VBE [挿入]-[クラスモジュール] をクリック ' 2. 1. で挿入したクラスのプロパティーウインドウでモジュール名を ' を [NumTextbox] に変更 ' 3. ソース2 をコピペ ' ソース2 Option Explicit ' // 数値入力用テキストボックス制御クラス Private WithEvents TextBoxCtrl As MSForms.TextBox ' ------------------------------------------------------------------- ' コンストラクタ・デストラクタ ' ------------------------------------------------------------------- Private Sub Class_Terminate() Set TextBoxCtrl = Nothing End Sub ' ------------------------------------------------------------------- ' プロパティー ' ------------------------------------------------------------------- Public Property Set Bind(ByVal Ctrl As MSForms.TextBox) Set TextBoxCtrl = Ctrl With TextBoxCtrl ' IME モードを無効にしてテキストを右揃えにする .IMEMode = fmIMEModeDisable .TextAlign = fmTextAlignRight End With End Property ' ------------------------------------------------------------------- ' イベント ' ------------------------------------------------------------------- ' 特定キー以外の入力を不可にする Private Sub TextBoxCtrl_KeyDown( _ ByVal KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer) Dim lPeriodPos As Long Dim sNum As String Select Case KeyCode ' 数字キー許可 Case 48 To 57, 96 To 105 ' ただし整数部が29桁以上ならフォーマットできないのでキャンセル With TextBoxCtrl If Len(.Text) > 0 Then lPeriodPos = InStr(.Text, ".") If lPeriodPos > 0 Then sNum = Left$(.Text, lPeriodPos - 1) Else sNum = .Text End If sNum = Replace(sNum, ",", "") sNum = Replace(sNum, "-", "") If Len(sNum) = 29 Then KeyCode = 0 End If End With ' Enter等の特定制御キーは許可 Case vbKeyReturn, vbKeyTab, vbKeyDelete, vbKeyBack Case vbKeyLeft To vbKeyDown ' マイナスは冒頭で一つまで許可 Case vbKeySubtract With TextBoxCtrl If Len(.Text) > 0 Or InStr(.Text, "-") > 0 Then KeyCode = 0 End With ' ピリオドは一つまで許可 Case 110, 190 If InStr(TextBoxCtrl.Text, ".") > 0 Then KeyCode = 0 ' その他キーキャンセル Case Else: KeyCode = 0 End Select End Sub ' 値が変化したらフォーマットする Private Sub TextBoxCtrl_Change() Dim lPeriodPos As Long Dim sNum As String Dim lNum As String On Error Resume Next With TextBoxCtrl If Len(.Text) > 0 Then lPeriodPos = InStr(.Text, ".") If lPeriodPos > 0 Then lNum = Left$(.Text, lPeriodPos - 1) sNum = Mid$(.Text, lPeriodPos) Else lNum = .Text End If .Text = FormatNumber$(lNum, 0, vbTrue, vbFalse, vbUseDefault) & sNum End If End With End Sub
お礼
KenKen_SP さん。ありがとうございます。 私はまだまだ未熟ですので、このコードを全て読みこなすことはできませんが、確かに電卓になりました。とりあえずテキストボックス入力中にリアルタイムで3桁区切り表示されればよかったのでChangeイベントで解決したのですが、KenKen_SPさんからご教示いただいたコードは本当に電卓みたいですね! ところで、「クラス」って初めてなのですが、簡単に言うとどのような利用の仕方をするものなのでしょうか? VBAって本当に奥が深いですね。私のような未熟者でもVBAをはじめてから仕事のスピードが10倍になりました。
- Wendy02
- ベストアンサー率57% (3570/6232)
こんばんは。 Form では、Enter を押して、確定するというように、私はずっと通してきていますが、そうでないなら、TextBox1_Change()です。電卓画面とか、私には良く分かりませんので、どちらがよいかは、お決めください。また、そういう好みの問題は、ご自身でお調べくださったほうがよいと思います。
お礼
ありがとうございます。 Changeイベントで解決しました。今後はイベントの種類も勉強していきたいと思います。
- Wendy02
- ベストアンサー率57% (3570/6232)
こんばんは。Wendy02です。 私だったら、こんな風にしますね。Enter で起動します。 Change イベントだとうっとうしく思いますので。 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) If KeyCode = 13 Then TextBox1.Text = Format(TextBox1.Text, "#,##0") End If End Sub
お礼
ありがとうございます。 これだと入力後Enterキーを押さないと3桁にならないですね。 あと、イベントを利用するのではなくて、テキストボックスへ入力中にリアルタイムで3桁区切りになる方法は無理なものでしょうか?電卓画面の感覚で入力を希望しています。
- myCat
- ベストアンサー率60% (9/15)
こんばんは。 AfterUpdateイベントやExitイベントで。。。 Private Sub TextBox1_AfterUpdate() TextBox1.Text = Format(TextBox1.Text, "#,##0") End Sub 以上です。
お礼
ありがとうございます。 イベントを利用すればよかったですね。 ところで、一番の希望していた形としてはテキストボックスへ入力中(リアルタイム)で3桁区切りになる方法はないものでしょうか?それは無理ですかね?電卓に入力している感覚で。 やはりイベントを利用するとなると_AfterUpdate後でないと3桁区切りにならないので。
お礼
私の希望はChangeイベントでした。ありがとうございます。 これからはイベントの種類も勉強していきたいと思います。