• ベストアンサー

VBA テキストボックスで日付を変更するとエラー

VBAにて、ユーザーフォーム上のテキストボックスに初期値として今日の日付が入力されており、さらにそれを任意で変更するというマクロを作成しようとしています。 'テキストボックス2に初期値として今日の日付を入力 Private Sub UserForm_Initialize() TextBox2.Text = Format$(Date, "yyyy/mm/dd") End Sub 'テキストボックス2に入力された日付はdenpyoudateという変数に格納される Private Sub TextBox2_Change() denpyoudate = UserForm2.TextBox2.Value End Sub 入力された日付を変数として利用したいので、上記のようなコードにしたのですが、実際に初期値である今日の日付を編集すると「型が一致しません」というエラーが出てしまいます。 このエラーを回避し、テキストボックスに入力された日付を変数として使用するにはどうすればよいでしょうか?

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

  • ベストアンサー
  • myRange
  • ベストアンサー率71% (339/472)
回答No.3

変数DenpyouDateがDate型でもVariant型でも   DenpyouDate=TextBox2.Value とする前に、TextBox2.ValueがDate型なのかチェックの必要があります。 どのイベントでチェックするかは場合によるでしょうが、 BeforUpDateイベントでやれば、TextBox2の値が日付でなかった場合 引数CanceをTrueにすることによりTextBox2の入力を取り消すことができます。 この取り消すと言う意味は他のイベントを使ってみれば分かります。 '-------------------------------------------   Dim DenpyouDate As Date (or As Variant) '------------------------------------------------ Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)   If IsDate(TextBox2.Value) Then     DenpyouDate = TextBox2.Value   Else    TextBox2.Value = ""    Cancel = True   End If End Sub '------------------------------------------ ● TextBox2.Value = "" を省いた場合もテストしてみることをお勧めします。 以上です。

kentaroror
質問者

お礼

回答ありがとうございます。 検討の結果、以下のコードを流用させていただくことにしました。   Dim DenpyouDate As Date (or As Variant) '------------------------------------------------ Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)   If IsDate(TextBox2.Value) Then     DenpyouDate = TextBox2.Value   Else    TextBox2.Value = ""    Cancel = True    msgbox("日付が不正です")   End If End Sub ありがとうございました。

その他の回答 (3)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.4

こんにちは。 今回のUserFormのTextBox に入力する場合に、日付を正しく入れるというのは、本当は、実務レベルでは難しいのです。VBAの1年ぐらいのレベルでは、なかなか分からないのです。概ね、失敗して覚えるものです。私が、#2で書いたように、Variant 型変数にすることで、当面のエラーは消えます。ただし、その値が正しいとは限りません。後は、入力するUserさん任せです。それ以上は、入門レベルの方や基本を覚えただけの人には、それを言っても分からないようにも思いました。 こういう、私も、日付値の自動変換(キャスティング)が、さっぱり分からなかった時代があります。もともと、VBAは、米環境で、アジア式や欧州式でもありませんから、基本的な日付リテラル値は、#m/d/yyyy# スタイルが標準でした。Office やOS もバージョンがあがり、そういう点で、フレキシブルな対応するようになりました。 しかし、コードを提供する側としては、Office のVersionやロケールの違いという見えない問題を考える必要があるのです。だから、入力した日付データを検査しないでそのまま、Date型変数に代入するのは難しいのです。うまく入ったからといって、それが正しいというのは、たまたまだと解釈してよいのではないかと思います。 仮に、文字長のチェックをさせたとしても、  2009/09/31 など、存在しない日にち  特に、うるう年などで、2008/02/30 は存在するのに、2009/02/30 は存在しません。したがって、ダイレクトに入れたら、実行時エラーが発生します。私は、それを、On Error Resume Next などのエラートラップで処理する方法を好みません。本来、エラートラップは回避できないものに対してのみに置くべきです。これも、コーディングスタイルの一つです。 手間を省くために、文字長チェックをしない場合は、  9/31 と入れてしまった場合は、Date 型では、日付として認識してしまいます。  3/1/9 と入れた場合は、2003年1月9日と認識します。それが当たり前のような気がしているけれども、それは、本来、Office のバージョン、日本語OSやロケールの設定によるものだと思います。 また、もしも、month/day と入力されたときは、その年、Year(Date) と同じでなくてはなりませんが、間違った入力すると、まったく別の年になっています。そういうチェックも必要です。   もちろん、年/月/日の位置をガッチリ決めさせる方法がないわけではありません。それは、DTPicker などを使うなら、確実な日付値が得られますから、 例: Private Sub DTPicker1_KeyDown(KeyCode As Integer, ByVal Shift As Integer) Dim myDate As Date  If KeyCode <> 13 Then Exit Sub  myDate = DTPicker1.Value  TextBox1.Text = Format$(myDate, "yyyy/mm/dd") End Sub こういう方法も可能です。(Office XP以上だったと思いますが、標準的に、その他のコントロールに"Microsoft Date and Time Picker Control 6.0"として入っています。) 当面、こちらは、Excel 2003 +Win XP で、ロケールは日本で、日付値は日本型の標準にしてありますが、環境が違うことを想定すると、まだ足りないものがあるかもしれません。本来は、データの予測値というものを前提に置かなくてはならないのです。ただ、そこまでは、なかなか難しいのです。 今回のご質問者さんは、「denpyoudate = "伝票日"」ですから、ある程度の年の予測範囲は決まってくるのですが、たとえば、オールラウンドの年代の生年月日の入力なども、問題になってきます。だから、一概に、こういうコードだとは決められないのです。私は、単に、コーディング・スタイルとしてのTextBox の値を、直接、Date 型の変数に入れないということで、当面はよいのかと思っています。 サンプルマクロ '------------------------------------------- 'UserForm モジュール 'UserForm 'TextBox 2個 '------------------------------------------- Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)   Dim myDate As Date   Dim buf As Variant   If KeyCode <> 13 Then Exit Sub   buf = TextBox1.Text   buf = StrConv(buf, vbNarrow)    '  '文字数をカウントする。 '  If Len(buf) - Len(Replace(buf, "/", "")) <> 2 Or Len(buf) <> 10 Then '    MsgBox "yyyy/mm/dd で入力してください。", vbExclamation '    KeyCode = 0 '    Exit Sub '  End If      '日付が正しく入っているかチェック   If IsDate(buf) = False Then     MsgBox "日付値ではありません。", vbCritical     KeyCode = 0 '次のコントロールに行かない     Exit Sub   ElseIf Abs(Year(Date) - Year(buf)) > 10 Then '10年以上のブレ     If DateChecker(buf) = False Then       KeyCode = 0       Exit Sub     End If   End If   myDate = CDate(buf)   MsgBox myDate   TextBox2.Value = Format$(myDate, "GGGE年m月d日") End Sub Private Function DateChecker(ByVal buf As String) As Boolean '正しく日付が入力されているかメッセージを出す  If MsgBox(Format$(buf, "yyyy/mm/dd") & "日付は正しいでしょうか?", _      vbQuestion + vbYesNo + vbDefaultButton2) = vbNo Then    DateChecker = False  Else    DateChecker = True  End If End Function '------------------------------------------- なお、私の記憶では、この日付判定には、通常の入力には支障はありませんが、少なくとも、Office 2003 までにバグが存在していたようにも思います。

kentaroror
質問者

お礼

回答ありがとうございます。 検討の結果、以下のコードを流用させていただくことにしました。   Dim DenpyouDate As Date (or As Variant) '------------------------------------------------ Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)   If IsDate(TextBox2.Value) Then     DenpyouDate = TextBox2.Value   Else    TextBox2.Value = ""    Cancel = True    msgbox("日付が不正です")   End If End Sub ありがとうございました。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんばんは。 >denpyoudateという変数に格納される 質問には、どこにも変数の宣言が書かれていませんが、一般的に、UserForm のTextBox では、その変数に日付を入れるにしても、変数を節約して使う場合は、Variant 型にします。また、日付として認識できる形になっていれば、String 型でも良いのです。Date 型にしたら、Date型の値しか入れられません。型が違うというエラーが出てきてしまいます。もし、念を入れるなら、出力の際に日付になっているか、IsDate でチェックをします。 最初から、入力を日付型と決め付けないことで作るのは、コーディング・スタイルです。人は、誰でも間違いをするから入れ物自体はフリーにして起きます。ここで、On Error トラップはうまくありません。

kentaroror
質問者

お礼

回答ありがとうございます。 検討の結果、以下のコードを流用させていただくことにしました。   Dim DenpyouDate As Date (or As Variant) '------------------------------------------------ Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)   If IsDate(TextBox2.Value) Then     DenpyouDate = TextBox2.Value   Else    TextBox2.Value = ""    Cancel = True    msgbox("日付が不正です")   End If End Sub ありがとうございました。

  • kmetu
  • ベストアンサー率41% (562/1346)
回答No.1

denpyoudate As Date で宣言してるのだと思いますが TextBox2_Change()ではなくて Private Sub TextBox2_AfterUpdate() denpyoudate = UserForm2.TextBox2.Value End Sub にしてください。

kentaroror
質問者

お礼

回答ありがとうございます。 検討の結果、以下のコードを流用させていただくことにしました。   Dim DenpyouDate As Date (or As Variant) '------------------------------------------------ Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)   If IsDate(TextBox2.Value) Then     DenpyouDate = TextBox2.Value   Else    TextBox2.Value = ""    Cancel = True    msgbox("日付が不正です")   End If End Sub ありがとうございました。

関連するQ&A

  • VBA publicで日付が呼び出せない

    VBAにて、ユーザーフォーム上のテキストボックスに初期値として今日の日付が入力されており、さらにそれを任意で変更することも出来、最終的なテキストボックスの値を変数に格納するというマクロを作成しようとしています。 'テキストボックス2の初期値を今日の日付とする Private Sub UserForm_Initialize() TextBox2.Text = Format$(Date, "yyyy/mm/dd") 'テキストボックス2の値が日付かどうかチェック Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean) If IsDate(TextBox2.Value) Then DenpyouDate = TextBox2.Value Else TextBox2.Value = "" MsgBox ("日付が不正です") TextBox2.Text = Format$(Date, "yyyy/mm/dd") End If End Sub '他のモジュールでdenpyoudateを使用し、指定のセルに和暦形式で入力する Public DenpyouDate As Date Sheets("伝票").Range("A10").Value = Format(DenpyouDate, "e") Sheets("伝票").Range("C10").Value = Format(DenpyouDate, "m") 「ユーザーフォームのテキストボックスに初期値として日付を表示させ、その最終的な値を変数として格納、別のモジュールで呼び出してセルにセットする」というイメージです。 このマクロを実行した際、初期値である今日の日付を任意の日付に変更した場合は、問題なくそのままの値がセルにセットされるのですが、初期値のまま実行すると、その数値が反映されません。 ローカルウィンドウをチェックすると、ユーザーフォームの時点では、テキストボックスの初期値がきちんとdenpyoudateに格納されているのですが(例:2009/11/24)、それを別モジュールで呼び出した時は、denpyoudateの値が(#0:00:00#)になっており、これが原因だと考えています。 このエラーを回避し、初期値の場合でも値がきちんとセルにセットされるようにするには、どうしたらよいでしょうか?

  • エクセルVBA テキストボックス

    いつもお世話になっております。 エクセルでVBAを使いユーザーフォームのテキストボックスで 文章入力をしようと思っているのですが、少しトラブルがありましたのでお教え願います。 エクセルシートの横がa~k、縦を9~34までのシートを結合して その中にテキストボックスで入力した文章を入れるように作っています。 MultiLineとEnterKeyBehaviorをTrueにして Private Sub CommandButton1_Click() Unload Me End Sub Private Sub TextBox1_Change() Sheets("sheet1").Range("a9") = UserForm1.TextBox1 End Sub Private Sub UserForm_Initialize() TextBox1.Value = Range("a9").Value End Sub Private Sub UserForm_Activate() With Me .Left = Application.Left .Top = Application.Top .Left = .Left + 350 .Top = .Top + 80 End With End Sub という状態になっているのですが、文章を入力して16行目で改行するとシートの方で「#VALUE!」と出てきてしまうので一旦ユーザーフォームを閉じてもう一度フォームを立ち上げると 「実行時エラー’-2147352571(80020005) Valueプロパティが設定できません。種類が一致しません。」 と出てきます。 デバッグすると  Private Sub CommandButton1_Click() → UserForm1.Show  End Sub と出てきます。 なにがおかしいのでしょうか? 今回初めてVBAを作っているので初歩的な間違いかもしれませんがよろしくお願いします

  • VBA初心者です。

    VBA初心者です。 ユーザーフォームにテキストボックスとコンボボックスを1つずつ作り、それらを Private Sub ComboBox1_Change()    TextBox1.Value = ComboBox1.Value End Sub というふうに繋いでるとき、テキストボックスにフォーカスをあてさせないようするため、 Private Sub UserForm_Initialize()    TextBox1.Enabled = False End Sub このようにしました。ここまでは問題ありません。質問したいことは、このときテキストボックスに表示させる文字が淡色になるのを防ぐ方法です。    TextBox1.Locked = True これを上に付け加えればうまくいきそうなのですが、うまくいきませんでした…。どなたか解決方法を教えて下さい。

  • エクセルVBAユーザーフォーム「テキストボックス」「コンボボックス」の書式設定について

    ユーザーフォームを作成して、出荷実績を投入しようとしています。 現在、ユーザーフォームを作成して、 上から以下のようにボタンが並んでいます。 (1)コンボボックス1  商品コードと商品名を選択する。 (2)テキストボックス1~7  地域ごとの出荷実績を投入する。 (3)コマンドボタン1  決定→入力 (4)コマンドボタン2  終了 そして、以下3つの問題点がありますが、どのようにVBAを記述したら良いのか、わかりません。  a.コンボボックス1に表示される商品を商品コード   (アルファベット)と商品名で改行したい。   つまり「折り返して全体を表示する」ことは出来ないでしょうか。  b.「AAAA~」は5行目・「CCCC~」は7行目 といった   ように、商品ごとに値を投入する行を変更したい。  c.テキストボックス1~6の内容の合計が自動で(入力している   最中に)テキストボックス7に表示されるようにしたい。 次のようなVBAは記述出来たのですが、上記3つの要素を加えるには どのようにしたらよいのか、教えていただけないでしょうか? ちなみに入力する順番は次のようになっています。(設定済み) M4→L4→J4→K4→H4→I4 →M5→L5→J5→K5→H5→I5 ------------------------------------------------------------- ’フォームを表示させる。 Sub formdsp() UserForm1.Show End Sub ’フォーム内容 Dim cnt As Integer Private Sub Combobox1_Change() End Sub '入力ボタン Private Sub CommandButton1_Click() With ActiveSheet .Cells(cnt, 13) = TextBox1.Text .Cells(cnt, 12) = TextBox2.Text .Cells(cnt, 10) = TextBox3.Text .Cells(cnt, 11) = TextBox4.Text .Cells(cnt, 8) = TextBox5.Text .Cells(cnt, 9) = TextBox6.Text .Cells(cnt, 15) = TextBox7.Text cnt = cnt + 1 .Cells(cnt, 13) = Activate End With UserForm1.TextBox1.Text = "" UserForm1.TextBox2.Text = "" UserForm1.TextBox3.Text = "" UserForm1.TextBox4.Text = "" UserForm1.TextBox5.Text = "" UserForm1.TextBox6.Text = "" UserForm1.TextBox7.Text = "" UserForm1.Combobox1.Text = "" UserForm1.TextBox1.SetFocus End Sub '終了ボタン Private Sub CommandButton2_Click() Unload Me End End Sub 'コンボボックス Private Sub userform_initialize() cnt = 4 With UserForm1.Combobox1 .AddItem "AAAA 11111111111" .AddItem "BBBB 22222222222" .AddItem "CCCC 333333333" .AddItem "DDDD 444444" .AddItem "EEEE 5555555555" .AddItem "FFFF 666" .AddItem "GGGG 7777777" .AddItem "HHHH 88888" .AddItem "IIIII 999999999" .AddItem "JJJJ 0000000000000" .AddItem "KKKK 1111" .AddItem "LLLL 222222" .AddItem "MMMM 3333" End With End Sub

  • エクセルVBAでユーザーフォームのテキストボックス

    ユーザーフォーム上にテキストボックスを8個設置しました。 そこに数値が入力された場合は自動的にカンマ区切りが表示されるように以下のコードを書きました。 これで希望の動きはしてくれるのですが、このやりかたは正しいでしょうか? また、テキストボックスは8個あるので、それぞれに下記のように8通りコードをかかなければいけないのでしょうか?ご教示ください。 Private Sub TextBox1_Change()   If IsNumeric(TextBox1.Value) Then Application.EnableEvents=False     TextBox1.Text = Format(TextBox1.Value, "#,##0") Application.EnableEvents=True   End If End Sub 途中(2~7)略 Private Sub TextBox8_Change()   If IsNumeric(TextBox8.Value) Then Application.EnableEvents=False     TextBox8.Text = Format(TextBox8.Value, "#,##0") Application.EnableEvents=True   End If End Sub

  • Excel VBA テキストボックスに当日の日付

    Excel 2013において、VBAで入力フォームを作成中の初心者です。 入力フォームの中に日付の項目があり、テキストボックスに手入力しています。 そのテキストボックスに当日の日付を自動で表示させたく、ネットで調べ試しましたが、うまくいきません。 やりたいこととしては、テキストボックスに今日の日付を自動的に和暦で表示させ、その日付を変更する場合には、「2016-12-03」などと入力後、和暦に自動的に変換して表示させたいのです。 手入力において、「2016-12-03」と入力後、自動的に和暦に変換するコードはネットで見つけることができ、うまくいったのですが、当日の日付を自動的に表示させる方法がわからずにおります。 日付を手入力後、和暦で表示させるコードは以下のようにしてあります。 Private Sub textbox1_AfterUpdate() With Me.textbox1 If IsDate(.Value) Then .Value = Format(.Value, "ggge年m月d日") End If End With End Sub どなたか、教えていただけると助かります。 よろしくお願いいたします。

  • ユーザーフォームのテキストボックスの書式設定について

    ユーザーフォームのテキストボックスの書式設定について TextBox1に金額、TextBox2に日付を入力し、Sheet1に転記するような フォームを作っています。 TextBox1には、 Private Sub TextBox1_Change() y = TextBox1.Text TextBox1.Text = Format$(CLng(y), "#,##0") End Sub としています。 TextBox2には、書式をH○○.○.○という設定にしたいのですが、 どのようにしたらよいでしょうか。

  • VBE ユーザーフォーム

    下記3点につき、ご教授御願い致します。 (1)テキストボックスに日付を入力。 入力する値は6桁の数字。 テキストボックス入力→050902 テキストボックス表示→05/09/02 としたい。 Private Sub TextBox16_Exit(ByVal Cancel As MSForms.ReturnBoolean) TextBox1.Text = Left(TextBox1.Text, 2) & "/" & Mid(TextBox1.Text, 3, 2) _ & "/" & Right(TextBox1.Text, 2) End Sub とすると、見かけ上は「05/09/02」となってくれるのですが、そうするとテキストボックスに何も表示しないでEnterを押すと(入力後に消した場合等も)「//」が出てしまいます。 入力する日付は本日とは限りません。 表示は「2005/09/02」ではなく「05/09/02」としたい。 (2)テキストボックスに今日の日付を自動的に表示させたい。 (手入力で変更できるようにする為、テキストボックスを使用) Private Sub UserForm_initialize() TextBox2.Text = Date End Sub とすると「2005/09/02」となり、「05/09/02」としたい。 (3)テキストボックス同士の計算 TextBox3とTextBox4に数字を入力し、その積をTextbox5に表示させたい。 TextBox5.text = Textbox3.text * TextBox4.text とすると 「型が一致しません」と出てしまう。 (「text」を「value」に変えても同じ) できましたら、イベント名もお教え下さい。 ---------------------------------------- よろしく御願いします。

  • エクセルVBA

    ユーザーフォームのテキストボックスに現在時間を表示し、表示を時計のように現在時刻を表示し続ける方法を教えてください。 以下は現在のコマンドです。 Private Sub txtTime_Change() End Sub Private Sub UserForm_Initialize() UserForm1.txtTime.Value = Time End Sub よろしくお願いします。

  • エクセルVBA「スピンボタン」について

    エクセルVBA「スピンボタン」について スピンボタンとテキストボックスを組み合わせて Private Sub SpinButton1_Change() Me.TextBox1.Value = Me.SpinButton1.Value End Sub Private Sub UserForm_Initialize() With Me.SpinButton1 .Min = 1 .Value = .Min End With Me.TextBox1.Value = Me.SpinButton1.Min End Sub というコードを書きました。 「1、2、3、・・・10、11、・・・」という数の増加を「01、02、03・・・10、11・・・」という風にしたいのですがどのようにコーディングすればよいのでしょうか?お願いします。.

専門家に質問してみよう