Nhờ các Bác sửa code giúp Em những ô ko có kết quả thì hiện "" (1 người xem)

Liên hệ QC

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

Mình có gửi file và ghi chi tiết trong file. Mong các Bạn xem và giúp đỡ. Cảm ơn các Bạn nhiều!



Link tải file http://www.mediafire.com/view/?5cklkn8vtr1acz8

Hàm của bạn nên sửa lại như vầy:

[GPECODE=vb]
Public Function UniqueArray(ByVal Source As Variant) As Variant
Dim sArr As Variant
sArr = Source
If IsArray(sArr) Then
Dim sArray, item, dic, n As Long, iRow As Long
Set dic = CreateObject("Scripting.Dictionary")
iRow = UBound(sArr, 1) * UBound(sArr, 2)
iRow = IIf(iRow < 65536, 65536, iRow)
ReDim sArray(LBound(sArr) To iRow, 1 To 1)
For Each item In sArr
If Not IsEmpty(item) And Not dic.exists(item) Then
n = n + 1
dic.Add item, ""
sArray(n, 1) = item
End If
Next item
UniqueArray = sArray
Set dic = Nothing
Else
UniqueArray = sArr
End If
End Function
[/GPECODE]

Tôi dùng: iRow = IIf(iRow < 65536, 65536, iRow)

nhằm bảo đảm không bị lỗi N/A (tối thiểu không bị lỗi trong Excel 2003)

Khi kết quả khác với lọc duy nhất sẽ cho ra kết quả là 0, cái này định dạng lại hoặc bỏ check Zero Values là xong.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Hàm của bạn nên sửa lại như vầy:

[GPECODE=vb]
Public Function UniqueArray(ByVal Source As Variant) As Variant
Dim sArr As Variant
sArr = Source
If IsArray(sArr) Then
Dim sArray, item, dic, n As Long, iRow As Long
Set dic = CreateObject("Scripting.Dictionary")
iRow = UBound(sArr, 1) * UBound(sArr, 2)
iRow = IIf(iRow < 65536, 65536, iRow)
ReDim sArray(LBound(sArr) To iRow, 1 To 1)
For Each item In sArr
If Not IsEmpty(item) And Not dic.exists(item) Then
n = n + 1
dic.Add item, ""
sArray(n, 1) = item
End If
Next item
UniqueArray = sArray
Set dic = Nothing
Else
UniqueArray = sArr
End If
End Function
[/GPECODE]

Tôi dùng: iRow = IIf(iRow < 65536, 65536, iRow)

nhằm bảo đảm không bị lỗi N/A (tối thiểu không bị lỗi trong Excel 2003)

Khi kết quả khác với lọc duy nhất sẽ cho ra kết quả là 0, cái này định dạng lại hoặc bỏ check Zero Values là xong.


Bạn giúp mình đúng như mong muốn rồi. Cảm ơn Bạn nhiều nhé.
 
Upvote 0
Bạn giúp mình đúng như mong muốn rồi. Cảm ơn Bạn nhiều nhé.

Vẫn chưa phải là tối ưu đâu, hàm này tổng quát hơn:

[GPECODE=vb]Public Function UniqueArray(ParamArray Source()) As Variant
Dim SourceItem As Variant, SubItem As Variant, TmpArr As Variant
Dim Dict As Object, n As Double, Tmp As Variant
Set Dict = CreateObject("Scripting.Dictionary")
ReDim TmpArr(1 To 65536, 1 To 1)

For Each SourceItem In Source
Tmp = SourceItem
If Not IsArray(Tmp) Then Tmp = Array(Tmp)
For Each SubItem In Tmp
If Not IsEmpty(SubItem) And Not Dict.Exists(SubItem) Then
n = n + 1
Dict.Add SubItem, ""
TmpArr(n, 1) = SubItem
End If
Next
Next
UniqueArray = TmpArr
Set Dict = Nothing
End Function
[/GPECODE]

Bạn có thể sử dụng Hàm này với một hoặc nhiều vùng tham chiếu:

Công thức: =UniqueArray(D5:I17,L8:L11,D21:D36)

Kết thúc Ctrl+Shift+Enter

========================================================

Theo tôi thì tôi chả dùng công thức trong sheet, đã làm hàm tự tạo như thế này rồi thì cứ thế mà dùng macro "bụp" 1 phát thôi, và chiều dài (ubound(array)) của mảng phải hạn chế đúng với số phần tử của nó là hợp lý nhất. Còn hàm này tôi viết chỉ phục vụ cho việc dùng công thức trong sheet của bạn.

========================================================

Xin mọi người cho biết, tại sao với dòng này:

ReDim TmpArr(1 To 65536, 1 To 1)

Tôi thay số 65536 bằng một số lớn hơn, chẳng hạn 65537, thì khi đặt công thức trong sheet lại bị lỗi #Value?

Không lẽ một mảng trong sheet của Excel 2003 chỉ chứa được từng ấy hàng nên hơn lại phát sinh lỗi?
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn Bạn rất nhiều. Hay quá cái này đúng là mình đang cần tìm.
 
Upvote 0
Xin mọi người cho biết, tại sao với dòng này:

ReDim TmpArr(1 To 65536, 1 To 1)

Tôi thay số 65536 bằng một số lớn hơn, chẳng hạn 65537, thì khi đặt công thức trong sheet lại bị lỗi #Value?

Không lẽ một mảng trong sheet của Excel 2003 chỉ chứa được từng ấy hàng nên hơn lại phát sinh lỗi?

Bạn dùng công thức thì đúng thế.
Nếu bạn chạy sub test sau thì OK.

Mã:
Public Function UniqueArray(ParamArray Source()) As Variant
    ...
    ReDim TmpArr(1 To [COLOR=#ff0000]1000000[/COLOR], 1 To 1)
    
    ...
End Function

Sub test()
Dim arr
    arr = UniqueArray([D5:I17], [L8:L11], [D21:D36])
    Range("L13:L42").Value = arr
    
    Debug.Print LBound(arr) & " - " & UBound(arr)
End Sub

Theo tôi thì tôi chả dùng công thức trong sheet, đã làm hàm tự tạo như thế này rồi thì cứ thế mà dùng macro "bụp" 1 phát thôi, và chiều dài (ubound(array)) của mảng phải hạn chế đúng với số phần tử của nó là hợp lý nhất

Tôi cũng nghĩ thế. Và xin mời tham khảo code sửa như sau:

[GPECODE=vb]
Public Function UniqueArray(ParamArray Source())
Dim SourceItem, SubItem, TmpArr
Dim Dict As Object, Tmp
Set Dict = CreateObject("Scripting.Dictionary")

For Each SourceItem In Source
Tmp = SourceItem
If Not IsArray(Tmp) Then Tmp = Array(Tmp)
For Each SubItem In Tmp
If Not IsEmpty(SubItem) And Not Dict.Exists(SubItem) Then
Dict.Add SubItem, ""
End If
Next
Next

UniqueArray = Application.WorksheetFunction.Transpose(Dict.Keys)

Set Dict = Nothing
End Function

Sub Bup()
Dim arr
arr = UniqueArray([D5:I17], [L8:L11], [D21:D36])
Range("L13").Resize(UBound(arr)).Value = arr
End Sub
[/GPECODE]
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn dùng công thức thì đúng thế.
Nếu bạn chạy sub test sau thì OK.


Tôi cũng nghĩ thế. Và xin mời tham khảo code sửa như sau:

[GPECODE=vb]
Public Function UniqueArray(ParamArray Source())
Dim SourceItem, SubItem, TmpArr
Dim Dict As Object, Tmp
Set Dict = CreateObject("Scripting.Dictionary")

For Each SourceItem In Source
Tmp = SourceItem
If Not IsArray(Tmp) Then Tmp = Array(Tmp)
For Each SubItem In Tmp
If Not IsEmpty(SubItem) And Not Dict.Exists(SubItem) Then
Dict.Add SubItem, ""
End If
Next
Next

UniqueArray = Application.WorksheetFunction.Transpose(Dict.Keys)

Set Dict = Nothing
End Function

Sub Bup()
Dim arr
arr = UniqueArray([D5:I17], [L8:L11], [D21:D36])
Range("L13").Resize(UBound(arr)).Value = arr
End Sub
[/GPECODE]

Theo em thì em không làm hàm TRANSPOSE mà dùng vòng lặp để chuyển luôn. Với số liệu lớn thì hàm này làm chậm hơn cả dùng FOR ... NEXT.

Mã:
Public Function UniqueArray(ParamArray Source()) As Variant
    Dim SourceItem As Variant, SubItem As Variant
    Dim Dict As Object, n As Long, Tmp As Variant
    Set Dict = CreateObject("Scripting.Dictionary")
    For Each SourceItem In Source
        Tmp = SourceItem
        If Not IsArray(Tmp) Then Tmp = Array(Tmp)
        For Each SubItem In Tmp
            If Not IsEmpty(SubItem) And Not Dict.Exists(SubItem) Then
                n = n + 1
                Dict.Add SubItem, ""
            End If
        Next
    Next
    If n Then
        Dim Arr, TmpArr As Variant, i As Long
        Arr = Dict.Keys: n = n - 1
        ReDim TmpArr(0 To n, 1 To 1)
        For i = 0 To n
            TmpArr(i, 1) = Arr(i)
        Next
        UniqueArray = TmpArr
    End If
    Set Dict = Nothing
End Function

Làm hàm này em liên tưởng tới bài ĐỐ VUI VỀ VBA, Thầy dùng CLIPBOARD để chuyển dữ liệu. Thế nhưng lại liên quan đến Copy và Paste. Thủ tục thì được, trong hàm sẽ làm sao đây ta?
 
Upvote 0

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

Back
Top Bottom