web-dev-qa-db-ja.com

Excel VBAの日付形式

いくつかの日付を含むスプレッドシートがあります。これらは通常、_mm/dd/yyyy_または_mm/dd/yyyy hh:mm_のいずれかに表示されます。

問題は、日付が常に正しく入力されるとは限らず、コード内の日付であることを確認するためのチェックが必要なことです。

私の元々の考えは、IsDateを使用してチェックまたはCDateを使用することでしたが、これは機能していないようでした。日付の代わりに文字列を返していました。

それ以来、これらの機能が期待どおりに機能しないことを示す小さな実験を設定しました。方法論は次のとおりです。

  1. セルA1に式=DATE(2013,10,28)を入力します
  2. セルB1の数式_=A1*1_これは数値と等しくなければなりません(41575)
  3. この小さなスクリプトを実行する

    _Sub test()
    
    MsgBox ("Start:" & TypeName(ActiveCell.Value) & " " & IsDate(ActiveCell.Value))
    
    ActiveCell.Value = Format(ActiveCell.Value, "mm/dd/yyyy")
    MsgBox ("After format: " & TypeName(ActiveCell.Value) & " " & IsDate(ActiveCell.Value))
    
    ActiveCell.Value = CDate(ActiveCell.Value)
    MsgBox ("After Cdate: " & TypeName(ActiveCell.Value) & " " & IsDate(ActiveCell.Value))
    
    End Sub
    _

スクリプトが開始すると、セルは日付型であり、IsDateはtrueを返します。 Formatを実行した後は、文字列型ですが、IsDateは依然としてtrueを返します。 CDateもセルを文字列に変換します。セルB1も0を返します(文字列* 1であるため)。

だから私は質問を要約することを推測する:

  1. なぜFormatCDateがセルを文字列に変更するのですか?
  2. セルが日付のように見える文字列だけでなく、日付の値を返すようにするにはどうすればよいですか?
13
gtwebb

セルのcontent、セルの表示形式、 VBAによるセルからのデータ型読み取り、およびデータ型書き込み VBAからのセルとExcelがこれを自動的に解釈する方法。 (たとえば this previous answer を参照してください。)これらの関係は少し複雑になる可能性があります。Excelは、あるタイプ(文字列など)の値を特定の他のデータタイプ(たとえば日付)そして、これに基づいて表示形式を自動的に変更します。最も安全なのは、明示的にすべてを行い、この自動機能に依存しないことです。

私はあなたの実験を実行しましたが、あなたと同じ結果は得られません。私のセルA1はずっと日付のままで、B1は41575のままです。だからあなたの質問#1に答えることができません。結果はおそらく、Excelのバージョン/設定がその内容に基づいてセルの数値形式を自動的に検出/変更する方法に依存します。

質問#2、「セルが日付値を返すことを確認するにはどうすればよいですか」:まあ、日付値を「返す」ことの意味がわかりませんが、必要な場合はVBAからの書き込み内容に基づいて、日付として表示される数値どちらか:

  • Excelが日付や形式として自動的に解釈することを期待する文字列値をセルに書き込みます。指をクロスします。明らかにこれは非常に堅牢ではありません。または、

  • VBAからセルに数値を書き込み(明らかに日付型が目的の型ですが、整数、長整数、単数、または倍精度でも同様です)、.NumberFormatを使用してセルの数値形式を目的の日付形式に明示的に設定しますプロパティ(またはExcelで手動)。これははるかに堅牢です。

既存のセルの内容を日付として表示できることを確認したい場合は、次の関数が役立ちます。

Function CellContentCanBeInterpretedAsADate(cell As Range) As Boolean
    Dim d As Date
    On Error Resume Next
    d = CDate(cell.Value)
    If Err.Number <> 0 Then
        CellContentCanBeInterpretedAsADate = False
    Else
        CellContentCanBeInterpretedAsADate = True
    End If
    On Error GoTo 0
End Function

使用例:

Dim cell As Range
Set cell = Range("A1")

If CellContentCanBeInterpretedAsADate(cell) Then
    cell.NumberFormat = "mm/dd/yyyy hh:mm"
Else
    cell.NumberFormat = "General"
End If

Formatは値を文字列に変換します。 IsDateは、文字列を解析して有効な日付を取得できるため、依然としてtrueを返します。

セルを文字列に変更したくない場合は、Formatを使用しないでください。 (IOW、最初から文字列に変換しないでください。)Cell.NumberFormatを選択し、表示する日付形式に設定します。

ActiveCell.NumberFormat = "mm/dd/yy"   ' Outputs 10/28/13
ActiveCell.NumberFormat = "dd/mm/yyyy" ' Outputs 28/10/2013
2
Ken White

入力いただきありがとうございます。明らかに、他のマシンでは再現されない問題がいくつか見られます。ジャンの答えに基づいて、私はうまくいくように見えるエレガントではない解決策を思いつきました。

セルにcdateから直接値を渡すか、単に数値としてフォーマットする場合、セル値を文字列として残すため、その数値をセルに戻す前に日付値を数値変数に渡す必要がありました。

Function CellContentCanBeInterpretedAsADate(cell As Range) As Boolean
    Dim d As Date
    On Error Resume Next
    d = CDate(cell.Value)
    If Err.Number <> 0 Then
        CellContentCanBeInterpretedAsADate = False
    Else
        CellContentCanBeInterpretedAsADate = True
    End If
    On Error GoTo 0
End Function

使用例:

Dim cell As Range
dim cvalue as double
Set cell = Range("A1")

If CellContentCanBeInterpretedAsADate(cell) Then
    cvalue = cdate(cell.value)
    cell.value = cvalue
    cell.NumberFormat = "mm/dd/yyyy hh:mm"
Else
    cell.NumberFormat = "General"
End If
1
gtwebb

サイドでvalue(cellref)を使用して、セルを評価します。文字列は「#Value」エラーを生成しますが、日付は数値に解決されます(例:43173)。

0
Craig