ツイッター出題回答
日付の謎:IsDateとCDate

ExcelマクロVBAとエクセル関数についての私的雑感
公開日:2020-06-14 最終更新日:2020-06-15

日付の謎:IsDateとCDate


ツイッターで出したVBAのお題です。
エクセルにおける日付のちょっと不思議な挙動についての、ちょっと変わった、ちょっと意地悪な問題です。


お題のツイート

https://twitter.com/yamaoka_ss/status/1271776939343110146

【VBA問題】
画像のVBAはエラーになる事があるでしょうか?

VBA マクロ 日付の謎 IsDate CDate


回答用の投票
・IsDateで判定しているのでエラーにならない
・VBAなら何が起こるか分からないエラーもありえる
・わからない

エクセル Excel サンプル画像

エラーにならないが41.2%と一番多くなりました。
さて、答えはどうなのでしょうか。

解説のツイート

以下のツイートからの一連のスレッドで解説しています。

https://twitter.com/yamaoka_ss/status/1271838985011122181

結構割れましたね。
では答えです、
答えは「エラーになる場合がある」
どんな場合にエラーになるか。
言って見れば、ここが問題です。
細かいことを書いていると結構長くなりそうです。

IsDate関数は、日付変換可能かの判定をします。
つまり、IsDateでTrueならCDate関数でエラーになりません。
では、でなぜ先のVBAはエラーになる事があるのか、、、
CDate関数ではエラーにならないのですが、Range.Valueへの代入でエラーになる場合があります。

エラーになるのは、
1899/12/29以前の日付を入れた時です。
微妙ですよね、12/29って何?12/30は?
1899/12/30はエラーになりません。
ここが不思議なところです。

セルに入れられる日付は1900/1/0以降です。
えっ、"1/0"って何?
セルに、
=DATEVALUE("1900/1/1")-1といれると0となります。
これを表示形式で日付けにすると、1900/1/0となります。

ご存じの通り1900/1/1のシリアル値が1です。
従って0は1899/12/31なのですが、そのような表示がエクセルには無いからです。
=DATEVALUE("1900/1/1")-2といれると、セル幅いっぱいに#表示になります。
シリアル値がマイナスとなり、マイナス数値を日付形式にした場合にこのような表示になります。

VBAで日付けをセルに入れた時、シリアル値がマイナスになる日付はエラーとなります。
あれ、でも、1899/12/30はエラーにならない、これと矛盾していませんか、、、
v = "1900/1/1"
として先のVBAを実行すると、セルには1900/1/2と表示されます。
VBAとシートで1日ずれています。

VBAで1899/12/31をセルに入れると1900/1/1シリアル値1
VBAで1899/12/30をセルに入れると1900/1/0シリアル値0
VBAで1899/12/29をセルに入れるとマイナス1なのでエラーとなります。
ではVBAの日付とシートの日付が全てずれているかと言うと、もちろんそんなことはありません。

1900/3/1以降は一致します。
つまり、それより前の日付がずれてしまいます。
これは、シートの日付に1900/2/29が存在しているからです。
1900年はうるう年ではないのに、シートでは1900/2/29が存在しています。
(この理由については省略します。)
しかし、VBAでは1900/2/29は存在しないので、そこで1日ずれてしまっています。

話を戻します。
では、1899/12/29以前が全部エラーとなるかと言うと、これも簡単な話ではありません。
v= "100/1/1"とした場合、これはマイナスのシリアル値なのでエラーになります。
v= "99/1/1"これはエラーになりません。
でも、シートには1999/1/1と表示されます。
VBAでは、100/1/1以降のデータしか扱えません。

CDate("99/1/1")これは1999/1/1となります。
2桁年はCDateでは1900年が加算されます。
これは、DateSerialでも同じです。
DateSerial(99, 1, 1)これは1999/1/1となります。

以上の事からエラーになるのは、
100/1/1から1899/12/29
この範囲の日付に変換可能な値が変数vに入っていた時にエラーになります。

日付に関するVBA関数

Date関数
Date関数は、現在のシステムの日付を返します、バリアント型(内部処理形式DateのVariant)の値を返します。Date関数 Date 現在の日付を設定するには、Dateステートメントを使います。グレゴリオ暦の場合、DateとDate$の動作は同じです。
DateAdd関数
DateAdd関数は、指定された時間間隔を加算した日付を返します、バリアント型(内部処理形式StringのVariant)で返します。DateAdd関数 DateAdd(interval,number,date) interval 必ず指定します。
DateDiff関数
DateDiff関数は、2つの指定した日付の時間間隔を表す値を返します。ワークシート関数のDATEDIF関数とはスペルも引数も違います、さらに、年の計算は違ったものとなっていますので注意してください。DateDiff関数 DateDiff(interval,date1,date2[,firstdayofweek[,
DatePart関数
DatePart関数は、日付の指定した部分の値を返します、バリアント型(内部処理形式DateのVariant)の値を返します。DatePart関数 DatePart(interval,date[,firstdayofweek[,firstweekofyear]]) interval 必ず指定します。
DateSerial関数
DateSerial関数は、引数に指定した年、月、日に対応する日付を返す関数です、バリアント型(内部処理形式DateのVariant)の値を返します。DateSerial関数 DateSerial(year,month,day) year 必ず指定します。
DateValue関数
DateValue関数は、日付を表す文字列式を日付に変換します、バリアント型(内部処理形式DateのVariant)の値を返します。DateValue関数 DateValue(date) date 必ず指定します。引数dateには、通常、100年1月1日から9999年12月31日までの範囲の日付を表す文字列式を指定…

Year関数
Year関数は、日付から年の値を返します、バリアント型(内部処理形式IntegerのVariant)の値を返します。Year関数 Year(date) date 必ず指定します。日付を表すバリアント型(Variant)の値、数式、文字列式、またはこれらを組み合わせた値を指定します。
Month関数
Month関数は、日付から何月かを表す月の値を返します、バリアント型(内部処理形式IntegerのVariant)の値を返します。Month関数 Month(date) date 必ず指定します。日付を表すバリアント型(Variant)の値、数式、文字列式、またはこれらを組み合わせた値を指定します。
Day関数
Day関数は、日付から何日かを表す日の値を返します、バリアント型(内部処理形式IntegerのVariant)の値を返します。Day関数 Day(date) date 必ず指定します。日付を表すバリアント型(Variant)の値、数式、文字列式、またはこれらを組み合わせた値を指定します。

MonthName関数
MonthName関数は、指定された月を表す文字列を返します。MonthName関数 MonthName(month[,abbreviate]) month 必ず指定します。月を示す数値を指定します。
Weekday関数
Weekday関数は、何曜日であるかを表す整数を返します、バリアント型(内部処理形式IntegerのVariant)の値を返します。Weekday関数 Weekday(date,[firstdayofweek]) date 必ず指定します。
WeekdayName関数
WeekdayName関数は、指定された曜日を表す文字列を返します。WeekdayName関数 WeekdayName(weekday,abbreviate,firstdayofweek) weekday 必ず指定します。曜日を示す数値を指定します。

データ判定のVBA関数

IsArray関数
IsArray関数は、変数が配列であるかどうかを調べ、結果をブール型(True,False)で返します。IsArray関数 IsArray(varname) varname 必ず指定します。引数varnameには、変数の識別子を指定します。
IsDate関数
IsDate関数は、式を日付に変換できるかどうかを調べ、結果をブール型(True,False)で返します。IsDate関数は、値が日付変換可能かどうかを判定する関数です。IsDate関数 IsDate(expression) expression 必ず指定します。
IsEmpty関数
IsEmpty関数は、変数がEmpty値かどうかを調べ、結果をブール型(True,False)で返します。IsEmpty関数 IsEmpty(expression) expression 必ず指定します。数式または文字列式を含むバリアント型(Variant)の式を指定します。
IsNumeric関数
IsNumeric関数は、式が数値として評価できるかどうかを調べ、結果をブール型(True,False)で返します。IsNumeric関数は値が数値変換可能かどうかを判定する関数です。IsNumeric関数 IsNumeric(expression) expression 必ず指定します。
IsMissing関数
プロシージャを呼び出すときに省略可能なバリアント型(Variant)の引数がプロシージャに渡されたかどうかを調べるために使用します。IsMissing関数 IsMissing(argname) argname 引数argnameは必ず指定します。
IsObject関数
識別子(主にバリアント変数)がオブジェクト変数を表しているかどうかを判断する場合に使用します。バリアント変数がオブジェクト変数を表しているかどうかを示すBoolean値(True/False)を返します。IsObject関数の構文 Isobject(識別子) 識別子は、主にバリアント変数名を指定します。
TypeName関数
TypeName関数は、引数で指定された変数に関する情報を文字列で返します。TypeName関数 TypeName(varname) varname 必ず指定します。ユーザー定義型の変数を除く、任意のバリアント型(Variant)の変数を指定します。
VarType関数
VarType関数は、引数に指定された変数の内部処理形式を表す整数型(Integer)の値を返します。VarType関数 VarType(varname) varname 必ず指定します。引数varnameには、ユーザー定義型の変数を除く、任意のバリアント型(Variant)の変数を指定します。

データ型変換のVBA関数

CBool関数
CBool関数は、引数をBoolean型(True,False)に変換します。式がゼロの値に評価される場合Falseを返し、それ以外の場合はTrueを返します。CBool関数 CBool(expression) expression 任意の文字列式または数式を指定します。
CByte関数
CByte関数は、引数をByte型(0~255)に変換します。CByte関数 CByte(expression) expression 文字列式または数式を指定します。この引数は必ず指定します。引数が0~255に変換できない場合はエラーとなります。
CCur関数
CCur関数は、引数をCurrency型(通貨型)に変換します。CCur関数 CCur(expression) expression には任意の文字列式または数式を指定します。この引数は必ず指定します。
CDate関数
CDate関数は、引数の数値または文字列をDate型(日付型)に変換します。CDate関数 CDate(expression) expression 任意の文字列式または数式を指定します。この引数は必ず指定します。
CDbl関数
CDbl関数は、引数をDouble型(倍精度浮動小数点数型)に変換します。CDbl関数 CDbl(expression) expression 任意の文字列式または数式を指定します。この引数は必ず指定します。
CDec関数
CDec関数は、引数をDecimal型(10進型)に変換します。CDec関数 CDec(expression) expression には任意の文字列式または数式を指定します。この引数は必ず指定します。
CInt関数
CInt関数は、引数をInteger型(整数型)に変換します。CInt関数 CInt(expression) expression には任意の文字列式または数式を指定します。この引数は必ず指定します。
CLng関数
CLng関数は、引数をLong型(長整数型)に変換します。CLng関数 CLng(expression) expression 任意の文字列式または数式を指定します。この引数は必ず指定します。引数がLong型(長整数型)に変換できない場合はエラーとなります。
CLngLng関数,CLngPtr関数
CLngLng関数は、引数をLongLong型に変換します。CLngPtr関数は、引数をLongPtr型に変換します。CLngLng関数 CLngLng関数は、引数をLongLong型に変換します。LongLongデータ型 64ビット(8バイト)の符号付き数値です。
CSng関数
CSng関数は、引数をSingle型(単精度浮動小数点数型)に変換します。CSng関数 CSng(expression) expression には任意の文字列式または数式を指定します。この引数は必ず指定します。
CStr関数
CStr関数は、引数をString型(文字列型)に変換します。CStr関数 CStr(expression) expression 任意の文字列式または数式を指定します。この引数は必ず指定します。Str関数は、正の数値の場合は先頭に半角空白が入りますが、CStr関数は、この半角空白が入りません。
CVar関数
CVar関数は、引数をVariant型(バリアント型)に変換します。CVar関数 CVar(expression) expression 任意の文字列式または数式を指定します。この引数は必ず指定します。
CVErr関数
CVErr関数は、指定した数値(エラー番号)を、バリアント型のエラー値に変換した値を返す変換関数です。CVErr関数 CVErr(errornumber) errornumber 任意の数値(エラー番号)を指定します。この引数は必ず指定します。



同じテーマ「ツイッター出題回答 」の記事

IFステートメントの判定

ツイッターでIfステートメントの書き方が話題になっていたのを見て、結構いろいろな要素があるということで、ちょっと意地悪な問題にしてみました。お題のツイート https://twitter.com/yamaoka_ss/status/1271402726174277632 VBA問題 さて、いくつが表示されるでしょう…
日付の謎:IsDateとCDate
ツイッター投稿用に文字数と特定文字で区切る
ツイッターで出したVBAのお題です。ツイッター投稿には文字数制限がありますので、セルに入れた下書き文章をツイート用に区切る問題です。お題のツイート https://twitter.com/yamaoka_ss/status/1272033174575407105 【エクセルお題】 ツイートの下書きをA1セルに入れて…
マクロ記録での色のマイナス数値について
ツイッターで出したVBAのお題です。マクロの記録で文字色などの色を指定するとマイナス数値で記録される場合がありますが、このマイナス数値は何かを問う問題です。お題のツイート https://twitter.com/yamaoka_ss/status/1272119270026051587 【エクセル問題】 マクロの記…
VBAのString型の最大文字数について
ツイッターで出したVBAのお題です。String型はVBAリファレンスでは、「可変長文字列は、最大で約20億(2^31)文字を格納できます。」と書かれています。これについて、本当は何文字まではいるのかについての問題です。
Variantの数値型と文字列型の比較
ツイッターで出したVBAのお題です。Variant型は、どんなデータ型も入れることができます。具体的なデータ型の代わりに使用することで、より柔軟にVBA記述ができるようになります。ただしその一方で、少々特殊な挙動もあり、使いこなすにはそれなりの知識が必要になる場合もあります。
Variant仮引数にRange.Valueを配列で渡す方法
ツイッターで出したVBAのお題です。Variant型は、どんなデータ型も受け入れることができます。RangeオブジェクトのValueを配列で受け取るにはVariant変数が必要です。ただし、実引数にRangeオブジェクトを直接指定する場合には注意が必要です。
Variant仮引数のByRefとByValの挙動違い
ツイッターで出したVBAのお題です。Variant型は、どんなデータ型も入れることができてしまいます。具体的なデータ型の代わりに使用することで、より柔軟にVBA記述ができるようになります。ただしこの便利さゆえに、逆に注意しなければならない挙動もあります。
100桁の正の整数値の足し算
ツイッターで出したVBAのお題です。数の単位に「無量大数」というものがあります。VBAでこの無量大数の足し算をするにはどうしたら良いでしょうか。そこで、100桁の正の整数の足し算をVBAで実現してみましょう。
「VBA Match関数の限界」についての誤解
ツイッターで出したVBAのお題です。発端はエゴサーチからです。(笑) 「教えて!goo」で引用されていたのを見つけました。あちこちで引用されているのは見かけることはあるのですが、以下ではよく言うディスられているような文章を見かけました。
VBAで数値を漢数字に変換する方法
ツイッターで出したVBAのお題です。算用数字を漢数字に変換するVBAです。滅多に必要になるものではないのに、なぜこんな問題を出したかと言うと、最近シリーズで書き始めた「Excel将棋」で必要になったからです。


新着記事NEW ・・・新着記事一覧を見る

TRIMRANGE関数(セル範囲をトリム:端の空白セルを除外)|エクセル入門(2024-08-30)
正規表現関数(REGEXTEST,REGEXREPLACE,REGEXEXTRACT)|エクセル入門(2024-07-02)
エクセルが起動しない、Excelが立ち上がらない|エクセル雑感(2024-04-11)
ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.繰り返し処理(For Next)|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.変数宣言のDimとデータ型|VBA入門
5.RangeとCellsの使い方|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.セルのクリア(Clear,ClearContents)|VBA入門
8.メッセージボックス(MsgBox関数)|VBA入門
9.条件分岐(Select Case)|VBA入門
10.ブック・シートの選択(Select,Activate)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。


このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ