title: Determining the full type of a variable
body: <p>By the <em>full type</em> of a variable I mean the sort of information that you get in the immediate window:</p>
  
  <p><a href="https://i.stack.imgur.com/TKAfm.gif"><img src="https://i.stack.imgur.com/TKAfm.gif" alt="enter image description here"></a></p>
  
  <p>I would like to determine the type information dynamically using VBA. The function <code>TypeName()</code> doesn't do what I want since it returns the <em>subtype</em> of a variant and doesn't distinguish between e.g. a variant variable holding a range, an object variable holding a range, and a range variable holding a range.</p>
  
  <p>As a preliminary step, I wrote a function which detects if a variant is passed to it. It works by exploiting pass-by-reference semantics. The code does things with its argument that can only be done with a variant and will thus trigger an error if the passed variable isn't actually a variant:</p>
  
  <pre><code>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 &gt; 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
  </code></pre>
  
  <p>Based on this, I wrote:</p>
  
  <pre><code>Function FullType(var As Variant) As String
      If IsVariant(var) Then
          FullType = "Variant/" &amp; TypeName(var)
      Else
          FullType = TypeName(var)
      End If
  End Function
  </code></pre>
  
  <p>Testing code:</p>
  
  <pre><code>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: " &amp; FullType(v1)
      Debug.Print "i: " &amp; FullType(i)
      Debug.Print "v2: " &amp; FullType(v2)
      Debug.Print "Ob: " &amp; FullType(Ob)
      Debug.Print "R: " &amp; FullType(R)  
  End Sub
  </code></pre>
  
  <p>Output:</p>
  
  <pre><code>v1: Variant/Integer
  i: Integer
  v2: Variant/Range
  Ob: Range
  R: Range
  </code></pre>
  
  <p>This is almost what I want -- but doesn't distinguish between an object variable holding a range and a range variable holding a range. I've tried to write a function called <code>IsTypeObject</code> which works similarly to <code>IsVariant</code> but can't seem to get it to work:</p>
  
  <pre><code>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 &gt; 0 Then
              isGeneric = False
          Else
              isGeneric = True
          End If
      On Error GoTo 0
  
      Set var = temp
      IsTypeObject = isGeneric
  End Function
  </code></pre>
  
  <p>Test:</p>
  
  <pre><code>Sub test()
      Dim R As Range
      Set R = Range("A1")
      Debug.Print IsTypeObject(R)
  End Sub
  </code></pre>
  
  <p>But this prints <code>True</code> even though I would think that the same pass-by-reference semantics which makes <code>IsVariant</code> work should also make <code>IsTypeObject</code> work (you can't assign a collection to a range). I've tried various tweaks but can't seem to distinguish between the generic object variables and specific object variables such as range variables.</p>
  
  <p>So -- any ideas for how to dynamically get the full type of a variable? (The motivation is as part of a debug-log utility)</p>