0

我最初使用 LDAP 的目的是返回当前是活跃员工的指定组的所有活跃成员。

我来到了这个解决方案:

Public Const ADConString = "Provider=ADsDSOObject;
                            Encrypt Password=False;
                            Integrated Security=SSPI;
                            Data Source=
                            LDAP://Domain:Numbers/DC=ROOT,
                            DC=Someplace,OU=SomePlace;
                            Mode=Read
                            Bind Flags=0;ADSI Flag=-2147483648"


Public Function getActiveDirectoryGroup(groupName As String)

Dim cmd As ADODB.Command
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim test As Variant

Set cmd = CreateObject("ADODB.Command")
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")

cn.Open ADConString 

cmd.CommandText = 
      "SELECT sn,adspath,cn,givenname,userAccountControl 
          FROM 'LDAP://RootPlace _
          "WHERE MemberOf='cn=" & groupName & 
          ",CN=SomePlace,DC=KMC,DC=SomePlace' " & _
          "AND userAccountControl<>514
           AND sn <>'name1' AND sn <>'name2' 
           AND sn           <>'name3' " & _
          "ORDER BY givenname"

Debug.Print cmd.CommandText

cmd.ActiveConnection = cn

Set rs = cmd.execute
groupPath = rs.Fields("adspath").Value
Do While Not rs.EOF
    'Debug.Print rs.Fields("adspath").Value
    Debug.Print rs.Fields("givenname").Value & " " 
        & rs.Fields("sn").Value & "     " 
        & rs.Fields("userAccountControl")
    'Debug.Print rs.Fields("cn").Value

rs.MoveNext
Loop

End Function

现在,如果你将它传递给一个组,这个解决方案就可以工作,但我想扩展它,以便有人可以只抓住活跃成员或摆脱sn <>'name1' AND sn <>'name2' AND sn<>'name3'条件。

到目前为止,我已经建立了这个类

Option Compare Database
Option Explicit

Private pADConnectionString As String
Private pRootLocation As String
Private pGroupName As String
Private Sub class_Initialize()
     pADConnectionString = "Provider=ADsDSOObject;
                            Encrypt Password=False;
                            Integrated Security=SSPI;
                            Data Source=
                            LDAP://Domain:Numbers/DC=ROOT,
                            DC=Someplace,OU=SomePlace;
                            Mode=Read
                            Bind Flags=0;ADSI Flag=-2147483648"

pRootLocation = getNC()



End Sub
Sub retreiveUsers()

End Sub
Public Property Get ADConnectionString() As Double
    ADConnectionString = pADConnectionString
End Property
Public Property Let ADConnectionString(connectionString As Double)
    pADConnectionString = connectionString
End Property
Function getNC()
    Set objRoot = GetObject("LDAP://RootDSE")
    getNC = objRoot.Get("defaultNamingContext")
End Function
Public Property Get groupName() As String
    groupName = pGroupName
End Property
Public Property Let groupName(group As String)
    pGroupName = group
End Property

我对类有点生疏,我不太确定如何在WHERE这个类中引入动态语句。那么,我应该继续沿着这条路走下去吗?如果可以,我可以考虑采取哪些解决方案来处理该WHERE条款?

我正在考虑使用一些草率的东西,例如将用户发送的内容附加到已应用于新whereStatement私有变量的内容的设置器,这样它就可以继续附加到WHERE子句。我担心的是,如果没有完全清楚,我将无法删除单个条件语句,例如sn<>'Name1'

4

3 回答 3

1

你可以overload的功能。
也许您正在寻找这样的东西:

Function getActiveDirectoryGroup(Optional groupName as string)

    Dim sQuery as string        

    if LenB(groupname) = 0 then 
        sQuery = "<general sql statement>"
    else
        sQuery = "<sql statement with conditions>"
    end if 

End Function

编辑

像您在更广泛的 OOP 语言(如 C++、C# 和 Java)中发现的函数重载在 VBA 中是不可能的。
但是,使用 Optional 参数,您可以模拟行为。

于 2013-10-24T20:24:11.883 回答
1

VBA 中的类与标准模块相比几乎没有优势,尤其是对于您在这里尝试做的事情。在 VBA 中,我认为类是一种将密切相关的函数/方法和属性组合成一个可重用的“容器”的方式。在我的大多数课程中,我开始在标准模块中获得我需要的东西,然后在事后将它变成一个课程。使用类,您可以设置一堆属性,然后运行其中一个方法,而使用模块,您需要将所有属性作为参数传递,或者使用全局变量或者自定义类型或类来保存属性。所以是的,类在那里有一个小的优势,但主要是对程序员来说。在您的情况下,一个类不提供标准模块不提供的任何功能。

如果你继续你的班级想法,这肯定是一个可以接受的命题,我认为你实际上应该继续你在问题末尾提出的“草率”想法。我认为这可以称为“谓词构建器”方法/函数。如果您希望能够在不清除整个内容的情况下删除特定标准,您必须自己构建它。当您使用谓词构建器函数添加条件时,只需将每个附加条件放入某种容器对象中,例如虚构的 ADO 记录集、字典对象或数组。这样,您始终可以查看结构/容器并添加、编辑或删除条目。然后你需要一个小函数来循环你的容器并构造完整的 WHERE 语句。

但是请记住,在这种情况下,课程对您的帮助很小。是的,它会让你封装和隐藏一些底层机制。例如,当您添加一个标准时,它将被附加到您的调用代码不必知道的某种私有容器/结构/变量中。然后,当您再次调用 Get 方法时,您的调用代码不需要知道标准是如何存储、制造等的。但是您也应该能够在没有类的情况下完成所有这些工作,尽管它会更加“松散”,而且肯定不太理想。

于 2013-10-25T16:26:47.363 回答
0

还有一件事我不确定你是否知道,但它可能对你非常有用;也许它甚至可能是您最终要寻找的东西。

确实,为此使用类模块并不是很有用,因为创建该对象的多个实例并没有真正的用处。
但是,您可以使标准模块的行为类似于他们在 C# 中所谓的“静态类”,尽管 VBA 没有实现静态类的概念。

考虑一下 C# 中静态类的定义:

静态类与非静态类基本相同,但有一个区别:静态类不能实例化。换句话说,您不能使用 new 关键字来创建类类型的变量。因为没有实例变量,所以您可以使用类名本身来访问静态类的成员。例如,如果您有一个名为 UtilityClass 的静态类,该类有一个名为 MethodA 的公共方法,您可以调用该方法,如下例所示:

C#
UtilityClass.MethodA();

作为这个概念的证明,请尝试以下操作:
将相同的代码放入两个标准模块并调用它们m_Classand m_Class2

Option Explicit

Private m_Number As Long

Public Function store_number(value As Long)

m_Number = value

End Function

Public Function get_number()

get_number = m_Number

End Function

现在,创建第三个标准模块,其中存储以下两个子项:

Sub test()


m_Class.store_number (10)
m_Class2.store_number (5)

End Sub

Sub test_2()

MsgBox (m_Class.get_number)
MsgBox (m_Class2.get_number)

End Sub

我想通过这个测试表明,两个标准模块实际上是两个独立的实例,具有自己的私有属性,每个实例都实现相同的功能。
因此,您会注意到标准模块的行为与静态类非常相似(尽管其内部底层机制并不相同)。

我建议您创建一个标准模块并实现此逻辑。
我确实认为创建这样一个“静态”类很有用,因为正如您所提到的,您将多次重复使用它,而您不需要该类的多个实例。

于 2013-10-25T18:54:58.143 回答