TẠO HÀM MỚI BẰNG VBA DỰA VÀO EVALUATE (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Tôi tuân thủ nội quy khi đăng bài

mrfeed87

Thành viên mới
Tham gia
5/11/21
Bài viết
33
Được thích
17
Giới tính
Nam
Chào các Bác, em đang tạo 1 hàm mới dựa vào Evaluate trong VBA
Em có tạo 1 ví dụ nhưng kết quả khi gõ bằng hàm excel lại khác với khi evaluate tính toán
Dù giống hệt nhau
Rất mong nhận được sự trợ giúp, cám ơn các Bác
1739606657949.png
 

File đính kèm

Chào các Bác, em đang tạo 1 hàm mới dựa vào Evaluate trong VBA
Em có tạo 1 ví dụ nhưng kết quả khi gõ bằng hàm excel lại khác với khi evaluate tính toán
Dù giống hệt nhau
Rất mong nhận được sự trợ giúp, cám ơn các Bác
View attachment 307099
Cột C, có những dòng không phải dạng số, nên dẫn đến kết quả không đúng

1739622840568.png
 
Upvote 0
Cột C, có những dòng không phải dạng số, nên dẫn đến kết quả không đúng

View attachment 307101
Cám ơn bạn
Cột C mình lấy dữ liệu qua truy vấn SQL nên nó chưa phải dạng số nên mình mới nhân thêm 1 ở chỗ hàm Lookup ở cột C
Vấn đề là Hàm excel cho ra kết quả đúng, Còn hàm tạo bằng VBA cũng tương tự như hàm excel lại cho ra kết quả khác
Mong bạn tìm hiểu thêm lý do
Cám ơn bạn
 
Upvote 0
Application.Evaluate là tính bắt đầu tại trang tính hiện hành
[Sheet].Evaluate là tính bắt đầu tại trang tính chỉ định
Application.Evaluate("'Sheet1'!A1") là tính tại trang tính hiện hành tham chiếu đến A1 Sheet1
rng.Address(0, 0, , 1) lấy toàn bộ đường dẫn tham chiếu thay cho rng.Address

Dựa vào đó mà bạn tính

Dữ liệu truy vấn SQL là ngày tháng, thì định dạng cột trong mảng thành yyyy/mm/dd hh:mm:ss, định dạng cột ghi là ngày tháng


Chuẩn hóa nghiêm ngặt khi viết hàm Excel vào Evaluate:
  1. Dấu tách đối số , và ; hoăc dấu . và , thập phân dùng Application.UseSystemSeparators, Application.DecimalSeparator,Application.International(xlDecimalSeparator )
  2. Dấu tách mảng {0\1\2\3;4\5\6\7} và {0,1,2,3;4,5,6,7}
  3. Dấu nhấy đôi (")
  4. Ngày tháng cần chuyển thành số: viết đúng là Evaluate("=A1<" & CDec(#20/12/2024#) & ")"
Lưu ý: Nếu UDF trong Evaluate thì Evaluate sẽ gọi VBA UDF đến 2 lần, lần thứ 2 mới có thể lấy được giá trị của tham chiếu có công thức.
 
Lần chỉnh sửa cuối:
Upvote 0
Application.Evaluate là tính bắt đầu tại trang tính hiện hành
[Sheet].Evaluate là tính bắt đầu tại trang tính chỉ định
Application.Evaluate("'Sheet1'!A1") là tính tại trang tính hiện hành tham chiếu đến A1 Sheet1
rng.Address(0, 0, , 1) lấy toàn bộ đường dẫn tham chiếu thay cho rng.Address

Dựa vào đó mà bạn tính

Dữ liệu truy vấn SQL là ngày tháng, thì định dạng cột trong mảng thành yyyy/mm/dd hh:mm:ss, định dạng cột ghi là ngày tháng


Chuẩn hóa nghiêm ngặt khi viết hàm Excel vào Evaluate:
  1. Dấu tách đối số , và ; dùng Application.UseSystemSeparators, Application.DecimalSeparator,Application.International(xlDecimalSeparator )
  2. Dấu tách mảng {0\1\2\3;4\5\6\7} và {0,1,2,3;4,5,6,7}
  3. Dấu nhấy đôi (")
  4. Ngày tháng cần chuyển thành số: viết đúng là Evaluate("=A1<" & CDec(#20/12/2024#) & ")"
Lưu ý: Nếu UDF trong Evaluate thì Evaluate sẽ gọi VBA UDF đến 2 lần, lần thứ 2 mới có thể lấy được giá trị của tham chiếu có công thức.
Vâng, Bác có thể sửa giúp e ở File trên để e hiểu hơn được không ạ
Cám ơn Bác
 
Upvote 0
Vấn đề nằm ở bảng truy vấn: A3 là 2, Bạn đã dùng =A3 để lấy số 2
Ở bài viết trên tôi có để lưu ý
 
Upvote 0
Vâng, Bác có thể sửa giúp e ở File trên để e hiểu hơn được không ạ
Sửa vào hàm của bạn thì không biết, nhưng viết hàm khác thì GPT làm ổn:
Mã:
Function HamDoTim(lookupValue As Variant, criteriaValue1 As Variant, criteriaValue2 As Variant) As Variant
    Dim ws As Worksheet
    Dim i As Long
    Dim lastMatch As Variant
    
    ' Xác d?nh Sheet ch?a d? li?u
    On Error Resume Next
    Set ws = ThisWorkbook.Sheets("THONG TIN CONG TY (BO SUNG)")
    If ws Is Nothing Then
        HamDoTim = CVErr(xlErrRef) ' L?i #REF! n?u không tìm th?y Sheet
        Exit Function
    End If
    On Error GoTo 0

    ' M?c d?nh k?t qu? là l?i n?u không tìm th?y
    lastMatch = CVErr(xlErrNA)
    
    ' L?p ngu?c t? dòng cu?i lên (gi?i h?n l?i 9999 n?u c?n)
    For i = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row To 2 Step -1
        If ws.Cells(i, 2).Value = lookupValue And _
           IsNumeric(ws.Cells(i, 3).Value) And _
           ws.Cells(i, 3).Value <= criteriaValue1 And _
           ws.Cells(i, 4).Value = criteriaValue2 Then
            
            lastMatch = ws.Cells(i, 5).Value
            Exit For ' D?ng vòng l?p khi tìm th?y k?t qu?
        End If
    Next i
    
    HamDoTim = lastMatch
End Function
 
Upvote 0
Hàm của bạn cần chuẩn hóa:


PHP:
Function DoTim(RngMaDonVi As Range, RngNgayThang As Range, RngTuTraCuu As Range) As Variant
  Dim x$, s$, z$
  If Application.UseSystemSeparators Then
    s = Application.International(xlDecimalSeparator)
  Else
    s = Application.DecimalSeparator
  End If
  x = IIf(s = ",", ";", ",")  '' ->  Tách đối số , và ;
  z = IIf(s = ",", "\", ",") '' ->  Mảng {0\1\2\3;4\5\6\7} và {0,1,2,3;4,5,6,7}
  Dim CongThuc As String
  CongThuc = _
        "=LOOKUP(1" & x & "1/" & _
        "(B3:B9999=" & "'" & RngMaDonVi.Parent.Name & "'!" & RngMaDonVi.Address & ")/" & _
        "(C3:C9999*1<=" & Replace(CDec(RngNgayThang.Value), ".", s) & ")/" & _
        "(D3:D9999=" & "'" & RngTuTraCuu.Parent.Name & "'!" & RngTuTraCuu.Address & ")" & x & "" & _
        "E3:E9999)"
  
  '' Sai -> RngMaDonVi.Address    "'" & RngMaDonVi.Parent.Name & "'!" &  RngMaDonVi.Address
  '' Sai -> RngNgayThang.Address
  '' Sai -> RngTuTraCuu.Address
 
  '' Sai -> B2:B9999   'Sheet'!B2:B9999
  '' Sai -> C2:C9999
  '' Sai -> D2:D9999
  '' Sai -> E2:E9999

  DoTim = Application.Evaluate(CongThuc)
  '' Sai -> Application.Evaluate(CongThuc)
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Mục đích của hàm UDF này là gì?
Nếu chỉ để học cách dùng Evaluate thì chịu khó đi học thêm lý thuyết, phần không gian định danh (namespace)
Nếu chỉ dùng để giản dị hóa một công thức dài và phức tạp thì nên học cách dùng hàm Lambda. Vừa chuẩn hơn, vừa giúp cho file không phải mang tiếng chứa macro.
 
Upvote 0
Web KT

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

Back
Top Bottom