Nhập số và định dạng các ô số trên UserForm.

  • Thread starter Thread starter sealand
  • Ngày gửi Ngày gửi
Liên hệ QC

sealand

Thành viên gạo cội
Tham gia
16/5/08
Bài viết
4,883
Được thích
7,688
Giới tính
Nam
Nghề nghiệp
Kế Toán
Mình thường gặp khó khăn trong việc tạo và định dạng các đối tượng trên Form để nhập các giá trị số. Khi nhập số thường có nhu cầu như sau:
-Trong ô dù con trỏ ở đâu, nếu nhấn phím “-“ thì số trong ô được chuyển thành số âm, nếu đang số âm chuyển thành số dương.
-Chỉ nhập các số, dấu thập phân và dấu trừ. Ngoài ra không cho nhập và phát ra tiếng Beep cảnh báo nhập sai.
-Nhập số đến đâu định dạng ngay đến đó để người nhập dễ dàng nhận biết mình nhập đúng hay sai.
-Trong ô cho phép nhập tối đa bao nhiêu số thập phân.
-v.v…
Mình viết 3 hàm ngắn để trong 1 Module giải quyết vấn đề này như sau:

1/ Hàm LocSo:
+Tác dung: Lọc các ký tự nhập vào, nếu hợp lệ mới cho ô nhận. Ngoài ra, chặn lại và phát tiếng Beep cảnh báo.
+Cú pháp: LocSo(Ma)
Trong đó : -Ma là mã Ascii của phím nhập.
+Nội dung hàm:

Mã:
Function Locso(ByVal ma As Long) As Long
  If IsNumeric(Chr$(ma)) Then
  Locso = ma
  ElseIf ma = 45 Then
  Locso = 45
  ElseIf ma = 44 Or ma = 46 Then
  Locso = Asc(Application.DecimalSeparator)
  Else
  Locso = 0: Beep
  End If
  End Function
2/Hàm ToStr:
+Tác dụng: Chuyển 1 số, chuỗi dạng số hoặc chuỗi có thể chuyển thành số thành 1 chuỗi dạng số theo định dạng quy định trong Control Parnel.Cho phép chuyển thành số âm-dương bằng cách nhấn phím “-“ khi con trỏ ở bất cứ đâu trong ô. Hàm cũng hạn chế số thập phân theo yêu cầu.

+Cú pháp: ToStr(ch, n)
Trong đó:- ch là chuỗi cần chuyển.
-n số chữ số thập phân.
+ Nội dung hàm :

Mã:
Function ToStr(ByVal ch As String, n As Integer)
  Dim i, tam, Kt, Kt1
  Kt = Application.DecimalSeparator
  ch = Trim(ch)
  'Dua dau tru ve dau dong va chuyen 2 dau am thanh duong
  i = Len(ch) - Len(Replace(ch, "-", ""))
  ch = IIf(i = 1, "-", "") & Replace(ch, "-", "")
  'Dinh dang so
  If InStr(1, ch, Kt) > 0 Then
  tam = Split(ch, Kt)
  ToStr = Format(tam(0), "#,##0") & Kt & tam(1)
  Else
  ToStr = Format(ch, "#,##0")
  End If
  'Cat so thap phan
  If InStr(1, ToStr, Kt) > 0 Then ToStr = Left(ToStr, InStr(1, ToStr, Kt) + n)
  End Function
3/Hàm ToNum(ch)
+ Tác dụng : Chuyển các chuỗi đã định dạng thành số phục vụ tính toán hay nhập vào bảng tính
+ Cú pháp: ToNum(ch) (Trong đó ch là chuỗi số đã định dạng)

+Nội dung hàm:
Mã:
Function ToNum(ByVal ch As String)
  Dim Kt
  Kt = Application.ThousandsSeparator
  ToNum = Val(Replace(ch, Kt, ""))
  End Function
Mẹo bắt KeyAscii trên ô nhập số: Ta lợi dụng sự kiện KeyPress chỉ trả về mã KeyAscii của các phím ký tự, còn các phím chức năng như Enter, Alt,Shift, Fn….bỏ qua. Vậy ta đặt hàm LocSo ở đây là hợp lý nhất, ít ảnh hưởng đến chức năng của các phím chức năng.

VÍ DỤ ÁP DỤNG:
Giả sử ta có 1 Form và có 3 Textbox:
Textbox1: Nhập tiền hàng
Textbox2: Thuế VAT 10%
Textbox1: Tổng cộng

Yêu cầu: Nhâp số vào ô tiền hàng tự động tính lại và định dạng các ô
Sửa ô Thuế sẽ ccaapj nhật lại ô tổng cộng
Mã sử lý của Form:

Mã:
Option Explicit
  Private Sub TextBox1_Change()
  TextBox1 = ToStr(TextBox1, 2)
  TextBox2 = ToStr(ToNum(TextBox1) * 0.1, 2)
  TextBox3 = ToStr(ToNum(TextBox1) + ToNum(TextBox2), 2)
  End Sub
  ‘---------------------------------------------------------------------------------
  Private Sub TextBox2_Change()
  TextBox1 = ToStr(TextBox1, 2)
  TextBox3 = ToStr(ToNum(TextBox1) + ToNum(TextBox2), 2)
  End Sub
  ‘---------------------------------------------------------------------------------
  Private Sub TextBox2_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
  KeyAscii = Locso(KeyAscii)
  End Sub
  ‘----------------------------------------------------------------------------------
  Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
  KeyAscii = Locso(KeyAscii)
  End Sub
  ‘-----------------------------------------------------------------------------------
  Private Sub UserForm_Initialize()
  Me.TextBox1 = 0
  Me.TextBox1.SetFocus
  End Sub

Để cụ thể các bạn xem file ví dụ kèm theo.
Đây là Code mình viết và tặng tất cả các bạn chứ không chép từ đâu cả. Rất mong các bạn tham gia hoàn thiện để chúng ta có 1 hỗ trợ tạo Form trong VBA.
 

File đính kèm

Lần chỉnh sửa cuối:
Mình thường gặp khó khăn trong việc tạo và định dạng các đối tượng trên Form để nhập các giá trị số. Khi nhập số thường có nhu cầu như sau:
-Trong ô dù con trỏ ở đâu, nếu nhấn phím “-“ thì số trong ô được chuyển thành số âm, nếu đang số âm chuyển thành số dương.
-Chỉ nhập các số, dấu thập phân và dấu trừ. Ngoài ra không cho nhập và phát ra tiếng Beep cảnh báo nhập sai.
-Nhập số đến đâu định dạng ngay đến đó để người nhập dễ dàng nhận biết mình nhập đúng hay sai.
-Trong ô cho phép nhập tối đa bao nhiêu số thập phân.

Để cụ thể các bạn xem file ví dụ kèm theo.
Đây là Code mình viết tặng tất cả các bạn nên không lo về bản quyền. Rất mong các bạn tham gia hoàn thiện để chúng ta có 1 hỗ trợ tạo Form trong VBA.

Em nghĩ rằng phần này dùng
Private Sub TextBox1_AfterUpdate()
có vẻ tốt hơn.
Em xin phép edit 1 chút nhé. Phần TextBox1
PHP:
Option Explicit
Private Sub TextBox1_AfterUpdate()
'TextBox1 = ToStr(TextBox1, 2)
TextBox2 = ToStr(Round(ToNum(TextBox1) * 0.1, 2), 0)
TextBox3 = ToStr(ToNum(TextBox1) + ToNum(TextBox2), 2)
End Sub
Private Sub TextBox1_Change()
TextBox1 = ToStr(TextBox1, 2)
'TextBox2 = ToStr(ToNum(TextBox1) * 0.1, 2)
'TextBox3 = ToStr(ToNum(TextBox1) + ToNum(TextBox2), 2)
End Sub
Và phần

PHP:
Function ToStr(ByVal ch As String, n As Integer)
Dim i, tam, Kt, Kt1
Kt = Application.DecimalSeparator
ch = Trim(ch)
...
'Cat so thap phan
If InStr(1, ToStr, Kt) > 0 Then ToStr = Left(ToStr, InStr(1, ToStr, Kt) + n)
If Right(ToStr, 1) = "." Then
  ToStr = Left(ToStr, InStr(1, ToStr, Kt) + n - 1)
End If

End Function
thành
PHP:
'Cat so thap phan
If InStr(1, ToStr, Kt) > 0 Then ToStr = Left(ToStr, InStr(1, ToStr, Kt) + n)
If Right(ToStr, 1) = "." Then
  ToStr = Left(ToStr, InStr(1, ToStr, Kt) + n - 1)
End If
phần này có thể rút gọn lại.
Em thấy cứ nhập vào textbox_1 mà textbox_2 và 3 nhảy theo nhìn khó chịu và nhất là sợ chậm.
Nếu chưa đúng ý đồ, mong anh thông cảm.
 
Upvote 0
Thu Nghi à, phần định dạng thì phải dựa vào Change chứ dựa vào After_Update thì khó chịu lắm. Nhập cả dãy số mà luôn nơm nớp đúng sai thiếu thừa. Hơn nữa nếu để After_Update thì dùng hàm Format luôn khỏi phải UDF.
Còn việc nhảy số ô thuế và tổng cộng thì mỗi cái có 1 ưu điểm riêng. Bạn để ý 1 số phần mềm nhập tiền là nhảy số thuế và cộng, một số cập nhật xong mới tính. Đôi khi ta nhập 1 hóa đơn số quá mờ và ta nghi ngờ 1 vài số nếu cứ phải cập nhật xong mới phát hiện sai và quay lại sửa.
Riêng về tốc độ thì không ngại, vì khi cập nhật mã KH hay HH ta cũng soát từng ký tự. Khí đến ký tự tạo thành chuỗi mà không có mã nào bắt đầu như vậy thì mở bảng chọn. Việc làm đó còn lâu hơn nhiều mà vẫn thực hiện được
 
Upvote 0
Thu Nghi à, phần định dạng thì phải dựa vào Change chứ dựa vào After_Update thì khó chịu lắm. Nhập cả dãy số mà luôn nơm nớp đúng sai thiếu thừa. Hơn nữa nếu để After_Update thì dùng hàm Format luôn khỏi phải UDF.
Còn việc nhảy số ô thuế và tổng cộng thì mỗi cái có 1 ưu điểm riêng. Bạn để ý 1 số phần mềm nhập tiền là nhảy số thuế và cộng, một số cập nhật xong mới tính. Đôi khi ta nhập 1 hóa đơn số quá mờ và ta nghi ngờ 1 vài số nếu cứ phải cập nhật xong mới phát hiện sai và quay lại sửa.
Riêng về tốc độ thì không ngại, vì khi cập nhật mã KH hay HH ta cũng soát từng ký tự. Khí đến ký tự tạo thành chuỗi mà không có mã nào bắt đầu như vậy thì mở bảng chọn. Việc làm đó còn lâu hơn nhiều mà vẫn thực hiện được
Em chỉ nói là TextBox_1 change với định dạng , và . thôi còn định dạng TextBox_2, 3 thì nên cho khi TextBox_1 After_Update
Chớ khi After_Update change thì vd có 100 change theo ie định dạng theo thì khó nhìn.
 
Upvote 0
Vấn đề này em hỏi trên DĐ từ hôm qua đến giờ nhưng vẫn muốn hỏi thêm.
1- Theo em hiểu giải pháp anh Sea đưa ra có lẽ phù hợp với những người còn yếu về VBA như em. Tránh được trường hợp mắc đâu hỏi đó gây thiếu thiện cảm cho người trả lời.
2- Vẫn hỏi tiếp (???) tại File đính kèm về định dạng của Textbox3
 

File đính kèm

Upvote 0
Vấn đề này em hỏi trên DĐ từ hôm qua đến giờ nhưng vẫn muốn hỏi thêm.
1- Theo em hiểu giải pháp anh Sea đưa ra có lẽ phù hợp với những người còn yếu về VBA như em. Tránh được trường hợp mắc đâu hỏi đó gây thiếu thiện cảm cho người trả lời.
2- Vẫn hỏi tiếp (???) tại File đính kèm về định dạng của Textbox3
Thấy bạn làm đúng rồi TC=A+B
Vậy yêu cầu của bạn làm gì, mình xin phép trả lời thế anh Sealand để mình còn học hỏi.
 
Upvote 0
Thấy bạn làm đúng rồi TC=A+B
Vậy yêu cầu của bạn làm gì, mình xin phép trả lời thế anh Sealand để mình còn học hỏi.
Theo Em nghĩ có lẽ khi nhập số có thập phân ô tổng cộng vẫn là số nguyên.
VD: Textbox1 nhập 15.4 thì ô tổng cộng vẫn là 15
 
Upvote 0
To Minh Cong Thì bạn viết ToStr(so,0) cho ô kết quả thôi
To Truong Giang: Như Thu Nghi nói, mình cũng không hiểu bạn hỏi gì? Làm ơn cho rõ thêm.
Các bạn lưu ý: Khi số kết quả luôn thể hiện n số thập phân thì định dạng sau After_update chứ dùng trong Change thì hơi khó vì số 0 sẽ không biết là gõ vào hay thêm cho đủ n số thập phân.

Và đây là code chuyển định dạng ô TextBox1 sang 3 số thập phân, n=3 (Lưu ý trong Change của Textbox1 cũng ghi ToStr(Textbox1,3):

Mã:
Private Sub TextBox1_AfterUpdate()
Dim n, m
n = 3
m = Len(TextBox1) - InStr(1, TextBox1, Application.DecimalSeparator)
If m < Len(TextBox1) And m < n Then _
TextBox1 = TextBox1 & String(n - m + 1, "0")
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Ý mình là : Định dạng tại T1 và T2 thì tốt rồi nhưng định dạng tại T3 là vẫn có 1 số lẻ ở phần thập phân ý.
1/ Thêm hàm round
Private Sub TextBox2_Change()
TextBox1 = ToStr(TextBox1, 2)
TextBox3 = ToStr(Round(ToNum(TextBox1) + ToNum(TextBox2), 2), 0)
End Sub
2/ Bỏ dấu chấm, phần Function ToStr(ByVal ch As String, n As Integer)
Them đoạn
'Cat so thap phan
If InStr(1, ToStr, Kt) > 0 Then ToStr = Left(ToStr, InStr(1, ToStr, Kt) + n)
If
Right(ToStr, 1) = "." Then
ToStr
= Left(ToStr, InStr(1, ToStr, Kt) + n - 1)
End If
 
Upvote 0
Giờ mình mới hiểu câu hỏi:
+Muốn bỏ số thập phân của Textbox3 ta đổi tham số n của hàm ToStr(So,n) (n=0)
Cụ thể sửa sự kiện Change của T1 và T2 như sau
TextBox3 = ToStr(ToNum(TextBox1) + ToNum(TextBox2), 0)

+Muốn bỏ dấu thập phân của T3 ta dùng:
Mã:
Private Sub TextBox3_Change()
TextBox3 = Replace(TextBox3, Application.DecimalSeparator, "")
End Sub
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom