Hàm mảng động dynamic array và ứng dụng trong UDF trả về nhiều kết quả.

Liên hệ QC

Hau151978

Thành viên tích cực
Tham gia
19/10/11
Bài viết
1,477
Được thích
1,440
Chào các bạn, mình tham gia diễn đàn đã lâu, học hỏi được nhiều thứ từ các anh chị và các bạn. Hôm nay nhân lúc uống tý rượu, mình xin chia sẻ những tìm hiểu của mình về mảng động, một tính năng sắp áp dụng trên excel. Các công thức mới có thể dễ dàng tìm trên Google nên mình chỉ viết về hàm tự tạo (UDF) trong VBA.
Như chúng ta đã biết, khi viết hàm tự tạo và sử dụng trên sheet, Excel từ trước tới nay không cho phép thay đổi giá trị của các ô trên sheet trừ ô gọi hàm (không tính cách sử dụng công thức mảng, công thức mảng cũng không linh hoạt vì ta không biết có bao nhiêu giá trị trả về). Để “lách luật”, có lẽ cách đơn giản nhất là sử dụng Evaluate, hàm này sẽ gọi một thủ tục phụ để trả về giá trị. Ví dụ sau đây là hàm MultiVlookup tương tự Vlookup nhưng trả về nhiều giá trị nếu trùng khớp, hàm nhận đối số thứ nhất là giá trị dò, đối số thứ 2 là một cột, đối số thứ 3 có thể âm hay dương là vị trí tương đối của cột kết quả so với cột dò tìm tương tự như tham số của OFFSET, áp dụng cho mọi phiên bản Excel (hàm này mình tự viết chỉ để làm ví dụ nên không test kỹ, có thể còn một số lỗi, cái mà các bác hay gọi là "hàm co giãn" cũng tương tự):
Mã:
Option Explicit
Private KQ()
Function MultiVlookup(LookupValue, LookupCol As Range, Col&)
    Dim arr1(), arr2(), i&, k&, n&
    n = LookupCol.Rows.Count
    arr1 = LookupCol.Value
    arr2 = LookupCol.Offset(, Col).Value
    ReDim KQ(1 To n, 1 To 1)
    Application.Volatile
    For i = 1 To n
        If arr1(i, 1) = LookupValue Then
            If k = 0 Then
                MultiVlookup = arr2(i, 1)
            Else
                KQ(k, 1) = arr2(i, 1)
            End If
            k = k + 1
        End If
    Next
    If k > 1 Then Evaluate "xxx(" & Application.Caller.Offset(1).Resize(k - 1).Address(0, 0) & ")"
End Function
Sub xxx(Cl As Range)
    Cl = KQ
End Sub
Ta thấy xây dựng hàm trên khá phức tạp, mặc dù nếu là Sub thì quá đơn giản. Tuy nhiên tới đây, chức năng mảng động sẽ thay đổi căn bản các công thức Excel, 1 hàm có sẵn hoặc UDF có thể trả về mảng mà không cần dùng công thức mảng. Nếu là UDF thì chỉ việc gán kết quả là mảng, Excel sẽ xuất toàn bộ kết quả. Hiện tính năng này mới áp dụng cho Excel 365 đã đăng ký Office insider, bạn nào đang sử dụng phiên bản này có thể thử ví dụ sau đây MultiVlookup365 đơn giản hơn rất nhiều:
Mã:
Function MultiVlookup365(LookupValue, LookupCol As Range, Col&)
    Dim arr1(), arr2(), arrKQ(), i&, k&, n&
    n = LookupCol.Rows.Count
    arr1 = LookupCol.Value
    arr2 = LookupCol.Offset(, Col).Value
    ReDim arrKQ(1 To n)
    For i = 1 To n
        If arr1(i, 1) = LookupValue Then
            k = k + 1
            arrKQ(k) = arr2(i, 1)
        End If
    Next
    If k = 0 Then Exit Function
    ReDim Preserve arrKQ(1 To k)
    MultiVlookup365 = Application.WorksheetFunction.Transpose(arrKQ)
End Function
Mong nhận được ý kiến đóng góp của các bạn.
 

File đính kèm

Lần chỉnh sửa cuối:
Các Bạn nếu ai biết chút ADO ... SQL thì thử viết cái Hàm ( lấy dữ liệu cùng File hay File tạm keo đóng ) gõ trên 1 cells trả về 1 bảng dữ liệu Value đi xem tình hình sao ???!!!
nếu Bạn nào biết chút ADO thì sẻ là một lợi thế vì khi ta lọc dữ liệu sẻ truyền chuỗi SQL vào hàm đấy
....
Thuật ngữ code két với Mạnh là 1 cái chi đó xa vời nên Tạm keo cái chữ to màu đen trên phòng ai đó lại vặn vẹo nó đang co néc sao keo đóng thế thôi ....... Vui vẻ là chính và Mình hiểu làm chạy ok là Tốt thế thôi
 
Upvote 0
Mấy cái ký tự &,%,^,!... linh tinh kia là đồ cổ, không nên dùng, tránh xa ra.
Thời Bill Gates đưa ra ngôn ngữ Basic, lúc đó chương trình ghi trên băng đục lỗ, băng từ, đĩa mềm nhỏ, người ta mới dùng tới mấy ký tự đó để tiết kiệm kích thước mã nguồn chương trình lưu.
Giờ sau nay, theo coding standard thống nhất cho VB (và các ngôn ngữ khác), người ta đã bỏ và không cho dùng kiểu khai báo đó rồi, ở đây còn cố dùng, nhìn rối rắm,càng làm thêm phức tạp, hổ lốn....
Nguyên tắc viết code thì có 2 điểm quan trọng nhất sau:
1. Trong sáng, đơn giản nhất tới hết mức có thể
2. Ai đọc cũng hiểu, ai cũng có thể bảo trì nâng cấp sau này, không thì nó ngồi vừa fix vừa chửi cho nghe thúi đầu.
Ba cái goto, gosub, go nhảy tá lã lắc cái đầu, nhảy con mắt mệt nghĩ cũng tránh xa ra, dẹp đi. Viết sao cho người đọc đọc hiểu luồng thực thi hàm của mình chỉ 1 chiều từ trên xuống tới hết.
Tâm lý mấy anh mới học code hay code biết sơ sơ thì càng cố thích làm cho code mình "bờ rồ", rối rắm, phức tạp, như 1 đống bùi nhùi, chả ai hiểu gì.
Càng sau này thì người ta sẽ càng code trong sáng, rõ ràng hơn thôi.
Nguyên tắc khai báo biến của VB/VBA:
1. Khai báo rõ ràng ra kiểu của biến: vd As Long, As String, As Integer rõ ràng ra. Variant thì cũng phải là As Variant
2. Các biến cũng kiểu thì nên group chung nhóm lại. Nếu được thì 1 biến trên 1 hàng, tab vào.
3. Dùng các tiền tố (prefix) thống nhất cho các kiểu của biến, vd: s, str cho String, i, n cho Integer, l, lng cho Long, var cho Variant.
Chịu khó tìm đọc "Hungarian notation". Để có ở đâu cũng biết được biến đó loại gì.
4. Nếu tên biến là tiếng Anh thì nên là danh từ
5. Biến toàn cục trong module thì m_ trước, toàn cục toàn chương trình thì g_ trước.
.... vân vân và vân vân, còn nhiều, lười gõ.
Ai muốn làm theo thì làm, không thì thôi,
em viết code không theo quy luật gì hết hehehhehe
Nhiều lúc đọc lại không biết mình viết cái chi mô hehe
 
Lần chỉnh sửa cuối:
Upvote 0
Đây là help của MS viết năm 2018, trong đó ghi rõ "The shorthand for the types is: % -integer; & -long; @ -currency; # -double; ! -single; $ -string" chứ không phải chuyện thể hiện gì ở đây cả. Đặt tên biến kiểu Hungary cũng là một cách, mình thì không dùng kiểu này mà thường viết kiểu hỗn hợp chữ hoa và chữ thường, về sau mới thấy gọi là kiểu lạc đà.
Thiếu ký tự ^ là LongLong.
 
Upvote 0
Web KT

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

Back
Top Bottom