Подстрока Excel VBA - PullRequest
       7

Подстрока Excel VBA

9 голосов
/ 30 марта 2012

Я пишу макрос, который принимает список имен в формате LDAP, преобразует их в First, Last (region).Для тех из вас, кто не знает, как выглядит LDAP, он приведен ниже:

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

В Excel VBA я не могу использовать string.substring (start, end).Похоже, что поиск в Google показал, что Mid (строка, начало, конец) - лучший вариант.Проблема заключается в следующем: в середине целое число для конца - это расстояние от начала, а не фактическое местоположение индекса символа.Это означает, что разные размеры имен будут иметь разные конечные местоположения, и я не могу использовать индекс ")", чтобы найти конец региона.Поскольку все имена начинаются с 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 ]

11 голосов
/ 30 марта 2012

Это vba .. без string.substring;)

это больше похоже на VB 6 (или любой другой ниже) .. так что вы застряли с mid, instr, len (чтобы получить общее значение lenстроки) .. Я думаю, что вы пропустили Лен, чтобы получить общее количество символов в строке?Если вам нужны пояснения, просто оставьте комментарий.

edit:

Еще один быстрый взлом ..

    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

Очевидно, что ваша проблема в том, что вам нужно различие дляВторой параметр, вы всегда должны делать некоторые математические вычисления ...

4 голосов
/ 30 марта 2012

Я не уверен, что правильно понял ваш вопрос, но вот моя реализация (надеюсь) того, что вы хотите:

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

Это иллюстрирует использование функций Split и Mid.

Это быстрая и грязная реализация, предназначенная только для иллюстративных целей.Чтобы использовать его в реальном коде, вам нужно добавить несколько проверок (например, что коллекции kv и parts содержат как минимум два элемента).

UPD: Для охвата двух возможных форматовполя CN, а именно "last\, first (region)" и "first last (region)" и сделать вещи немного менее запутанными, я бы использовал подход регулярных выражений.

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 голосов
/ 30 марта 2012

Я бы использовал 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

Затем объедините их, чтобы получить желаемый вывод строки.

0 голосов
/ 01 мая 2015

Бит имени / фамилии будет простым, если вы начнете с этого:

MsgBox Split(Mid$(sLDAP, 4), ")")(0) & ")" 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...