[[20190807182735]] 『特殊な日付の入力制限』(かば) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『特殊な日付の入力制限』(かば)

お世話になります。
宜しくお願いします。

以下の条件の特殊な日付を入力するセルについて、
「スラッシュ込みで半角10桁」で入力していない場合、エラーとなるよう設定をしたいと考えています。

入力条件
・スラッシュ込みで10桁「YYYY/MM/DD」(半角)
・ただし、生年月のみ判明している場合は「YYYY/MM/99」、生年のみ判明している場合は「YYYY/99/99」と入力する。

(入力例)
・2001年4月1日生の場合…「2001/04/01」
・2001年4月生、日にちは不明の場合…「2001/04/99」
・2001年生、月日は不明…「2001/99/99」

【自身で試した方法】
月または月日が判明していない場合は、Excel上で「日付」の判定はできないと思われることから、妥協して、「10桁」の入力制限をかけました。

「データの入力規則」
→入力値の種類「文字列(長さ指定)」
→データ「次の値に等しい」
→長さ「10」

この場合、2001/04/99や2001/99/99のような、日付としてありえないデータについては入力可能ですが、2001/04/01はなぜかエラーとなってしまいます。

なにかよい方法はありませんでしょうか。
最低限の希望としては、上記の場合、2001/04/01が入力可能で、10桁に満たない場合はエラーとしたいです。
最大の希望としては、「13月」や「32日」のようなありえない日付の場合にもエラーにしたいです。

< 使用 Excel:Excel2010、使用 OS:Windows7 >


後ろ2文字が99⇒真ん中2文字が99⇒最初4文字が1900以上2100以下 ⇒ 反応せず
後ろ2文字が99⇒真ん中2文字が99でない⇒最初4文字の年、真ん中2文字の月、1日が日付 ⇒ 反応せず
後ろ2文字がでない⇒対象が日付 ⇒ 反応せず
その他の場合はエラーを吐く
などの処理を関数やマクロで用意するのがよいかと思われます。
ただ関数で行う場合、非常に長くなるので隣のセルや隣の隣のセルに分けて記載し、それらのいずれもがTRUEならば正常と目視確認するのがよいのではないでしょうか。

ただ、丁寧に処理を書かないと予想外の入力(低:「あかさた/なは/まや」「//////////」といった入力まで想定しだすと途端に非常に複雑になっていきます。

あまり良い方法が思い浮かびませんがご参考までに。
内心では日付を入力する欄と判明している情報量を示す欄は分けたほうが便利な気はしますが、入力の簡素化が目的でしょうかね。
(高橋) 2019/08/07(水) 22:02


 現実問題としては、こんなのでいいような気がするんですが。(厳密性には欠けますが・・)
                  ↓
 入力の種類    → ユーザー設定
 数式ボックス → =IF(COUNTIF(A1,"????/??/??"),SUBSTITUTE(A1,"/99","/01")*1,A1*1)

 ※なお、セルの書式(表示形式)は、ユーザー設定で、yyyy/mm/dd としておく。

(半平太) 2019/08/07(水) 22:22


 以前何かのタイミングで同じようなコードを書いたので、
 VBAでもよければ、

 月日の成否判定はできますが、年は1900年以上、日付は上本日まで。
 一応閏年の対応はしてありますが、その他の誤差修正計算は無し。

 A1の書式は yyyy/mm/dd に設定。

 A1に入力された日付の判定

 該当シートのコードモジュールへ

 Private Sub Worksheet_Change(ByVal Target As Range)
     If Intersect(Target, [a1]) Is Nothing Then Exit Sub
     If Target.Value = "" Then Exit Sub
     If Not IsValid(Target) Then
         MsgBox "Invalid Entry", vbCritical, Target.Text
         Application.EnableEvents = False
         Target.ClearContents
         Application.EnableEvents = True
     End If
 End Sub

 標準モジュールへ

 Function IsValid(r As Range) As Boolean
     Dim sm As Object, myDate
     With CreateObject("VBScript.RegExp")
         .Pattern = "(?=(?=^\d{4}/99/99$)|(?=^\d{4}/(?:0[1-9]|1[0-2])/99$)|" & _
                    "(?=^\d{4}/(?:0[13578]|1[02])/(?:0[0-9]|[12][0-9]|3[01])$)|" & _
                    "(?=^\d{4}/(?:0[469]|11)/(?:0[0-9]|[12][0-9]|30)$)|" & _
                    "(?=^\d{4}/02/(?:0[0-9]|1[0-9]|2[0-9])$))^(\d{4})/(\d{2})/(\d{2})$"
         If .test(r.Text) Then
             Set sm = .Execute(r.Text)(0).submatches
             If (sm(1) <> "99") * (sm(2) <> "99") Then
                 myDate = DateSerial(Val(sm(0)), Val(sm(1)), Val(sm(2)))
                 If (Year(myDate) >= 1900) * (myDate <= Date) Then
                     If Format$(myDate, "yyyy/mm/dd") = r.Text Then IsValid = True
                 End If
             Else
                 IsValid = True
             End If
         End If
     End With
 End Function
(seiya) 2019/08/07(水) 23:44

その後、「2001/04/01」がエラーになる問題は、書式を「テキスト」に変えることで解消されました。ご返信が遅くなり失礼しました。

(高橋)様
 ありがとうございます。本件はあまり複雑な条件で作成しない想定ですので、場合分けはしない方向です。
とはいえ、「99」が付く場合と付かない場合で分けて考えるのは非常に参考になりました。
おっしゃる通り、入力簡素化が目的なので項目は増やせない状況です。

(半平太)様
 ありがとうございます。やりたいことが概ね満たされており、シンプルでよい方法だと思いました。
少し要件が加わったので、教えていただいた方法にプラスして対応できないか考えてみます。
 
(seiya)様
 ありがとうございます。やはりマクロ対応ですかね。
データが重いのでなるべくマクロは使用しない想定でした。
法人の設立年月日も入力するので、「1900年以上」に限定できない(でも、おかしな日付は入力させたくない)のがネックです。参考にさせていただきます。
(かば) 2019/08/09(金) 08:53


 >法人の設立年月日も入力するので、「1900年以上」に限定できない(でも、おかしな日付は入力させたくない)のがネックです。
 (Year(myDate) >= 1900)の1900を好きに変えれば済みます。

 それと
 >データが重いのでなるべくマクロは使用しない想定でした。
 使用するしないは勿論自由ですが、その根拠が理解できません。
(seiya) 2019/08/09(金) 12:18

(seiya)様
失礼致しました。
正直申し上げますと、当方の勉強不足でそもそもVBAの記述についての理解不足のため、
VBAを使用しない方向で検討しておりました。
(お恥ずかしながら、標準モジュールへ記載する方法は何となく分かりますが、コードモジュールへ記載するとはどうすればよいのだろう、といったレベルの知識しかありません)

ちなみに本件は、数十名分のデータを一つのシートに入力するもので、教えていただいたVBAそのままではいけないのだろうと思います。

生年月日以外にも多数の項目について処理をしている段階ですので、他の項目の作業が終わりましたら再度、VBA含めて検討してみます。
(かば) 2019/08/09(金) 20:07


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.