VBA技術解説
VBAのVariant型について

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
最終更新日:2020-06-30

VBAのVariant型について


Variantデータ型は、他の何らかのデータ型として明示的に宣言されていない変数で、全てのデータ型を入れることができます。
Variantデータ型には型宣言文字はありません。


Variant型は、特別な値 Empty、Error、Nothing、Null を格納することもできます。
ただし、固定長文字列データ型として格納することはできません。
また、ユーザー定義型を格納することもできません。

Variantデータ型を他の具体的なデータ型の代わりに使用することにより、データをより柔軟に処理できます。
データ型の基本については以下を参照してください。
変数宣言のDimとデータ型|VBA入門
マクロVBA入門者が、まず最初につまずくのが、このDimで変数を宣言することでしょう。変数とは、数値や文字列など(すなわちデータ)を一時的に格納する入れ物 と良く説明されますが、まずはこの考えで良いでしょう。この入れ物には、いろいろなタイプの入れ物があります。
定数宣言のConstと型宣言文字|VBA入門
前回は変数を説明しましたが、変数があれば、当然の定数もありConstで宣言します。つまり、変数は値が変わるもの、定数は値が変わらないものです。定数とは、数値や文字列の代わりに使用される、意味を持たせた名前のことです。

Variant型変数のデータ型を調べる

Variant型変数をローカルウィンドウでみると、Variant/の後に実際に入っているデータの型が表示されます。
VBE(VisualBasicEditor)は、VBAで使われるコードエディタ、コンパイラ、デバッガ、その他の開発支援ツールが統合された開発環境です。ここではローカルウィンドウの使い方について説明します。ローカルウィンドウの表示 メニュー「表示」→「イミィディエイトウィンドウ」初期設定では、コードウィンドウの下にドッキング表示されます。

VBA マクロ Variant

Variant型変数のデータ型をVBAで判定する場合は、VarType関数またはTypeName関数を使用します。

VarType関数は、引数に指定された変数の内部処理形式を表す整数型(Integer)の値を返します。
VarType関数は、引数に指定された変数の内部処理形式を表す整数型(Integer)の値を返します。VarType関数 VarType(varname) varname 必ず指定します。引数varnameには、ユーザー定義型の変数を除く、任意のバリアント型(Variant)の変数を指定します。
TypeName関数は、引数で指定された変数に関する情報を文字列で返します。
TypeName関数は、引数で指定された変数に関する情報を文字列で返します。TypeName関数 TypeName(varname) varname 必ず指定します。引数varnameには、ユーザー定義型の変数を除く、任意のバリアント型(Variant)の変数を指定します。

バリアント型 (Variant) 変数の初期値はEmptyです。
変数がEmpty値であるかの判定には、IsEmpty関数を使用してください。
IsEmpty関数は、変数がEmpty値かどうかを調べ、結果をブール型(True,False)で返します。IsEmpty関数 IsEmpty(expression) expression 必ず指定します。引数expressionには、数式または文字列式を含むバリアント型(Variant)の式を指定します。

Variant型変数のメモリアドレス

変数のアドレス位置にはデータ型を区別する数値が入っています。
詳しくは以下を参照してください。
VBAにおける変数のメモリアドレスについて
VBA開発においてメモリアドレスを気にすることはほとんど無いと思います。気になる場合があるとしたら、・String変数の処理が遅い ・Variant変数の処理が遅い ・ByRef,ByValの違い ・WindowsAPI使用時 このような場合に多少は気になる事があるくらいではないでしょうか。

Variant型どうしの算術演算

Byte、Integer、Long、Singleを格納しているVariant対して算術演算を実行し、結果が元のデータ型の通常の範囲を超えた場合、結果は Variant内で次に大きいデータ型に昇格されます。
ByteはIntegerへ、IntegerはLongへ、LongとSingleはDoubleへ昇格されます。

Dim v1, v2, v3, v4, v5, v6, v7
v1 = CByte(125)
v2 = CByte(125)
v3 = v1 + v2
v4 = v1 * v2
v5 = v1 * v2 * 10
v6 = v1 ^ v2
v7 = v1 / v2
Stop
VBA マクロ Variant

Currency、Decimal、Doubleの値が格納されているVariant変数がそれぞれの範囲を超えると、エラーが発生します。

Variant型どうしの比較演算

バリアントの基になる型に応じて、式の比較方法または比較の結果が変わります。

条件 Then
両方のバリアント型 (Variant) の式が数値 数値比較を実行します。
両方のバリアント型 (Variant) の式が文字列 文字列比較を実行します。
一方のバリアント型 (Variant) の式が数値で、もう一方が文字列 数値式は文字列式よりも小さくなります。
一方のバリアント型 (Variant) の式がEmptyで、もう一方は数値 0をEmpty式として使用して、数値比較を実行します。
一方のバリアント型 (Variant) の式がEmptyで、もう一方が文字列 長さ0の文字列 ("") をEmpty式として使用して、文字列比較を実行します。
両方のバリアント型 (Variant) の式がEmpty 式は等しくなります。

最も注意すべき点は、一方が数値で、もう一方が文字列の場合です。
数値式は文字列式よりも小さくなります。

Dim v1, v2
v1 = 123
v2 = "120"
Debug.Print v1 < v2
Debug.Print v1 = v2
Debug.Print v1 > v2

上記VBAにおいては、実際の数値に関係なく常に、
True ・・・ 左辺が数値式なのでTrueになります。
False
False
このように数値式は常に小さく判定されます。

RangeのValueプロパティの比較

RangeのValueプロパティはVariantです。
従ってVariantの比較になるので注意が必要です。

VBA マクロ Variant
A1は数値、A2は文字列になっています。

VBA マクロ Variant

Dim v
v = "123"
Debug.Print Range("A1").Value = Range("A2").Value
Debug.Print Range("A1").Value = v
Debug.Print Range("A2").Value = v

数値式は文字列式よりも小さくなりますので、この結果は、
False
False
True ・・・ 文字列式どうしの比較
となります。

つまり、Valueは単純比較できません。
文字列を数値変換するには、
CLng関数
CLng関数は、引数をLong型(長整数型)に変換します。CLng関数 CLng(expression) 引数expressionには任意の文字列式または数式を指定します。この引数は必ず指定します。引数がLong型(長整数型)に変換できない場合はエラーとなります。
CDbl関数
CDbl関数は、引数をDouble型(倍精度浮動小数点数型)に変換します。CDbl関数 CDbl(expression) 引数expressionには任意の文字列式または数式を指定します。この引数は必ず指定します。
これらを使いますが、そもそも数値に変換できない場合はこれらの関数がエラーとなってしまいます。
そこで、事前に数値変換可能かを、IsNumeric関数を使い判定しておきます。
IsNumeric関数は、式が数値として評価できるかどうかを調べ、結果をブール型(True,False)で返します。IsNumeric関数 IsNumeric(expression) expression 必ず指定します。引数expressionには、数式または文字列式を含むバリアント型(Variant)の式を指定します。
さらに、そもそもエラー値の判定は、IsError関数で行う必要があります。
引数の式がエラー値かどうかを示すブール型(Boolean)の値を返します。IsError関数は、引数の式がエラーを示す場合にTrueを返します。それ以外の場合は、Falseを返します。IsError関数は、数式がエラーを表しているかどうかを判断するために使用されます。

Sub test()
  Debug.Print CompareValue(Range("A1"), Range("A2"))
End Sub

Function CompareValue(rng1 As Range, rng2 As Range)
  'エラー値の場合はFalseを返す
  If IsError(rng1.Value) Or IsError(rng2.Value) Then
    CompareValue = False
    Exit Function
  End If
  
  '両方数値の場合は数値比較する
  If IsNumeric(rng1.Value) And IsNumeric(rng2.Value) Then
    If CDbl(rng1.Value) = CDbl(rng2.Value) Then
      CompareValue = True
    Else
      CompareValue = False
    End If
    Exit Function
  End If
  
  '文字列比較
  If rng1.Value = rng2.Value Then
    CompareValue = True
  Else
    CompareValue = False
  End If
End Function

ユーザー定義型(Type)とバリアント(Variant)変数

ユーザー定義型をバリアント(Variant)変数に代入するとエラーとなります。

VBA マクロ Variant

VBAリファレンスには、
(Variant 型はユーザー定義型をサポートするようになりました)。
このように書かれていますが、
これは、ActiveXプロジェクトやタイプライブラリの構造体の事をさしていると思われます。
VBA内で定義した構造体を、バリアント(Variant)変数に代入することはできません。

Variant型の配列

通常の配列には、同じデータ型しか入れることはできません。

Dim n(1 To 3) As Long

この変数nの各要素には、数値または数値変換可能な文字しか代入できません。
しかし、Variant型の場合は、任意のデータ型を入れることができます。

Dim n(1 To 3) As Variant
n(1) = 123
n(2) = 1.23
n(3) = "ABC"
Stop

VBA マクロ Variant

配列をVariant型の仮引数に渡す

配列を引数に指定する場合は、ByRef(参照渡し)が強制されます。
ByValで配列を指定した場合は、赤字のコンパイルエラーとなります。

VBA マクロ Variant

しかし、仮引数をVariantで直接受け取る場合はByValで受け取ることができます。

Sub test()
  Dim str(2) As String
  str(0) = "A": str(1) = "B": str(2) = "C"
  Dim v
  v = fnc(str)
  Stop
End Sub

Function fnc(ByVal v) As Variant
  v(0) = "Z"
  fnc = v
End Function

VBA マクロ Variant



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

Variantの数値型と文字列型の比較|エクセル雑感(7月1日)
VBAのVariant型について|VBA技術解説(6月30日)
VBAのString型の最大文字数について|エクセル雑感(6月20日)
VBAで表やグラフをPowerPointへ貼り付ける|VBAサンプル集(6月19日)
アクティブシート以外の表示(Window)に関する設定|VBA技術解説(6月17日)
マクロ記録での色のマイナス数値について|エクセル雑感(6月16日)
ツイッター投稿用に文字数と特定文字で区切る|エクセル雑感(6月15日)
日付の謎:IsDateとCDate|エクセル雑感(6月14日)
IFステートメントの判定|エクセル雑感(6月13日)
インクリメンタルサーチの実装|ユーザーフォーム入門(6月12日)


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

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




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


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



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