Variant data type in VBA and positive uses of it
Google上有很多关于变体数据类型的东西。 我通常会说
通常,请始终使用您可以使用的最小内存变量。变体是最大的,因此,只有在没有更好类型的变体时才应使用它。这里有些例子
Array()
1 | vArr = Array(1,"a", True) |
将数组分配给范围
如果必须将一堆数据写入单元格,则将它们放入数组并一次全部写入而不是一次写入一个单元的方法要快得多。如果您的数据都是相同的数据类型,请使用正确类型的数组。但是,如果不是全部相同的数据,则可能需要使用一组Variants。
1 2 3 4 5 6 7 8 | 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,而不管单元中的数据类型如何
1 | vArr = Range("A1:C10").Value |
工作表功能
一些(全部?)工作表函数可以返回错误以及它们的正常值。可以保存例如Double和Error的唯一数据类型是Variant。
1 | vRes = Application.WorksheetFunction.Match(...) |
这是我能想到的三个例子。可能还有更多。
变量类型比任何其他变量占用更多的内存空间(在这里,您将找到宏的代码进行测试,我只是为变量添加了例程)
可能还有其他一些因素在起作用,这是一个非常主观的话题,因为这是我的个人经验:
1.一个好的代码必须被明确地解释,使用variant可能导致首先应该定义的内容混乱。
2.变体可能无法获得对象的真实属性,因此,它将花费更多时间进行编码,并且您可能看不到对象IE的真实属性:
1 2 3 4 5 6 | 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不能阻止它,所以,应该做?
1 2 3 4 5 6 7 8 9 10 11 12 | 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是Variant的地方,因为用户仍然可以按下单词键,但是我们将定义所按下的内容并在代码内部进行研究-其他方法可能会导致错误调试器给用户,使我们的体验变得不那么顺畅。
2.如果您不想添加适当的引用以避免后期绑定或早期绑定,但是您知道变量本身允许使用这些函数,那么这也有助于避免将来可能需要执行的一些变通方法迟了,早绑定了(尽管我没有那样做,但是我没有遇到任何问题):
1 2 3 4 | Sub ImportFile() Dim MyFile As Variant MyFile = Application.GetOpenFilename("Import File*.CSV", Title:="CSV Data") If MyFile = False ... |
3.可以包含大量数据的数组,而您想这样控制它们
1 2 3 4 | 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 |
4.元素中的元素您没有找到正确调用它们的方法,以后您将学习或不会真正影响与正确调用它们的方法相关的性能。
1 2 3 4 | 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语言编程,以避免编译器的任何干扰,这是我们的初衷。
"...an example of passing a variant to a function as opposed to an explicitly declared variable"
Joel Spolsky在这里提到了这种形式的一种形式,但是我发现通过使用Variant类型的参数来模拟方法重载非常有用。
例如,看一下将工作表添加到工作簿的此宏:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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 |
因为它将接受wsNames参数的字符串或字符串数组,所以以下两个调用均有效:
1 2 3 4 | '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")) |
通过使用变体和" IsArray"方法(以及类似的方法,例如" IsNumeric"," IsDate"等)来强制单个方法接受单个参数的多种数据类型,您可以避免必须创建单独的方法来完成相似的操作 任务(例如," addSheet"用于添加一个WS," addSheets"用于添加多个WS)。