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
- Mở file Excel, nhấn Alt + F11 để mở cửa sổ Microsoft Visual Basic for Applications.
- Chọn menu Insert → Module.
- Dán toàn bộ mã ở mục 2 vào khung trống bên phải.
- Đó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á.
- Tại ô cần ghi bằng chữ, gõ
=DocSo(A1).
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ố) |
|---|---|
| 0 | Không đồng |
| 15 | Mười lăm đồng |
| 21 | Hai mươi mốt đồng |
| 105 | Một trăm linh năm đồng |
| 110 | Một trăm mười đồng |
| 1.015 | Một nghìn không trăm mười lăm đồng |
| 25.000 | Hai mươi lăm nghìn đồng |
| 1.000.005 | Một triệu không trăm linh năm đồng |
| 12.345.678 | Mườ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.040 | Hai 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ằngU("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.
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
- Mở bảng tính, chọn Extensions → Apps Script (Tiện ích mở rộng → Apps Script).
- Xoá mã mẫu, dán đoạn mã dưới đây, bấm biểu tượng lưu.
- 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.