Last active
          March 19, 2019 09:48 
        
      - 
      
- 
        Save wqweto/7952402 to your computer and use it in GitHub Desktop. 
    Scripting.Dictionary supports For Each enumeration through IEnumVARIANT on DISPID_NEWENUM, not by using Variant array default property.
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | Option Explicit | |
| Private Const LOCALE_SYSTEM_DEFAULT As Long = &H800 | |
| Private Const S_OK As Long = 0 | |
| Private Type DISPPARAMS | |
| rgPointerToVariantArray As Long | |
| rgPointerToLongNamedArgs As Long | |
| cArgs As Long | |
| cNamedArgs As Long | |
| End Type | |
| Private Type EXCEPINFO | |
| wCode As Integer | |
| wReserved As Integer | |
| Source As String | |
| Description As String | |
| HelpFile As String | |
| dwHelpContext As Long | |
| pvReserved As Long | |
| pfnDeferredFillIn As Long | |
| sCode As Long | |
| End Type | |
| Public Enum UcsInvokeCallEnum | |
| ucsIclMethod = 1 | |
| ucsIclPropGet = 2 | |
| ucsIclPropLet = 4 | |
| ucsIclPropSet = 8 | |
| End Enum | |
| Public Function DispInvoke( _ | |
| ByVal pDisp As IVbDispatch, _ | |
| Name As Variant, _ | |
| Optional ByVal CallType As UcsInvokeCallEnum = ucsIclMethod, _ | |
| Optional Result As Variant, _ | |
| Optional Args As Variant) As Boolean | |
| Const DISPID_PROPERTYPUT As Long = -3 | |
| Dim IID_NULL As VBGUID | |
| Dim lDispID As Long | |
| Dim uParams As DISPPARAMS | |
| Dim uInfo As EXCEPINFO | |
| Dim aParams() As Variant | |
| Dim lNamedParam As Long | |
| Dim lIdx As Long | |
| Dim lParamCount As Long | |
| Dim lArgErr As Long | |
| Dim lPtrResult As Long | |
| If pDisp Is Nothing Then | |
| Exit Function | |
| End If | |
| '--- get disp id | |
| If IsNumeric(Name) Then | |
| lDispID = CLng(Name) | |
| Else | |
| If pDisp.GetIDsOfNames(IID_NULL, CStr(Name), 1, LOCALE_SYSTEM_DEFAULT, lDispID) <> S_OK Then | |
| Exit Function | |
| End If | |
| End If | |
| '--- process params | |
| If Not IsMissing(Args) Then | |
| If IsArray(Args) Then | |
| lParamCount = UBound(Args) - LBound(Args) | |
| ReDim aParams(0 To lParamCount) | |
| For lIdx = 0 To lParamCount | |
| Call VariantCopy(aParams(lParamCount - lIdx), Args(lIdx)) | |
| Next | |
| Else | |
| ReDim aParams(0 To 0) | |
| Call VariantCopy(aParams(0), Args) | |
| End If | |
| With uParams | |
| .cArgs = lParamCount + 1 | |
| .rgPointerToVariantArray = VarPtr(aParams(0)) | |
| End With | |
| If CallType = ucsIclPropLet Or CallType = ucsIclPropSet Then | |
| lNamedParam = DISPID_PROPERTYPUT | |
| With uParams | |
| .cNamedArgs = 1 | |
| .rgPointerToLongNamedArgs = VarPtr(lNamedParam) | |
| End With | |
| End If | |
| End If | |
| If CallType = ucsIclPropGet Or CallType = ucsIclMethod And Not IsMissing(Result) Then | |
| Result = Empty | |
| lPtrResult = VarPtr(Result) | |
| End If | |
| DispInvoke = (pDisp.Invoke(lDispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, CallType, uParams, ByVal lPtrResult, uInfo, lArgErr) = S_OK) | |
| End Function | |
| Private Sub Command1_Click() | |
| Const DISPID_NEWENUM As Long = -4 | |
| Dim pDict As Object | |
| Dim vResult As Variant | |
| Set pDict = CreateObject("Scripting.Dictionary") | |
| If DispInvoke(pDict, DISPID_NEWENUM, ucsIclMethod, vResult) Then | |
| Debug.Print TypeName(vResult) | |
| End If | |
| End Sub | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment