PDA

View Full Version : function đổi số thành chuổi



haiboss
09-09-2006, 08:04
trong MSsql anh chị nào đã viết Function đổi số thành chuổi ở dạng như sau
ví dụ : bằng số : 5210
bằng chữ : năm nghìn hai trăm mười đồng
anh chị nào viết rồi thì giúp em với em đang cần gấp lắm vì đang viết in hóa đơn mà gặp giá tiền bằng số thì phải viết ra bằng chữ.mong anh chị chỉ giúp em cảm ơn trước.

xbacala
11-09-2006, 21:36
thông thường người ta làm công việc này ở cấp ứng dụng chứ không làm ở cấp database vì database không mạnh về xử lý như ngôn ngữ lập trình ứng dụng.

Nếu bạn dùng NNLT họ VB thì có thể dùng cái hàm ở đây:
http://www.webketoan.com/forum/showthread.php?t=13195

Còn nếu muốn dùng ở SQL thì dựa vào giải thuật đó viết lại cho SQL Server !

haiboss
12-09-2006, 09:10
vậy khi bạn viết report ở dạng hóa đơn giống như hóa đơn điện thoại, diện, nước... ngoài số tiền bằng số còn có số tiền bằng chữ. mình dùng VB.Net và crystal report mình load data vào dataset để hiện ra trên crystal report ở phần số tiền bằng chữ mình không đổi ra được mình nghĩ là trong sqlserver có function nên mình đổi ra luôn bằng chữ để khi load data lên chỉ việc hiện ra thôi không sử lý gì nữa hết.
Bạn có ý kiến nào khác không giúp mình tí.Cảm ơn đã trả lời.

xbacala
12-09-2006, 11:05
tui cũng đã từng làm như bạn trong Crystal Report. Cách làm là define hàm dịch số ngay trong Cystal Report bằng Visual Basic luôn

Còn nếu bạn muốn viết hàm này trong SQL thì có thể dựa vào giải thuât trên để viết, tuy nhiên sẽ khó hơn vì T/SQL không hỗ trợ array.

Tạo 1 cái formular cho Cystal Report như sau (nhớ chọn Basic Syntax):

'--------------------------
Dim SoInput as String
SoInput=Cstr({SummarySales.Subtotal})

Dim KetQua As String, SoTien As String, Nhom As String, Dich As String
Dim Chu As String, S1 As String, S2 As String, S3 As String
Dim i , j , Vitri , S
Dim Hang, Doc, Dem
Dim KHONG_DONG,SO_LON,TRU,TRAM,MUOI,GIDO,NGANTY,TY,TRI EU,NGAN,DONG,XU
Dim MOT, HAI, BA, BON, NAM, SAU, BAY, TAM, CHIN ,CHAN, LE, MUOIMOT, MUOIMOTT

KHONG_DONG = "không đồng"
SO_LON = "số quá lớn"

TRU = "trừ"

TRAM = "trăm"
MUOI = "mươi"
GIDO = "gì đó"

NGANTY = "ngàn tỷ"
TY = "tỷ"
TRIEU = "triệu"
NGAN = "ngàn"
DONG = "đồng"
XU = "xu"

MOT = "một"
HAI = "hai"
BA = "ba"
BON = "bốn"
NAM = "năm"
SAU = "sáu"
BAY = "bảy"
TAM = "tám"
CHIN = "chín"

CHAN = "chẵn"
LE = "lẽ"
MUOIMOT = "mười một"
MUOIMOTT = "mươi mốt"


If CDBL(SoInput) = 0 Then
formula = KHONG_DONG
Else
If Abs(CDbl(SoInput)) >= 1000000000000000 Then
formula = SO_LON
Else
If CDBL(SoInput) <= 0 Then
SoInput = TRU & Space(1)
End If
SoTien = ToText(Abs(CDbl(SoInput)),"####################0.00")
SoTien = Right(Space(15) & SoTien, 18)
Hang = Array(TRAM, MUOI, GIDO)
Doc = Array(NGANTY, TY, TRIEU, NGAN, DONG, XU)
Dem = Array(MOT, HAI, BA, BON, NAM, SAU, BAY, TAM, CHIN)
For i = 1 To 6
Nhom = Mid(SoTien, i * 3 - 2, 3)
If Nhom <> Space(3) Then
Select Case Nhom
Case "000"
If i = 5 Then
Chu = DONG & Space(1)
Else
Chu = Space(0)
End If
Case ".00", ",00"
Chu = CHAN
Case Else
S1 = Left(Nhom, 1)
S2 = Mid(Nhom, 2, 1)
S3 = Right(Nhom, 1)
Chu = Space(0)
Hang(3) = Doc(i)
For j = 1 To 3
Dich = Space(0)
S = Val(Mid(Nhom, j, 1))
If S > 0 Then
Dich = Dem(S) & Space(1) & Hang(j) & Space(1)
End If
Select Case j
Case 2
if S = 1 then Dich = MUOI & Space(1)
if S = 0 And S3 <> "0" then
If ((S1 >= "1") And (S1 <= "9")) Or ((S1 = "0") And (i = 4)) Then
Dich = LE & Space(1)
End If
end if
Case 3
If S = 0 And Nhom <> Space(2) & "0" then Dich = Hang(j) & Space(1)
If (S = 5 And S2 <> Space(1) And S2 <> "0") then
Dich = "l" & Mid(Dich, 2)
End If
End Select
Chu = Chu & Dich
Next j
End Select
Vitri = InStr(1, Chu, MUOIMOT, 1)
'If Vitri > 0 Then Mid(Chu, Vitri, 9) = MUOIMOTT
KetQua = KetQua & Chu
End If
Next i
End If
End If
formula = UCase(Left(KetQua, 1)) & Mid(KetQua, 2)


- thay cái field red color trên thành field mà bạn muốn dịch số
- Kéo cái formular vào report để xài

haiboss
25-09-2006, 15:12
cảm ơn bạn rất nhiều

kuthanh88
17-04-2009, 23:57
ko biết là được hay ko nhưng thanks nhìu nhìu...

[=========> Bổ sung bài viết <=========]

anh Xbacala ơi giờ em bị vướng chỗ này. vì khi em khai báo tổng tiền là foat thì giờ load lên report sẻ là float vd: 12,278.00 giờ thì cái hàm của anh báo bad conver số sang chuỗi. Giúp em với, thnks nhìu

mtqanhct
26-06-2013, 09:34
bác ơi, em copy làm giống bác , nhưng báo lỗi :" the remaining text does not appear to be part of the formula". các bác sửa giúp em với , em đang rất cần. Da tạ các bác

chip07
03-07-2013, 15:56
Hơi muộn, nhưng vẫn up lên cho những bạn cần ^^




-- ref: http://dotnet-assembly.blogspot.com/2012/08/sql-server-query-to-convert-numbers.html
CREATE FUNCTION fnNumberToWords
(
@Number AS BIGINT
) RETURNS VARCHAR(MAX)

AS

BEGIN

DECLARE @Below20 TABLE (ID INT IDENTITY(0,1), Word VARCHAR(32))

DECLARE @Below100 TABLE (ID INT IDENTITY(2,1), Word VARCHAR(32))

DECLARE @BelowHundred AS VARCHAR(126)

INSERT @Below20 (Word) VALUES ('zero')
INSERT @Below20 (Word) VALUES ('one')
INSERT @Below20 (Word) VALUES ('two')
INSERT @Below20 (Word) VALUES ('three')
INSERT @Below20 (Word) VALUES ('four')
INSERT @Below20 (Word) VALUES ('five')
INSERT @Below20 (Word) VALUES ('six')
INSERT @Below20 (Word) VALUES ('seven')
INSERT @Below20 (Word) VALUES ('eight')
INSERT @Below20 (Word) VALUES ('nine')
INSERT @Below20 (Word) VALUES ('ten')
INSERT @Below20 (Word) VALUES ('eleven')
INSERT @Below20 (Word) VALUES ('twelve')
INSERT @Below20 (Word) VALUES ('thirteen')
INSERT @Below20 (Word) VALUES ('fourteen')
INSERT @Below20 (Word) VALUES ('fifteen')
INSERT @Below20 (Word) VALUES ('sixteen')
INSERT @Below20 (Word) VALUES ('seventeen')
INSERT @Below20 (Word) VALUES ('eighteen')
INSERT @Below20 (Word) VALUES ('nineteen')

INSERT @Below100 VALUES ('twenty')
INSERT @Below100 VALUES ('thirty')
INSERT @Below100 VALUES ('forty')
INSERT @Below100 VALUES ('fifty')
INSERT @Below100 VALUES ('sixty')
INSERT @Below100 VALUES ('seventy')
INSERT @Below100 VALUES ('eighty')
INSERT @Below100 VALUES ('ninety')

IF @Number > 99
BEGIN
SELECT @belowHundred = dbo.fnNumberToWords(@Number % 100)
END

DECLARE @NumberInWords VARCHAR(MAX)

SET @NumberInWords =
(
SELECT
CASE
WHEN @Number = 0 THEN ''
WHEN @Number BETWEEN 1 AND 19
THEN (SELECT Word FROM @Below20 WHERE ID = @Number)
WHEN @Number BETWEEN 20 AND 99
THEN (SELECT Word FROM @Below100 WHERE ID = @Number/10) + '-' + dbo.fnNumberToWords(@Number % 10)
WHEN @Number BETWEEN 100 AND 999
THEN (dbo.fnNumberToWords(@Number / 100)) + ' hundred ' +
CASE
WHEN @belowHundred <> ''
THEN 'and ' + @belowHundred ELSE @belowHundred
END
WHEN @Number BETWEEN 1000 AND 999999
THEN (dbo.fnNumberToWords(@Number / 1000)) + ' thousand ' + dbo.fnNumberToWords(@Number % 1000)
WHEN @Number BETWEEN 1000000 AND 999999999
THEN (dbo.fnNumberToWords(@Number / 1000000)) + ' million ' + dbo.fnNumberToWords(@Number % 1000000)
WHEN @Number BETWEEN 1000000000 AND 999999999999
THEN (dbo.fnNumberToWords(@Number / 1000000000)) + ' billion ' + dbo.fnNumberToWords(@Number % 1000000000)
ELSE ' INVALID INPUT'
END
)

SELECT @NumberInWords = RTRIM(@NumberInWords)
SELECT @NumberInWords = RTRIM(LEFT(@NumberInWords, LEN(@NumberInWords) - 1)) WHERE RIGHT(@NumberInWords, 1) = '-'

RETURN (@NumberInWords)

END

---------------------------------------------------------------------------------------
-- CREATE BY HienPTT - 2013.05.07
ALTER FUNCTION fnAmountToWords
(
@Amount NUMERIC(19,5)
) RETURNS NVARCHAR(4000)

AS

BEGIN

DECLARE @AmountP1 BIGINT
DECLARE @AmountP2 BIGINT
DECLARE @AmountInWords NVARCHAR(4000)

SELECT @AmountP1 = CAST(SUBSTRING(CAST(@Amount AS NVARCHAR(50)), 1, CHARINDEX('.',CAST(@Amount AS NVARCHAR(50))) - 1) AS BIGINT),
@AmountP2 = CAST(SUBSTRING(CAST(@Amount AS NVARCHAR(50)), CHARINDEX('.',CAST(@Amount AS NVARCHAR(50))) + 1, 5) AS BIGINT)

--SELECT @AmountP1, @AmountP2

SELECT @AmountP2 =
CASE
WHEN @AmountP2 % 100000 = 0 THEN @AmountP2 / 100000
WHEN @AmountP2 % 10000 = 0 THEN @AmountP2 / 10000
WHEN @AmountP2 % 1000 = 0 THEN @AmountP2 / 1000
WHEN @AmountP2 % 100 = 0 THEN @AmountP2 / 100
WHEN @AmountP2 % 10 = 0 THEN @AmountP2 / 10
ELSE @AmountP2
END

--SELECT @AmountP1, @AmountP2

--SELECT dbo.fnNumberToWords(@AmountP1), dbo.fnNumberToWords(@AmountP2)

IF dbo.fnNumberToWords(@AmountP1) = ''
SELECT @AmountInWords = NULL
ELSE
SELECT @AmountInWords = dbo.fnNumberToWords(@AmountP1) + ' dollars'

IF dbo.fnNumberToWords(@AmountP2) = ''
SELECT @AmountInWords = @AmountInWords
ELSE
SELECT @AmountInWords = ISNULL(@AmountInWords + ', ', '') + dbo.fnNumberToWords(@AmountP2) + ' cents'

IF ISNULL(@AmountInWords, '') <> ''
SELECT @AmountInWords = @AmountInWords + ' only.'

IF ISNULL(@AmountInWords, '') <> ''
SELECT @AmountInWords = UPPER(LEFT(@AmountInWords, 1)) + RIGHT(@AmountInWords, LEN(@AmountInWords) - 1)

RETURN (@AmountInWords)

END

GO

SELECT dbo.fnAmountToWords(505424555141.20100)

GO

-----------------------------------------------------------------------------------------
-- ref: http://dotnet-assembly.blogspot.com/2012/08/sql-server-query-to-convert-numbers.html
-- CREATE by HienPTT - 2013.05.10 - ref fnNumberToWords
CREATE FUNCTION fnNumberToWords_VN
(
@Number AS BIGINT,
@Exception AS INT -- 0: @Below20, 1: @Below20_VN
) RETURNS NVARCHAR(MAX)

AS

BEGIN

DECLARE @Below20 TABLE (ID INT IDENTITY(0,1), Word NVARCHAR(32))

DECLARE @Below100 TABLE (ID INT IDENTITY(2,1), Word NVARCHAR(32))

DECLARE @Below20_VN TABLE (ID INT IDENTITY(0,1), Word NVARCHAR(32))

DECLARE @BelowHundred AS NVARCHAR(MAX)

INSERT @Below20 (Word) VALUES (N'không')
INSERT @Below20 (Word) VALUES (N'một')
INSERT @Below20 (Word) VALUES (N'hai')
INSERT @Below20 (Word) VALUES (N'ba')
INSERT @Below20 (Word) VALUES (N'bốn')
INSERT @Below20 (Word) VALUES (N'năm')
INSERT @Below20 (Word) VALUES (N'sáu')
INSERT @Below20 (Word) VALUES (N'bảy')
INSERT @Below20 (Word) VALUES (N'tám')
INSERT @Below20 (Word) VALUES (N'chín')
INSERT @Below20 (Word) VALUES (N'mười')
INSERT @Below20 (Word) VALUES (N'mười một')
INSERT @Below20 (Word) VALUES (N'mười hai')
INSERT @Below20 (Word) VALUES (N'mười ba')
INSERT @Below20 (Word) VALUES (N'mười bốn')
INSERT @Below20 (Word) VALUES (N'mười lăm')
INSERT @Below20 (Word) VALUES (N'mười sáu')
INSERT @Below20 (Word) VALUES (N'mười bảy')
INSERT @Below20 (Word) VALUES (N'mười tám')
INSERT @Below20 (Word) VALUES (N'mười chín')

INSERT @Below100 VALUES (N'hai mươi')
INSERT @Below100 VALUES (N'ba mươi')
INSERT @Below100 VALUES (N'bốn mươi')
INSERT @Below100 VALUES (N'năm mươi')
INSERT @Below100 VALUES (N'sáu mươi')
INSERT @Below100 VALUES (N'bảy mươi')
INSERT @Below100 VALUES (N'tám mươi')
INSERT @Below100 VALUES (N'chín mươi')

INSERT @Below20_VN (Word) VALUES (N'không')
INSERT @Below20_VN (Word) VALUES (N'mốt') -- be used
INSERT @Below20_VN (Word) VALUES (N'hai')
INSERT @Below20_VN (Word) VALUES (N'ba')
INSERT @Below20_VN (Word) VALUES (N'tư') -- be used
INSERT @Below20_VN (Word) VALUES (N'lăm') -- be used

IF @Number > 99
BEGIN
SELECT @belowHundred = dbo.fnNumberToWords_VN(@Number % 100, 0)
END

DECLARE @NumberInWords NVARCHAR(MAX)

SET @NumberInWords =
(
SELECT
CASE
WHEN @Number = 0 THEN ''
WHEN @Number BETWEEN 1 AND 19
THEN (
CASE
WHEN @Exception = 0 THEN (SELECT Word FROM @Below20 WHERE ID = @Number)
ELSE (SELECT Word FROM @Below20_VN WHERE ID = @Number)
END
)
WHEN @Number BETWEEN 20 AND 99
THEN (SELECT Word FROM @Below100 WHERE ID = @Number/10) + ' ' + dbo.fnNumberToWords_VN(@Number % 10, 1)
WHEN @Number BETWEEN 100 AND 999
THEN (dbo.fnNumberToWords_VN(@Number / 100, 0)) + N' trăm ' +
(
CASE
WHEN (@Number % 100) < 10 THEN N'linh '
ELSE ''
END
) + @belowHundred
WHEN @Number BETWEEN 1000 AND 999999
THEN (dbo.fnNumberToWords_VN(@Number / 1000, 0))+ N' nghìn '+ dbo.fnNumberToWords_VN(@Number % 1000, 0)
WHEN @Number BETWEEN 1000000 AND 999999999
THEN (dbo.fnNumberToWords_VN(@Number / 1000000, 0)) + N' triệu '+ dbo.fnNumberToWords_VN(@Number % 1000000, 0)
WHEN @Number BETWEEN 1000000000 AND 999999999999
THEN (dbo.fnNumberToWords_VN(@Number / 1000000000, 0))+ N' tỷ '+ dbo.fnNumberToWords_VN(@Number % 1000000000, 0)
ELSE N' INVALID INPUT'
END
)

RETURN (@NumberInWords)

/**
Hỏi một câu các bác đừng cười. Quả thật là mình không còn nhớ quy tắc viết số 5 trong một dãy số như thế nào cho đúng nữa rồi ~X(
Nhờ bác nào còn nhớ thì có thể nhắc lại cho biết được không
Ví dụ dãy số này chẳng hạn thì viết thế nào : 1.505.555.005
15, 205 ...

Viết? Ý bạn là "viết bằng chữ" như cái dòng ký nhận tiền khi ... ra ngân hàng ý hả ;))
1.505.555.005: Một tỉ, năm trăm linh năm triệu, năm trăm năm mươi lăm nghìn, không trăm linh năm
15: mười lăm
205: hai trăm linh năm
Còn gì nữa không? đang muốn ngủ chiều, tiện thể đỡ phải đếm cừu :))

p/s còn quy tắc ý hả, ví dụ trong cụm 3 số ***
- Nếu là 5XX: viết là năm
- Nếu là X5X: viết là năm
- Nếu là XY5: Y>0: lăm; Y=0: năm
**/

END

GO

-----------------------------------------------------------------------------------------
-- CREATE BY HienPTT - 2013.05.10
CREATE FUNCTION fnAmountToWords_VN
(
@Amount BIGINT
) RETURNS NVARCHAR(4000)

AS

BEGIN
DECLARE @AmountInWords NVARCHAR(4000)

IF dbo.fnNumberToWords_VN(@Amount, 0) <> ''
SELECT @AmountInWords = dbo.fnNumberToWords_VN(@Amount, 0) + N' đồng chẵn.'

IF ISNULL(@AmountInWords, '') <> ''
SELECT @AmountInWords = UPPER(LEFT(@AmountInWords, 1)) + RIGHT(@AmountInWords, LEN(@AmountInWords) - 1)

RETURN (@AmountInWords)

END

GO

SELECT dbo.fnAmountToWords_VN(505424555141)

GO