- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
变量的完整类型是指您在即时窗口中获得的信息类型:
我想使用 VBA 动态确定类型信息。函数TypeName()
不做我想要的,因为它返回变体的子类型并且不区分例如一个变量变量保存一个范围,一个对象变量保存一个范围,一个范围变量保存一个范围。
作为初步步骤,我编写了一个函数来检测是否有变体传递给它。它通过利用传递引用语义来工作。该代码使用其参数执行只能使用变体完成的操作,因此如果传递的变量实际上不是变体,则会触发错误:
Function IsVariant(var As Variant) As Boolean
Dim temp As Variant
Dim isVar As Boolean
If IsObject(var) Then
Set temp = var
Else
temp = var
End If
On Error Resume Next
Set var = New Collection
var = "test"
If Err.Number > 0 Then
isVar = False
Else
isVar = True
End If
On Error GoTo 0
If IsObject(temp) Then
Set var = temp
Else
var = temp
End If
IsVariant = isVar
End Function
Function FullType(var As Variant) As String
If IsVariant(var) Then
FullType = "Variant/" & TypeName(var)
Else
FullType = TypeName(var)
End If
End Function
Sub TestTypes()
Dim R As Range
Dim Ob As Object
Dim i As Integer
Dim v1 As Variant
Dim v2 As Variant
v1 = 10
i = 10
Set v2 = Range("A1")
Set Ob = Range("A2")
Set R = Range("A3")
Debug.Print "v1: " & FullType(v1)
Debug.Print "i: " & FullType(i)
Debug.Print "v2: " & FullType(v2)
Debug.Print "Ob: " & FullType(Ob)
Debug.Print "R: " & FullType(R)
End Sub
v1: Variant/Integer
i: Integer
v2: Variant/Range
Ob: Range
R: Range
IsTypeObject
的函数其工作方式类似于
IsVariant
但似乎无法让它工作:
Function IsTypeObject(var As Variant) As Boolean
Dim temp As Variant
Dim isGeneric As Boolean
If (Not IsObject(var)) Or IsVariant(var) Then
IsTypeObject = False
Exit Function
End If
Set temp = var
On Error Resume Next
Set var = New Collection
Set var = ActiveWorkbook
If Err.Number > 0 Then
isGeneric = False
Else
isGeneric = True
End If
On Error GoTo 0
Set var = temp
IsTypeObject = isGeneric
End Function
Sub test()
Dim R As Range
Set R = Range("A1")
Debug.Print IsTypeObject(R)
End Sub
True
即使我认为相同的传递引用语义使
IsVariant
工作也应该使
IsTypeObject
工作(您不能将集合分配给范围)。我尝试了各种调整,但似乎无法区分通用对象变量和特定对象变量(例如范围变量)。
最佳答案
是的,您可以这样做:它需要对指针和“取消引用”的概念有一点了解......
这是执行此操作的代码:
Public Function VariantTypeName(ByRef MyVariant) As String
' Returns the expanded type name of a variable, indicating
' whether it's a simple data type (eg: Long Integer), or a
' Variant containing data of that type, eg: "Variant/Long"
Dim iType As Integer
Const VT_BYREF = &H4000&
CopyMemory iType, MyVariant, 2
' iType now contains the VarType of the incoming parameter
' combined with a bitwise VT_BYREF flag indicating that it
' was passed by reference. In other words, it's a pointer,
' not the data structure of the variable (or a copy of it)
' So we should have VT_BYREF - and we'd always expect to
' when MyVariant is a Variant, as variants are a structure
' which uses a pointer (or pointers) to the stored data...
' However, the VBA implementation of a variant will always
' dereference the pointer - all the pointers - passing us
' straight to the data, stripping out all that information
' about references...
If (iType And VT_BYREF) = VT_BYREF Then
' Bitwise arithmetic detects the VT_BYREF flag:
VariantTypeName = TypeName(MyVariant)
Else
' No VT_BYREF flag. This is a Variant, not a variable:
VariantTypeName = "Variant/" & TypeName(MyVariant)
End If
End Function
CopyMemory
API 函数的声明在后面几段)。
ByRef
中。和
ByVal
我们在声明函数时用于传入参数的标识符。
VarType
和
TypeName
检测我们已经被传递了一个值,或者一个对它的引用;甚至是对引用的引用,对引用的引用。
varType
从来没有告诉我们我们通过指针定义的连续地址通过几跳间接到达那里。
VT_BYREF
表示这是对存储数据类型的引用或指针,而不是数据本身。所以这段代码会可靠地告诉你你的 var 类型,当我们不希望它不是时,稍微横向思考一下克服 VBA 是有帮助的:
Public Function DereferencedType(ByRef MyVar) As Long
Dim iType As Integer
Const VT_BYREF = &H4000&
' The first two bytes of a variable are the type ID with a
' bitwise OR to VT_BYREF if we were passed the variable by
' reference... Which is exactly what this function does:
CopyMemory iType, MyVar, 2
DereferencedType = iType ' Mod VT_BYREF
'Use "Mod VT_BYREF" to separate out the type if you want
End Function
乍一看,这个函数似乎是弄巧成拙:我通过引用传递变量 - 变体或简单类型,所以它总是会与
VT_BYREF
结合使用。 .无论如何,我已经注释掉了“模”算法......
Dim str1 As String
str1 = "One Hundred"
Debug.Print "String Variable: " & DereferencedType(str1)
...你得到输出
vbString OR VT_BYREF
:
String Variable: 16392
Dim varX As Variant
varX = "One Hundred"
Debug.Print "String Variant: " & DereferencedType(varX)
...你得到输出:
String Variant: 8
VT_BYREF
对返回的值进行 OR 或 NOT 操作编码。 , 为您的 Variant/String 和 Variant/Long 输出的扩展字符串描述符提供“Variant/”标签。
VariantTypeName
]
#If VBA7 And Win64 Then ' 64 bit Excel under 64-bit Windows
' Use LongLong and LongPtr
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As LongLong)
#ElseIf VBA7 Then ' 64 bit Excel in all environments
' Use LongPtr only, LongLong is not available
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)
#Else ' 32 bit Excel
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)
#End If
VarX is set equal to a range object variable: varX: type=8204 Range Dereferenced Type=9 rng1: type=8204 Range Dereferenced Type=16393
VarX is set equal to a range object's value, a 2-dimensional array: varX: type=8204 Variant() Dereferenced Type=8204 arr1: type=8204 Variant() Dereferenced Type=8204
The array variable is erased to Empty(). Inspect varX: varX: type=8204 Variant() Dereferenced Type=8204 arr1: type=8204 Variant() Dereferenced Type=8204
VarX is set equal to an 'object' variable, which has been set to a range: varX: type=8204 Range Dereferenced Type=9 obj1: type=8204 Range Dereferenced Type=16393
Here's the code that generated that, and the full output:
Public Sub TestVar()
Dim varX As Variant
Dim str1 As String
Dim lng1 As Long
Dim rng1 As Excel.Range
Dim arr1 As Variant
Dim obj1 As Object
Debug.Print "Uninitialised:"
Debug.Print
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print vbTab & "str1: type=" & VarType(str1) & vbTab & vbTab & TypeName(str1) & vbTab & "Dereferenced Type=" & DereferencedType(str1)
Debug.Print vbTab & "lng1: type=" & VarType(lng1) & vbTab & vbTab & TypeName(lng1) & vbTab & "Dereferenced Type=" & DereferencedType(lng1)
Debug.Print
varX = "One Hundred"
str1 = "One Hundred"
lng1 = 100
Debug.Print "varX and str1 are populated with the same literal:"
Debug.Print
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print vbTab & "str1: type=" & VarType(str1) & vbTab & vbTab & TypeName(str1) & vbTab & "Dereferenced Type=" & DereferencedType(str1)
Debug.Print vbTab & "lng1: type=" & VarType(lng1) & vbTab & vbTab & TypeName(lng1) & vbTab & "Dereferenced Type=" & DereferencedType(lng1)
Debug.Print
varX = 100
lng1 = 100
Debug.Print "varX and lng1 are populated with the same integer:"
Debug.Print
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print vbTab & "str1: type=" & VarType(str1) & vbTab & vbTab & TypeName(str1) & vbTab & "Dereferenced Type=" & DereferencedType(str1)
Debug.Print vbTab & "lng1: type=" & VarType(lng1) & vbTab & vbTab & TypeName(lng1) & vbTab & "Dereferenced Type=" & DereferencedType(lng1)
Debug.Print
varX = str1
Debug.Print "VarX is set equal to str1:"
Debug.Print
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print vbTab & "str1: type=" & VarType(str1) & vbTab & vbTab & TypeName(str1) & vbTab & "Dereferenced Type=" & DereferencedType(str1)
Debug.Print
varX = lng1
Debug.Print "VarX is set equal to lng1:"
Debug.Print
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print vbTab & "lng1: type=" & VarType(lng1) & vbTab & vbTab & TypeName(lng1) & vbTab & "Dereferenced Type=" & DereferencedType(lng1)
Debug.Print
Set varX = ActiveSheet.Range("A1:C3")
Debug.Print "VarX is set equal to a range:"
Debug.Print
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print
Set rng1 = ActiveSheet.Range("A1:C3")
Set varX = Nothing
Set varX = rng1
Debug.Print "VarX is set equal to a range object variable:"
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print vbTab & "rng1: type=" & VarType(rng1) & vbTab & vbTab & TypeName(rng1) & vbTab & "Dereferenced Type=" & DereferencedType(rng1)
Debug.Print
arr1 = rng1.Value2
Set varX = Nothing
varX = arr1
Debug.Print "VarX is set equal to a range object's value, a 2-dimensional array:"
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print vbTab & "arr1: type=" & VarType(rng1) & vbTab & vbTab & TypeName(arr1) & vbTab & "Dereferenced Type=" & DereferencedType(arr1)
Debug.Print
Erase arr1
Debug.Print "The array variable is erased to Empty(). Inspect varX:"
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print vbTab & "arr1: type=" & VarType(rng1) & vbTab & vbTab & TypeName(arr1) & vbTab & "Dereferenced Type=" & DereferencedType(arr1)
Debug.Print
Set obj1 = ActiveSheet.Range("A1:C3")
Set varX = Nothing
Set varX = obj1
Debug.Print "VarX is set equal to an 'object' variable, which has been set to a range:"
Debug.Print vbTab & "varX: type=" & VarType(varX) & vbTab & vbTab & TypeName(varX) & vbTab & "Dereferenced Type=" & DereferencedType(varX)
Debug.Print vbTab & "obj1: type=" & VarType(rng1) & vbTab & vbTab & TypeName(obj1) & vbTab & "Dereferenced Type=" & DereferencedType(obj1)
Debug.Print
End Sub
关于vba - 确定变量的完整类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33941363/
我有一个 VBA 脚本,可以将数据从一张表复制到另一张表。复制的数据被放入公式中,计算出的数量被复制回原始工作表。我正在尝试获取它,以便 VBA 脚本为每一行执行此操作。我有 1000 行数据。 Su
如何让 excel 在我的“临时”表上列出所有可用的环境变量?下面的代码没有为我返回任何东西...... Sub ListEnvironVariables() Dim strEnviron A
好的,这就是我想要完成的事情:我正在尝试将所有 VBA 代码从“Sheet2”复制到“Sheet 3”代码 Pane 。我不是指将模块从一个模块复制到另一个模块,而是指 Excel 工作表对象代码。
我正在做一个项目来使用 rule-triggered 处理一些传入的 Outlook 邮件。 VBA 代码。 但是,我不想在代码需要更改的任何时候手动更新每个用户收件箱的代码。所以我的想法是把一个文本
我想从另一个代码 VBA 中评论包含 Msg Box 的行。我正在尝试使用 Library VBA EXTENSIBILITY,但我没有找到解决方案。 欢迎任何帮助。 这是我的代码: Sub Comm
我正在尝试编写程序的最后一部分,我需要从 Access 文档中提取数据并将其打印到新的工作簿中。 首先,我将获取产品供应商的名称并创建一个包含每个供应商名称的工作表,然后我想遍历每个工作表并打印每个供
我有一个要求,我试图查找数据中的日期是否大于或等于当前日期,那么它应该显示"is"。 这是我的代码, RDate = Application.WorksheetFunction.if(RSDate>=
我试图想出一个宏来检查单元格中是否存在任何数字值。如果存在数字值,请复制该行的一部分并将其粘贴到同一电子表格内的另一个工作表中。 Sheet1 是包含我所有数据的工作表。我正在尝试查看 R 列中是否有
我有一个具有密码保护(防止未经授权访问宏)的 VBA 宏,它按预期运行。用户单击按钮,宏运行。内容大致如下: Sub sample() ActiveSheet.Unprotect Pass
我想通过VBA删除工作表中包含的VBA代码。目前,我有一个代码可以将工作表复制到新工作簿并从中删除所有图像。但是,这些图像被设置为在代码中的 Worksheet_Activate 上执行操作,每当我轻
我有一个 vba 代码,它指定要查看的特定工作表名称,例如工作表 2, 但是,如果有人忘记将工作表名称更改为sheet2,我可以添加一段动态代码来自动更改调用工作表名称的vba代码吗?例如,从左边算起
VBAExcel 2016 如果执行某些代码后该范围的列数较少,我将尝试动态调整该范围的大小。引用了 MS 文件和各种在线示例,但没有成功。 https://msdn.microsoft.com/en
我在任何地方都找不到这个问题。在 Visual Basic (excel) 中,我可以按 F8 并循环浏览每一行。但是假设我想开始子程序,然后在执行前两行之后,我想跳到第 200 行。到目前为止,我一
这是我昨天的问题的补充,所以我开始一个新问题。基本上,我在 excel 的工作表上得到不同范围的数据,并且数据范围每周都不同,因此最后使用的列和最后使用的行会有所不同。 我想根据名称合并第 3 行和第
我的想法是创建一个函数来传递这样的双数组: Function pass(a() As Double, b() as double) As Boolean Dim i As Integer, j As
我正在使用 vlookup 运行 VBA 代码,但是,它需要几秒钟才能完成,尽管具有行的工作表只有不到 150 行。 滞后主要出现在 col 23 的生成期间。 包含此代码的主工作表有大约 2300
我在 VBA 中有一个小问题,我想将 Range 函数的行和列以 String 格式放置,如下所示: debut = "BH" & LTrim(Str(i)) fin = "DB" &
我正在尝试使用 Visual Basic 编写 Webcrawler。我有一个包含链接的列表,存储在 Excel 中(第 1 列)。然后宏应打开每个链接并将网站中的某些信息添加到 excel 文件中。
我正在尝试自动生成报告(请原谅我缺乏 Excel 经验),但遇到了这个错误。在单元格中显示#NAME。代码应为工作簿另一页上的所有列 E 选择单元格和 COUNTIF <1。这是一个简单的语法错误吗?
我正在使用“Sheet1”上的命令按钮使用 VBA 创建图表,但是该图表正在添加到另一个工作表(“Sheet2”)。 添加图表后,我使用以下代码根据 DataLabel 值对条形图进行着色并更改 Da
我是一名优秀的程序员,十分优秀!