Hàm tự tạo 'viết tắt họ tên' như thế nào? (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Hoàng Trọng Nghĩa

Chuyên gia GPE
Thành viên BQT
Moderator
Tham gia
17/8/08
Bài viết
8,662
Được thích
16,725
Giới tính
Nam
Xin vui lòng hướng dẫn hàm viết tắt họ tên sẽ được viết như thế nào?

Xin cám ơn rất nhiều.

Giả sử tôi có tên là Hoàng Trọng Nghĩa, kết quả sẽ là H.T.NGHĨA

Nó giống như trong hình:
 

File đính kèm

  • TenVietTat.jpg
    TenVietTat.jpg
    32 KB · Đọc: 207
Xin vui lòng hướng dẫn hàm viết tắt họ tên sẽ được viết như thế nào?

Xin cám ơn rất nhiều.

Giả sử tôi có tên là Hoàng Trọng Nghĩa, kết quả sẽ là H.T.NGHĨA

Vu gì vậy?
Thứ nhất: Hàm này đã từng làm trên diễn đàn rồi
Thứ hai: Chẳng lẽ Nghĩa không tự viết được?
 
Upvote 0
Vu gì vậy?
Thứ nhất: Hàm này đã từng làm trên diễn đàn rồi
Thứ hai: Chẳng lẽ Nghĩa không tự viết được?

Tìm hỏng thấy bài nên hỏi mà Thầy!

Thật ra là có làm thử rồi, nhưng có vẽ lượm thượm nên không tự tin lắm.

PHP:
Function ShortName(ByVal FullName As String) As String
    
    FullName = Trim(FullName)
    
    If Len(FullName) = 0 Then
        ShortName = vbNullString
        Exit Function
    End If
    
    If InStr(FullName, " ") = 0 Then
        ShortName = UCase(FullName)
    Else
        Dim FirstName As String, LastName As String
            FirstName = " " & FullName
            LastName = FullName
        
        Do While InStr(FirstName, " ")
            FirstName = Mid(FirstName, InStr(FirstName, " ") + 1, Len(FirstName))
            LastName = Replace(LastName, Left(LastName, InStr(LastName, " ")), "")
            ShortName = ShortName & Left(FirstName, 1) & "."
        Loop
        
        ShortName = UCase(Left(ShortName, Len(ShortName) - 2) & LastName)
    End If
    
End Function

Xin nhờ góp ý và sửa chữa.
 

File đính kèm

Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Vấn đề này sẽ có rất nhiều cách giải quyết. Tôi xin góp vui bằng cách này:
PHP:
Function ShortName(ByVal FullName As String) As String
Dim i As Long
Do While InStr(FullName, " ")
    i = i + 2
    FullName = Application.Replace(FullName, i, InStr(FullName, " ") - i + 1, ".")
Loop
ShortName = UCase(FullName)
End Function
 
Upvote 0
Em viết tạm hàm củ chuối như sau:

Mã:
Function strName(str As String) As String
Dim sTemp() As String
Dim i As Long
sTemp = Split(Application.WorksheetFunction.Trim(str))
For i = 0 To UBound(sTemp) - 1
    strName = strName & UCase(Left(sTemp(i), 1)) & "."
Next i
strName = UCase(strName & sTemp(UBound(sTemp)))
End Function
 
Upvote 0
Em viết tạm hàm củ chuối như sau:

Mã:
Function strName(str As String) As String
Dim sTemp() As String
Dim i As Long
[COLOR=#ff0000][B]sTemp = Split(Application.WorksheetFunction.Trim(str))[/B][/COLOR]
For i = 0 To UBound(sTemp) - 1
    strName = strName & UCase(Left(sTemp(i), 1)) & "."
Next i
strName = UCase(strName & sTemp(UBound(sTemp)))
End Function
ODE][/QUOTE]

Tôi thấy [COLOR=#ff0000][B]sTemp = Split(Trim(str))[/B][/COLOR] cũng được mà.
 
Upvote 0
Tôi thấy sTemp = Split(Trim(str)) cũng được mà.

Không được đâu ạ, nếu ở khoảng giữa 2 chữ có nhiều khoảng trắng, thì nó sẽ thay đổi mỗi khoảng trắng là 1 dấu chấm (.) ạ.

Cũng với hàm của Hai Lúa Miền Tây, đoạn này thừa hàm UCase:

strName = strName & UCase(Left(sTemp(i), 1)) & "."

Nên để cho nó tính toán hết rồi mới cho nó UCase sẽ tốt hơn trong vòng lặp và số ký tự nó sẽ ít hơn sau khi hết vòng lặp thì thời gian sẽ tăng nhanh hơn (tí ti thôi).

====================================================

CÁM ƠN CÁC BẠN ĐÃ GIÚP MÌNH RẤT NHIỀU.
 
Lần chỉnh sửa cuối:
Upvote 0
Không được đâu ạ, nếu ở khoảng giữa 2 chữ có nhiều khoảng trắng, thì nó sẽ thay đổi mỗi khoảng trắng là 1 dấu chấm (.) ạ.

.......

Ý của tôi là: trong VBA đã có hàm Trim thì không cần phải dùng Application.WorksheetFunction nhưng Test lại thì thấy không được thật,
Nhưng nếu dùng sTemp = Split(Application.Trim(str)) thì OK.
 
Lần chỉnh sửa cuối:
Upvote 0
Hãy thử làm bài này mà không có sự có mặt có WorksheetFunction đi! Thế mới là VB chứ!
----------------
Thật ra là có làm thử rồi, nhưng có vẽ lượm thượm nên không tự tin lắm.
Xin nhờ góp ý và sửa chữa.
Nghĩa có nghĩ đến tình huông mà chuổi chứa nhiều khoảng trắng thừa không?
 
Upvote 0
Hãy thử làm bài này mà không có sự có mặt có WorksheetFunction đi! Thế mới là VB chứ!
----------------

Nghĩa có nghĩ đến tình huông mà chuổi chứa nhiều khoảng trắng thừa không?

Dùng For - Next (abc VBA) thông thường duyệt từ đầu đến cuối là Ok thôi.
 
Upvote 0
Dùng For - Next (abc VBA) thông thường duyệt từ đầu đến cuối là Ok thôi.
Thì đúng vậy sư phụ à!
Thế nên dùng cái của Hai Lúa cho nó đơn giản, chỉ sửa tí nữa để:
- Không phải dùng WorksheetFunction.Trim
- Bẫy lỗi với chuổi rổng
 
Upvote 0
Ngoại trừ việc bẫy lỗi chuỗi rỗng và chuỗi 1 từ, thuật toán đại khái như sau:

- Trim (trim VBA được rồi) chuỗi để xóa ký tự trắng cuối chuỗi
- Thêm 1 ký tự rỗng đầu chuỗi
- For i = 1 to Len(chuoi)
- Nếu ký tự thứ i <> " " và ký tự i - 1 = " " thì lụm, thêm dấu chấm, nối vào tmpStr
- lặp hết chuỗi
- xóa 2 ký tự cuối của tmpStr
- Bù vào là từ cuối của chuỗi. Từ cuối của chuỗi quá dễ.
 
Upvote 0
Theo mình, bài này cứ phang "chim, chim" như anh Hai Lúa cho chắc cú.
Cách của Thầy Mỹ thì truyền thống rối, nhưng vòng lặp phải chạy hết chuỗi ==> mệt
Cách của Thầy Ndu hổng xài "chim" & bẫy lỗi cũng Ok nhưng nếu khoảng trắng dư ở cuối chuỗi mà không có "chim" thì cũng .....hơi mệt í
Híc
 
Upvote 0
Theo mình, bài này cứ phang "chim, chim" như anh Hai Lúa cho chắc cú.
Cách của Thầy Mỹ thì truyền thống rối, nhưng vòng lặp phải chạy hết chuỗi ==> mệt
Cách của Thầy Ndu hổng xài "chim" & bẫy lỗi cũng Ok nhưng nếu khoảng trắng dư ở cuối chuỗi mà không có "chim" thì cũng .....hơi mệt í
Híc

Chuẩn, nhưng có thể cứ TRIM thường ở VB và sau đó split ==> rồi xét phần tử Array khác trắng là đủ, bác ạ
 
Upvote 0
Mình gom ý kiến mọi người vào hàm của Hai Lua xem sao:
Mã:
Function strName(str As String) As String
Dim sTemp() As String
Dim i As Long
Do While InStr(1, str, "  ") > 0
str = Replace(str, "  ", " ")
Loop
sTemp = Split(IIf(Trim(str) <> "", Trim(str), " "))
If UBound(sTemp) = 1 Then
strName = Trim(Str)
Else
For i = 0 To UBound(sTemp) - 1
    strName = strName & Left(sTemp(i), 1) & "."
Next i
strName = UCase(strName) & sTemp(UBound(sTemp))
End If
End Function
 
Upvote 0
Mình gom ý kiến mọi người vào hàm của Hai Lua xem sao:
Mã:
Function strName(str As String) As String
Dim sTemp() As String
Dim i As Long
Do While InStr(1, str, "  ") > 0
str = Replace(str, "  ", " ")
Loop
sTemp = Split(IIf(Trim(str) <> "", Trim(str), " "))
If UBound(sTemp) = 1 Then
strName = Trim(Str)
Else
For i = 0 To UBound(sTemp) - 1
    strName = strName & Left(sTemp(i), 1) & "."
Next i
strName = UCase(strName) & sTemp(UBound(sTemp))
End If
End Function
Hình như code của Thầy Sealand dính 2 chưởng:
1)- Tên không viết in hoa
2)- Chỗ này
If UBound(sTemp) = 1 Then
strName = Trim(Str)
hình như số 1 phải thay bằng số 0 ( số không)
Hihihi, tối buồn quá
Híc
 
Upvote 0
Theo mình, bài này cứ phang "chim, chim" như anh Hai Lúa cho chắc cú.
Cách của Thầy Mỹ thì truyền thống rối, nhưng vòng lặp phải chạy hết chuỗi ==> mệt
Cách của Thầy Ndu hổng xài "chim" & bẫy lỗi cũng Ok nhưng nếu khoảng trắng dư ở cuối chuỗi mà không có "chim" thì cũng .....hơi mệt í
Híc

Làm được tuốt anh à!
Sửa lại code của Hai Lúa thế này là được rồi:
PHP:
Function strName(ByVal str As String) As String
  Dim sTemp, tmp As String, n As Long, i As Long, Arr()
  sTemp = Split(Trim(str))
  If UBound(sTemp) > -1 Then
    For i = 0 To UBound(sTemp)
      tmp = sTemp(i)
      If Len(tmp) Then
        n = n + 1
        ReDim Preserve Arr(1 To n)
        Arr(n) = IIf(i = UBound(sTemp), UCase(tmp), UCase(Left(tmp, 1)))
      End If
    Next
    If n Then strName = Join(Arr, ".")
  End If
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Làm được tuốt anh à!
Sửa lại code của Hai Lúa thế này là được rồi:
Mã:
Function strName(ByVal str As String) As String
  Dim sTemp, tmp As String, n As Long, i As Long, Arr()
  sTemp = Split(Trim(str))
  If UBound(sTemp) > -1 Then
    For i = 0 To UBound(sTemp)
      tmp = sTemp(i)
      If Len(tmp) Then
        n = n + 1
        ReDim Preserve Arr(1 To n)
       [COLOR=#0000cd] [B]Arr(n) = IIf(i = UBound(sTemp), UCase(tmp), UCase(Left(tmp, 1)))[/B][/COLOR]
      End If
    Next
[COLOR=#0000cd][B]    If n Then strName = Join(Arr, ".")[/B][/COLOR]
  End If
End Function

Em bon chen sửa lại tí ở 2 dòng xanh nhé:

Arr(n) = IIf(i = UBound(sTemp), tmp, Left(tmp, 1))

If n Then strName = UCase(Join(Arr, "."))
 
Upvote 0
Code này mà dung Ucase e không ổn lắm vì dính mã tiếng Việt thì Ucase đi đời. Vì vậy mà mình bỏ Ucase phần tên (Xác xuất lỗi cực cao)

If UBound(sTemp) = 1 Then
strName = Trim(Str)

là đúng đấy bác Cò ơi.
 
Upvote 0
Code này mà dung Ucase e không ổn lắm vì dính mã tiếng Việt thì Ucase đi đời. Vì vậy mà mình bỏ Ucase phần tên (Xác xuất lỗi cực cao)

If UBound(sTemp) = 1 Then
strName = Trim(Str)

là đúng đấy bác Cò ơi.
Anh thử cho 1 trường hợp mà ÚCase bị sai xem
Xưa giờ em dùng UCase, LCase đều hoạt động tốt với Unicode anh à
 
Upvote 0
Bài này dùng thuật toán xử lý chuỗi cũng được mà. Nếu hạn chế dùng WorksheetFunction thì thay thế bằng hàm khác. Em làm thế này, mấy anh xem thử thế nào.
PHP:
Function ShortName(ByVal Str As String) As String
Dim i As Long
Str = Trim(Str)
Do While InStr(Str, " ")
    If InStr(Str, " ") > i + 1 Then i = i + 2
    Str = Replace(Str, Mid(Str, i, InStr(Str, " ") - i + 1), ".", , 1)
Loop
ShortName = UCase(Str)
End Function
 
Upvote 0
Bài này dùng thuật toán xử lý chuỗi cũng được mà.
Thì được... nhưng mà.. làm biếng lắm!
Cứ Split ra rồi For.. Next trên mảng cho nó đơn giản
-------------
Ngoài ra thì 1 lời khuyên thiết nghĩ cũng không thừa: Giải thuật dùng Split bao giờ cũng nhanh hơn so với xử lý chuổi thông thường (đương nhiên chỉ nói với những bài toán lớn)
 
Upvote 0
Thì được... nhưng mà.. làm biếng lắm!
Cứ Split ra rồi For.. Next trên mảng cho nó đơn giản
-------------
Ngoài ra thì 1 lời khuyên thiết nghĩ cũng không thừa: Giải thuật dùng Split bao giờ cũng nhanh hơn so với xử lý chuổi thông thường (đương nhiên chỉ nói với những bài toán lớn)

theo mình giải cách nào cũng được quan trọng là kết quả ok, đồng thời tiết kiểm được thời gian-\\/.
 
Upvote 0
Làm được tuốt anh à!
Sửa lại code của Hai Lúa thế này là được rồi:
PHP:
Function strName(ByVal str As String) As String
  Dim sTemp, tmp As String, n As Long, i As Long, Arr()
  sTemp = Split(Trim(str))
  If UBound(sTemp) > -1 Then
    For i = 0 To UBound(sTemp)
      tmp = sTemp(i)
      If Len(tmp) Then
        n = n + 1
        ReDim Preserve Arr(1 To n)
        Arr(n) = IIf(i = UBound(sTemp), UCase(tmp), UCase(Left(tmp, 1)))
      End If
    Next
    If n Then strName = Join(Arr, ".")
  End If
End Function


Thì được... nhưng mà.. làm biếng lắm!
Cứ Split ra rồi For.. Next trên mảng cho nó đơn giản
-------------
Ngoài ra thì 1 lời khuyên thiết nghĩ cũng không thừa: Giải thuật dùng Split bao giờ cũng nhanh hơn so với xử lý chuổi thông thường (đương nhiên chỉ nói với những bài toán lớn)

Vậy thế này cho đơn giản, (cũng Split lun, NHƯNG không cần Join)

PHP:
Function convName(fullName As String) As String
    Dim sT As String, Tmp, i As Long
    sT = Trim(fullName)
    If sT <> "" Then
       Tmp = Split(sT)
       sT = ""
       For i = 0 To UBound(Tmp) - 1
            If Tmp(i) <> "" Then sT = sT & Left(Tmp(i), 1) & "."
       Next i
       sT = UCase(sT & Tmp(UBound(Tmp)))
    End If
    convName = sT
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
1. Cho em hỏi cái này đổi tên thành chữ hoa đầu câu thì code như thế nào? VD như: PHẠM MINH TUẤN thì thành P.M.Tuấn.
Em lấy code của anh HuuThangbd
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
1. Cho em hỏi cái này đổi tên thành chữ hoa đầu câu thì code như thế nào? VD như: PHẠM MINH TUẤN thì thành P.M.Tuấn.
Thử thế này coi, chắc chưa ổn lắm
PHP:
Public Function tach(cell As Range)
Dim i, tam, kq
tam = Application.Trim(tam)
tam = Split(cell, " ")
For i = 0 To UBound(tam) - 1
   kq = kq & " " & UCase(Left(tam(i), 1)) & "."
Next
tach = kq & " " & Application.Proper(tam(UBound(tam)))
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Thử thế này coi, chắc chưa ổn lắm
PHP:
Public Function tach(cell As Range)
Dim i, tam, kq
tam = Application.Trim(tam)
tam = Split(cell, " ")
For i = 0 To UBound(tam) - 1
   kq = kq & " " & UCase(Left(tam(i), 1)) & "."
Next
tach = kq & " " & Application.Proper(tam(UBound(tam)))
End Function
Cảm ơn anh nhiều. Em đã thử thấy được rồi. Chúc anh cuối tuần vui nhé.
 
Upvote 0
để tránh lằng nhằng tui làm thêm hàm trìm2 để loại tất cả các khoảng trắng thừa ở hai đầu và ở giữa.

Function Trim2(s$)
Dim str$
str = s
Do While InStr(str, " ") > 0
str = Replace(str, " ", " ") 'thay 2 khoảng trắng bằng 1 khoảng trắng
Loop
Trim2 = Trim(str)
End Function
 
Upvote 0
để tránh lằng nhằng tui làm thêm hàm trìm2 để loại tất cả các khoảng trắng thừa ở hai đầu và ở giữa.

Function Trim2(s$)
Dim str$
str = s
Do While InStr(str, " ") > 0
str = Replace(str, " ", " ") 'thay 2 khoảng trắng bằng 1 khoảng trắng
Loop
Trim2 = Trim(str)
End Function
Đâu nhất thiết phải xây dựng thêm một hàm phụ đâu nhỉ, nếu áp dụng cho Excel thì ta đã có WorksheetFunction.Trim rồi mà.
 
Upvote 0
Các Thầy cho em hỏi. Vậy muốn giữ nguyên định dạng của kiểu chữ ban đầu thì code ophải sửa thế nào vậy?
Vd:
Mã:
Hoàng Trọng Nghĩa => H.T.Nghĩa

------------------
Xin lỗi em không để ý bài cuả Anh QuangHai đã đề cập!
Phiền Mod xóa giúp bài này hoặc là chỉ thêm cách mới!
Cảm ơn!
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Em không rành quá về VBA nên làm theo một hướng tư duy đơn giản về xử lý chuỗi bằng vòng lặp for như thế này ạ! Mọi người xem giúp giải pháp này có vấn đề gì không:
PHP:
Function HoTen(a As String) As String
Dim i As Integer, j As Integer
Dim VT As String
If a = "" Then
    HoTen = ""
    Exit Function
End If
a = Trim(a)
VT = Left(a, 1) & "."
For i = 1 To Len(a)
    If Mid(a, i, 1) = ChrW(32) And Mid(a, i + 1, 1) <> ChrW(32) Then
        VT = VT & Mid(a, i + 1, 1) & "."
        j = i
    End If
Next
HoTen = Left(VT, Len(VT) - 2) & Right(a, Len(a) - j)
End Function
 
Upvote 0
Cho mình xin hỏi code trên các anh đề cập đến thấy tốt.
ví dụ mình muốn viết tắt hết tất cả các tên luôn thì code như thế nào? cho mình xin code nhé.
VD: Nguyễn Văn Trường ---> NVT
Xin cảm ơn các bạn xem bài.
 
Lần chỉnh sửa cuối:
Upvote 0
Cho mình xin hỏi code trên các anh đề cập đến thấy tốt.
ví dụ mình muốn viết tắt hết tất cả các tên luôn thì code như thế nào? cho mình xin code nhé.
VD: Nguyễn Văn Trường ---> NVT
Xin cảm ơn các bạn xem bài.

Anh thử code này xem nhé


Mã:
Function getInitialName(name As String) As String
    Dim arr() As String
    Dim i As Long
    arr = Split(name)
    For i = LBound(arr) To UBound(arr)
        getInitialName = getInitialName & Left(arr(i), 1)
    Next i
End Function

code trả lời topic:

Mã:
Function getInitialName(name As String) As String
    Dim arr() As String
    Dim i As Long
    
    If Len(Trim(name)) = 0 Then Exit Function
    
    arr = Split(name)
    
    For i = LBound(arr) To UBound(arr) - 1
        getInitialName = getInitialName & Left(arr(i), 1) & "."
    Next i
    
    getInitialName = getInitialName & arr(UBound(arr))
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Cho mình xin hỏi code trên các anh đề cập đến thấy tốt.
ví dụ mình muốn viết tắt hết tất cả các tên luôn thì code như thế nào? cho mình xin code nhé.
VD: Nguyễn Văn Trường ---> NVT
Xin cảm ơn các bạn xem bài.
Thử hàm này
Cú pháp = VT(A1)
PHP:
Function VT(Cell As Range)
With CreateObject("vbscript.regexp")
   .Global = True
   .Pattern = "[^A-Z]"
   VT = .Replace(Cell, "")
End With
End Function
 
Upvote 0
Đã giải quyết vấn đề, cảm ơn 2 bạn.
Cho mình hỏi thêm ví dụ có dữ liệu như thế này
THPT NGUYỄN QUANG DIÊU ---> thành THPT NQD
THCS NGUYỄN TRÃI ---> thành THCS NT
Vậy cho mình xin code nhé, 1 lần nữa xin cảm ơn.
 
Lần chỉnh sửa cuối:
Upvote 0
Đã giải quyết vấn đề, cảm ơn 2 bạn.
Cho mình hỏi thêm ví dụ có dữ liệu như thế này
THPT NGUYỄN QUANG DIÊU ---> thành THPT NQD
THCS NGUYỄN TRÃI ---> thành THCS NT
Vậy cho mình xin code nhé, 1 lần nữa xin cảm ơn.
PHP:
Function VT(Cell As Range) As String
Dim tam, i, kq
tam = Split(Application.Trim(Cell), " ")
For i = 1 To UBound(tam)
   kq = kq & Left(tam(i), 1)
Next
VT = tam(0) & " " & kq
End Function
 
Upvote 0
Thử hàm này
Cú pháp = VT(A1)
PHP:
Function VT(Cell As Range)
With CreateObject("vbscript.regexp")
   .Global = True
   .Pattern = "[^A-Z]"
   VT = .Replace(Cell, "")
End With
End Function

Hàm này gặp Ông Văn Trường thì ra sai.
RegEx sử dụng với unicode hơi rắc rối một chút.
 
Upvote 0

Bài viết mới nhất

Back
Top Bottom