VBA/エクセルの日付入力でYYYYMMDD

このQ&Aのポイント
  • VBAやエクセルを使用して特定のセルに日付を入力する際、さまざまな入力がされることがあります。入力された文字列がYYYYMMDDの連続数字の形式である場合には、正しく日付として扱うことができません。それを解決するために、マクロを使用して入力規則を設定することができますが、再度YYYYMMDDの連続数字で入力するとエラーが発生する問題があります。
  • 上記の問題を解決するために、マクロのコードを修正する必要があります。修正後のコードは、入力された文字列がYYYYMMDDの連続数字の形式である場合は、日付として正しく扱い、それ以外の形式の場合は日付に変換するようになります。
  • さらに、日付をYYYYMMDDの連続数字で入力することは一般的ではありません。一般的には、yyyy/mm/ddやmm/dd/yyyyのような形式で入力されます。しかし、特定の場合には、YYYYMMDDの形式で入力されることもあります。
回答を見る
  • ベストアンサー

VBA/エクセルの日付入力でYYYYMMDD

エクセル2013です。 特定のセルに日付を入力してもらうのですが、人によりさまざまな入力をされてしまいます。 どんな入力でも日付であれば、シリアル値なのであとからなんとかなるのですが、困るのはYYYYMMDDの連続数字、例えば今日なら20140712と入力されてしまうことです。 入力規則で排除したいのですが、それは許されず、20140712も日付として扱わなければならなくなりそうです。 そこでマクロで対処しようと以下のコードを書きました。 Private Sub Worksheet_Change(ByVal Target As Range)   Select Case Target.Address(0, 0)     Case "D2", "F2", "C4"       If Target.Value = "" Then Exit Sub       If IsDate(Target.Value) Then         Target.NumberFormatLocal = "yyyy/m/d"       Else         Application.EnableEvents = False         Target.Value = CDate(Format(Target.Value, "@@@@/@@/@@"))         Application.EnableEvents = True       End If     Case Else       Exit Sub   End Select End Sub これで最初はうまくいき、20140712と入力されても、ちゃんと2014/7/12になります。 ところが、同じセルに再度YYYYMMDD数字形式で入力すると、実行時エラー「オーバーフローしました」になってしまいます。多分セルが、YYYYMMDDの数字をシリアル値として見てありえない日付と判断したのだと思います。 どのようにコードを修正したらよろしいでしょうか? もう1点、日付をYYYYMMDDの連続数字で入力することは普通、エクセルではあまり見たことないですが、これって一般的な方法なのでしょうか?

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

  • ベストアンサー
  • tom04
  • ベストアンサー率49% (2537/5117)
回答No.8

No.3・6です。 たびたびごめんなさい。 No.7さんのご指摘は判っていたのですが、分岐が面倒なのでスルーしていました。 今度は色々な入力間違いを考慮してみました。 (うるう年・大の月小の月等) 尚、2000年は100年に一度のうるう年でない年なのですが、この100年に一度は考慮していません。 Private Sub Worksheet_Change(ByVal Target As Range) Dim k As Integer, myY As Integer, myM As Integer, myD As Integer, myFlg As Boolean, myArry If Intersect(Target, Range("D2,F2,C4")) Is Nothing Or Target.Count > 1 Then Exit Sub With Target .NumberFormatLocal = "G/標準" On Error GoTo 1 If IsNumeric(.Value) And Len(.Value) = 8 Then myY = Left(.Value, 4) myM = Mid(.Value, 5, 2) myD = Right(.Value, 2) myArry = Array(3, 5, 7, 8, 10, 12) For k = 0 To UBound(myArry) If myM = myArry(k) Then myFlg = True Exit For End If Next k If myFlg = True Then If myD > 31 Then GoTo 1 End If Else If myM = 2 Then If myY Mod 4 = 0 Then If myD > 29 Then GoTo 1 Exit Sub End If Else If myD > 28 Then GoTo 1 Exit Sub End If End If Else If myD > 30 Then GoTo 1 End If End If End If Application.EnableEvents = False .Value = DateSerial(myY, myM, myD) Application.EnableEvents = True Else If Year(.Value) < 2100 Then .NumberFormatLocal = "yyyy/m/d" Else GoTo 1 Exit Sub End If End If Exit Sub 1: MsgBox "入力値が不正です" .Select Exit Sub End With End Sub ※ 細かい検証はしていませんので、間違いがあったらごめんなさいね。m(_ _)m

emaxemax
質問者

お礼

tom04 さん、なんどもありがとうございます。 いろいろ検討した結果、tom04 さんに最初に教えていただいたコードをベースに以下のようにしてみました。 Private Sub Worksheet_Change(ByVal Target As Range) Dim pw As String pw = "password" If Intersect(Target, Range("D2,F2,C4")) Is Nothing Or Target.Count > 1 Then Exit Sub With Target Me.Protect Password:=pw, UserInterfaceOnly:=True Application.ScreenUpdating = False .NumberFormatLocal = "G/標準" On Error GoTo line If .Value <> "" Then If IsNumeric(.Value) And Len(.Value) = 8 Then Application.EnableEvents = False .Value = Left(.Value, 4) & "/" & Mid(.Value, 5, 2) & "/" & Right(.Value, 2) End If .NumberFormatLocal = "yyyy/m/d" Application.ScreenUpdating = True If Not IsDate(.Value) Then MsgBox "日付を認識できません。", vbCritical ElseIf .Value >= "2100/01/01" Or .Value <= "1910/12/31" Then MsgBox "対象外の日付です。", vbCritical End If End If End With line: Application.ScreenUpdating = True Application.EnableEvents = True Me.Protect Password:=pw, UserInterfaceOnly:=False End Sub さいわい、入力させる日付の範囲が限定できるので、これでほとんど対応できると思います。 ありがとうございました。

emaxemax
質問者

補足

せっかく、いろんなエラー対策を考えていただいたのにごめんなさい。

その他の回答 (14)

  • nishi6
  • ベストアンサー率67% (869/1280)
回答No.4

提示されているコードを3箇所修正すれば大丈夫と思います。Excel2010です。 Private Sub Worksheet_Change(ByVal Target As Range)   Select Case Target.Address(0, 0)     Case "D2", "F2", "C4"       If Target.Formula = "" Then Exit Sub '■■修正1 Formula       If IsDate(Target.Text) Then      '■■修正2 Text         Target.NumberFormatLocal = "yyyy/m/d"       Else         Application.EnableEvents = False         Target.Value = CDate(Format(Target.Formula, "@@@@/@@/@@")) '■■修正3 Formula         Application.EnableEvents = True       End If     Case Else       Exit Sub   End Select End Sub >もう1点、日付をYYYYMMDDの連続数字で入力することは普通、エクセルではあまり見たことないですが、これって一般的な方法なのでしょうか? 金融系の某会社ですが、金融会社間のデータのやり取り、お客様とのデータのやり取り、メインフレームのデータ、メインフレームとのデータのやり取りは基本というか、昔から今も年月日は8桁が普通です。新人研修などではメインフレームのデータ8桁をExcel上の年月日に変換する方法(逆も)をいろいろ教えます。 ご参考に。

emaxemax
質問者

お礼

ありがとうございます。 やってみましたが、20140229等の誤入力だと、型が一致しないというエラーになってしまいます。 あと、8桁入力はデータ交換のためのやり方なんですね、勉強になりました。

  • tom04
  • ベストアンサー率49% (2537/5117)
回答No.3

こんにちは! 入力間違いがない!という前提であれば Private Sub Worksheet_Change(ByVal Target As Range) If Intersect(Target, Range("D2,F2,C4")) Is Nothing Or Target.Count > 1 Then Exit Sub With Target .NumberFormatLocal = "G/標準" If IsNumeric(.Value) And Len(.Value) = 8 Then Application.EnableEvents = False .Value = DateSerial(Left(.Value, 4), Mid(.Value, 5, 2), Right(.Value, 2)) Application.EnableEvents = True End If .NumberFormatLocal = "yyyy/m/d" End With End Sub のような感じではどうでしょうか? ※ あくまでExcel的にシリアル値として認識できる入力方法、もしくは8桁数値の場合の時は大丈夫だと思いますが、 色々なケースの入力間違いを想定するとどんなコードを考えても限界があると思います。 別案として、年・月・日付 の数値を別々にインプットボックスに入力してもらう方法はどうでしょうか? Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim myY As Integer, myM As Integer, myD As Integer If Intersect(Target, Range("D2,F2,C4")) Is Nothing Or Target.Count > 1 Then Exit Sub On Error Resume Next myY = Application.InputBox("年を (例) 2014 のように入力") myM = Application.InputBox("月を入力") myD = Application.InputBox("日付を入力") With Target .Value = DateSerial(myY, myM, myD) .NumberFormatLocal = "yyyy/m/d" End With End Sub こんな感じで・・・ ちゃんとシリアル値を入力できる人であれば面倒だと感じるかもしれませんね。m(_ _)m

emaxemax
質問者

お礼

ありがとうございます。 入力間違いを想定し、以下のようにしてみました。 Private Sub Worksheet_Change(ByVal Target As Range) If Intersect(Target, Range("D2,F2,C4")) Is Nothing Or Target.Count > 1 Then Exit Sub With Target .NumberFormatLocal = "G/標準" If .Value = "" Then Exit Sub If IsNumeric(.Value) And Len(.Value) = 8 Then Application.EnableEvents = False .Value = DateSerial(Left(.Value, 4), Mid(.Value, 5, 2), Right(.Value, 2)) Application.EnableEvents = True End If .NumberFormatLocal = "yyyy/m/d" If Not IsDate(.Value) Then MsgBox "日付を認識できません。" End With End Sub あってますでしょうか?

emaxemax
質問者

補足

別案の、年・月・日付 の数値を別々にインプットボックスに入力する方法は帰って使う方の手間がかかるのでやはり無理ですね。

回答No.2

Formula で判断するとよいかも? 今Excel2002なので違う結果になるかも? Private Sub Worksheet_Change(ByVal Target As Range) On Error GoTo erH   Select Case Target.Address(0, 0)     Case "D2", "F2", "C4"       If Target.Formula = "" Or IsNumeric(Target.Formula) = False Then Exit Sub       If IsDate(Target.Formula) Then         Target.NumberFormatLocal = "yyyy/m/d"       Else         Application.EnableEvents = False         Target.Value = CDate(Format(Target.Formula, "@@@@/@@/@@"))         Application.EnableEvents = True       End If     Case Else       Exit Sub   End Select   Exit Sub erH: Application.EnableEvents = True MsgBox Err.Number & vbCrLf & Err.Description End Sub ありえない日付(20001232 とか)でも不親切なメッセージになるので Target.Value = CDate(Format(Target.Formula, "@@@@/@@/@@")) を if isdate(CDate(Format(Target.Formula, "@@@@/@@/@@"))) Target.Value = CDate(Format(Target.Formula, "@@@@/@@/@@")) else msgbox "Boo" みたいなのが良いかも。 一般的かどうかは置いといて、そういう要望はあります。 時刻でも 12:15 のコロンが離れているので打ちづらいから テンキーで12.15 と入力したら 12:15 になるようにして頂戴!とか。

emaxemax
質問者

お礼

ありがとうございます。 YYYYNNDD形式は正しく入力されました。 しかし、2014/7/12と、通常の日付をいれると、1932/4/18とかのとんでもない日付に化けました。年を入れず7/12とかの入力でも日付が変わってしまいます。 やりたいことは、たとえば 20140712 2014/7/12 2014/07/12 7/12 H26.7.12 以上、どれを入力されても正しく日付となることです。

noname#196873
noname#196873
回答No.1

わたしなら、ですが。 If Not IsDate(請求日) Then ' エラーメッセージ表示 MsgBox "yyyy/mm/ddの形式で入力してください。" _ & vbCrLf & "処理を中止します。", vbCritical ' マクロの実行を中止 Exit Sub を途中に入れます。 ただ、IsDate関数は日本人にはなじみがない形式も日付と認めるのが難点ですが。 http://kozhouse.homeip.net/progtec/11/ http://it-doc.jp/index.php/excelforwork/vba/94-myisdate

emaxemax
質問者

お礼

早速ありがとうございます。 要は、IsDate関数でTRUE以外をすべて排除するということですか? それが許されないので質問しているのです・・・。

関連するQ&A

  • エクセル 加算 

    1つのセルに数字を入力すると加算されているマクロを探していたら 以下の回答がありました Dim memo Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address <> "$A$1" Then Exit Sub If Target.Value <> "**" And IsNumeric(Target.Value) = False Then Exit Sub Application.EnableEvents = False If Target.Value = "**" Then memo = 0 Else memo = memo + Target.Value End If Target.Value = memo Application.EnableEvents = True End Sub このマクロですがA1に入力した場合に適用しますが、このマクロをたとえばA1からC1の範囲で使用した1場合にどのようなマクロをすればよいかわかりません それか、このマクロではそのようなことができるのかもわかりませんので教えて頂けないでしょうか

  • EXCEL VBAについて教えてください

    はじめまして。 過去ログに私のやりたいような内容を探していたらこのような下記のエクセルVBAがあったので、教えて頂きたいです。 Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address <> "$A$1" Then Exit Sub If Target.Value = "" Then Exit Sub x = Target.Value With Application .ScreenUpdating = False .EnableEvents = False .Undo y = Target.Value Target.Value = x + y .EnableEvents = True .ScreenUpdating = True End With With Cells(ActiveSheet.Rows.Count, "C").End(xlUp) .Offset(1, 0).Value = x .Offset(1, 1).Value = Time() End With End Sub A1に入力するたびに同一セルに加算。 A1をクリアできる。 C列に入力履歴、D列に入力時間を記録。 If Target.Address <> "$A$1" Then Exit Sub の$A$1を変えることによって他のセルにも設定できる。 と、いう内容なのですが、これをたとえば同一シートのA1~E10のセルとA12~E22にも同じよう別々に処理できるように設定したいのですが、どのようにすればいいのでしょうか?ちなみにA11~E11とA23~E23は合計を表示するセルにしたいです。 Excelのバージョンは2003です。 よろしくお願い致します

  • Excel 置換? VBA

    先ほども質問したんですが、 A1に010と入力すると田中、020入力で鈴木と出来るように、 ------------------------------------------------------ Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address <> "$A$1" Then Exit Sub Select Case Target.Value Case "010": myStr = "田中" Case "020": myStr = "鈴木" Case "030": myStr = "岡田" Case "": myStr = "" Case Else: myStr = "非該当" End Select Application.EnableEvents = False On Error GoTo line Target.Value = myStr line: Application.EnableEvents = True End Sub ---------------------------------------------------- を教えていただきました! が、A2でも同じようなことを行いたいのです! VBAの知識が乏しいのでコピペでいろいろやってみたのですが、エラーで出来ませんでした…。 A1 A2 ・ ・ ・ と同じように入力できるようにするにはどのようにすればよいのでしょうか?もう一度教えて下さい。よろしくお願いします。

  • VBAの日付チェックでオーバーフローを回避したい。

    VBAの日付チェックでオーバーフローを回避したい。 ExcelのG列のセルに入力されたものが日付型であるかどうかのチェックかけたいと思います。 以下のコードだと、数字2958466以上の入力でオーバーフローが発生します。 これを回避する方法はありますか? セルを日付型に設定しているため、2958465(2999/12/31)までしか判別できないのでしょうが、 利用者が2958466以上を入力してしまう可能性はあります。 オーバーフローではなく、エラーメッセージが出せたら・・・と思います。 Private Sub Worksheet_Change(ByVal Target As Range) If Target.Column = 8 Then Application.EnableEvents = False If Target <> "" And Not IsDate(Target) Then MsgBox "日付型で入力してください。" & vbCrLf & "(例:2010/10/31)", vbCritical, "入力エラー" Target = "" Target.Select End If Application.EnableEvents = True End If End Sub こんなコードも試しましたが、結果は同じでした。 ↓ Private Sub Worksheet_Change(ByVal Target As Range) If Target.Column = 8 Then Application.EnableEvents = False If Target > 2958466 Then MsgBox "日付型で入力してください。" & vbCrLf & "(例:2010/10/31)", vbCritical, "入力エラー" Target = "" Target.Select Else If Target <> "" And Not IsDate(Target) Then MsgBox "日付型で入力してください。" & vbCrLf & "(例:2010/10/31)", vbCritical, "入力エラー" Target = "" Target.Select End If End If Application.EnableEvents = True End If End Sub On Error Resume Next や On Error GoTo ... での対処も考えましたが、同じ結果でした。 何か良い方法がありましたら、お願いいたします。

  • Excel 2000です。VBAを改造していただきたいのですが

    入荷品のチェックシートです。B列に受領数を入力するとA列に年月日が記録されるVBAを作っていただき必要なブックのシートごとにコピーして使っていました。全品入荷完了後 別のロットにシートタブの名目を書き換えて再利用します。  ('複数セルが選択された場合、動作をキャンセル  がなぜ必要かも理解できないVBAの勉強を挫折の高齢者です) B列のセル一個づつ選択削除でないとB列が空白になるだけでA列には日付が残ります。複数のセル選択で一気に日付を削除したいのです。 お助けください。 Private Sub Worksheet_Change(ByVal Target As Range) '複数セルが選択された場合、動作をキャンセル If Target.Count <> 1 Then Exit Sub If Intersect(Target, Range("B5:B1000")) Is Nothing Then Exit Sub 'B5:B1000"の範囲外は除外 Application.EnableEvents = False If Target.Value <> "" Then If IsDate(Target.Offset(, -1).Value) Then GoTo EXIT_LABEL '日付が記入済の場合は実行しない Target.Offset(, -1).Value = Format$(Now, "mm/dd hh:mm") Else 'セルを空白にした場合、日付を削除 Target.Offset(, -1).Value = "" End If EXIT_LABEL: Application.EnableEvents = True End Sub

  • エクセルで日付と時間を自動入力する

    エクセルでF13~P13に何か入力したら、その下のセルの F14~P14に日付と時間が自動入力される という質問、回答を見つけました。 これで日付を削除するかどうかのメッセージボックスを出さずに 入力するセルのデータを削除した時に日付も削除するには どの部分を削除すれば良いですか? Private Sub Worksheet_Change(ByVal Target As Excel.Range) Dim mRng As Range Application.EnableEvents = False For Each mRng In Target If Not Intersect(mRng, Range("F13:P13")) Is Nothing Then If mRng.Value = "" Then If MsgBox("日付も削除しますか?", vbYesNo + vbDefaultButton2) = vbYes Then mRng.Offset(1, 0).Value = "" End If Else mRng.Offset(1, 0).Value = Format(Now, "yyyy/mm/dd"" ""hh:mm:ss") End If End If Next mRng Application.EnableEvents = True End Sub

  • VBAの時間入力について

    先日、時間を文字列で、HH:mmのフォーマット入力するPGを教えて頂き、 内容理解をしているのですがわからない部分があります。 ★の部分の条件で、00:00も入力したいです。 ご存知か方がおられましたら教えてください。 よろしくお願い致します。 Private Sub Worksheet_Change(ByVal Target As Range) 'この行から 'Intersect:http://officetanaka.net/excel/vba/tips/tips118.htm 'Is Nothing:nullではない 'Selection.Count <> 1:選択数が1以下ではない(<> :等しくない) ' Not IsNumeric(Target):数値ではない If Intersect(Target, Columns(12)) Is Nothing Or Selection.Count <> 1 _ Or Not IsNumeric(Target) Then Exit Sub ' 'Target:セルの値は24:00以下 '2つの数値の除算を行いし,その剰余を返す 'Mod:2つの数値の除算を行いし,その剰余を返す '★ここで00:00時も入力したい。 If Target <= 2400 And Target Mod 100 < 60 Then ' Application.EnableEvents = False ' With Target ' If Len(Target) = 3 Then .Value = 0 & ":" & Right(Target, 2) ElseIf Len(Target) = 3 Then .Value = Left(Target, 1) & ":" & Right(Target, 2) Else .Value = Left(Target, 2) & ":" & Right(Target, 2) End If .NumberFormatLocal = "hh:mm" ' End With ' Application.EnableEvents = True ' Else MsgBox "入力値が不正です。" ' With Target ' .Value = "" .Select End With Exit Sub ' End If End Sub 'この行まで

  • エクセルでデータ入力された日付と時間を自動入力する

    前回ご質問にて 1行目に何か入力したら2行目に日付と時間を自動入力する というVBAを教えて頂きました。 ------------------------ Private Sub Worksheet_Change(ByVal Target As Excel.Range) Application.EnableEvents = False If Target.Row = 1 Then Target.Offset(1, 0).Value = Format(Now, "yyyy/mm/dd"" ""hh:mm:ss") End If Application.EnableEvents = True End Sub ------------------------ これを1行目に何か入力したら2行目に日付と時間ではなく セル指定を行いたいのです。 例)F13~P13に何か入力したら、その下のセルの F14~P14に日付と時間が自動入力される という作りです。 よろしくお願いします。

  • エクセルで数字を入力すると隣のセルに特定の文字に変換する方法

    Private Sub Worksheet_Change(ByVal Target As Range) If Target.Count <> 1 Then Exit Sub Application.EnableEvents = False Select Case Target.Value Case 93 Target.Value = "アフガニスタン" Case 971 Target.Value = "アラブ首長国連邦" Case 967 Target.Value = "イエメン共和国" End Select Application.EnableEvents = True End Sub 国別電話番号の表を作りたいのですが、VLOOKUP関数を使用せずに上記のプログラムを利用して数字を入れたセルの隣のセルに特定の文字を反映させたいのですが、初心者の為に苦労しております。 どのようなプログラムを付け加えたら良いのかお教えください。 よろしくお願いいたします。

  • エクセルのVBAについて教えてください。

    エクセルのVBAについて教えてください。 下記のような構文で、Dの行にAやBの文字が入力された時、その都度 セルの色が変わるようにはできたのですが、本当は、「C5」セルに文字が 入力された時、「C5」だけでなく「B5:J5」の範囲でセルの色を変えたい のですが、どうすれば良いのでしょうか。 ご存知の方是非教えてください。 Private Sub Worksheet_Change(ByVal Target As Range) Dim myColor As Integer If Target.Count > 1 Then Exit Sub If Target.Column <>4 Then Exit Sub Select Case Target.Value Case "A" myColor = 34 '水色 Case "B" myColor = 40 '肌色 Case Else myColor = xlNone End Select Target.Interior.ColorIndex = myColor End Sub

専門家に質問してみよう