2012-03-30 92 views
7

Tôi đang viết macro có danh sách tên có định dạng LDAP chuyển đổi chúng thành Thứ nhất, Cuối cùng (vùng). Đối với những người bạn không biết LDAP trông như thế nào, dưới đây là:Chuỗi VBA Excel VBA

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

Trong Excel VBA, tôi có vẻ như không thể sử dụng string.substring (bắt đầu, kết thúc). Một tìm kiếm trên Google dường như tiết lộ rằng Mid (chuỗi, bắt đầu, kết thúc) là lựa chọn tốt nhất. Vấn đề là: ở giữa, số nguyên cho kết thúc là khoảng cách từ đầu, không phải là vị trí chỉ mục thực tế của ký tự. Điều này có nghĩa là các kích thước tên khác nhau sẽ có các vị trí kết thúc khác nhau và tôi không thể sử dụng chỉ mục ")" để tìm phần cuối của khu vực. Vì tất cả các tên bắt đầu bằng CN =, tôi có thể tìm thấy kết thúc của chuỗi con đầu tiên đúng cách, nhưng tôi không thể tìm thấy ")" đúng bởi vì tên có độ dài khác nhau.

Tôi có một số mã dưới đây:

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

Có ai biết một cách thực sự sử dụng một điểm kết thúc đã thay vì một điểm kết thúc mà là rất nhiều giá trị đi từ đầu?

Trả lời

10

Đây là VBA .. không string.substring;)

này là giống như VB 6 (hoặc bất kỳ một bên dưới) .. vì vậy bạn đang mắc kẹt với mid, InStr, len (để có được tổng len của một chuỗi) .. Tôi nghĩ rằng bạn bỏ lỡ len để có được tổng số ký tự trong một chuỗi? Nếu bạn cần một số làm rõ chỉ cần gửi bình luận.

chỉnh sửa:

Một nhanh chóng Hack ..

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 

Rõ ràng vấn đề của bạn là vì bạn cần một diference cho tham số thứ hai, bạn nên luôn luôn làm một số toán học cho nó ...

+0

Tổng số ký tự trong chuỗi sẽ không giúp tôi. Tôi chiều dài có thể khác nhau ở hai bên của ")" vì vậy tôi không thể tìm thấy vị trí chỉ mục để dừng dựa trên đó. – spassen

+0

bạn có thể đăng một ví dụ về đầu ra bạn cần không? thông thường, bạn phải mã hóa vòng lặp for để hoàn thành – gbianchi

+0

CN = Smith, John (vùng), OU = Legal, DC = example, DC = comand phải trở thành Smith, John (vùng) – spassen

4

Tôi không chắc tôi có câu hỏi của bạn đúng, nhưng đây là triển khai của tôi (hy vọng) những gì bạn muốn:

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 

Nó minh họa việc sử dụng các hàm SplitMid.

Việc triển khai nhanh chóng và dơ bẩn chỉ nhằm mục đích minh họa. Để sử dụng mã này trong mã thực, bạn cần phải thêm một số kiểm tra (ví dụ: các bộ sưu tập kvparts chứa ít nhất hai phần tử).

UPD: Để che hai định dạng có thể của lĩnh vực CN, cụ thể là "last\, first (region)""first last (region)" và làm cho mọi việc một chút ít lộn xộn tôi sẽ có cách tiếp cận biểu thức thông thường.

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 
+0

Điều này có vẻ như nó sẽ làm việc, nhưng khi tôi thử GetName (CN = last \, đầu tiên (AAA-một nơi nào đó), OU = IT, OU = Người dùng, OU = một nơi nào đó - aaa, OU = vị trí, DC = aaa, DC = com) Tôi nhận được một chỉ số lỗi ngoài phạm vi tại Giá trị = kv (1) vào lần thứ hai của nó thông qua vòng lặp. – spassen

+0

@spassen, tôi không biết có thể có dấu phẩy (thoát) trong tên. Điều này sẽ làm phức tạp mã. – Gebb

+0

Tôi thực sự đã tìm ra. Tôi hoàn toàn quên tôi có thể làm kết thúc - bắt đầu. Đó là một ngày dài. Cảm ơn sự giúp đỡ của bạn. Đó là một chức năng hữu ích để sử dụng trong tương lai. – spassen

2

Tôi sẽ sử dụng InStr để tìm vị trí của ba ký tự tách riêng các giá trị và sau đó sử dụng Trái/Phải trên chúng.

Đây là những gì tôi bị hack cùng nhau thực nhanh:

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 

Sau đó ghép chúng để có được đầu ra chuỗi bạn muốn.

0

Bit tên đầu tiên/cuối cùng là dễ dàng nếu bạn bắt đầu với điều này:

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