Giúp mình VBA này với

Liên hệ QC

ChinMuoi

Thành viên mới
Tham gia
17/2/19
Bài viết
3
Được thích
0
Mong giúp đỡ
Mình có 2 đoạn code dùng vba trên excel, không hiểu sao đoạn thứ nhất chạy được, đoạn thứ 2 không chạy được khi nhập số lớn hơn 33.
khó hiểu quá, mong các cao thủ giúp!
Bài đã được tự động gộp:

'TTmg

Public Function TTmg(sl As Integer, ten As String, mkh As String)

'ty le thue
Dim v As Double
mkh = Left(mkh, 3)
Select Case mkh
Case "LHA"
v = 1.15
Case "MTA"
v = 1.05
End Select



'gia truoc thue
Dim x As Integer
x = 20000


'khoi luong
Dim t As Integer
t = InStr(1, ten, "TB")
If t > 0 Then
sl = sl - 3
End If
If sl < 0 Then
sl = 0
End If

'thanh tien
TTmg = v * sl * x


End Function
Bài đã được tự động gộp:

Đoạn 2 như sau

'TTnc

Public Function TTnc(sl As Integer, ten As String, mkh As String)


'ty le thue
Dim v As Double
If mkh = "LHA 2499" Then
mkh = "MTA"
End If
mkh = Left(mkh, 3)
Select Case mkh
Case "LHA"
v = 1.15
Case "MTA"
v = 1.05
End Select

'gia truoc thue
Dim x, y, z, k As Integer
x = 8000
y = 9600
z = 11200
k = 11200
Dim t1 As Integer
t1 = InStr(1, ten, "KD")
If t1 > 0 Then
k = 20000
End If

'khoi luong
Dim t2 As Integer
t2 = InStr(1, ten, "TB")
If t2 > 0 Then
sl = sl - 3
End If

Dim a, b, c, d As Integer
b = 0
c = 0
d = 0
If sl <= 0 Then
a = 0
ElseIf sl <= 10 Then
a = sl
ElseIf sl <= 20 Then
a = 10
b = sl - 10
ElseIf sl <= 30 Then
a = 10
b = 10
c = sl - 20
ElseIf sl > 30 Then
a = 10
b = 10
c = 10
d = sl - 30
End If


'thanh tien
TTnc = v * (a * x + b * y + c * z + d * k)


End Function
 
Bạn sửa các biến thành Kiểu dữ liệu 8byte trở lên
Mã:
  Dim v# '-> As Double
  Dim x&, y&, z&, k& '-> As Long
  Dim t1&, t2& 
  Dim a&, b&, c&, d&
 
Bạn sửa các biến thành Kiểu dữ liệu 8byte trở lên
Mã:
  Dim v# '-> As Double
  Dim x&, y&, z&, k& '-> As Long
  Dim t1&, t2&
  Dim a&, b&, c&, d&

Tks bạn nhiều! mình đổi sang 8byte thì ok.
mà vẫn đang không hiểu, hôm trước mình đặt biến 4 byte rất ok, không lưu, giờ viết lại thì lỗi! (~_")
 
Tks bạn nhiều! mình đổi sang 8byte thì ok.
mà vẫn đang không hiểu, hôm trước mình đặt biến 4 byte rất ok, không lưu, giờ viết lại thì lỗi! (~_")
Bạn đọc 2 bài tôi viết hơn 5 năm trước thì bạn sẽ hiểu.

Bài #494
https://www.giaiphapexcel.com/diendan/threads/các-câu-hỏi-về-mảng-trong-vba-array.46834/post-548363

và

Bài #5
https://www.giaiphapexcel.com/diendan/threads/lỗi-vba-trong-việc-tính-toán-số-quá-lớn.90497/post-565069

Tùy trường hợp cụ thể mà không có lỗi (hôm trước mình đặt biến 4 byte rất ok) hoặc có lỗi (hôm nay mình đặt biến 4 byte nhưng không ok)
Ví dụ hôm trước và hôm nay
Mã:
Sub homqua()
Dim a As Long, b As Long, c As Long
    a = 120000000   ' 7 so 0
    b = 130000000   ' 7 so 0
    c = (a + b) / 2
    MsgBox c
End Sub

Sub homnay()
Dim a As Long, b As Long, c As Long
    a = 1200000000  ' 8 so 0
    b = 1300000000  ' 8 so 0
    c = (a + b) / 2
    MsgBox c
End Sub

Rõ ràng trong cả 2 trường hợp thì các giá trị nhập vào a, b và c đều nằm trong phạm vi kiểu dữ liệu Long, nhưng code homnay lại có lỗi.

Nguyên nhân là trước khi thực hiện phép chia cho 2 để có kết quả nhồi vào c thì kết quả (a + b) được "lưu vào nơi trung gian", và nó có kiểu "lớn nhất, "rộng nhất", "bao trùm" được cả 2 kiểu của a và b. Do a và b có kiểu Long nên kết quả trung gian có kiểu Long. Nhưng trong sub homnay thì a + b = 2 500 000 000, vượt quá giới hạn kiểu Long (từ -2 147 483 648 đến 2 147 483 647) nên sẽ có lỗi overflow.

Trong sub homqua có a + b = 250 000 000, vẫn trong giới hạn của kiểu Long nên không có lỗi.
-----------
Về vd. của bạn nếu có
Mã:
x = 8000
y = 9600
z = 11200
k = 11200

a = 10
b = 10
c = 10
d = sl - 30 = 4

TTnc = v * (a * x + b * y + c * z + d * k)

Thì trong quá trình tính a * x, b * y, c * z và d * k sẽ có lỗi overflow.

Do x, y, z, k, a, b, c, d đều có kiểu Integer nên các giá trị tính toán trung gian a * x, b * y, c * z và d * k cũng được gán cho kiểu Integer. Nhưng kết quả tính các giá trị trung gian đó lại cho kết quả 80 000, 96 000, 112 000, 44 800. Tất cả 4 giá trị trung gian này đều vượt quá giới hạn của kiểu Integer (từ -32 768 đến 32 767), vì thế sẽ có lỗi overflow
 
Code gì mà nhìn bắt hãi.
a, b, c,... là thừa số. Thường chỉ nên đặt cho biến dạng số thực.
x, y,... là trị số thực. Và cũng chỉ nên đặt cho biến dạng số thực.

Bạn sửa các biến thành Kiểu dữ liệu 8byte trở lên
Mã:
  Dim v# '-> As Double
  Dim x&, y&, z&, k& '-> As Long
  Dim t1&, t2&
  Dim a&, b&, c&, d&
Long trong VBA là 4 bytes, chỉ chứa đến hơn 2 tỷ 1 chút. Làm việc với tiền VN thì cũng có ngày tràn số.
Nếu hệ thống 64 bit thì phải dùng Long Long -> 8 bytes

Nhưng mà code bài này tính tiền. Vì vậy a, b, c phải khai dạng Double; và x, y khai dạng Currency mới đúng. Currency tính được đến gần triệu tỷ, và khá chính xác.
 
Bạn đọc 2 bài tôi viết hơn 5 năm trước thì bạn sẽ hiểu.

Bài #494
https://www.giaiphapexcel.com/diendan/threads/các-câu-hỏi-về-mảng-trong-vba-array.46834/post-548363

và

Bài #5
https://www.giaiphapexcel.com/diendan/threads/lỗi-vba-trong-việc-tính-toán-số-quá-lớn.90497/post-565069

Tùy trường hợp cụ thể mà không có lỗi (hôm trước mình đặt biến 4 byte rất ok) hoặc có lỗi (hôm nay mình đặt biến 4 byte nhưng không ok)
Ví dụ hôm trước và hôm nay
Mã:
Sub homqua()
Dim a As Long, b As Long, c As Long
    a = 120000000   ' 7 so 0
    b = 130000000   ' 7 so 0
    c = (a + b) / 2
    MsgBox c
End Sub

Sub homnay()
Dim a As Long, b As Long, c As Long
    a = 1200000000  ' 8 so 0
    b = 1300000000  ' 8 so 0
    c = (a + b) / 2
    MsgBox c
End Sub

Rõ ràng trong cả 2 trường hợp thì các giá trị nhập vào a, b và c đều nằm trong phạm vi kiểu dữ liệu Long, nhưng code homnay lại có lỗi.

Nguyên nhân là trước khi thực hiện phép chia cho 2 để có kết quả nhồi vào c thì kết quả (a + b) được "lưu vào nơi trung gian", và nó có kiểu "lớn nhất, "rộng nhất", "bao trùm" được cả 2 kiểu của a và b. Do a và b có kiểu Long nên kết quả trung gian có kiểu Long. Nhưng trong sub homnay thì a + b = 2 500 000 000, vượt quá giới hạn kiểu Long (từ -2 147 483 648 đến 2 147 483 647) nên sẽ có lỗi overflow.

Trong sub homqua có a + b = 250 000 000, vẫn trong giới hạn của kiểu Long nên không có lỗi.
-----------
Về vd. của bạn nếu có
Mã:
x = 8000
y = 9600
z = 11200
k = 11200

a = 10
b = 10
c = 10
d = sl - 30 = 4

TTnc = v * (a * x + b * y + c * z + d * k)

Thì trong quá trình tính a * x, b * y, c * z và d * k sẽ có lỗi overflow.

Do x, y, z, k, a, b, c, d đều có kiểu Integer nên các giá trị tính toán trung gian a * x, b * y, c * z và d * k cũng được gán cho kiểu Integer. Nhưng kết quả tính các giá trị trung gian đó lại cho kết quả 80 000, 96 000, 112 000, 44 800. Tất cả 4 giá trị trung gian này đều vượt quá giới hạn của kiểu Integer (từ -32 768 đến 32 767), vì thế sẽ có lỗi overflow

Tks bạn! vì sự tỷ mỉ, giúp ích rất nhiều!
Bài đã được tự động gộp:

Code gì mà nhìn bắt hãi.
a, b, c,... là thừa số. Thường chỉ nên đặt cho biến dạng số thực.
x, y,... là trị số thực. Và cũng chỉ nên đặt cho biến dạng số thực.


Long trong VBA là 4 bytes, chỉ chứa đến hơn 2 tỷ 1 chút. Làm việc với tiền VN thì cũng có ngày tràn số.
Nếu hệ thống 64 bit thì phải dùng Long Long -> 8 bytes

Nhưng mà code bài này tính tiền. Vì vậy a, b, c phải khai dạng Double; và x, y khai dạng Currency mới đúng. Currency tính được đến gần triệu tỷ, và khá chính xác.
Tks bạn!
 
Web KT
Back
Top Bottom