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?
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 ...
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
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.
Le bit prénom/nom est facile si vous commencez par ceci:
MsgBox Split(Mid$(sLDAP, 4), ")")(0) & ")"