Friday, August 31, 2007

Function การแปลงตัวเลขเป็นตัวอักษร ด้วย Visual Basic .NET (ฉบับปรับปรุง 2014)

** แก้ไข 12/5/2014 ปรับปรุงไฟล์รูปภาพ **
( ดาวน์โหลดซอร์สโค้ดได้ที่ https://github.com/noomdev/ThaiBaht )

การเขียน Function เพื่อเปลี่ยนจากตัวเลขเป็นตัวอักษร นั้น ถือว่าเป็นเรื่องสุดคลาสสิกที่โปรแกรมเมอร์ทุกคนต้องสามารถ “เขียนได้” ข้อสอบเข้าทำงานของบริษัทต่างๆ ก็มีให้เขียนโปรแกรมแปลงตัวเลขเป็นตัวอักษรทั้งนั้น ดังนั้นจะเป็นการดีไหมที่โปรแกรมทุกคนควรเขียน Function เหล่านี้เอง และทำความเข้าใจ Logic ของโปรแกรมให้ถ่องแท้และปรับแต่งให้ดีสุด ให้โปรแกรมมีขนาดเล็ก และทำงานได้อย่างถูกต้องตามต้องการ ในบทความนี้ผมได้เขียน Function ชื่อ ThaiBaht ขึ้นมา ซึ่งเป็น Function ที่แปลงจากตัวเลขเป็นตัวอักษร เช่น 10 เป็น สิบ, 121 เป็น หนึ่งร้อยยี่สิบเอ็ด, 150.25 เป็น หนึ่งร้อยห้าสิบบาทยี่สิบห้าสตางค์ ตาม Code Listing ด้านล่างนี้

Listing 1 : Function ThaiBaht

Public Shared Function ThaiBaht(ByVal pAmount As Double) As String
        If pAmount = 0 Then
            Return "ศูนย์บาทถ้วน"
        End If

        Dim _integerValue As String ' จำนวนเต็ม
        Dim _decimalValue As String ' ทศนิยม
        Dim _integerTranslatedText As String ' จำนวนเต็ม ภาษาไทย
        Dim _decimalTranslatedText As String ' ทศนิยมภาษาไทย

        _integerValue = Format(pAmount, "####.00") ' จัด Format ค่าเงินเป็นตัวเลข 2 หลัก
        _decimalValue = Mid(_integerValue, Len(_integerValue) - 1, 2) ' ทศนิยม
        _integerValue = Mid(_integerValue, 1, Len(_integerValue) - 3) ' จำนวนเต็ม

        ' แปลง จำนวนเต็ม เป็น ภาษาไทย
        _integerTranslatedText = NumberToText(CDbl(_integerValue))

        ' แปลง ทศนิยม เป็น ภาษาไทย
        If CDbl(_decimalValue) = 0 Then
            _decimalTranslatedText = NumberToText(CDbl(_decimalValue))
        Else
            _decimalTranslatedText = ""
        End If

        ' ถ้าไม่มีทศนิม
        If _decimalTranslatedText.Trim = "" Then
            _integerTranslatedText += "บาทถ้วน"
        Else
            _integerTranslatedText += "บาท" & _decimalTranslatedText & "สตางค์"
        End If

        Return _integerTranslatedText
    End Function


Listing 2 : Function NumberToText

Private Shared Function NumberToText(ByVal pAmount As Double) As String
        ' ตัวอักษร
        Dim _numberText() As String = {"", "หนึ่ง", "สอง", "สาม", "สี่", "ห้า", "หก", "เจ็ด", "แปด", "เก้า", "สิบ"}

        ' หลัก หน่วย สิบ ร้อย พัน ...
        Dim _digit() As String = {"", "สิบ", "ร้อย", "พัน", "หมื่น", "แสน", "ล้าน"}
        Dim _value As String, _aWord As String, _text As String
        Dim _numberTranslatedText As String = ""
        Dim _length, _digitPosition As Integer

        _value = pAmount.ToString
        _length = Len(_value) ' ขนาดของ ข้อมูลที่ต้องการแปลง เช่น 122200 มีขนาด เท่ากับ 6

        For i As Integer = 0 To _length - 1 ' วนลูป เริ่มจาก 0 จนถึง (ขนาด - 1)
            ' ตำแหน่งของ หลัก (digit) ของตัวเลข
            ' เช่น
            ' ตำแหน่งหลักที่0 (หลักหน่วย)
            ' ตำแหน่งหลักที่1 (หลักสิบ)
            ' ตำแหน่งหลักที่2 (หลักร้อย)
            ' ถ้าเป็นข้อมูล i = 7 ตำแหน่งหลักจะเท่ากับ 1 (หลักสิบ)
            ' ถ้าเป็นข้อมูล i = 9 ตำแหน่งหลักจะเท่ากับ 3 (หลักพัน)
            ' ถ้าเป็นข้อมูล i = 13 ตำแหน่งหลักจะเท่ากับ 1 (หลักสิบ)
            _digitPosition = i - (6 * ((i - 1) \ 6))
            _aWord = Mid(_value, Len(_value) - i, 1)
            _text = ""
            Select Case _digitPosition
                Case 0 ' หลักหน่วย
                    If _aWord = "1" And _length > 1 Then
                        ' ถ้าเป็นเลข 1 และมีขนาดมากกว่า 1 ให้มีค่าเท่ากับ "เอ็ด"
                        _text = "เอ็ด"
                    ElseIf _aWord <> "0" Then
                        ' ถ้าไม่ใช่เลข 0 ให้หา ตัวอักษร ใน _numberText()
                        _text = _numberText(CInt(_aWord))
                    End If
                Case 1 ' หลักสิบ
                    If _aWord = "1" Then
                        ' ถ้าเป็นเลข 1 ไม่ต้องมี ตัวอักษร อื่นอีก นอกจากคำว่า "สิบ"
                        '_numberTranslatedText = "สิบ" + _numberTranslatedText
                        _text = _digit(_digitPosition)
                    ElseIf _aWord = "2" Then
                        ' ถ้าเป็นเลข 2 ให้ตัวอักษรคือ "ยี่สิบ"
                        _text = "ยี่" + _digit(_digitPosition)
                    ElseIf _aWord <> "0" Then
                        ' ถ้าไม่ใช่เลข 0 ให้หา ตัวอักษร ใน _numberText() และหาหลัก(digit) ใน _digit()
                        _text = _numberText(CInt(_aWord)) + _digit(_digitPosition)
                    End If
                Case 2, 3, 4, 5 ' หลักร้อย ถึง แสน
                    If _aWord <> "0" Then
                        _text = _numberText(CInt(_aWord)) + _digit(_digitPosition)
                    End If
                Case 6 ' หลักล้าน
                    If _aWord = "0" Then
                        _text = "ล้าน"
                    ElseIf _aWord = "1" And _length - 1 > i Then
                        _text = "เอ็ดล้าน"
                    Else
                        _text = _numberText(CInt(_aWord)) + _digit(_digitPosition)
                    End If
            End Select
            _numberTranslatedText = _text + _numberTranslatedText
        Next

        Return _numberTranslatedText
    End Function


อธิบาย
Function ThaiBaht เป็น function หลักในการทำงาน โดยมีหน้าที่จัดรูปแบบจำนวนเงินที่ส่งเข้ามาซึ่งมี data type เป็น double โดยทำการเปลี่ยนเป็น string ที่มีทศนิยม 2 หลัก และทำการแยกข้อมูล ตัวเลขจำนวนเต็ม กับ ตัวเลขทศนิยม ออกจากกัน จากนั้นจึงส่งข้อมูล ตัวเลขจำนวนเต็ม และ ตัวเลขทศนิยม ไปยัง function NumberToText ทีละตัว แล้วนำข้อความตัวอักษรมารวมกัน (concat) อีกครั้งก่อน return ตัวอักษรกลับไปทั้งหมด

ทดลองใช้งาน
1.สร้าง class ชื่อ sample.vb ใน Visual Basic .NET 2005 โดยมี function ทั้ง 2 ข้างต้น


2.สร้าง Form1 ให้มีหน้าตาตามรูป


3.เขียน code ดังนี้


   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
       MessageBox.Show(Sample.ThaiBaht(TextBox1.Text))
   End Sub

4.ลอง run และทดสอบผลลัพธ์


ลองนำไปประยุกต์และปรับปรุงได้ตามความเหมาะสมนะครับ

-- NooM --

16 comments:

Anonymous said...

ขอบคุณครับ
มีประโยชน์กับผมมากเลย
เขียนได้ดีครับ
เดียวจะลองเอาไปใช้ มีอะไรผิดพลาดจะแจ้งให้ทราบนะครับ

thk a lot

Anonymous said...

แปลงข้อมลจากตัวเลขเป็นตัวอักษร ได้แล้ว แต่การนำมาใช้ คือ กรอกตัวเลขลงText ให้อีกText เป็นตัวอักษรได้ แต่ตอนบันทึกข้อมูล มันขึ้น Error ว่า Conversion from string "" to type 'Double' is not valid.
จะแก้ error ยังไงค่ะ
ขอบคุณค่ะ

Unknown said...

ขอโทษครับทีตอบช้าไป
Error ที่บอกมากนั้นเกิดจากมันส่งค่าว่าง "" ไปแปลงเป็น Double ครับ ซึ่งมันแปลงไม่ได้ครับ
คุณควรตรวจสอบค่าก่อนว่าหากเป็น "" ให้กำหนดเป็น "0.00" ก่อนก็ได้ครับ

Unknown said...

คุณหน่องกอง
ยินดีน้อมรับข้อผิดพลาดครับ
;-)

Anonymous said...

พี่ค่ะ พอดีทำโปรเจ็คเกี่ยวกับ กองทุนหมู่บ้าน
มันต้องฝากเงิน แต่พอดีมีปัญหา ว่ามันฝากซ้ำเลขที่สมาชิกเดิมไม่ได้ ทำไงดี
คือต้องเก็บทุกครั้งที่ฝาก
ขอบคุณค่ะ

Anonymous said...

คุณ 111
แล้วทำไมจึงฝากซ้ำเลขสมาชิกเดิมไม่ได้ล่ะครับ

แมน said...

ขอบพระคุณมากครับ

KaiTunClub said...

ขอบคุณมาก

Anonymous said...

ผมไม่เข้าใจตรง

_digitPosition = i - (6 * ((i - 1) \ 6)) อะครับ ผมลองคิดแล้วยังไงออกมาก็เท่ากับ 1 ตลอดอะครับ หรือผมเข้าใจอะไรผิดหรือป่าวครับ

Unknown said...

เครื่องหมาย \ เป็นการหารเอาผลลัพธ์จำนวนเต็มเท่านั้น ดังนั้น
ถ้า i = 1
i - (6 * ((i - 1) \ 6))
= 1 - (6 * ((1 - 1) \ 6))
= 1 - (6 * 0)
= 1 - 0
= 1

ถ้า i = 7
i - (6 * ((i - 1) \ 6))
= 7 - (6 * ((7 - 1) \ 6))
= 7 - (6 * ((6) \ 6))
= 7 - (6 * 1)
= 1

Unknown said...

ถ้า i = 3
i - (6 * ((i - 1) \ 6))
= 3 - (6 * ((3 - 1) \ 6))
= 3 - (6 * ((2) \ 6))
= 3 - (6 * 0)
= 3

ถ้า i = 8
i - (6 * ((i - 1) \ 6))
= 8 - (6 * ((8 - 1) \ 6))
= 8 - (6 * ((7) \ 6))
= 8 - (6 * 1)
= 2

Anonymous said...

thankyou naka
very good

Anonymous said...

ขอบคุณมากเลยนะครับ

ยังคิดอยู่เลยว่าถ้าต้องทำ function แบบนี้เอง
จะรอดมั้ยนะ (แต่ดูแล้วไม่น่ารอด ^,^)

ขอบคุณอีกครั้งครับ

Anonymous said...

ขอบคุณมาก ๆ จากใจจริงครับสำหรับความรู้ที่แบ่งปัน
วันใดที่ผมเขียนโปรแกรมเก่ง ผมจะนึกถึงบุญคุณผู้เขียนบทความดีๆแบบนี้ให้อ่าน

Unknown said...

ขอบคุณจากใจจริงครับ

Unknown said...

สวัสดีคับผม ผมมีเรื่องปรึกษาเกี่ยวกับ โปรแกรมแปลง ตัวเลขเป็นตัวอักษร ในVB ที่พี่เคยทำไว้อ่ะคับ http://noomdev.blogspot.com/2007/08/function-visual-basic.html ผมอยากจะสอบถามว่าพี่ใช้แกรมม่าอะไรในการเขียนอ่ะคับ โปรแกรมของพี่เป็นแนวทางให้ผมได้พัฒนาต่อเป็นโปรเจคของวิชา compiler อ่ะคับ รบกวนด้วยนะคับ ขอขอบพระคุณล่วงหน้าคับผม