VBA練習問題
VBA100本ノック 7本目:日付データの扱い

VBAを100本の練習問題で鍛えます
最終更新日:2020-10-26

VBA100本ノック 7本目:日付データの扱い


日付データに関する問題です。
そもそも日付とはどのようなデータなのかも考えてみましょう。


ツイッター連動企画です。
ツイートでの見やすさを考慮して、ブック・シート指定等を適宜省略しています。


出題

出題ツイートへのリンク

#VBA100本ノック 7本目
A列は文字列データ(表示形式が文字列)で日付が入っています。
日付とみなされる場合はB列に月末日付をmmddの形式で出力してください。
日付け以外の場合は空欄にしてください。
例.B2は「0930」と出力する。
※何をもって日付とみなすかも含めて考えてください。

VBA マクロ 日付 IsDate CDate


頂いた回答

解説

#VBA100本ノック 7本目 解答
日付の判定はIsDate関数を使います。
ただし人が日付と認識するものとは少しずれがあります。
どのような経緯で発生したデータかによって注意して使ってください。
添付ではIsDateでFalse判定される中から"."区切りだけを救っています。
シート指定は省略しています。

Sub VBA100_07()
  Dim i As Long
  Dim d As Variant
  For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
    d = Replace(Cells(i, 1).Value, ".", "/")
    If IsDate(d) Then
      d = CDate(d)
      Cells(i, 2) = Format(DateSerial(Year(d), Month(d) + 1, 0), "'mmdd")
    Else
      Cells(i, 2) = ""
    End If
  Next
End Sub


末日の算出はDateSerial関数を使うと簡単です。
問題文は「mmddの形式で出力」なので、表示形式ではなくデータとしてmmddで出力しました。
元号の合字はIsDateがFalseになります。
これを救うには1文字ずつ変換するしかありません。
※何をもって日付とするかは適宜変わってくると思います。


日付の判定及び末日算出の詳細については、記事の補足をお読みください。
元号の合字を変換するFunctionのVBAサンプルも掲載しておきました。


補足

コンピューター処理において日付はかなり厄介なものです。
特に文字列として日付が入っている場合は、それが日付なのかどうか判断に困る場合も多々あります。
今回の主題としては、IsDate関数とCDate関数の挙動について把握することにあります。

今回の解答としては、IsDateで日付判定されるものはそのまま信用して、
それ以外に、人間が見た時に日付とみなされそうなものを救って見ようという主旨で作成しました。

エクセルだけで考えたら、日付を正しく入力しましょう。
という事になりますが、VBAが扱うデータはエクセルで入力したものとは限りません。
他システムからの出力データやWEBからのコピーデータを扱う事も多いので、日付けデータの形式については理解しておきましょう。


日付けの判定について
日付かどうかを判定する関数としてVBAにはIsDate関数があります。
これは、Date型(つまりシリアル値)に変換可能かの判定になります。
あくまでVBAがDate型に変換できるかどうかであり、人の見た目で日付とみなすかどうかとは関係ありません。
この点に注意して使ってください。

日付 IsDate
2020/9/1 True
2020/9/02 True
10/3 True
20 10 4 True
2020.10.5 False
2020-10-6 True
令和元年10月 True
令1年11月2日 True
令元年11月03日 True
?元年11月04日 False

IsDate関数でTrueならCDateでシリアル値に変換できます。

月末日の算出
DateSerial(Year, Month, Day)
DateSerial関数のDayに0を指定すると、前月末日になります。
末日より大きい数値を指定した場合は、超えた日数分の翌月の日付けになります。
Monthに0と指定すれば、前年の12月、13と指定すれば翌年の1月

Format関数
Format関数の書式指定文字は、シートとは若干の違いがあるもののほぼ同じなので基本的な指定については覚えおきましょう。
Format関数は、式を指定した書式に変換し、その文字列を示す値を返します、バリアント型(内部処理形式StringのVariant)で返します。Format関数 Format(expression[,format[,firstdayofweek[,firstweekofyear]]]) expression 必ず指定します。
この関数の戻り値をそのままセルに出力すると、数値としてセルに入るので先頭の0が消えてしまいます。
そこで、文字列にするにあたり、セルの表示形式を"@"で文字列にしておいてももちろん良いのですが、
上記のVBAでは、
"'mmdd"
これで先頭に"'"をつけて文字列としてセルに入れています。

合字について
VBA マクロ 日付 IsDate CDate
これらの文字については、IsDateは元号として認識しません。
またVBAで固定文字として入れようとした時、
VBA マクロ 日付 IsDate CDate
これは、?となってしまいます。
これは文字コードの問題です。
以下のFunctionは、この元号の合字をIsDateが認識できる元号に変換するものです。

Function EditDate(ByVal d As String) As String
  Dim g1, g2
  g1 = Array(&H337E, &H337D, &H337C, &H337B, &H32FF)
  g2 = Array("明治", "大正", "昭和", "平成", "令和")
  Dim i As Long
  For i = LBound(g1) To UBound(g1)
    If InStr(d, ChrW(g1(i))) > 0 Then
      d = Replace(d, ChrW(g1(i)), g2(i))
      Exit For
    End If
  Next
  EditDate = d
End Function

令和以外はVBAに直接合字を記入できますが、令和に合わせて文字コードで記載しました。


サイト内関連ページ

IsDate関数|VBA関数
IsDate関数は、式を日付に変換できるかどうかを調べ、結果をブール型(True,False)で返します。IsDate関数 StrConv(string,conversion,LCID) expression は必ず指定します。日付や時刻として認識できる日付式または文字列式を含むバリアント型(Variant)の式を指定します。
CDate関数|VBA関数
CDate関数は、引数の数値または文字列をDate型(日付型)に変換します。CDate関数 CDate(expression) 引数expressionには任意の文字列式または数式を指定します。この引数は必ず指定します。
DateSerial関数|VBA関数
DateSerial関数は、引数に指定した年、月、日に対応する日付を返す関数です、バリアント型(内部処理形式DateのVariant)の値を返します。DateSerial関数 DateSerial(year,month,day) year 必ず指定します。
DateValue関数|VBA関数
DateValue関数は、日付を表す文字列式を日付に変換します、バリアント型(内部処理形式DateのVariant)の値を返します。DateValue関数 DateValue(date) date は必ず指定します。引数dateには、通常、100年1月1日から9999年12月31日までの範囲の日付を表す文字列式を指定します。
Day関数|VBA関数
Day関数は、日付から何日かを表す日の値を返します、バリアント型(内部処理形式IntegerのVariant)の値を返します。Day関数 Day(date) date 必ず指定します。引数dateには、日付を表すバリアント型(Variant)の値、数式、文字列式、またはこれらを組み合わせた値を指定します。
Month関数|VBA関数
Month関数は、日付から何月かを表す月の値を返します、バリアント型(内部処理形式IntegerのVariant)の値を返します。Month関数 Month(date) date 必ず指定します。引数dateには、日付を表すバリアント型(Variant)の値、数式、文字列式、またはこれらを組み合わせた値を指定します。
Year関数|VBA関数
Year関数は、日付から年の値を返します、バリアント型(内部処理形式IntegerのVariant)の値を返します。Year関数 Year(date) date 必ず指定します。引数dateには、日付を表すバリアント型(Variant)の値、数式、文字列式、またはこれらを組み合わせた値を指定します。




同じテーマ「Python入門」の記事

VBA100本ノック 4本目:セルの消去
VBA100本ノック 5本目:セルの計算
VBA100本ノック 6本目:セルに計算式
VBA100本ノック 7本目:日付データの扱い
VBA100本ノック 8本目:点数の合否判定
VBA100本ノック 9本目:フィルターコピー
VBA100本ノック 10本目:行の削除
VBA100本ノック 11本目:セル結合の警告
VBA100本ノック 12本目:セル結合を解除
VBA100本ノック 13本目:文字列の部分フォント
VBA100本ノック 14本目:社外秘シート削除


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

VBA100本ノック 39本目:数値リストの統合(マージ)|VBA練習問題(12月5日)
VBA100本ノック 魔球編:組み合わせ問題|VBA練習問題(12月3日)
VBA100本ノック 38本目:1シートを複数シートに振り分け|VBA練習問題(12月3日)
VBA100本ノック 37本目:グラフの色設定|VBA練習問題(12月2日)
VBA100本ノック 36本目:列の並べ替え|VBA練習問題(12月1日)
VBA100本ノック 35本目:条件付き書式|VBA練習問題(11月29日)
VBA100本ノック 34本目:配列の左右回転|VBA練習問題(11月28日)
VBA100本ノック 33本目:マクロ記録の改修|VBA練習問題(11月26日)
VBA100本ノック 32本目:Excel終了とテキストファイル出力|VBA練習問題(11月25日)
VBA100本ノック 31本目:入力規則|VBA練習問題(11月24日)


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

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.マクロって何?VBAって何?|VBA入門
6.繰り返し処理(For Next)|VBA入門
7.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.とにかく書いてみよう(Sub,End Sub)|VBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門




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


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



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