Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(指定なし : 指定なし)
2度目の入力時にそれ以降のテキストボックスの値が消えてしまう。
投稿日時: 24/09/14 21:38:12
投稿者: けけちゃま

いつもお世話になっております。
 
ユーザーフォームを作成したのですが、どうも変な動きをすることに気づき、どなたかお分かりになればと思い投稿させていただきました。
 
【ユーザーフォーム】
上から
TextBox3
TextBox1
TextBox2
Label1
を作ります。
このTextBoxには数値しか入らないように設定し(表示の時にフォーマットで円の形にする)、
TextBox1とTextBox2の値が入力されたら、Label1に(TextBox2の値)−(TextBox1の値)の差額を表示させるというものです。
 
 
私の作った現状のコードです。↓
 

Option Explicit

Dim N As Long

Dim N2 As Long

 

 

Private Sub TextBox1_AfterUpdate()

       

        '@テキスト入力後のフォーマット編集

       

        If TextBox1.Text = "" Then

            Exit Sub

        End If

       

        N = CLng(TextBox1.Text)

        TextBox1.Text = Format(TextBox1.Text, "##,###円")

       

        Call Cal_sagaku

        

        

End Sub

 

Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

 

        '@テキスト入力確定前チェック

       

        If TextBox1.Text <> "" And Not IsNumeric(TextBox1.Text) Then

            Cancel = True

            TextBox1.Text = ""

        End If

               

End Sub

 

 

Private Sub TextBox1_Change()

                       

                Call Cal_sagaku

 

End Sub

 

Private Sub TextBox2_AfterUpdate()

       

        'Aテキスト入力確定後のフォーマット編集

       

        If TextBox2.Text = "" Then

            Exit Sub

        End If

       

        N2 = CLng(TextBox2.Text)

       

        TextBox2.Text = Format(TextBox2.Text, "##,###円")

      

                Call Cal_sagaku

       

End Sub

 

Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

 

        'Aテキスト入力確定前チェック

       

        If TextBox2.Text <> "" And Not IsNumeric(TextBox2.Text) Then

            Cancel = True

            TextBox2.Text = ""

        End If

       

        

End Sub

 

 

Private Sub TextBox2_Change()

 

                Call Cal_sagaku

       

End Sub

 

Private Sub Cal_sagaku()

 

 

             '差額表示

            If TextBox1.Text = "" Or TextBox2.Text = "" Then

                        Label1.Caption = ""

                 Exit Sub

             End If

           

            

            Dim sgk As Long

            

            sgk = N2 - N

            Label1.Caption = Format(sgk, "##,###円")

           

End Sub

 

Private Sub TextBox3_AfterUpdate()

       

        'Bテキスト入力確定後のフォーマット編集

       

        If TextBox3.Text = "" Then

            Exit Sub

        End If

       

        TextBox3.Text = Format(TextBox3.Text, "##,###円")

       

        

End Sub

 

Private Sub TextBox3_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

       

        'Bテキスト入力前チェック(数値のみ)

       

        If TextBox3.Text <> "" And Not IsNumeric(TextBox3.Text) Then

            Cancel = True

            TextBox3.Text = ""

        End If
        

End Sub

 
 
これでよし動く!とおもって3日間くらい使っていたのですが、
TextBox3→TextBox1→TextBox2の順番で入力したのちに、TextBox1の値を変えようとカーソルをあて変更したら、TextBox2の値も自動で消えてしまったのです。
自動で消えてもちゃんと数字をいれれば計算はしてくれるのですが、1か所だけ変更したいときにこれではとても使いづらいと思い修正をしたいのですが、原因がわからないのです。。
 
F9でF8でやろうと思ったのですが、1文字目をいれた瞬間、コードに画面で止まり、それ以上確認することができませんでした。
 
 
大変恐縮ではございますが、どなたかはお分かりになられる方がおりましたら、ご教示頂ければ幸いです・・
 

回答
投稿日時: 24/09/14 22:33:12
投稿者: WinArrow

最初にやること。
 
1つのコントロールに複数のイベントが存在します。
ステップ実行で、イベントが発生する順番を確認すること。
そして、コントロールの値を確認(手入力以外でに変化を確認)
 
私見ですが、
 
AfterUpdate,Beforupdate,Change
と3つも使う必要があるのか?疑問です。
 
特に、Changeイベントは、1文字でもイベント発生しますから
使い方が難しいと思います。
ステップ実行を使うと、おkしな動きを発見できます。
おかしいか/おかしくないかは、自分で探すこと。

回答
投稿日時: 24/09/14 23:05:23
投稿者: WinArrow

テイストボックスの値を「円」をつけて文字列に変換しているから、
Not Numeric チェックでスペースになっています。
 
修正案

引用:

        If TextBox3.Text <> "" And Not IsNumeric(TextBox3.Text) Then


 
       If Me.TextBox3.Text = "" Then Exit Sub
        If Not IsNumeric(Replace(Replace(Me.TextBox3.Text, ",", ""), "円", "")) Then

のように変更すれば、この問題は解決するかも

回答
投稿日時: 24/09/15 21:16:56
投稿者: WinArrow

>If Not IsNumeric(Replace(Replace(Me.TextBox3.Text, ",", ""), "円", "")) Then

If Not IsNumeric(Replace(Me.TextBox3.Text, "円", "")) Then
 
でも大丈夫です。

投稿日時: 24/09/16 00:33:25
投稿者: けけちゃま

WinArrow 様
 
いつもありがとうございます…。
動きました!
Chengeイベントの発動タイミングについても改めて勉強なりました。
 
愛用している参考書も見直したのですが、Chengeイベントはスピンボタンをクリックしたときやコンボボックスの値変更したときくらいにしかつかれておりませんでした。
(今まで、Before→After→Chengeでいままで作っており、たまたま書式変更しなかったからうまくいっていただけで、それが王道処理とよく意味もわからず誤認識しておりました…)
 
モロ完コピではないのですが、頂いた内容で改めてコードを書きなおしてみました。

 

Option Explicit

 

Private Sub TextBox1_AfterUpdate()

 

 

        '@テキスト入力後のフォーマット編集

 

      

        If TextBox1.Text = "" Then

 

            Exit Sub

 

        End If

 

              

        TextBox1.Text = Format(TextBox1.Text, "##,###円")

 

      

        Call Cal_sagaku

       

        

 

End Sub

 


 

Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

 


 

        '@テキスト入力確定前チェック

 

      

 

        If TextBox1.Text <> "" And Not IsNumeric(Replace(TextBox1.Text, "円", "")) Then

 

            Cancel = True

 

            TextBox1.Text = ""

 

        End If

 

              

 

End Sub

 


 

Private Sub TextBox2_AfterUpdate()

 

      

        'Aテキスト入力確定後のフォーマット編集

 

      

        If TextBox2.Text = "" Then

 

            Exit Sub

 

        End If

 

      

 

        TextBox2.Text = Format(TextBox2.Text, "##,###円")

 

     

 

                Call Cal_sagaku

 

      

 

End Sub

 


 

Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

 


 

        'Aテキスト入力確定前チェック

 

      

 

        If TextBox2.Text <> "" And Not IsNumeric(Replace(TextBox2.Text, "円", "")) Then

       

            Cancel = True

 

            TextBox2.Text = ""

 

        End If

       

 

End Sub

 


Private Sub Cal_sagaku()

 


 

            '差額表示

            If TextBox1.Text = "" Or TextBox2.Text = "" Then

                        Label1.Caption = ""

                 Exit Sub

             End If

           

            Dim N2 As Long

            Dim N As Long

            Dim sgk As Long

           

            N = CLng(Replace(TextBox1.Text, "円", ""))

            N2 = CLng(Replace(TextBox2.Text, "円", ""))

            sgk = N2 - N

           

            Label1.Caption = Format(sgk, "##,###円")

           

           

 

End Sub

 


 

Private Sub TextBox3_AfterUpdate()

 

        'Bテキスト入力確定後のフォーマット編集

 

 

        If TextBox3.Text = "" Then

 

            Exit Sub

 

        End If

 

      

 

        TextBox3.Text = Format(TextBox3.Text, "##,###円")

 

      

 

End Sub

 


 

Private Sub TextBox3_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

 

      

 

        'Bテキスト入力前チェック(数値のみ)

 

      

 

        If TextBox3.Text <> "" And Not IsNumeric(Replace(TextBox3.Text, "円", "")) Then

       

 

            Cancel = True

 

            TextBox3.Text = ""

 

        End If

       

 

End Sub

 
ありがとうございます。
わたしの求めていた内容でうごきました。
 
しかし新たな問題を発見してしまい、これだと0と入力したときに0円と表示させたいのに「円」と表示され、バグが生じてしまいました。
 
「0」の入力のときは「0円」と表示されるとIF文書いたりしたのですが、そうなると「0」の時はバグがでてしまったり、「0円」をRepleceしてくれなかったりとか(ここら辺から自分でもよくわからなくなっている)…。
そもそもIF文よりも絶対もっとシンプルなコードがあるんじゃないのかと思うのですが「Format 0円表示 VBA」で検索してもでてこずで(TT)
 
これの対処法など、もしお分かりになれば、ヒントだけでもいいので教えていただけると幸いです。
(こんな長いコードにつきあってもらっただけでも大感謝なので、もしわかればで大丈夫です・・)

回答
投稿日時: 24/09/16 09:48:33
投稿者: WinArrow

引用:
これだと0と入力したときに0円と表示させたい

だったら、
>TextBox1.Text = Format(TextBox1.Text, "##,###円")

TextBox1.Text = Format(TextBox1.Text, "#,##0円")
 
に変更すれば、できます。
カンマの左の"#"は1つでよい。

投稿日時: 24/09/16 22:49:07
投稿者: けけちゃま

WinArrow様
 
ありがとうございます泣
あきらめて自分なりに下記のダサいコードを作ってましたが、すぐにコード書き換えました!!!
 

Private Sub TextBox1_AfterUpdate()

         '@テキスト入力後のフォーマット編集

        If TextBox1.Text = "" Then

            Exit Sub

        End If

       

        If TextBox1.Text = "0" Then

            TextBox1.Text = "0円"

            Exit Sub

        End If


        TextBox1.Text = Format(TextBox1, "##,###円")

           Call Cal_sagaku


End Sub

 
"##,##0円"なら一旦自分でやってはみたのですが、"#,##0円"が正解だったんですね(TT)
 
また、考えてみれば最初のF9F8で1文字入れたらコードにうつる現象も、なんでだろうと思ったのですがChengeイベントの正しい動きだったんですね・・
 
きっと、今までのコードも無駄な部分がありそうなので見直してみたいと思いました。
本当にありがとうございました。