Excel VBA子串

时间:2012-03-30 18:08:03

标签: excel vba excel-vba ldap substring

我正在编写一个宏,它采用LDAP格式的名称列表将它们转换为First,Last(region)。对于那些不知道LDAP是什么样的人,它在下面:

CN=John Smith (region),OU=Legal,DC=example,DC=comand

在Excel VBA中,我似乎无法使用string.substring(start,end)。对Google的搜索似乎表明,Mid(字符串,开头,结尾)是最好的选择。问题是:在Mid中,end的整数是从开始的距离,而不是字符的实际索引位置。这意味着不同的名称大小将具有不同的结束位置,并且我不能使用索引“)”来查找区域的结尾。由于所有名称都以CN =开头,我可以正确找到第一个子字符串的结尾,但我找不到“)”因为名称长度不同。

我有以下代码:

mgrSub1 = Mid(mgrVal, InStr(1, mgrVal, "=") + 1, InStr(1, mgrVal, "\") - 4)
mgrSub2 = Mid(mgrVal, InStr(1, mgrVal, ","), InStr(1, mgrVal, ")") - 10)
manager = mgrSub1 & mgrSub2

有没有人知道一种实际使用设定终点的方法,而不是一个距离一开始就有这么多值的终点?

4 个答案:

答案 0 :(得分:11)

这是vba ..没有string.substring;)

这更像是VB 6(或下面的任何一个)..所以你被困在mid,instr,len(得到一个字符串的总len)..我想你错过了len来得到字符总数在一个字符串?如果您需要澄清,请发表评论。

编辑:

另一个快速破解......

    Dim t As String
    t = "CN=Smith, John (region),OU=Legal,DC=example,DC=comand"
    Dim s1 As String
    Dim textstart As Integer
    Dim textend As Integer
    textstart = InStr(1, t, "CN=", vbTextCompare) + 3
    textend = InStr(1, t, "(", vbTextCompare)
    s1 = Mid(t, textstart, textend - textstart)
    MsgBox s1
    textstart = InStr(1, t, "(", vbTextCompare) + 1
    textend = InStr(1, t, ")", vbTextCompare)
    s2 = Mid(t, textstart, textend - textstart)
    MsgBox s2

显然你的问题是因为你需要与第二个参数不同,你应该总是为它做一些数学...

答案 1 :(得分:4)

我不确定我的问题是否正确,但这是我希望的实现(希望如此):

Function GetName(arg As String) As String
    parts = Split(arg, ",")
    For Each p In parts
        kv = Split(p, "=")
        Key = kv(0)
        Value = kv(1)
        If Key = "CN" Then
            commonName = Value
        End If
    Next p
    regIndex = InStr(1, commonName, "(")
    region = Mid(commonName, regIndex, Len(commonName) - regIndex + 1)
    parts = Split(commonName, " ")
    first = parts(0)
    last = parts(1)
    GetName = first & ", " & last & " " & region
End Function


Sub test()
 'Prints "John, Smith (region)"
 Debug.Print GetName("CN=John Smith (region),OU=Legal,DC=example,DC=comand")
End Sub

它说明了SplitMid函数的使用。

这是一个快速而肮脏的实现,仅用于说明目的。要在实际代码中使用它,您需要添加几个检查(例如,kvparts集合包含至少两个元素。)

UPD:要涵盖CN字段的两种可能格式,即"last\, first (region)""first last (region)",并使事情变得不那么混乱,我会采用正则表达式方法。< / p>

Function GetName(arg As String) As String
    Dim RE As Object, REMatches As Object

    Set RE = CreateObject("vbscript.regexp")
    With RE
        .MultiLine = False
        .Global = False
        .IgnoreCase = True
        .Pattern = "CN=(\w+)\s*?(\\,)?.*?,"
    End With
    Set REMatches = RE.Execute(arg)
    If REMatches.Count < 1 Then
        GetName = ""
        Return
    End If

    cn = REMatches(0).Value
    withComma = (InStr(1, cn, "\,") > 0)
    If withComma Then
        lastIndex = 0
        firstIndex = 2
        regionIndex = 3
        patt = "(\w+)\s*?(\\,)?\s*?(\w+)\s*(\(.*?\))"
    Else
        lastIndex = 1
        firstIndex = 0
        regionIndex = 2
        patt = "(\w+)\s*?(\w+)\s*(\(.*?\))"
    End If
    Set RE = CreateObject("vbscript.regexp")
    With RE
        .MultiLine = False
        .Global = False
        .IgnoreCase = True
        .Pattern = patt
    End With
    Set REMatches = RE.Execute(arg)
    If REMatches.Count < 1 Then
        GetName = ""
        Return
    End If

    Set m = REMatches(0)
    first = m.SubMatches(firstIndex)
    last = m.SubMatches(lastIndex)
    region = m.SubMatches(regionIndex)
    GetName = first & ", " & last & " " & region
End Function


Sub test()
 ' Prints "first, last (AAA-somewhere)" two times.
 Debug.Print GetName("CN=last\, first (AAA-somewhere),OU=IT,OU=Users,OU=somewhere - aaa,OU=place,DC=aaa,DC=com")
 Debug.Print GetName("CN=first last (AAA-somewhere),OU=IT,OU=Users,OU=somewhere - aaa,OU=place,DC=aaa,DC=com")
End Sub

答案 2 :(得分:2)

我会使用InStr来找到分隔值的三个字符的位置,然后在它们上使用左/右。

这就是我快速入侵的原因:

Dim tmp, new_string, first, last, region As String

tmp = "CN=John Smith (region),OU=Legal,DC=example,DC=comand"

new_string = Right(tmp, Len(tmp) - 3)
' John Smith (region),OU=Legal,DC=example,DC=comand
new_string = Left(new_string, (InStr(1, new_string, ",") - 2))
' John Smith (region)

region = Right(new_string, Len(new_string) - InStr(1, new_string, "("))
' region
new_string = Left(new_string, (InStr(1, new_string, "(") - 2))
' John Smith

last = Right(new_string, Len(new_string) - InStr(1, new_string, " "))
' Smith
first = Left(new_string, (InStr(1, new_string, " ") - 1))
' John

然后连接它们以获得所需的字符串输出。

答案 3 :(得分:0)

如果你从这开始,名字/姓氏就很容易了:

MsgBox Split(Mid$(sLDAP, 4), ")")(0) & ")"