web-dev-qa-db-fra.com

Sous-chaîne Excel VBA

J'écris une macro qui prend une liste de noms au format LDAP et les convertit en Premier, Dernier (région). Pour ceux d’entre vous qui ne savent pas à quoi ressemble LDAP, c’est la suivante:

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

Dans Excel VBA, il semble que je ne puisse pas utiliser string.substring (début, fin). Une recherche sur Google semble révéler que Mid (string, start, end) est la meilleure option. Le problème est le suivant: dans Mid, le nombre entier pour end correspond à la distance depuis le début, et non à la position réelle de l'index du caractère. Cela signifie que différentes tailles de noms auront des emplacements de fin différents et je ne peux pas utiliser l'index de ")" pour rechercher la fin de la région. Étant donné que tous les noms commencent par CN =, je peux trouver la fin de la première sous-chaîne correctement, mais je ne trouve pas correctement ")" car les noms ont des longueurs différentes. 

J'ai du code ci-dessous:

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

Est-ce que quelqu'un connaît un moyen d'utiliser réellement un point final défini au lieu d'un point final qui contient autant de valeurs que le début? 

8
spassen

C'est vba .. no string.substring;)

cela ressemble plus à VB 6 (ou à un autre ci-dessous) .. donc vous êtes coincé avec mid, instr, len (pour obtenir la longueur totale d'une chaîne) .. Je pense que vous avez manqué len pour obtenir le total de caractères dans une chaîne? Si vous avez besoin de précisions, n'hésitez pas à poster un commentaire.

modifier: 

Un autre hack rapide .. 

    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

Clairement, votre problème est que, puisque vous avez besoin d'une différence pour le second paramètre, vous devriez toujours faire quelques calculs pour cela ...

11
gbianchi

Je ne suis pas sûr d'avoir bien compris votre question, mais voici ma mise en œuvre de ce que vous voulez (espérons-le):

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

Il illustre l'utilisation des fonctions Split et Mid.

C'est une implémentation rapide et sale servant uniquement à des fins d'illustration. Pour l'utiliser dans du code réel, vous devez ajouter plusieurs vérifications (par exemple, si les collections kv et parts contiennent au moins deux éléments).

UPD: Pour couvrir deux formats possibles du champ CN, à savoir "last\, first (region)" et "first last (region)", et rendre les choses un peu moins compliquées, je prendrais l'approche des expressions régulières.

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
4
Gebb

Je voudrais utiliser InStr pour trouver la position des trois caractères qui séparent les valeurs et ensuite utiliser Gauche/Droite sur eux.

C'est ce que j'ai piraté ensemble très vite:

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

Puis concaténez-les pour obtenir la sortie de chaîne souhaitée.

2
Todd

Le bit prénom/nom est facile si vous commencez par ceci:

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