11
votes

Analysez la sous-chaîne du texte

J'écris une macro qui convertit une liste de noms dans un format LDAP en premier, dernier (région).

Pour ceux qui ne savent pas ce que LDAP ressemble, il est ci-dessous:

cn = John Smith (région), ou = légal, dc = exemple, DC = COMAND

dans Excel VBA, je ne semble pas pouvoir utiliser string.Substring (début, fin). Une recherche sur Google semble révéler que la moyenne (chaîne, début, fin) est la meilleure option.

Le problème est celui-ci: Au milieu, l'entier de fin est la distance entre le début, pas l'index réel emplacement du personnage. Cela signifie que différentes tailles de noms auront différents emplacements de fin et je ne peux pas utiliser l'index de ")" pour trouver 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 de trouver ")" correctement parce que les noms sont des longueurs différentes.

J'ai du code ci-dessous: xxx

est un moyen d'utiliser un point d'extrémité défini au lieu d'un point final qui est tellement de valeurs loin de le début?


0 commentaires

4 Réponses :


13
votes

Ceci est VBA .. No String.Substring;)

Ceci ressemble plus à la VB 6 (ou n'importe quel ci-dessous) .. Donc, vous êtes coincé avec Mid, Instr, Len (pour obtenir le total len d'une chaîne ) .. Je pense que vous avez manqué Len pour obtenir le total des caractères dans une chaîne? Si vous avez besoin de quelques éclaircissements, postez un commentaire.

EDIT:

Un autre hack rapide .. xxx

clairement votre problème est clairement que puisque vous avez besoin d'une différence pour le deuxième paramètre, vous devriez toujours faire des mathématiques pour cela ...


4 commentaires

Le nombre total de caractères dans la chaîne ne m'aidera pas. I La longueur peut varier de chaque côté de la ")", donc je ne trouve donc pas l'emplacement de l'index pour arrêter en fonction de cela.


Pouvez-vous poster un exemple de la sortie dont vous avez besoin? généralement, vous devez coder une boucle pour accomplir cette


CN = Smith, John (Région), ou = Juridique, DC = Exemple, DC = Comand devrait devenir Smith, John (région)


Je ne sais pas pourquoi je ne pensais pas à utiliser des mathématiques. Cela aurait dû être évident. Devinez que ça fait une longue journée. Merci.



5
votes

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

Il illustre l'utilisation de divisée code > et MID code> Fonctions. P>

Il s'agit d'une mise en œuvre rapide et sale desservant des fins d'illustration uniquement. Pour l'utiliser dans un code réel, vous devez ajouter plusieurs vérifications (par exemple, que les code> kv code> et pièces code> contiennent au moins deux éléments). P>

Upd upd: strong> pour couvrir deux formats possibles du champ CN, nommément "dernier \, premier (région)" code> et "premier (Code)" et Faites des choses un peu moins sales, je prendrais l'approche des expressions régulières. 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


3 commentaires

Cela ressemble à cela devrait fonctionner, mais quand j'essaye GetName (cn = dernier \, premier (AAA-quelque part), ou = IT, OU = utilisateurs, ou = quelque part - AAA, OU = Place, DC = AAA, DC = com ) Je reçois une erreur d'erreur hors de portée de la valeur = kv (1) sur sa deuxième fois par la boucle.


@spassen, je ne savais pas qu'il pourrait y avoir des virgules (échappées) au nom. Cela compliquera le code.


Je l'ai effectivement compris. J'ai complètement oublié que je pourrais faire la fin - commencer. Ça a été une longue journée. Merci pour l'aide en tout cas. C'est une fonction utile pour une utilisation future.



3
votes

J'utiliserais des installs de trouver la position des trois caractères qui séparent les valeurs, puis utilisez la gauche / droite sur eux.

C'est ce que j'ai piraté ensemble réel rapide: xxx

puis les concaténer pour obtenir la sortie de chaîne que vous souhaitez.


0 commentaires

0
votes

Le bit du premier / dernier nom est facile si vous commencez avec ceci:

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


0 commentaires