データの取得


セルにどんなデータが入力されているかを調べるには、データの入力と同じようにRangeオブジェクトのValueプロパティを参照します。次のコードは、セルA2に入力されているデータを画面に表示します。

Sub Sample1()
    MsgBox Range("A2").Value
End Sub

もちろん、データを入力するときと同じようにValueプロパティを省略することもできます。では、データの入力と同じように、複数のセルに入力されているデータを同時に取得することもできるのでしょうか。もちろんできます。しかし、データの入力ほど簡単ではありません。次のコードは、セル範囲A2:A5に入力されているデータを配列bufに取り込みます。

Sub Sample2()
    Dim buf As Variant, n As Long
    buf = Range("A2:A5").Value
    n = InputBox("何番目のセル?(1~4)")
    MsgBox buf(n, 1)
End Sub

要素数の不明な配列を使用するときはバリアント型で宣言すると便利です。Sample2は、変数bufにセル範囲A2:A5のValueプロパティを配列として格納し、InputBoxで指定された番号の要素を画面に表示しています。MsgBoxの引数でわかるように、セルまたはセルのデータを配列に格納すると、その配列は2次元配列になります。取り込んだ範囲が1列(A2:A5)でも2次元配列になるので注意してください。

上の説明を理解できない方は、複数セルのデータを一気に取得しようなどと思わないことです。そんな無茶をしないで、セルのデータを1つずつ取得したとしても、VBAは十分高速です。

取得したデータを変数に入れる

マクロでセルのデータを取得する場合、その取得したデータを後で使うケースが多いです。そんなときは、セルのデータを一度変数に入れておくと便利です。セルのデータを変数に入れるときは、使用する変数の型に留意してください。

セルA2に「123」という数値データが入力されているとします。次のコードは、セルA2のデータを画面に表示します。

Sub Sample3()
    Dim buf As Long
    buf = Range("A2")
    MsgBox buf
End Sub

セルA2のデータは数値でした。そこで変数bufを長整数型で宣言して、数値を格納しています。これは何も問題ありません。では、変数bufを文字列型(String)で宣言するとどうなるでしょう。

Sub Sample4()
    Dim buf As String
    buf = Range("A2")
    MsgBox buf
End Sub

こちらも問題なく動作します。文字列型で宣言された変数bufに数値データを格納しようとすると、Excelが自動的に「数値→文字列」の型変換してくれるのです。な~んだ…ぢゃ心配ないや(^_^) と喜ぶのは早計です。セルに「田中」のような文字列が入力されていた場合、次のように「文字列→数値」の型変換は行われませんのでエラーになります。

Sub Sample5()
    Dim buf As Long
    buf = Range("A2")   ''←「田中」
    MsgBox buf
End Sub

セルに入力されているデータが、数値なのか文字列なのかがわからないと。それでも、そのセルのデータを変数に入れたいと。そんなときは、変数の型をバリアント(Variant)型で宣言します。

Sub Sample6()
    Dim buf As Variant
    buf = Range("A2")
    MsgBox buf
End Sub

データのタイプを調べる

安全なマクロを望むなら、セルに入力されているデータのタイプを調べてから変数に格納しましょう。また、変数に格納するとき以外でも、セルにどんなタイプのデータが入力されているかを判定すべきケースがあります。ここでは、セルに入力されているデータのタイプを判定する方法を解説します。

セルのデータが数値かどうかを判定するには、IsNumeric関数を使います。IsNumeric関数は、引数に指定した値が数値のときTrueを返します。

Sub Sample7()
    Dim buf As Long
    If IsNumeric(Range("A2")) = True Then
        buf = Range("A2")
    Else
        MsgBox "セルA2は数値が入力されていません"
    End If
End Sub

セルのデータが日付(かどうかを判定するには、IsDate関数を使います。IsDate関数は、引数に指定した値が日付のときTrueを返します。

Sub Sample8()
    Dim buf As Date
    If IsDate(Range("A2")) = True Then
        buf = Range("A2")
    Else
        MsgBox "セルA2は日付が入力されていません"
    End If
End Sub

日付データ(シリアル値)を格納する変数は、Date型で宣言するといいです。シリアル値の実体は連続した数値ですから、長整数(Long)型の変数に格納することもできますが、両者は"取り出した結果"が異なります。

Sub Sample9()
    Dim buf1 As Long, buf2 As Date
    buf1 = Range("A2")
    buf2 = Range("A2")
    MsgBox buf1 & vbCrLf & buf2
End Sub

このような「Is○○関数」には次の関数があります。

関数名 用途
IsArray関数 配列のときTrueを返します
IsDate関数 日付のときTrueを返します
IsError関数 エラーのときTrueを返します
IsMissing関数 省略可能引数が省略されたときTrueを返します
IsNull関数 Null値のときTrueを返します
IsNumeric関数 数値のときTrueを返します
IsObject関数 オブジェクトのときTrueを返します

一般的に、IsNull関数を使うことは、ほとんどありません。IsMissing関数は、省略可能な引数を定義したプロシージャで、省略可能な引数が「省略されたか?」の判定で使います。そうしたプロシージャを定義しないのなら、使う機会はありません。IsObject関数は、バリアント型変数にオブジェクトが格納されているかどうかを判定するときに使います。本コンテンツのテーマである「セルに入力されているデータのタイプ」を判定するのなら、IsNumeric関数、IsDate関数あたりを使うことが多いです。なお、「文字列かどうか」を判定するIsText関数はありません。

もっと確実に、セルデータのタイプを調べるには、TypeName関数を使うと便利です。TypeName関数は、どんなタイプのデータも格納できるバリアント型変数に、どんなタイプの値が格納されているかを調べる関数です。

Sub Sample10()
    Dim buf As Variant, msg As String
    buf = 100           ''数値を格納
    msg = msg & buf & " → " & TypeName(buf) & vbCrLf
    buf = "tanaka"      ''文字列を格納
    msg = msg & buf & " → " & TypeName(buf) & vbCrLf
    buf = #1/9/2010#    ''日付を格納
    msg = msg & buf & " → " & TypeName(buf) & vbCrLf
    MsgBox msg
End Sub

このTypeName関数で、セルの値(Valueプロパティ)を調べることで、セルに入力されているデータの形式を判定できます。

Sub Sample11()
    Dim msg As String
    msg = msg & TypeName(Range("A2").Value) & vbCrLf
    msg = msg & TypeName(Range("A3").Value) & vbCrLf
    msg = msg & TypeName(Range("A4").Value) & vbCrLf
    MsgBox msg
End Sub

数値が、IntegerだったりDoubleだったりしますが、これはどちらも数値を表しています。詳しくは、VBAのデータ型を学習するといいですが、よく分からないのなら「とりあえず、どっちも数値を表すんだ!そうなんだ!」と納得してください。

セルのデータをTypeName関数で調べるとき、Valueプロパティを省略してはいけません。TypeName(Range("A2")) とValueプロパティを省略すると、TypeNameは「Rangeオブジェクトの型」を返します。

セルA2に日付データ(シリアル値)が入力されているかどうかは、次のように判定します。

Sub Sample12()
    If TypeName(Range("A2").Value) = "Date" Then
        MsgBox "日付データです"
    Else
        MsgBox "日付データではありません"
    End If
End Sub