[HELP] Chỉnh Sửa Code Đọc Thành Tiền Trong Tiếng Anh

  • Thread starter Bandit
  • Ngày gửi
Trạng thái
Không mở trả lời sau này.
B

Bandit

Guest
Chào Anh Chị

Em có lấy một Code VBA đọc số tiền trong tiếng Anh trên mạng về, nhưng có một vài chỗ không đúng như ý muốn. Và em không thể chỉnh sửa do không biết về VBA. Em trình bày vấn đề và mong anh chị có thể giúp đỡ.

Đây là Code:

Mã:
Function USD(ByVal pNumber)
Dim Dollars, Cents
arr = Array("", "", " Thousand ", " Million ", " Billion ", " Trillion ")
pNumber = Trim(Str(pNumber))
xDecimal = InStr(pNumber, ".")
If xDecimal > 0 Then
    Cents = GetTens(Left(Mid(pNumber, xDecimal + 1) & "00", 2))
    pNumber = Trim(Left(pNumber, xDecimal - 1))
End If
xIndex = 1
Do While pNumber <> ""
    xHundred = ""
    xValue = Right(pNumber, 3)
    If Val(xValue) <> 0 Then
        xValue = Right("000" & xValue, 3)
        If Mid(xValue, 1, 1) <> "0" Then
            xHundred = GetDigit(Mid(xValue, 1, 1)) & " Hundred "
        End If
        If Mid(xValue, 2, 1) <> "0" Then
            xHundred = xHundred & GetTens(Mid(xValue, 2))
        Else
            xHundred = xHundred & GetDigit(Mid(xValue, 3))
        End If
    End If
    If xHundred <> "" Then
        Dollars = xHundred & arr(xIndex) & Dollars
    End If
    If Len(pNumber) > 3 Then
        pNumber = Left(pNumber, Len(pNumber) - 3)
    Else
        pNumber = ""
    End If
    xIndex = xIndex + 1
Loop
Select Case Cents
    Case ""
        Cents = " Only."
    Case "One"
        Cents = " And One Cent"
    Case Else
        Cents = " And " & Cents & " Cents Only."
End Select
USD = "U.S. Dollars " & Dollars & Cents
End Function
Function GetTens(pTens)
Dim Result As String
Result = ""
If Val(Left(pTens, 1)) = 1 Then
    Select Case Val(pTens)
        Case 10: Result = "Ten"
        Case 11: Result = "Eleven"
        Case 12: Result = "Twelve"
        Case 13: Result = "Thirteen"
        Case 14: Result = "Fourteen"
        Case 15: Result = "Fifteen"
        Case 16: Result = "Sixteen"
        Case 17: Result = "Seventeen"
        Case 18: Result = "Eighteen"
        Case 19: Result = "Nineteen"
        Case Else
    End Select
Else
Select Case Val(Left(pTens, 1))
    Case 2: Result = "Twenty "
    Case 3: Result = "Thirty "
    Case 4: Result = "Forty "
    Case 5: Result = "Fifty "
    Case 6: Result = "Sixty "
    Case 7: Result = "Seventy "
    Case 8: Result = "Eighty "
    Case 9: Result = "Ninety "
    Case Else
End Select
Result = Result & GetDigit(Right(pTens, 1))
End If
GetTens = Result
End Function
Function GetDigit(pDigit)
Select Case Val(pDigit)
    Case 1: GetDigit = "One"
    Case 2: GetDigit = "Two"
    Case 3: GetDigit = "Three"
    Case 4: GetDigit = "Four"
    Case 5: GetDigit = "Five"
    Case 6: GetDigit = "Six"
    Case 7: GetDigit = "Seven"
    Case 8: GetDigit = "Eight"
    Case 9: GetDigit = "Nine"
    Case Else: GetDigit = ""
End Select
End Function
Và đây là hình ảnh khi sử dụng Code và mong muốn chỉnh sửa Code cho phù hợp của em.

Bạn cần đăng nhập để thấy hình ảnh


File đính kèm ở Link này:
Add-in đính kèm:
Không biết cách trình bày của em như thế có gây khó hiểu cho các anh chị không, mong các anh chị thông cảm và góp ý thêm

Em xin chân thành cảm ơn.
 
Sửa lần cuối bởi điều hành viên:
B

bvtvba

Guest
Bạn kiểm tra lại giúp mình, code bạn đưa là không đủ.
Cụ thể:
Bạn hãy nén file ở đường link này thành file .zip rồi upload để mọi người download về:
Mã:
C:\Users\caocuonghu\AppData\Roaming\Microsoft\AddIns\Currency.xlam
Hiện tại code của bạn không chạy trên máy tính của mình, nó báo lỗi. Cụ thể:
Bạn cần đăng nhập để thấy hình ảnh

Nó không hiểu GetTens là gì.
 
B

Bandit

Guest
Bạn kiểm tra lại giúp mình, code bạn đưa là không đủ.
Cụ thể:
Bạn hãy nén file ở đường link này thành file .zip rồi upload để mọi người download về:
Mã:
C:\Users\caocuonghu\AppData\Roaming\Microsoft\AddIns\Currency.xlam
Hiện tại code của bạn không chạy trên máy tính của mình, nó báo lỗi. Cụ thể:
Bạn cần đăng nhập để thấy hình ảnh

Nó không hiểu GetTens là gì.
Do em Copy Code thiếu, em đã bổ sung ở #1. Còn đây là Add-in:
Anh xem qua giúp em nhé
 
B

bvtvba

Guest
Ừm, code chạy được rồi. Nhưng mình vẫn chưa rõ yêu cầu lắm. Định nghĩa như thế nào là lẻ.
Ví dụ:
112100
=> U.S. Dollars One Hundred Twelve Thousand One Hundred Only.
Trường hợp này có đúng không. Có cần And nữa không?

112000
=> U.S. Dollars One Hundred Twelve Thousand Only.
Trường hợp này có đúng không. Có cần And nữa không?

Bạn nên làm rõ khái niệm lẻ của bạn là gì? Cứ chữ số cuối cùng thì là lẻ, thêm And vào trước đó?
Hay là, các chữ số sau Thousand thì tìm chữ số cuối cùng, thêm And vào trước nó?
 
B

Bandit

Guest
Ừm, code chạy được rồi. Nhưng mình vẫn chưa rõ yêu cầu lắm. Định nghĩa như thế nào là lẻ.
Ví dụ:
112100
=> U.S. Dollars One Hundred Twelve Thousand One Hundred Only.
Trường hợp này có đúng không. Có cần And nữa không?

112000
=> U.S. Dollars One Hundred Twelve Thousand Only.
Trường hợp này có đúng không. Có cần And nữa không?

Bạn nên làm rõ khái niệm lẻ của bạn là gì? Cứ chữ số cuối cùng thì là lẻ, thêm And vào trước đó?
Hay là, các chữ số sau Thousand thì tìm chữ số cuối cùng, thêm And vào trước nó?
Cám ơn anh đã góp ý, do cách em trình bày hơi khó hiểu (Em cũng thấy thê, nhưng không tìm ra từ phù hợp).
Em xin nói lại vấn đề ạ. Lẻ ở đây ý em là phần thập phân sau dấu phẩy (Em quy ước như người VN hay dùng dấu cách là 112.100,20, như ở đây sau dấu phẩy là số 20 em gọi là lẻ)
- Và em muốn nếu khi đọc một số mà không có phần lẻ như là 112.100 thì thêm AND vào trước One Hundred vậy sẽ đọc là: U.S. Dollars One Hundred Twelve Thousand AND One Hundred Only.
Còn ví dụ 112.120 thì lại thêm AND trước Twenty nghĩa là: U.S. Dollars One Hundred Twelve Thousand One Hundred AND Twenty Only.
- Còn khi xuất hiện số lẻ ví dụ như 112.100,20 thì chữ AND sẽ xuất hiện trước số lẻ: U.S. Dollars One Hundred Twelve Thousand One Hundred AND Twenty Cents Only.
 

tuhocvba

Administrator
Thành viên BQT
Loạn đầu phết rồi nhỉ.
Cho mình hỏi:
Trường hợp dưới đây là không lẻ, và đáp án như vậy là đúng rồi phải không?
Nếu lấy đơn vị triệu làm chuẩn thì nó lẻ. Hoặc nếu lấy đơn vị chục ngàn làm chuẩn thì nó lẻ ra 2000. Nhưng nếu lấy đơn vị ngàn làm chuẩn thì nó không lẻ.
112000
=> U.S. Dollars One Hundred Twelve Thousand Only.
 
B

Bandit

Guest
Loạn đầu phết rồi nhỉ.
Cho mình hỏi:
Trường hợp dưới đây là không lẻ, và đáp án như vậy là đúng rồi phải không?
Nếu lấy đơn vị triệu làm chuẩn thì nó lẻ. Hoặc nếu lấy đơn vị chục ngàn làm chuẩn thì nó lẻ ra 2000. Nhưng nếu lấy đơn vị ngàn làm chuẩn thì nó không lẻ.
112000
=> U.S. Dollars One Hundred Twelve Thousand Only.
Nếu 112.000: U.S. Dollars One Hundred Twelve Thousand Only. Trường hợp này đọc vậy là chuẩn rồi, không cần And nữa.
Còn nếu là 112.100 Thì sẽ AND sau One Hundred thành: U.S. Dollars One Hundred Twelve Thousand AND One Hundred Only.
Ý em là thế ạ
 
B

bvtvba

Guest
Cho mình hỏi 126 kết quả là:
U.S. Dollars One Hundred Twenty Six Only.
Trường hợp này có cần And nữa không?
 

tuhocvba

Administrator
Thành viên BQT
Kết quả thì được như bạn yêu cầu rồi, bạn kiểm tra lại nhé:
Bạn cần đăng nhập để thấy hình ảnh


Hàm USD sửa lại như sau:
Mã:
Function USD(ByVal pNumber)
Dim Dollars, Cents
'tuhocvba.net
Dim arr
Dim flag As Boolean

arr = Array("", "", " Thousand ", " Million ", " Billion ", " Trillion ")
pNumber = Trim(Str(pNumber))
xDecimal = InStr(pNumber, ".")
If xDecimal > 0 Then
    Cents = GetTens(Left(Mid(pNumber, xDecimal + 1) & "00", 2))
    pNumber = Trim(Left(pNumber, xDecimal - 1))
End If
flag = False
Select Case Cents
    Case ""
        Cents = " Only."
    Case "One"
        Cents = " And One Cent"
        flag = True
    Case Else
        Cents = " And " & Cents & " Cents Only."
        flag = True
End Select
xIndex = 1
Do While pNumber <> ""
    xHundred = ""
    xValue = Right(pNumber, 3)
    If xIndex = 2 Then
        If flag = Flase Then
            Dollars = tuhocvba(Dollars)
            flag = True
        End If
    End If
    If Val(xValue) <> 0 Then
        xValue = Right("000" & xValue, 3)
        If Mid(xValue, 1, 1) <> "0" Then
            xHundred = GetDigit(Mid(xValue, 1, 1)) & " Hundred "
        End If
        If Mid(xValue, 2, 1) <> "0" Then
            xHundred = xHundred & GetTens(Mid(xValue, 2))
        Else
            xHundred = xHundred & GetDigit(Mid(xValue, 3))
        End If
    End If
    If xHundred <> "" Then
        Dollars = xHundred & arr(xIndex) & Dollars
    End If
    If Len(pNumber) > 3 Then
        pNumber = Left(pNumber, Len(pNumber) - 3)
    Else
        pNumber = ""
    End If
    xIndex = xIndex + 1
    
Loop

USD = "U.S. Dollars " & Dollars & Cents
End Function
Thêm hàm mới, bạn copy vào cùng chỗ với hàm USD là được:
Mã:
Function tuhocvba(ByVal s As String) As String
    Dim s_input As String
    Dim i   As Integer
    Dim j   As Integer
    Dim re  As String
    Dim le  As String
    
    
    s_input = Trim(s)
    i = InStr(1, s_input, "Hundred")
    If i = 0 Then GoTo thvba
    'One Hundred
    If i + 6 = Len(s_input) Then  'len(Hundred) = 7
        tuhocvba = " And " & s
        Exit Function
    End If
thvba:
    If Len(s_input) = 0 Then Exit Function
    i = InStrRev(s_input, " ")
    If i = 0 Then
        tuhocvba = " And " & s
        Exit Function
    End If
    re = Right(s_input, Len(s_input) - i)
    le = Left(s_input, i)
    tuhocvba = le & " And " & re
End Function
Nếu như đã đạt ý muốn của bạn thì phản hồi lại, và mình sẽ phản hồi giải thích code sau. Xin lỗi vì chưa có thời gian comment code cho bạn ngay được.
 
B

Bandit

Guest
Trước tiên cám ơn các anh đã giúp đỡ, em sẽ tải về và kiểm tra lại rồi sẽ phản hồi lại nhé.
 
B

Bandit

Guest
Code của các anh em thấy gần chính xác em mong muốn rồi, tuy còn một chỗ nhỏ như hình.
Bạn cần đăng nhập để thấy hình ảnh

Đó là em muốn chữ AND nó nối cái phần chục sau cùng, nếu 20 thì nó đọc đúng, mà 21..thì nó lại đọc "không đúng".
P/S: Do cách trình bày của em hơi rối dẫn đến mất thời gian anh chị sửa code, em mong các anh chị thông cảm ạ.
 

tuhocvba

Administrator
Thành viên BQT
Hàm USD code vẫn giữ nfguyên.
Hàm tuhocvba sẽ sửa lại:
Mã:
Function tuhocvba(ByVal s As String) As String
    Dim s_input As String
    Dim i   As Integer
'    Dim j   As Integer
    Dim re  As String
    Dim le  As String
    
    
    s_input = Trim(s)
    i = InStr(1, s_input, "Hundred")
    If i = 0 Then GoTo thvba
    'One Hundred
    If i + 6 = Len(s_input) Then  'len(Hundred) = 7
        tuhocvba = " And " & s
        Exit Function
    End If
    '116 => AND 100 AND 16
    re = Right(s_input, Len(s_input) - i - 6)
    le = Left(s_input, i + 6)
    tuhocvba = le & " And" & re
    Exit Function
thvba:
'    If Len(s_input) = 0 Then Exit Function
'    i = InStrRev(s_input, " ")
'    If i = 0 Then
'        tuhocvba = " And " & s
'        Exit Function
'    End If
'    re = Right(s_input, Len(s_input) - i)
'    le = Left(s_input, i)
'    tuhocvba = le & " And " & re
'==========================================
'16 => AND 16
    If s_input = "" Then Exit Function
    tuhocvba = " And " & s
End Function
Kết quả:
Bạn cần đăng nhập để thấy hình ảnh
 
B

Bandit

Guest
Code mà các anh sau khi sửa đã đúng những gì em mong muốn.
Em xin chân thành cảm ơn các anh đã dành thời gian giúp đỡ.
Xin chúc Forum phát triển và cảm ơn rất nhiều ạ.
 

tuhocvba

Administrator
Thành viên BQT
Ừ cám ơn em đã phản hồi. Cuối tuần rảnh (Chủ nhật), anh giải thích logic sửa code sau nhé. Bận quá nên anh cũng chưa comment vào code. Có thể đã đạt yêu cầu của em nhưng không giúp em tiến bộ nếu anh không nói rõ logic. Vậy chủ nhật, anh sẽ quay lại topic này giải thích sau.
P/S:
À mà cách trình bày của em cũng khá ổn đấy, nói chung là bài toán này cũng loằng ngoằng, trình bày yêu cầu đề bài như em cũng là tốt rồi. Chỉ phải xác nhận có một chút, nhỉ.
 
B

Bandit

Guest
Ừ cám ơn em đã phản hồi. Cuối tuần rảnh (Chủ nhật), anh giải thích logic sửa code sau nhé. Bận quá nên anh cũng chưa comment vào code. Có thể đã đạt yêu cầu của em nhưng không giúp em tiến bộ nếu anh không nói rõ logic. Vậy chủ nhật, anh sẽ quay lại topic này giải thích sau.
P/S:
À mà cách trình bày của em cũng khá ổn đấy, nói chung là bài toán này cũng loằng ngoằng, trình bày yêu cầu đề bài như em cũng là tốt rồi. Chỉ phải xác nhận có một chút, nhỉ.
Vâng anh. Em cám ơn đã góp ý ạ.
 

tuhocvba

Administrator
Thành viên BQT
Topic này đã được hỗ trợ code. Sau đây, tôi tái hiện lại quá trình hỗ trợ như sau.
1. Theo yêu cầu của topic này thì kết quả chỉ có một chữ And duy nhất nếu có.
Dựa theo code của USD thì ta thấy người ta đã xét And cho nó trong trường hợp đơn vị là lẻ (Cents).
Vì vậy tôi cho đoạn code xét Cents di chuyển lên trên, trước vòng lặp Loop. (Vòng lặp Loop là để xử lý số tiền chẵn).
Chả hạn ta có số tiền: 123456.78
Thì vòng lặp Loop xử lý phần 123456
Còn phần 78 là đoạn code cents như nói ở trên.
Vì chỉ có một chữ And cho nên ta tạo một biến cờ flag. Nếu kết quả đã có chữ And thì từ nay không cần quan tâm And nữa là vì có rồi.
Vậy mặc định flag = false (chưa có And).
Nếu có And thì dựng cờ flag = true và từ nay không xét nữa.
Bạn cần đăng nhập để thấy đính kèm

Như vậy nếu phần cents xử lý ra And thì phần Loop không cần tạo ra kết quả có And.
Ghép kết quả phần Loop(123456) với Cents(78) là xong.
Ngược lại nếu phần cents xử lý không ra And (chả hạn số tiền không lẻ, ví dụ 123000) thì không có cents và như vậy cents không có And.
Như thế kết quả có And hay không sẽ do phần Loop quyết định.
2. Phần Loop
Theo yêu cầu của đề bài, chữ And chỉ xuất hiện sau hàng nghìn tức là sau chữ Thousand.
Như vậy And có hay không sẽ do các phần tử arr(0), arr(1) quyết định.
Tức là trước khi xIndex = 2 (Thousand) thì ta phải chèn And vào.
Quá trình xử lý của nó như thế này:
Ví dụ ta có số tiền: 123456 thì nó sẽ đọc từ phải ra trái. Tức là đọc từ hàng đơn vị chục trăm ngàn triệu...
Như vậy ở ngay đầu vòng lặp, ngay khi xIndex = 2 (hàng ngàn), trước khi nó kịp xử lý thì ta chèn đoạn code của ta vào để thêm And.
Chính là phần tuhocvba(Dollars)
Bạn cần đăng nhập để thấy đính kèm


3. tuhocvba:
Giả sử ta có số tiền 123456 thì tuhocvba chỉ xử lý phần 456 và chèn And vào đó.
Đầu tiên xét xem 3 chữ số cuối có hàng trăm không. Do đó nó tìm có Hundred hay không, thể hiện qua ô tô đỏ ở dưới.

Bạn cần đăng nhập để thấy đính kèm

Ví dụ 3 chữ số cuối là 045 thì kết quả cần thể hiện là And 45.
Nếu là 045 tức là không có hàng trăm, tức là khi đó i = 0.
Bạn cần đăng nhập để thấy đính kèm


Nếu kết quả chỉ có hàng trăm mà không có phần đuôi. Ví dụ ba chữ số cuối là 400.
Thì ta muốn thể hiện kết quả là And 400. Hãy chú ý vào ô vuông đỏ đầu tiên.
Bạn cần đăng nhập để thấy đính kèm


Bình thường thì là có đủ 3 chữ số. Ví dụ 116 thì ta muốn kết quả thể hiện là 100 And 16.
Bạn cần đăng nhập để thấy đính kèm


Trên đây là toàn bộ logic. Tất nhiên trong thực tế, không ai ngồi đọc code mà lý giải hết được, điều các bạn nên làm là chặn code và thử nhập công thức trên excel rồi dùng F8, F5 để chạy từng dòng lệnh xem như thế nào. Hãy xem list video bài học của diễn đàn để có thêm kiến thức cơ bản nhé.
 
B

Bandit

Guest
Kiển thức VBA của em là con số 0, nên đọc giải thích của AD thì tạm thời chưa hiểu hết được, nhưng sẽ tìm hiểu dần dần cho tới lúc đọc có thể hiểu được. Một lần nữa em xin chân thành cảm ơn AD và anh chị đã giúp đỡ ạ.
 

Euler

Administrator
Thành viên BQT
Kiển thức VBA của em là con số 0
Thế thì bạn nên đi từ bài tập đơn giản trước. Đầu tiên đã muốn làm bài khó thì tác dụng phụ là sẽ cảm thấy sợ hãi và chán đấy.
List video hiện tại của diễn đàn cũng đang được xem xét. Có khi phải làm cho dễ hơn nữa.
 

tuhocvba

Administrator
Thành viên BQT
Không sao. Có thể vì thấy được khả năng tuyệt vời của VBA mà sẽ có thêm động lực để học.
Mình phải viết ngay suy nghĩ không có sau này quên mất. Mai mốt bạn có kiến thức thì quay lại tham khảo sau cũng được.
Topic đã được hỗ trợ đầy đủ nên cho phép mình khóa topic nhé.
 
Trạng thái
Không mở trả lời sau này.
Top