Đọc chữ thành số

Liên hệ QC

thaycung

Thành viên hoạt động
Tham gia
27/1/08
Bài viết
100
Được thích
87
Lần trước có lẽ do post bài không đúng chỗ, nên không có câu trả lời. Xin được làm lại.
[FONT=&quot]Tôi không hiểu về lập trình, có sưu tầm được đoạn code để đọc chữ thành số trong excel, nhưng không chạy được. Nhờ mọi người kiểm tra và sửa giúp. Xin cảm ơn!

Function CHUSO(so As Double) As String
Dim Chu As String, solop As Integer, so1 As Double, tg As Double
If so <= 0 Or so = Null Then
CHUSO = ""
End If
ReDim term(10) As String, lop(6) As Double, tlop(6) As String
term(1) = " mét"
term(2) = " hai"
term(3) = " ba"
term(4) = " bèn"
term(5) = " n¨m"
term(6) = " s¸u"
term(7) = " bÈy"
term(8) = " t¸m"
term(9) = " chÝn"
'-------------------
tlop(1) = ""
tlop(2) = " ngµn"
tlop(3) = " triÖu"
tlop(4) = " tû"
tlop(5) = " ngµn tû"
'----------------
so1 = so
solop = 1
Do While so1 > 0
tg = so1
so1 = Int(so1 / 1000)
lop(solop) = tg - so1 * 1000
solop = solop + 1
Loop
i = solop - 1
Chu = ""
Do While i > 0
so1 = lop(i)
If so1 > 0 Then
hangtram = so1 100
hangchuc = (so1 - hangtram * 100) 10
hangdonvi = so1 - (so1 10) * 10
If hangtram > 0 Then
'Chu so hang tram c¢ nghªa so1>=100
Chu = Chu + term(hangtram) + " tr¨m"
End If
'Xet chu so hang chuc
If hangchuc > 1 Then
Chu = Chu + term(hangchuc) + " m­¬i"
ElseIf hangchuc = 1 Then
Chu = Chu + " m­êi"
ElseIf hangchuc = 0 And so1 > 100 And hangdonvi <> 0 Then
Chu = Chu + " linh"
End If
' Xet ch§ s– h…ng ­ón v«
If hangdonvi <> 5 And hangdonvi <> 0 Then
Chu = Chu + term(hangdonvi)
ElseIf hangdonvi = 5 And hangchuc <> 0 Then
Chu = Chu + " l¨m "
ElseIf hangdonvi = 5 And hangchuc = 0 Then
Chu = Chu + " n¨m "
End If
Chu = Chu + tlop(i)
End If
' Xet lop ke tiep
i = i - 1
Loop
Chu = Trim(Chu)
If Chu <> "" Then
Chu = UCase(Left(Chu, 1)) & Right(Chu, Len(Chu) - 1)
End If
CHUSO = Chu
End Function

(Ghi chú: chữ một hai ba bốn ... trên với mã Font TCVN, bạn có thể đổi lại theo yêu cầu)
[/FONT]
 
Đây là code của tôi với Font Unicode.
PHP:
Function DocSo(Number) As String
Dim MyArray
Dim Str
Str = Format(Abs(Number), "000000000000000000")
MyArray = Array("không ", "m" & ChrW(7897) & "t ", "hai ", "ba ", "b" & ChrW(7889) & "n ", "n" & ChrW(259) & "m ", "sáu ", "b" & ChrW(7843) & "y ", "tám ", "chín ", "tri" & ChrW(7879) & "u, ", "ngàn, ", "t" & ChrW(7927) & ", ", "tri" & ChrW(7879) & "u, ", "ngàn, ", "", "tr" & ChrW(259) & "m ", "m" & ChrW(432) & ChrW(417) & "i ", "không " & "m" & ChrW(432) & ChrW(417) & "i" & " không ", "không " & "m" & ChrW(432) & ChrW(417) & "i", "l" & ChrW(7867), "m" & ChrW(432) & ChrW(417) & "i" & " không", "m" & ChrW(432) & ChrW(7901) & "i", "m" & ChrW(432) & ChrW(417) & "i" & " n" & ChrW(259) & "m", "m" & ChrW(432) & ChrW(417) & "i" & " l" & ChrW(259) & "m", "m" & ChrW(7897) & "t " & "m" & ChrW(432) & ChrW(417) & "i", "m" & ChrW(432) & ChrW(7901) & "i", "m" & ChrW(432) & ChrW(417) & "i" & " m" & ChrW(7897) & "t", "m" & ChrW(432) & ChrW(417) & "i" & " m" & ChrW(7889) & "t", "Âm ")
If Number = 0 Then
DocSo = MyArray(0)
Else
DocSo = ""
End If
For i = 1 To Len(Str)
If Left(Str, i) <> 0 And Mid(Str, (Int((i + 2) / 3) - 1) * 3 + 1, 3) <> 0 Then
    DocSo = DocSo & MyArray(Mid(Str, i, 1)) & MyArray(-(9 + i / 3) * (i Mod 3 = 0) - (15 + i Mod 3) * (i Mod 3 <> 0))
ElseIf i = 9 And Mid(Str, 7, 3) = 0 And Left(Str, 6) <> 0 Then
    DocSo = DocSo & MyArray(12)
End If
Next
DocSo = Trim(Replace(Replace(Replace(Replace(Replace(Replace(DocSo, MyArray(18), MyArray(15)), MyArray(19), MyArray(20)), MyArray(21), MyArray(22)), MyArray(23), MyArray(24)), MyArray(25), MyArray(26)), MyArray(27), MyArray(28)))
If Number < 0 Then
DocSo = MyArray(29) & DocSo
End If
DocSo = UCase(Left(DocSo, 1)) & Mid(DocSo, 2) & "."
End Function
 
Bạn thay 3 dòng 36 đến 38:
Nguyên bản:
Mã:
hangtram = so1 100
hangchuc = (so1 - hangtram * 100) 10
hangdonvi = so1 - (so1 10) * 10

thành:
Mã:
hangtram = int(so1 /100)
hangchuc = int((so1 - hangtram * 100)/10)
hangdonvi = so1 - hangtram*100 - hangchuc*10
 
Ở trên người ta hỏi:
ĐỔI CHỬ THÀNH SỐ mà bạn
Đổi số thành chữ đấy ndu ạ. Tác giả nhầm, bằng chứng là:

1.
Mã:
 Function CHUSO([COLOR="Red"]so[/COLOR] As Double) As String

2.
Mã:
so1 = so
solop = 1
Do While [COLOR="Red"]so1 > 0[/COLOR]
tg = so1
so1 =[COLOR="Red"] Int(so1 / 1000)[/COLOR]
lop(solop) = [COLOR="Red"]tg - so1 * 1000[/COLOR]
Có điều, tác giả hỏi lỗi code, không hỏi code mới.

yêu cầu tác giả xác nhận để đổi tiêu đề.
 
Sau khi thay đoạn code của sealand vào, tôi thấy hình như hàm ở trên chỉ đọc được số thành chữ chứ không phải đọc chữ thành số như tôi tưởng. Vậy có thể làm ngược lại là đọc chữ thành số được không?
 
Riêng vấn đề đọc chữ thành số mình xin có 1 chút tham gia: Không phải không làm được, nhưng kết quả đến đâu mới thành vấn đề. Ngôn ngữ tiếng Việt có quá nhiều trường hợp đặc biệt và tùy biến. Chỉ cần viết sai cú pháp, chính tả hay ngôn ngữ địa phương là kết quả khác đi rồi. Ví dụ: 204 đ theo bạn phải đọc sao đây:
-Hai trăm bốn đồng
-Hai trăm linh tư đồng.
-Hai trăm lẻ bốn đồng.
-Hai trăm không chục bốn đồng....
Bạn xem mấy phần mềm phiên dịch làm việc mà xem, các chuyên gia phần mềm họ cũng khá lúng túng nữa là chúng ta.
Hơn nữa, tính thực tiễn nó không bằng hàm dọc số ra chũ. Vậy nên để cho các nhà lập trình nghiên cứu tìm ra giải pháp cụ thể hơn.
 
Té ra là đổi chữ thành số thật. Nhầm là nhầm Function thôi.
Hàm Read(myStr) sau đây có thể đọc được chữ ra số nguyên.
- Chỉ cần đúng chính tả.
- bốn hay tư, nhăm hay lăm, lẻ hay linh, ngàn hay nghìn, ... không thành vấn đề.
- Font theo yêu cầu là font ABC
 

File đính kèm

  • Chu-So.xls
    30.5 KB · Đọc: 108
Lần chỉnh sửa cuối:
Mình thấy hàm của Ptm cũng là 1 giải pháp. Nhưng nó cũng chưa thể rào đón hết các trường hợp. Ví dụ:
-Mình gõ : "năm trăm ngàn" hàm cho số 5
-Cao hứng gõ cho chuẩn ngữ pháp: "Năm trăm ngàn" hàm báo lỗi

Ý mình nói là độ tin cậy trong thực tiễn. Nếu không thấy số chỉ thấy kết qua của hàm đọc số ra chữ ta cũng có thể yên tâm chi tiền. Nhưng không thấy chữ gốc chắc chưa ai dám chắc chi tiền theo số kết quả được
 
Cám ơn sealand.
Do làm nhanh nên còn lỗi, nhưng nghĩ lại, khó rào hết những lỗi số 1 như sealand nêu
Riêng lỗi số 2 (viết hoa đầu câu) có thể giải quyết được bằng hàm LCase()
 
Thưa các sư phụ! Em thì cho rằng đọc chử thành số dể hơn là đọc số thành chử đấy
Giải thuật em tạm nghĩ ra đại khái như sau:
- Giả sử ta có chuổi
năm trăm lẻ tám triệu, hai trăm năm mươi lăm nghìn không trăm hai mươi mốt.
- Ta lồng 2 dấu ( và ) vào đầu và cuối chuổi
(năm trăm lẻ tám triệu hai trăm năm mươi lăm nghìn không trăm hai mươi mốt.)
-Tiếp theo ta thay:
Không ... thành ... +0
Một ... ...thành ... +1
............
Chín ...ththành ... +9
Triệu
... thành ... )*1000000+(
Ngàn
... thành ... )*1000+(
Trăm
... thành ... *100
Mươi
... thành ... *10
Mười
... thành ... +10
lẻ
... ... thành ... +0
Mốt .....thành ... +1
vân vân ...
- Ta được
(5 *100 +0 +8)*1000000+(2*100 5*10 + 5)*1000 +(+0*100 +2*10 +1.)
-Evaluate chuổi này là ra kết quả
Đại khái thế
- Mấu chốt vấn đề là chia thành từng bộ 3 số 1 mà đọc (giống phân cách ngàn) dựa vào dấu hiệu nhận biết là TRIỆU, NGÀN, NGHÌN (nếu là TỶ, TRĂM TỶ hay NGHÌN TỶ thì cũng thế)
Em làm file này để test, nếu các sư phụ thấy ổn, có thể chuyển nó thành UDF

 

File đính kèm

  • Word2Num.xls
    23.5 KB · Đọc: 34
Lần chỉnh sửa cuối:
Ndu à, mình test:
mười hai triệu lẻ năm đồng thì không có kết quả.
 
Ndu à, mình test:
mười hai triệu lẻ năm đồng thì không có kết quả.
Ra chứ
Có điều ở trên chỉ là giải thuật, chưa Remove mấy dấu phẩy, chử đồng, xu gì gì đó
Nếu anh gỏ: Hai triêu lẻ năm thì ra ngay kết quả
Giải quyết vấn đề này rất dể, trước khi kết thúc sub, anh kết hợp thêm hàm TÁCH SỐ nữa là ra (dùng để loại hết các String thừa như Đồng, xu, VND... vân vân...)
------------
Anh tham khảo thêm file TÁCH SỐ này nha
 

File đính kèm

  • Word2Num_2.xls
    26.5 KB · Đọc: 41
Lần chỉnh sửa cuối:
Bạn nên chú ý nếu như ta đặt một chuỗi: Một triệu không trăm năm mươi ngàn đồng chẵn, thì mã của bạn sẽ không hiểu được, tôi sẽ làm một module hoàn toàn bằng VB/VBA. Để lựa chọn các trường hợp đổi từ chữ thành số có chút phức tạp hơn từ số ra chữ.
 
Riêng vấn đề đọc chữ thành số mình xin có 1 chút tham gia: Không phải không làm được, nhưng kết quả đến đâu mới thành vấn đề. Ngôn ngữ tiếng Việt có quá nhiều trường hợp đặc biệt và tùy biến. Chỉ cần viết sai cú pháp, chính tả hay ngôn ngữ địa phương là kết quả khác đi rồi. Ví dụ: 204 đ theo bạn phải đọc sao đây:
-Hai trăm bốn đồng
-Hai trăm linh tư đồng.
-Hai trăm lẻ bốn đồng.
-Hai trăm không chục bốn đồng....
Bạn xem mấy phần mềm phiên dịch làm việc mà xem, các chuyên gia phần mềm họ cũng khá lúng túng nữa là chúng ta.
Hơn nữa, tính thực tiễn nó không bằng hàm dọc số ra chũ. Vậy nên để cho các nhà lập trình nghiên cứu tìm ra giải pháp cụ thể hơn.
Bác nói đúng ý em quá, em mất cả một đêm tìm kiếm "Quy chuẩn các thông số đầu vào" vậy mà vẫn bó tay. Dân Việt mình nhiều khi có quan tâm gì đến chuẩn đâu, cứ viết sao thì viết thôi, nhưng nếu dùng các phần mềm để chuyển thì lại đơn giản hơn, vì số trường hợp là hữu hạn rồi và các hàm đọc số thành chữ cho dù thuật toán có khác nhau thì cách đọc vẫn giống nhau vậy là OK. Đằng này đọc chữ ra số có rất nhiều vấn đề cần nói:
- Để mà tìm hiểu và tăng tư duy sáng tạo thì tốt.
- Tính thiết thực là không có. Không ai lại đi viết thành chữ rồi dùng chương trình để chuyển thành số cả.
- Độ ổn định không cao, rất khó để kiểm tra nếu ta chuyển một lượng lớn các chuỗi thành số.
- Do ngôn ngữ Việt nam đa dạng và từ địa phương còn nhiều nên khó mà lường trước được vấn đề.
 
Bạn nên chú ý nếu như ta đặt một chuỗi: Một triệu không trăm năm mươi ngàn đồng chẵn, thì mã của bạn sẽ không hiểu được, tôi sẽ làm một module hoàn toàn bằng VB/VBA. Để lựa chọn các trường hợp đổi từ chữ thành số có chút phức tạp hơn từ số ra chữ.
Đó không phải là vấn đề lớn ---> Sửa quá dể luôn!
Quan trọng nhất vẫn là GIẢI THUẬT
Tôi không đồng ý ở điểm này:
Đằng này đọc chữ ra số có rất nhiều vấn đề cần nói:
- Do ngôn ngữ Việt nam đa dạng và từ địa phương còn nhiều nên khó mà lường trước được vấn đề.
Tôi cho rằng chuyển chử thành số là dể hơn làm ngược lại... Dù đọc kiểu gì thì vẩn có quy luật chung (TRIỆU, NGÀN...)
Ví dụ: một triệu năm trăm ngàn thì dù bạn đọc kiểu gì vẫn phải có chử TRIỆU (không thể khác)
---------------------------------------------
Lý ra tôi làm luôn cái Function này, nhưng vì:
- Tôi không mặn mà lắm mấy cái hàm đổi số, đổi chử
- Làm biếng chuyển mã mấy chử tiếng Việt
Ai có nhu cầu cứ việc phát triền tiếp, như giải thuật tôi đã trình bày ở trên: dựa vào sự nhận dạng dấu hiệu TRIỆU, NGÀN ... và theo tôi nó khá đơn giản!
--------------------------------------------
Nói thêm:
- Khi ta gõ 1 số, chưa chắc có thể đổi nó thành chử
- Nhưng nếu ta có thể "đọc số" thì điều hiển nhiên là có thể biến "chuổi số đang đọc" thành 1 số thực thụ, dù là đọc theo bất cứ kiểu gì (miển đừng đọc sai)
 
Lần chỉnh sửa cuối:
Lúc đưa đề tài này, tôi thấy khó sơi lắm, vì cách đọc đôi khi không thống nhất nên khó viết. Thấy các bạn viết, cũng muốn viết theo nhưng tìm thuật toán giải quyết quá khó, hôm nay mới góp bài cho các bạn được.
Từ các bài của các bạn đã viết, tôi mở rộng hơn cho đa dạng cách đọc và bảng mã. Cụ thể:
- 1 hàm ChuSangSo dùng chung cho cả 3 bảng mã VNI Windows, TCVN3 và Unicode. Hàm sẽ kiểm tra chuỗi số và chọn bảng mã cho phù hợp.
- Ngoài các từ thông dụng như không, một, hai, ..., chín, tỷ, triệu, ngàn, trăm, mươi, mười, lẻ còn cho phép nhập các từ tương tự như mốt, tư, lăm, tỉ, nghìn, chục, linh hoặc các từ có khả năng sai chính tả như lẽ, tỹ, tĩ.
- Hàm đọc đến 22 chữ số (nghìn tỷ tỷ)
Do số trong Excel chỉ chính xác chỉ đến 15 chữ số (ví dụ nhập số 12345678901234567 thì Excel ghi lại là 12345678901234600) nên nếu kết quả số <= 15 chữ số cho kết quả dạng số, từ 16 đến 22 chữ số cho kết quả dạng chuỗi.
Các bạn tải hàm ChuSangSo tại Đọc chữ ra số
 
Hàm của phamduylongndu9608161 đọc chính xác các số nguyên, nhưng còn số thập phân thì chưa được. Với file của ndu9608161 muốn lấy kết quả vào một cell nào đó thì làm thế nào?
Rất cảm ơn mọi người đã trợ giúp!
 
Hàm của phamduylongndu9608161 đọc chính xác các số nguyên, nhưng còn số thập phân thì chưa được. Với file của ndu9608161 muốn lấy kết quả vào một cell nào đó thì làm thế nào?
Rất cảm ơn mọi người đã trợ giúp!
Bài của tôi chỉ là gợi ý về giải thuật, nó vẫn chưa là 1 Function đâu, nếu muốn dùng bạn phải chỉnh code lại!
Còn bài của thầy Long vẫn chưa chính xác đâu!
Ví dụ:
Số tiền là hai mươi hai ---> Tịt
hai mươi hai đồng ---> Tịt
-----------------
Bạn lấy file này, theo tôi là chính xác đấy:
http://www.giaiphapexcel.com/forum/showpost.php?p=30611&postcount=13
Tuy nhiên vẫn chưa cái nào đọc số thập phân
---------------------
Nếu các cao thủ xây dựng hàm như giải thuật tôi đưa ở trên thì việc đọc thập phân cũng chẳng phải là vấn đề
- Cách đọc luôn thống nhất trong 1 nhóm 3 số
- Phần thập phân được nhận dạng = chử phẩy và tương đương với phép chia
Theo tôi chả có gì khó khăn cả (dể nữa là đàng khác)... có điều tôi chỉ oải nhất phần chuyển mã tiếng Việt (gõ 1 hồi thấy phát khùng... Mơ 1 ngày có thể gõ trực tiếp tiếng Việt trong cửa sổ lập trình)
Hic...
 
Lần chỉnh sửa cuối:
ndu96081631 đã viết:
Bài của tôi chỉ là gợi ý về giải thuật, nó vẫn chưa là 1 Function đâu, nếu muốn dùng bạn phải chỉnh code lại!
Còn bài của thầy Long vẫn chưa chính xác đâu!
Ví dụ:
Số tiền là hai mươi hai ---> Tịt
hai mươi hai đồng ---> Tịt
-----------------
Bạn lấy file này, theo tôi là chính xác đấy:
http://www.giaiphapexcel.com/forum/showpost.php?p=30611&postcount=13
Tuy nhiên vẫn chưa cái nào đọc số thập phân
Hàm ChuSangSo chưa xử lý các chuỗi như Số tiền là, đồng, ...

ndu96081631 đã viết:
Nếu các cao thủ xây dựng hàm như giải thuật tôi đưa ở trên thì việc đọc thập phân cũng chẳng phải là vấn đề
- Cách đọc luôn thống nhất trong 1 nhóm 3 số
- Phần thập phân được nhận dạng = chử phẩy và tương đương với phép chia
Theo tôi chả có gì khó khăn cả (dể nữa là đàng khác)... có điều tôi chỉ oải nhất phần chuyển mã tiếng Việt (gõ 1 hồi thấy phát khùng... Mơ 1 ngày có thể gõ trực tiếp tiếng Việt trong cửa sổ lập trình)
Hic...
Vấn đề này đã đề cập trong Đọc số thập phân (số lẻ) như thế nào là đúng ?
nhưng vẫn chưa giải quyết được vấn đề do khó mà thống nhất cách đọc. Nếu chỉ dùng chữ phẩy thì quá đơn giản.
Cách đọc phụ thuộc vào đơn vị của số.Ví dụ:
1,02: một đồng hai xu, một mét hai centimet, một mét hai mươi milimet
1,2: một đồng hai hào, một km hai trăm mét
...
 
Web KT
Back
Top Bottom