Option Explicit
Function AD_Info(ByVal sGroup_Name As String, Optional bExcludeWildCard As Boolean = True) As Variant
'Based on http://www.mrexcel.com/forum/excel-questions/553062-using-excel-visual-basic-applications-query-active-directory.html
'Get specific AD/LDAP info for a given group.
Const sNoEntry As String = "No Entry"
Dim GroupPaths() As Variant, GroupNames() As Variant, cmd As Object, cn As Object, rs As Object, objGroup As Object, lRecordCount As Long, lRecordTotal As Long
Dim lIndexCount As Long, objMember As Variant, lMemberCount As Long, vArray() As Variant, x As Long, lCurrentMemberCount As Long, lMemberCounter As Long
ReDim vArray(0, 0, 0)
vArray(0, 0, 0) = "Empty Set"
AD_Info = vArray 'Set default value
If sGroup_Name = "" Then Exit Function 'Nothing passed in so exit
'Remove wildcard characters
If bExcludeWildCard Then
sGroup_Name = Replace(sGroup_Name, "*", "")
End If
'Set up ADO query and excute to find group matches
Application.StatusBar = "Searching for Records..."
Set cmd = CreateObject("ADODB.Command")
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open "Provider=ADsDSOObject;"
cmd.CommandText = "SELECT adspath,cn from 'LDAP://" & GetNC & "' WHERE objectCategory = 'Group' and cn = '" & sGroup_Name & "'"
cmd.activeconnection = cn
Set rs = cmd.Execute
'Process the results of the query into arrays
lRecordTotal = -1
On Error GoTo Error_Handler
While rs.EOF <> True And rs.bof <> True
lRecordTotal = lRecordTotal + 1
ReDim Preserve GroupPaths(lRecordTotal)
ReDim Preserve GroupNames(lRecordTotal)
GroupPaths(lRecordTotal) = rs.Fields("adspath").Value 'AD comprehensive info
GroupNames(lRecordTotal) = rs.Fields("cn").Value 'Just the AD group name(s)
rs.movenext
Wend
cn.Close
Set cmd = Nothing
Set cn = Nothing
Set rs = Nothing
If lRecordTotal < 0 Then Exit Function 'AD group is empty or doesn't exist
lIndexCount = 1 'Adjust dimensions as needed
'Process each group found and extract all members
'Get the maximum number of members in the AD group(s) so we can dimension our array
lMemberCount = 0
For lRecordCount = 0 To lRecordTotal
lCurrentMemberCount = GetObject(GroupPaths(lRecordCount)).Members.Count 'Count of items in AD group name
If lCurrentMemberCount > lMemberCount Then lMemberCount = lCurrentMemberCount
Next lRecordCount
If lMemberCount = 0 Then Exit Function 'AD group is empty
ReDim vArray(lRecordTotal, lIndexCount, lMemberCount - 1) 'Adjust dimensions as needed
For lRecordCount = 0 To lRecordTotal
'Fill out Counts sheet
DoEvents
Set objGroup = GetObject(GroupPaths(lRecordCount))
lMemberCount = objGroup.Members.Count 'Count of items in AD group name
If lMemberCount > 0 Then
lMemberCounter = -1
For Each objMember In objGroup.Members
Application.StatusBar = "Getting " & lMemberCounter & " of " & lMemberCount
DoEvents
lMemberCounter = lMemberCounter + 1
[COLOR="#DAA520"]vArray(lRecordCount, 0, lMemberCounter) = GroupNames(lRecordCount)[/COLOR]
[COLOR="#008000"] 'Replace "z" with element values up to lIndexCount as needed
' vArray(lRecordCount, z, lMemberCounter) = objMember.cn 'Name as it appears in Lotus Notes, SameTime, etc.
' vArray(lRecordCount, z, lMemberCounter) = objMember.objectclass
' vArray(lRecordCount, z, lMemberCounter) = objMember.Description
' vArray(lRecordCount, z, lMemberCounter) = objMember.member
' vArray(lRecordCount, z, lMemberCounter) = objMember.distinguishedname
' vArray(lRecordCount, z, lMemberCounter) = objMember.instancetype
' vArray(lRecordCount, z, lMemberCounter) = objMember.whencreated
' vArray(lRecordCount, z, lMemberCounter) = objMember.whenchanged
' vArray(lRecordCount, z, lMemberCounter) = objMember.uSNCreated [COLOR="#FF0000"]'Caused error[/COLOR]
' vArray(lRecordCount, z, lMemberCounter) = objMember.uSNChanged [COLOR="#FF0000"]'Caused error[/COLOR]
' vArray(lRecordCount, z, lMemberCounter) = objMember.Name
' vArray(lRecordCount, z, lMemberCounter) = objMember.objectguid [COLOR="#FF0000"]'Caused error[/COLOR]
' vArray(lRecordCount, z, lMemberCounter) = objMember.objectsid [COLOR="#FF0000"]'Caused error[/COLOR]
[COLOR="#DAA520"]vArray(lRecordCount, 1, lMemberCounter) = objMember.samaccountname 'User's AD ID[/COLOR]
' vArray(lRecordCount, z, lMemberCounter) = objMember.samaccounttype
' vArray(lRecordCount, z, lMemberCounter) = objMember.grouptype
' vArray(lRecordCount, z, lMemberCounter) = objMember.objectcategory
' vArray(lRecordCount, z, lMemberCounter) = objMember.dscorepropagationdata
' vArray(lRecordCount, z, lMemberCounter) = objMember.dcxobjectowner
' vArray(lRecordCount, z, lMemberCounter) = objMember.nTSecurityDescriptor [COLOR="#FF0000"]'Caused error[/COLOR][/COLOR]
Next
Else
For x = 0 To lIndexCount
vArray(lRecordCount, x, 0) = sNoEntry
Next x
End If
Set objGroup = Nothing
Next lRecordCount
AD_Info = vArray 'Return AD group info
Exit Function
Error_Handler:
If InStr(5, Err.Description, "size limit") Then
MsgBox "Too many AD groups returned, possibly due to use of a wildcard character.", vbExclamation, "Process Aborted."
Else
MsgBox "Process Aborted!" & vbCrLf & Err.Number & vbCrLf & Err.Description, vbExclamation, "Error in AD_Info module."
End If
On Error Resume Next
cn.Close
Set cmd = Nothing
Set cn = Nothing
Set rs = Nothing
On Error GoTo 0
End Function
Function GetNC()
Dim objRoot As Object
Set objRoot = GetObject("LDAP://RootDSE")
GetNC = objRoot.get("defaultNamingContext")
Set objRoot = Nothing
End Function