Hàm nối chuổi theo điều kiện (1 người xem)

Liên hệ QC

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

Miền Cát Trắng

Thành viên hoạt động
Tham gia
18/5/13
Bài viết
171
Được thích
37
Xin chào các bạn,đầu xuân chúc các bạn luôn mạnh khỏe,luôn hạnh phúc và đạt nhiều thành công trong cuộc sống.
Tôi có một bài toán đã đề cập trong file kèm, các bạn xem và giúp mình với.
Cảm ơn!
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Bạn thử dùng hàm Jointext của bác ndu96081631 xem có được ko? --=0
Cảm ơn bạn đã giúp đỡ.
Bạn ơi vba mình còn kém quá, liệu có cách nào dùng với công thức?
(Hi,nhờ có file của bạn mà mình mới thấy file đính kém của mình gửi bị sai kết quả minh họa,cột table2 mình nhập sai tháng)
Cảm ơn bạn!
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn thử dùng hàm Jointext của bác ndu96081631 xem có được ko? --=0
Chào bạn, Mình đã test thử thấy kết quả đã đúng.
Nhưng có nhược điểm của hàm này mà mình không xử lý được là nếu ô nào không có dữ liệu nó sẽ hiển thị kết quả 0,lại phiền các bạn giúp mình khắc phục lỗi này với.
Cảm ơn bạn!
 
Upvote 0
Chào bạn, Mình đã test thử thấy kết quả đã đúng.
Nhưng có nhược điểm của hàm này mà mình không xử lý được là nếu ô nào không có dữ liệu nó sẽ hiển thị kết quả 0,lại phiền các bạn giúp mình khắc phục lỗi này với.
Cảm ơn bạn!
Thì bạn dùng hàm if để bắt lỗi.
Nếu A1="" thì "" còn lại sẽ là kết quả thu được nhờ hàm JoinText
 
Upvote 0
Thì bạn dùng hàm if để bắt lỗi.
Nếu A1="" thì "" còn lại sẽ là kết quả thu được nhờ hàm JoinText
Thật sự với hàm mảng và vba này mình chưa biết áp dụng cách của bạn thế nào nữa...mong được bạn chỉ thêm qua file kèm.

Cảm ơn bạn!
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Chào bạn, Mình đã test thử thấy kết quả đã đúng.
Nhưng có nhược điểm của hàm này mà mình không xử lý được là nếu ô nào không có dữ liệu nó sẽ hiển thị kết quả 0,lại phiền các bạn giúp mình khắc phục lỗi này với.
Cảm ơn bạn!
Hàm đó tôi cảm thấy khá rắc rối khi áp dụng, bạn dùng hàm này vậy:

[GPECODE=vb]
Option Explicit


Function TextJoin(ByVal ConditionalColumn As Range, _
ByVal ConditionalCell As Range, _
ByVal DataColumn As Range) As String

Dim ResultArr()
Dim Dict As Object
Dim r As Long, n As Long
Dim Item As String, CondCell As String
Dim CondColArr As Variant, DataColArr As Variant

CondCell = ConditionalCell.Value

If IsArray(ConditionalColumn) Then
CondColArr = ConditionalColumn
Else
ReDim CondColArr(1 To 1, 1 To 1)
CondColArr(1, 1) = ConditionalColumn
End If

If IsArray(DataColumn) Then
DataColArr = DataColumn
Else
ReDim DataColArr(1 To 1, 1 To 1)
DataColArr(1, 1) = DataColumn
End If

Set Dict = CreateObject("Scripting.Dictionary")

For r = 1 To UBound(CondColArr)
If CondColArr(r, 1) = CondCell Then
Item = DataColArr(r, 1)
If Not Dict.Exists(Item) And Item > "" Then
Dict.Add Item, Empty
ReDim Preserve ResultArr(0 To n)
ResultArr(n) = Item
n = n + 1
End If
End If
Next

If n Then
TextJoin = Join(ResultArr, ", ")
End If


End Function[/GPECODE]

Cách dùng như sau:

Giả sử cột A chứa tất cả điều kiện, cột B chứa dữ liệu và cột D chứa điều kiện, thì cột E có công thức như sau:

=TextJoin($A$1:$A$11,D1,$B$1:$B$11)

Rất giống hàng SUMIF phải không bạn? Có dễ dùng lắm không?

Lưu ý: Cột A và cột B phải có số hàng tương ứng nha bạn!
 

File đính kèm

Upvote 0
Thật sự với hàm mảng và vba này mình chưa biết áp dụng cách của bạn thế nào nữa...mong bạn chỉ chỉ thêm.
Cảm ơn bạn!
Hàm mảng hay hàm tự tạo cũng có quy luật chung mà bạn, bạn dùng if để biến đổi sẽ cho các kết quả như ý. Ví dụ
Mã:
=jointext(",",TRUE,IF([COLOR=#ff0000][B]($E$3:$E$20<>"")[/B][/COLOR]*($D$3:$D$20)=G3,$E$3:$E$20,""))
Đoạn màu đỏ là đoạn bắt lỗi trong If, thêm điều kiện cột E không rỗng. Bạn cứ thế triển khai thôi. Còn về cách sử dụng hàm JoinText thì bạn tìm trên diễn đàn sẽ có ngay.
 
Upvote 0
Cảm ơn anh Nghĩa,Cảm ơn mọi kết quả đã đúng với ý của em.
Có vấn đề em sẽ hồi âm lại.
Chúc GPE ngủ ngon và có nhiều giấc đẹp!
 
Upvote 0
Vì điều kiện tôi đưa ra là Cột Điều Kiện và Cột Dữ Liệu phải có số hàng tương ứng nên tôi đã sửa lại hàm cho gọn lại tí:

Mã:
Function TextJoin(ByVal ConditionalColumn As Range, _
                  ByVal ConditionalCell As Range, _
                  ByVal DataColumn As Range) As String
    
    Dim r As Long
    Dim Dict As Object
    Dim Item As String, CondCell As String
    Dim CondColArr As Variant, DataColArr As Variant
    
    CondCell = ConditionalCell.Value
    
    If IsArray(ConditionalColumn) Then
        CondColArr = ConditionalColumn
        DataColArr = DataColumn
    Else
        ReDim CondColArr(1 To 1, 1 To 1)
        ReDim DataColArr(1 To 1, 1 To 1)
        CondColArr(1, 1) = ConditionalColumn
        DataColArr(1, 1) = DataColumn
    End If
    
    Set Dict = CreateObject("Scripting.Dictionary")
    
    For r = 1 To UBound(CondColArr)
        If CondColArr(r, 1) = CondCell Then
            Item = DataColArr(r, 1)
            If Not Dict.Exists(Item) And Item > "" Then
                Dict.Add Item, Empty
            End If
        End If
    Next
    
[COLOR=#0000cd][B]    If Dict.Count Then[/B][/COLOR]
[COLOR=#0000cd][B]        TextJoin = Join(Dict.Keys, ", ")[/B][/COLOR]
[COLOR=#0000cd][B]    End If[/B][/COLOR]


End Function

--------------------------------------------------------------
Do làm một cách máy móc và vội vàng nên tôi đã thêm biến n và mảng ResultArr, bây giờ tôi đã sửa lại phần này!
 
Lần chỉnh sửa cuối:
Upvote 0
Hàm mảng hay hàm tự tạo cũng có quy luật chung mà bạn, bạn dùng if để biến đổi sẽ cho các kết quả như ý. Ví dụ
Mã:
=jointext(",",TRUE,IF([COLOR=#ff0000][B]($E$3:$E$20<>"")[/B][/COLOR]*($D$3:$D$20)=G3,$E$3:$E$20,""))
Đoạn màu đỏ là đoạn bắt lỗi trong If, thêm điều kiện cột E không rỗng. Bạn cứ thế triển khai thôi. Còn về cách sử dụng hàm JoinText thì bạn tìm trên diễn đàn sẽ có ngay.
Cảm ơn bạn.
Hàm này mình test không đúng với kết quả mong muốn nếu dữ liệu giống nhau chỉ lấy 1 giá trị.
Ngày 01-01-1900 dữ liệu là a và a thì kết quả lại là a,a theo kết quả mong muốn chỉ là thôi, lúc nào rảnh nếu không phiền bạn xem lại giúp mình nhé.
 

File đính kèm

Upvote 0
Cảm ơn bạn.
Hàm này mình test không đúng với kết quả mong muốn nếu dữ liệu giống nhau chỉ lấy 1 giá trị.
Ngày 01-01-1900 dữ liệu là a và a thì kết quả lại là a,a theo kết quả mong muốn chỉ là thôi, lúc nào rảnh nếu không phiền bạn xem lại giúp mình nhé.
Riêng dữ liệu của bạn đưa ra, cột điều kiện ở bảng 1 không có ngày 04/02/2014 và 05/02/2014 nha bạn, trong khi ở cột bảng 2 lại có ngày đó thì sao nó tính được?

Hàm ở bài vừa rồi (#921)tôi mới sửa lại nha, bạn copy về mà xài!
 
Upvote 0
Riêng dữ liệu của bạn đưa ra, cột điều kiện ở bảng 1 không có ngày 04/02/2014 và 05/02/2014 nha bạn, trong khi ở cột bảng 2 lại có ngày đó thì sao nó tính được?

Hàm ở bài vừa rồi (#921)tôi mới sửa lại nha, bạn copy về mà xài!
Cảm ơn anh Nghĩa hiện em đang sử dụng hàm mới cập của Anh nhưng chưa thấy lỗi để lập bảng dữ liệu xem có lỗi gì không em sẽ hồi âm lại,còn Dữ liệu này em cũng đã biết rồi. Nhưng cái lỗi mà em nêu ở 922 là đang phát sinh.

Một lần nữa cảm ơn Anh,Anh giữ gìn sức khỏe!
 
Upvote 0
Cảm ơn anh Nghĩa hiện em đang sử dụng hàm mới cập của Anh nhưng chưa thấy lỗi để lập bảng dữ liệu xem có lỗi gì không em sẽ hồi âm lại,còn Dữ liệu này em cũng đã biết rồi. Nhưng cái lỗi mà em nêu ở 922 là đang phát sinh.

Một lần nữa cảm ơn Anh,Anh giữ gìn sức khỏe!

Lỗi phát sinh là trùng dữ liệu nó không xử lý ở hàm JoinText, nhưng với hàm TextJoin của tôi thì đã xử lý việc trùng này và cấu trúc gọn gàng dễ sử dụng hơn nha bạn.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Lỗi phát sinh là trùng dữ liệu nó không xử lý ở hàm JoinText, nhưng với hàm TextJoin của tôi thì đã xử lý việc trùng này và cấu trúc gọn gàng dễ sử dụng hơn nha bạn.
Anh chưa ngủ ạ, vậy thì anh xem trường thêm trường hợp này nhé hàm TextJoin nếu định dạng khác nhau thì kết quả cũng sai hả Anh Nghĩa.
Ví dụ cùng 1 dữ liệu 1 ô em định dạng(Format) là "dd" và một ô là Value(number) thì kết quả bị sai lệch.
Anh xem file kèm nhé!
 

File đính kèm

Upvote 0
Anh chưa ngủ ạ, vậy thì anh xem trường thêm trường hợp này nhé hàm TextJoin nếu định dạng khác nhau thì kết quả cũng sai hả Anh Nghĩa.
Ví dụ cùng 1 dữ liệu 1 ô em định dạng(Format) là "dd" và một ô là Value(number) thì kết quả bị sai lệch.
Anh xem file kèm nhé!
Cho tôi hỏi, cột điều kiện luôn luôn là dạng ngày tháng phải không?
 
Upvote 0
Cảm ơn bạn.
Hàm này mình test không đúng với kết quả mong muốn nếu dữ liệu giống nhau chỉ lấy 1 giá trị.
Ngày 01-01-1900 dữ liệu là a và a thì kết quả lại là a,a theo kết quả mong muốn chỉ là thôi, lúc nào rảnh nếu không phiền bạn xem lại giúp mình nhé.

Bộ hàm nối chuổi mà tôi viết gồm có 2 hàm: JoinTextJoinIf. Bài này bạn nên dùng JoinIf mới đúng (vì liên quan đến Unique)
Hàm thế này:
Mã:
Function JoinIf(ByVal Delimiter As String, ByVal CriteriaArray, ByVal Criteria, Optional ByVal TargetArray) As String
  Dim aTmpCrit, aTmpDes, tmp1, tmp2, Arr(), dic As Object
  Dim bComp As Boolean, Chk As Boolean
  Dim i As Long, j As Long, k As Long, dTmpVal As Double
  Set dic = CreateObject("Scripting.Dictionary")
  If IsMissing(TargetArray) Then TargetArray = CriteriaArray
  aTmpCrit = ConvertTo1DArray(CriteriaArray)
  aTmpDes = ConvertTo1DArray(TargetArray)
  If (Not IsArray(aTmpCrit)) Or (Not IsArray(aTmpDes)) Then Exit Function
  On Error Resume Next
  bComp = (InStr("<>=", Left(Criteria, 1)) > 0)
  For i = LBound(aTmpDes) To UBound(aTmpDes)
    tmp1 = aTmpCrit(i): tmp2 = aTmpDes(i)
    If bComp And Len(Criteria) Then
      dTmpVal = CDbl(aTmpCrit(i))
      If Evaluate(dTmpVal & Criteria) Then dic.Add tmp2, ""
    Else
      If (Left(Criteria, 1) = "!") Then
        If Not (UCase(tmp1) Like UCase(Mid(Criteria, 2, Len(Criteria)))) Then dic.Add tmp2, ""
      Else
        If (UCase(tmp1) Like UCase(Criteria)) Then dic.Add tmp2, ""
      End If
    End If
  Next
  If dic.Count Then
    Arr = dic.Keys
    JoinIf = Join(Arr, Delimiter)
  End If
End Function
Tất cả được xử lý trên mảng.
---------------------------------------------------------------------------
Mặc khác, bạn đang dùng hàm JoinText version cũ đấy, mới nhất nó là thế này:
Mã:
Function JoinText(ByVal Delimiter As String, ParamArray Arrays()) As String
  Dim aTmp, Arr(), Item, tmp As String
  Dim i As Long, n As Long
  'On Error Resume Next
  For i = LBound(Arrays) To UBound(Arrays)
    aTmp = Arrays(i)
    If Not IsArray(aTmp) Then aTmp = Array(aTmp)
    For Each Item In aTmp
      If TypeName(Item) <> "Error" Then
        tmp = CStr(Item)
        n = n + 1
        ReDim Preserve Arr(1 To n)
        Arr(n) = tmp
      End If
    Next
  Next
  If n Then JoinText = Join(Arr, Delimiter)
End Function
--------------------
Với file của bạn thì cú pháp hàm dùng trên bảng tính là:
Mã:
=JoinIf(", ",$D$3:$D$20,G3,$E$3:$E$20)
 

File đính kèm

Upvote 0
@ThầyNdu:
Ui,Thầy! Có Anh nào Thấy hàm JoinText của Thầy không đạt hiệu quả nên Alô cho Thầy ạ... hix!-+*/
Em sẽ test kết quả ạ.
++++++++++
@Anh Nghĩa: Ý của em không nhất thiết dữ liệu của em định dạng kiểu ngày hay number nhưng em vô tình định dạng như vậy thì phát hiện sự cố đó để anh tìm giải pháp cho hoàn thiện hơn thôi ạ.Còn theo bài của anh em có thể định dạng sao cho kết quả đúng với ý của mình là được.
==========
Cảm ơn Thầy và Anh!Thật là khó lựa chọn khi có 2 bài đạt chuẩn ý -> bí mật! :)
 
Upvote 0
Anh chưa ngủ ạ, vậy thì anh xem trường thêm trường hợp này nhé hàm TextJoin nếu định dạng khác nhau thì kết quả cũng sai hả Anh Nghĩa.
Ví dụ cùng 1 dữ liệu 1 ô em định dạng(Format) là "dd" và một ô là Value(number) thì kết quả bị sai lệch.
Anh xem file kèm nhé!

Nếu cột điều kiện đều là dạng DATE thì hàm này chỉ viết riêng cho trường hợp của bạn:

Mã:
Function TextJoin(ByVal ConditionalColumn As Range, _
                  ByVal ConditionalCell As Range, _
                  ByVal DataColumn As Range) As String
    On Error Resume Next
    Dim r As Long
    Dim Dict As Object
    Dim Item As String, CondCell As Date
    Dim CondColArr As Variant, DataColArr As Variant
    CondCell = ConditionalCell.Value
    If IsArray(ConditionalColumn) Then
        CondColArr = ConditionalColumn
        DataColArr = DataColumn
    Else
        ReDim CondColArr(1 To 1, 1 To 1)
        ReDim DataColArr(1 To 1, 1 To 1)
        CondColArr(1, 1) = ConditionalColumn
        DataColArr(1, 1) = DataColumn
    End If
    Set Dict = CreateObject("Scripting.Dictionary")
    For r = 1 To UBound(CondColArr)
        If CDate(CondColArr(r, 1)) = CondCell Then
            Item = DataColArr(r, 1)
            If Not Dict.Exists(Item) And Item > "" Then
                Dict.Add Item, Empty
            End If
        End If
    Next
    If Dict.Count Then
        TextJoin = Join(Dict.Keys, ", ")
    End If
End Function

Bạn muốn định dạng kiểu "quái" nào cũng được, miễn là từ DATE mà ra!
 

File đính kèm

Upvote 0
Anh chưa ngủ ạ, vậy thì anh xem trường thêm trường hợp này nhé hàm TextJoin nếu định dạng khác nhau thì kết quả cũng sai hả Anh Nghĩa.
Ví dụ cùng 1 dữ liệu 1 ô em định dạng(Format) là "dd" và một ô là Value(number) thì kết quả bị sai lệch.
Anh xem file kèm nhé!

File mới của bạn, nếu dùng hàm JoinIf của tôi thì sẽ thế này:
Mã:
=JoinIf(", ",$H$8:$H$100,[COLOR=#ff0000]"="&K8[/COLOR],$I$8:$I$100)
---------------------
Nếu cột điều kiện đều là dạng DATE thì hàm này chỉ viết riêng cho trường hợp của bạn:
Ai lại làm thế! Hàm phải tổng quát chứ
Trường hợp này nó giống với Advanced Filter và Filter đấy (dạng đặc biệt) và ta cũng phải lường trước trong code
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Web KT

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

Back
Top Bottom