用于填充行的Excel自定义函数

用于填充行的Excel自定义函数,excel,vba,excel-formula,Excel,Vba,Excel Formula,我有一个自定义excel函数“GetADUser”,它以用户名作为输入,返回几个Active Directory属性,如Firstname、姓氏、SAM帐户名、可分辨名称 如何将这些属性放入保存穹窿的单元格左右两侧的单元格中。即: 公共函数GetADUser(用户名作为字符串)作为字符串 暗淡的迈塞尔山脉 设置rootDSE=GetObject(“LDAP://rootDSE”) Base=“” '对具有给定帐户名的用户对象进行筛选 fltr=“(&(objectClass=user)(obj

我有一个自定义excel函数“GetADUser”,它以用户名作为输入,返回几个Active Directory属性,如Firstname、姓氏、SAM帐户名、可分辨名称

如何将这些属性放入保存穹窿的单元格左右两侧的单元格中。即:

公共函数GetADUser(用户名作为字符串)作为字符串
暗淡的迈塞尔山脉
设置rootDSE=GetObject(“LDAP://rootDSE”)
Base=“”
'对具有给定帐户名的用户对象进行筛选
fltr=“(&(objectClass=user)(objectCategory=Person)”和_
“(sAMAccountName=“&UserName&”)
'根据您的要求添加其他属性
attr=“区分名称、序列号、手机、sAMAccountName、GivenName、l、邮政信箱”
Scope=“子树”
Set conn=CreateObject(“ADODB.Connection”)
连接提供程序=“ADsDSOObject”
连接打开“Active Directory提供程序”
Set cmd=CreateObject(“ADODB.Command”)
设置cmd.ActiveConnection=conn
cmd.CommandText=Base&“;”&fltr&“;”&attr&“;”&Scope
设置rs=cmd.Execute
arrPOBox=rs.Fields(“postOfficeBox”).值
秩=CStr(arrPOBox(0))
ActiveCell.Offset(0,-1).Value=(rs.Fields(“sn”).Value)
ActiveCell.Offset(0,-2).Value=(rs.Fields(“GivenName”).Value)
ActiveCell.Offset(0,2).Value=(rs.Fields(“l”).Value)
ActiveCell.Offset(0,1).Value=(rs.Fields(“mobile”).Value)
rs.Close
关闭连接
GetADUser=GetADUser
端函数
但是,ActiveCell在函数中不可用

我确实读过一种返回变量而不是字符串的方法,但它涉及到CTRL-SHIFT-ENTER来拆分值,这些值都位于保存公式的单元格的右侧。我不想为每个单元格调用Active Directory

是否有可以实现的功能或过程,以便当用户退出用户名列中的单元格时,填充其他相关单元格

更新

这应该在原始问题中详细说明,但用户名单元格可以位于工作簿中的任何工作表中,而不是位于四个可能列之一的连续单元格集。(例如,请参见黄色单元格)

图纸名称也可以更改

对可采用的范围有一个限制(30)

我考虑使用regex,因为用户名总是[a-z]{4}[a-z]{2},但它会在每个单元格上触发

我怎么做交叉点

类似这样:

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim rng As Range, c As Range

    'any updates to username(s)?
    Set rng = Application.Intersect(Me.Range("C2:C1000"), Target)
    If Not rng Is Nothing Then
        Application.EnableEvents = False '<< don't re-trigger the event
        For Each c In rng.Cells
            UpdateAdInfo c  'update the row for this user
        Next c
        Application.EnableEvents = True '<< re-enable events
    End If
End Sub




Public Sub UpdateAdInfo(rngUserName As Range)

    'clear existing data
    rngUserName.EntireRow.Range("A1:B1,D1:E1").ClearContents '<< note range is relative to row, not to sheet

    If Len(rngUserName.Value) = 0 Then Exit Sub 'no username entered, or was deleted

    '...
    '...snipped for clarity: open the recordset using rngUserName.Value
    '...

    Set rs = cmd.Execute

    With rngUserName.EntireRow
        .Cells(1).Value = rs.Fields("GivenName").Value
        .Cells(2).Value = rs.Fields("sn").Value
        'etc etc
    End With

    rs.Close
    conn.Close
End Sub
Private子工作表\u更改(ByVal目标作为范围)
变暗rng As范围,c As范围
'用户名有任何更新吗?
设置rng=Application.Intersect(Me.Range(“C2:C1000”),目标)
如果不是,那么rng什么都不是

Application.EnableEvents=False'一般来说,公式不允许修改其他单元格的内容。函数是一个函数,即它应该返回一个值,而不是修改多个单元格。这里需要的是宏,而不是函数。请注意,可能会有一些黑客使函数修改其他单元格,但事实上,这将是一个黑客。哦,不。。。别再这样了!从技术上讲,UDF可以用来修改另一个单元格(请参阅),但实际上不应该。如果函数返回数组,则可以使用它作为数组公式填充整行(并将用户名列移动到行的任意一端),使用工作表\u Change事件也可能是一个很好的途径来探索如何创建单元格(1).是否为作为目标的原始单元格的相对引用赋值?像Offset?在我发布的代码中已经这样了:ColC中的每个更改的单元格都作为参数
rngUserName
传递给
UpdateInfo
,并且
rngUserName.EntireRow
表示该用户名单元格的特定行,因此
.Cells(1)
是该行上的ColA。我已经使用了rngUserName.Offset(0,-3).Value=etc而不是.Cells(1).Value-这很有效。
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim rng As Range, c As Range

    'any updates to username(s)?
    Set rng = Application.Intersect(Me.Range("C2:C1000"), Target)
    If Not rng Is Nothing Then
        Application.EnableEvents = False '<< don't re-trigger the event
        For Each c In rng.Cells
            UpdateAdInfo c  'update the row for this user
        Next c
        Application.EnableEvents = True '<< re-enable events
    End If
End Sub




Public Sub UpdateAdInfo(rngUserName As Range)

    'clear existing data
    rngUserName.EntireRow.Range("A1:B1,D1:E1").ClearContents '<< note range is relative to row, not to sheet

    If Len(rngUserName.Value) = 0 Then Exit Sub 'no username entered, or was deleted

    '...
    '...snipped for clarity: open the recordset using rngUserName.Value
    '...

    Set rs = cmd.Execute

    With rngUserName.EntireRow
        .Cells(1).Value = rs.Fields("GivenName").Value
        .Cells(2).Value = rs.Fields("sn").Value
        'etc etc
    End With

    rs.Close
    conn.Close
End Sub