Cách đọc số tiền thành chữ trong Excel bằng hàm VBA

Tạo hàm =DocSo(A1) đọc số tiền thành chữ tiếng Việt trong Excel: mã VBA đã kiểm thử, xử lý đúng linh, mốt, lăm, nghìn, triệu, tỷ; kèm bản cho Google Sheets.

Excel không có sẵn hàm đọc số tiền thành chữ tiếng Việt — thứ bắt buộc trên phiếu thu, phiếu chi, hoá đơn và hợp đồng. Cách chủ động và an toàn nhất là tự thêm một hàm VBA nhỏ tên DocSo: dán mã một lần, lưu file dạng .xlsm, sau đó gõ =DocSo(A1) là ra “Một triệu hai trăm năm mươi nghìn đồng”. Mã dưới đây đã được kiểm thử với các trường hợp khó như 105, 1015, 1000005, 2000300040.

1. Thêm hàm DocSo vào Excel

  1. Mở file Excel, nhấn Alt + F11 để mở cửa sổ Microsoft Visual Basic for Applications.
  2. Chọn menu Insert → Module.
  3. Dán toàn bộ mã ở mục 2 vào khung trống bên phải.
  4. Đóng cửa sổ VBA, quay lại Excel, chọn File → Save As và chọn kiểu Excel Macro-Enabled Workbook (*.xlsm). Nếu lưu .xlsx, mã sẽ bị xoá.
  5. Tại ô cần ghi bằng chữ, gõ =DocSo(A1).
Vì sao mã có “\u1ED9”?Trình soạn thảo VBA không lưu được chữ tiếng Việt có dấu (sẽ thành dấu hỏi). Vì vậy mỗi chữ có dấu được viết bằng mã Unicode, hàm U trong mã sẽ tự đổi lại thành chữ đúng.

2. Mã VBA hàm DocSo

Option Explicit

' Doi chuoi co ma \uXXXX thanh chu tieng Viet
Private Function U(ByVal s As String) As String
    Dim i As Long, r As String
    i = 1
    Do While i <= Len(s)
        If Mid$(s, i, 2) = "\u" Then
            r = r & ChrW(CLng("&H" & Mid$(s, i + 2, 4)))
            i = i + 6
        Else
            r = r & Mid$(s, i, 1)
            i = i + 1
        End If
    Loop
    U = r
End Function

Private Function ChuSo(ByVal d As Long) As String
    ChuSo = U(Split("kh\u00F4ng,m\u1ED9t,hai,ba,b\u1ED1n,n\u0103m,s\u00E1u,b\u1EA3y,t\u00E1m,ch\u00EDn", ",")(d))
End Function

Private Function Noi(ByVal a As String, ByVal b As String) As String
    If a = "" Then Noi = b Else Noi = a & " " & b
End Function

' Doc nhom 3 chu so; full = True thi doc ca "khong tram", "linh"
Private Function Doc3(ByVal n As Long, ByVal full As Boolean) As String
    Dim h As Long, t As Long, d As Long, s As String
    h = n \ 100
    t = (n \ 10) Mod 10
    d = n Mod 10
    If full Or h > 0 Then s = Noi(s, ChuSo(h) & " " & U("tr\u0103m"))
    If t = 0 Then
        If d > 0 Then
            If full Or h > 0 Then s = Noi(s, "linh")
            s = Noi(s, ChuSo(d))
        End If
    ElseIf t = 1 Then
        s = Noi(s, U("m\u01B0\u1EDDi"))
        If d = 5 Then
            s = Noi(s, U("l\u0103m"))
        ElseIf d > 0 Then
            s = Noi(s, ChuSo(d))
        End If
    Else
        s = Noi(s, ChuSo(t) & " " & U("m\u01B0\u01A1i"))
        If d = 1 Then
            s = Noi(s, U("m\u1ED1t"))
        ElseIf d = 5 Then
            s = Noi(s, U("l\u0103m"))
        ElseIf d > 0 Then
            s = Noi(s, ChuSo(d))
        End If
    End If
    Doc3 = s
End Function

' Doc so nho hon 1 ty
Private Function DocDuoiTy(ByVal n As Long, ByVal full As Boolean) As String
    Dim g(2) As Long, dv(2) As String, i As Long, s As String
    g(0) = n \ 1000000
    g(1) = (n \ 1000) Mod 1000
    g(2) = n Mod 1000
    dv(0) = " " & U("tri\u1EC7u")
    dv(1) = " " & U("ngh\u00ECn")
    dv(2) = ""
    For i = 0 To 2
        If g(i) > 0 Then
            s = Noi(s, Doc3(g(i), full) & dv(i))
            full = True
        End If
    Next i
    DocDuoiTy = s
End Function

Private Function DocNguyen(ByVal n As Double) As String
    Dim ty As Double, r As Double, s As String
    If n >= 1000000000# Then
        ty = Int(n / 1000000000#)
        r = n - ty * 1000000000#
        s = DocNguyen(ty) & " " & U("t\u1EF7")
        If r > 0 Then s = s & " " & DocDuoiTy(CLng(r), True)
        DocNguyen = s
    Else
        DocNguyen = DocDuoiTy(CLng(n), False)
    End If
End Function

' Dung trong o: =DocSo(A1)  hoac  =DocSo(A1,"") de bo chu "dong"
Public Function DocSo(ByVal SoTien As Double, Optional ByVal DonVi As Variant) As String
    Dim n As Double, s As String
    If IsMissing(DonVi) Then DonVi = U("\u0111\u1ED3ng")
    n = Int(Abs(SoTien) + 0.5)
    If n >= 1E+15 Then
        DocSo = "#SO QUA LON"
        Exit Function
    End If
    If n = 0 Then s = ChuSo(0) Else s = DocNguyen(n)
    If SoTien < 0 And n > 0 Then
        s = U("\u00C2m ") & s
    Else
        s = UCase$(Left$(s, 1)) & Mid$(s, 2)
    End If
    If DonVi <> "" Then s = s & " " & DonVi
    DocSo = s
End Function

3. Kết quả kiểm thử

Số=DocSo(số)
0Không đồng
15Mười lăm đồng
21Hai mươi mốt đồng
105Một trăm linh năm đồng
110Một trăm mười đồng
1.015Một nghìn không trăm mười lăm đồng
25.000Hai mươi lăm nghìn đồng
1.000.005Một triệu không trăm linh năm đồng
12.345.678Mười hai triệu ba trăm bốn mươi lăm nghìn sáu trăm bảy mươi tám đồng
2.000.300.040Hai tỷ ba trăm nghìn không trăm bốn mươi đồng

Một số tuỳ biến hay dùng:

  • Bỏ chữ “đồng”: =DocSo(A1,""). Thêm “chẵn” hoặc “./.” cho đúng mẫu phiếu: =DocSo(A1)&" chẵn./.".
  • Thích đọc “lẻ” thay vì “linh” (giọng miền Nam): trong mã, thay chữ "linh" bằng U("l\u1EBB").
  • Số có phần thập phân được làm tròn đến đồng; hàm đọc tối đa dưới 1 triệu tỷ.

4. Mở file .xlsm và dùng ở file khác

Khi mở lại file, Excel hiện thanh vàng Enable Content — bấm vào để hàm chạy. File tải từ email hoặc Internet có thể bị chặn macro hoàn toàn; chỉ khi chắc chắn file do chính bạn tạo, bấm chuột phải vào file → Properties → tích Unblock.

Muốn dùng hàm ở mọi file mà không phải dán lại: lưu một file chỉ chứa module này dưới dạng Excel Add-in (*.xlam), rồi bật nó trong File → Options → Add-ins → Manage: Excel Add-ins → Go.

Lưu ýExcel bản web (Excel for the web) và Excel trên điện thoại không chạy VBA. Excel cho Mac có hỗ trợ VBA, cách làm tương tự.

5. Lựa chọn khác: add-in đọc số có sẵn

Nhiều kế toán dùng các add-in đọc số tiếng Việt phổ biến (ví dụ bộ VnTools), cài xong có hàm đọc số dùng ngay, đôi khi hỗ trợ cả đọc ngoại tệ. Cú pháp tuỳ add-in và phiên bản. Chỉ tải từ trang chính thức của tác giả hoặc nguồn đáng tin; add-in Excel có toàn quyền chạy mã trên máy, file “đã chỉnh sửa” trôi nổi trên mạng có thể chứa mã độc. Đọc thêm cách nhận diện lừa đảo, phần mềm độc hại.

6. Google Sheets: hàm DOCSO bằng Apps Script

  1. Mở bảng tính, chọn Extensions → Apps Script (Tiện ích mở rộng → Apps Script).
  2. Xoá mã mẫu, dán đoạn mã dưới đây, bấm biểu tượng lưu.
  3. Quay lại trang tính, gõ =DOCSO(A1).
const SO = ['không', 'một', 'hai', 'ba', 'bốn', 'năm', 'sáu', 'bảy', 'tám', 'chín'];

function noi_(a, b) { return a === '' ? b : a + ' ' + b; }

function doc3_(n, full) {
  const h = Math.floor(n / 100), t = Math.floor(n / 10) % 10, d = n % 10;
  let s = '';
  if (full || h > 0) s = noi_(s, SO[h] + ' trăm');
  if (t === 0) {
    if (d > 0) {
      if (full || h > 0) s = noi_(s, 'linh');
      s = noi_(s, SO[d]);
    }
  } else if (t === 1) {
    s = noi_(s, 'mười');
    if (d === 5) s = noi_(s, 'lăm');
    else if (d > 0) s = noi_(s, SO[d]);
  } else {
    s = noi_(s, SO[t] + ' mươi');
    if (d === 1) s = noi_(s, 'mốt');
    else if (d === 5) s = noi_(s, 'lăm');
    else if (d > 0) s = noi_(s, SO[d]);
  }
  return s;
}

function docDuoiTy_(n, full) {
  const g = [Math.floor(n / 1e6), Math.floor(n / 1e3) % 1000, n % 1000];
  const dv = [' triệu', ' nghìn', ''];
  let s = '';
  for (let i = 0; i < 3; i++) {
    if (g[i] > 0) {
      s = noi_(s, doc3_(g[i], full) + dv[i]);
      full = true;
    }
  }
  return s;
}

function docNguyen_(n) {
  if (n >= 1e9) {
    const ty = Math.floor(n / 1e9), r = n - ty * 1e9;
    let s = docNguyen_(ty) + ' tỷ';
    if (r > 0) s = s + ' ' + docDuoiTy_(r, true);
    return s;
  }
  return docDuoiTy_(n, false);
}

/**
 * Đọc số tiền thành chữ tiếng Việt.
 * @customfunction
 */
function DOCSO(so, donVi) {
  if (donVi === undefined) donVi = 'đồng';
  const n = Math.round(Math.abs(so));
  let s = (n === 0) ? SO[0] : docNguyen_(n);
  if (so < 0 && n > 0) s = 'Âm ' + s;
  else s = s.charAt(0).toUpperCase() + s.slice(1);
  if (donVi !== '') s = s + ' ' + donVi;
  return s;
}

Trên Sheets đặt vùng Việt Nam, bỏ chữ “đồng” bằng =DOCSO(A1;""). Nếu cần trộn số tiền bằng chữ vào mẫu Word hàng loạt, xem bài trộn thư Mail Merge.

Zalo