2016-06-17 5 views
2

バリアントデータ型に関するGoogleにはたくさんのものがあります。大抵、彼らは"Avoid using it too much and here's why"または"It can hold any type of data"のようなものを私が理解するものと言う。しかし、私はまだそれらをいつ使うべきか完全に理解していません。誰かが簡潔に説明することができますし、もっと重要なのは、バリアントデータ型のベスト・ユースの例を提供できますか(明示的に宣言された変数ではなく、関数にバリアントを渡す例さえ)?VBAのバリアントデータ型とそれを積極的に使用

+0

私はフルタイムのVB6プログラマーで7年間、意識的にVariantを使用することに決めた時間は正確に0でした。気まぐれな振る舞いや、魅力的なコードをはるかに上回る魔法の能力の欠点は、あなたがそれらのコードを書くことができるかもしれないので、そのコードを悪夢のように保つことになるでしょう。 – Jeremy

答えて

4

通常、できる限り小さなメモリ変数を使用します。バリアントが最も大きいので、タイプミスがない場合にのみ使用してください。ここで、いくつかの例

アレイ()

Array関数は配列を含むバリアントを返しています。 Arrayを使用する唯一の方法は、バリアントに割り当てることです。範囲

あなたがセルにデータの束を記述する必要があります場合に

vArr = Array(1, "a", True) 

割り当て配列は、それが配列にそれらを入れて、一度ではなく、一つのセルでそれらすべてを書くこと方法高速です時間。データがすべて同じデータ型の場合は、適切に型付けされた配列を使用します。しかし、すべてが同じデータでない場合は、多分Variantsの配列を使用する必要があります。

Dim vaWrite(1 To 2, 1 To 2) As Variant 

vaWrite(1, 1) = 1 
vaWrite(1, 2) = "Bob" 
vaWrite(2, 1) = 2 
vaWrite(2, 2) = "Tim" 

Range("A1").Resize(2, 2).Value = vaWrite 

そして、他の道を行くが、 - 配列の範囲は、細胞内にかかわらず、データ型のVariantを必要と

vArr = Range("A1:C10").Value 

ワークシート関数

いくつかの(すべての?)ワークシート関数をすることができます正常な値が何であれ、エラーを返す。保持できる唯一のデータ型(DoubleやErrorなど)はバリアントです。

vRes = Application.WorksheetFunction.Match(...) 

これは私が考えることができる3つの例です。もっとあるかもしれない。

2

Variant型は、他の変数と比べてメモリに多くのスペースを取る(テストするhere you'll find the code for the macro、私はちょうどバリアントのためのルーチンを追加しました)

enter image description here
このため劇であってもよく、他のいくつかの要因がありますが、それはです
1.優れたコードを明示的に説明する必要があります。バリアントを使用すると、最初に定義する必要のある内容が混乱する可能性があります。
2.バリアントは、このように、それはあなたにコーディングすると、あなたがオブジェクトのIE用不動産が表示されないことがあり、より多くの時間がかかります、オブジェクトの不動産を取得しないことがあります。

Dim myRange as Range 
Set myRange = Range("A1:A10") 
myRange. 'I can see the properties of the object! 
Dim myRange as Variant 
Set myRange = Range("A1:A10") 
myRange. 'I can't see what properties this may have in this context! 


私は与えたいと思いました本当の文脈なぜそれらを避けるために私は両方に同意すると思う - 。
今、いつ使用しますか?これは議論の対象となる場合もありますが、入力を制御できない場合にはとなりました。
これはどうして起こりますか?
例1:TextBox値をユーザー入力にして、ユーザーが単語を入力したくない場合は(数字を入力するたびにブロックする必要があります)、TextBoxだけでブロックすることはできません。何をすべきか?

Private Sub TextBox_Value_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger) 
Dim ChrPressed As Variant 
    ChrPressed = Chr(KeyAscii) 
    Select Case ChrPressed 
     Case IsNumeric(ChrPressed) 
     Me.TextBox_Value.Value = Me.TextBox_Value.Value & ChrPressed 
     KeyAscii = 0 
     Case "0" 
     Me.TextBox_Value.Value = Me.TextBox_Value.Value & ChrPressed 
     KeyAscii = 0 
    End Select 
End Sub 
ChrPressedは、ユーザーがまだ単語のキーを押すことができるが、我々が押されているものを定義しようと私たちのコード内で研究を行っている - その他のアプローチは、我々の経験は、その滑らかではなくなってユーザーにエラーデバッガにつながる可能性がされているので、変異体である

- 。
2. late or early bindingを避けるために適切な参照を追加したくない場合は、それらの関数が変数自体で許可されていることがわかっています。これは、後で遅くなる可能性のあるいくつかの回避策を回避するのにも役立ちます、(私はそのように行うならば、私は問題に直面していないが)事前バインディング:多数のデータを持っているし、あなたがそのような

Dim ArrayForTest() as Variant 
Select Case ArrayForTest(ArrayElement) 
Case IsNumeric(ArrayForTest(ArrayElement)) 
Case IsString(ArrayForTest(ArrayElement)) 'Just representative not the real way to do so 
としてそれらを制御したいことができ

Sub ImportFile() 
Dim MyFile As Variant 
MyFile = Application.GetOpenFilename("Import File*.CSV", Title:="CSV Data") 
    If MyFile = False ... 


3.配列


4.あなたが方法を見つけられていない要素内の要素oそれらを適切に呼び出すと、後でそのことを知るか、適切な方法でパフォーマンスに影響を与えることはありません。

Sub Graphs_makegraph(XValues As Variant, ChartStyle... 
ActiveSheet.Shapes.AddChart2(ChartTypeNumber, ChartStyle).Select 
... 
ActiveChart.FullSeriesCollection(1).XValues = XValues 


あなたはExcelが「物事を扱う」せているので、ほとんどのプログラマが良いコーディング練習はあなたがすべてがOOP定義として定義されているということです、このアプローチが好きではない、しかし、私はそのエクセル汎用性を見つけますその速度を上げてソリューションをスピードアップし、いくつかの.class/interfacesを保存してから、もう一度メインクラスに戻って、MVPプログラミングで別のやり方をしなければならないだろう。 OTとして:私たちが厳しくしたいのであれば、私たちの本来の意図をコンパイラの干渉を避けるためにasm languageにプログラムする必要があります。

0

「...明示的に宣言された変数とは対照的に、関数にバリアントを渡す例」

ジョエル・スポルスキはこのhereの一形態に言及し、私はそれが非常に便利なシミュレートすることを見つけますVariant型パラメータを使用してメソッドオーバーロードを実行します。それは文字列またはwsNamesパラメータの文字列の配列、次の呼び出しの両方があるのいずれかを受け付けますので

Sub addSheets(wb As Workbook, ByVal wsNames As Variant) 
'Adds one or more worksheets (wsNames) to a workbook (wb) 

    Dim ws As Worksheet 
    Dim i As Long 

    If Not IsArray(wsNames) Then 
     wsNames = Array(wsNames) 
    End If 

    For Each ws In wb.Sheets 
     For i = LBound(wsNames) To UBound(wsNames) 
      If ws.Name = wsNames(i) Then 
       MsgBox "Error: Sheet " & wsNames(i) & " already exists in workbook" 
       Stop 
       Exit Sub 
      End If 
     Next 
    Next 

    For i = LBound(wsNames) To UBound(wsNames) 
     Dim newWS As Worksheet 
     Set newWS = wb.Worksheets.Add 
     newWS.Name = wsNames(i) 
    Next 

End Sub 

はたとえば、ワークブックにワークシートを追加して、このマクロを見てみましょう有効:単一のパラメータに対して複数のデータタイプを受け入れるように、個々のメソッドを強制する(「IsNumeric関数」、「IsDate関数」などのように、同様のもの)の変種と「でIsArray」方法を用いることにより

'Adds sheet called "TestWS1" to the active workbook 
Call addSheets(ActiveWorkbook,"TestWS1") 
'Adds sheets called "TestWS2" and "TestWS3" to the active workbook 
Call addSheets(ActiveWorkbook, Array("TestWS2","TestWS3")) 

、することができます類似のtaを達成するための別個のメソッドを作成する必要はありません1つのWSを追加する場合は「addSheet」、複数の場合は「addSheets」を追加します。

関連する問題