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!
Cảm ơn bạn đã giúp đỡ.Bạn thử dùng hàm Jointext của bác ndu96081631 xem có được ko?![]()
Chào bạn, Mình đã test thử thấy kết quả đã đúng.Bạn thử dùng hàm Jointext của bác ndu96081631 xem có được ko?![]()
Thì bạn dùng hàm if để bắt lỗi.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ậ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.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
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: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 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ụ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!
=jointext(",",TRUE,IF([COLOR=#ff0000][B]($E$3:$E$20<>"")[/B][/COLOR]*($D$3:$D$20)=G3,$E$3:$E$20,""))
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
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ụ
Đ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.Mã:=jointext(",",TRUE,IF([COLOR=#ff0000][B]($E$3:$E$20<>"")[/B][/COLOR]*($D$3:$D$20)=G3,$E$3:$E$20,""))
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?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é.
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.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!
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.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.
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?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é!
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é.
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
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
=JoinIf(", ",$D$3:$D$20,G3,$E$3:$E$20)
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é!
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
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é!
=JoinIf(", ",$H$8:$H$100,[COLOR=#ff0000]"="&K8[/COLOR],$I$8:$I$100)
Ai lại làm thế! Hàm phải tổng quát chứ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:
Bài đó chưa có hay đâu, bài này mới đã nè!Hix!@ThầyNDU và Anh Nghĩa!
Em đã test cả 2 bài mới nhất và kết quả thật sự là đẹp mỹ mãn lắm rồi ạ...
Xin cảm ơn Thầy và Anh rất nhiều và nhân dịp đầu năm chúc Thầy và Anh luôn vui vẻ và mãi gắn bó với GPE để bầu trời tươi đẹp của thế hệ trẻ sau này được rộng mở.
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)
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
Em đã làm một cách tổng quát cho Hàm TextJoin và khi so sánh thì Hàm JoinIf còn nhiều trường hợp chưa chính xác.
Xem file.
=JoinIf(", ",$B$2:$B$94,E2,$C$2:$C$94)
=JoinIf(", ",$B$2:$B$94,[COLOR=#ff0000]"="&E2[/COLOR],$C$2:$C$94)
Không hẳn là cố tình đưa ra dữ liệu tào lao, mà vì:Còn cái chuyện Nghĩa cố tình đưa ra những dữ liệu tào lao để cố chứng minh rằng hàm tôi không chính xác thì tôi.. không quan tâm. Vì dữ liệu thật chẳng bao giờ như vậy cả
Ẹc... Ẹc...
Cái này như tôi đã nói ở trên: Thêm dấu "=" để so sánh rồi còn gìMột, có thể một lúc nào đó người ta định dạng kiểu d/m/y nhưng cũng có thể người ta định dạng kiểu khác thì hàm của Thầy chưa đáp ứng được.
Quá dễ, nếu muốn sửa codeHai, cũng tương tự hàm SUMIF, cột điều kiện là rỗng thì nó không tính
Cái này thì Nghĩa đã suy nghĩ quá xa rồi. Nối chuổi có bao giờ ra kết quả mấy ngàn từ không? Cho dù có ra được kết quả cũng chẳng đọc đượcBa, dùng hàm Evaluate để tính toán, với dữ liệu lớn chắc chắn 100% sẽ chậm hơn phép so sánh bằng.
Như ta đã biết, đã gọi là SO SÁNH thì không chỉ có SO SÁNH BẰNG. Còn có LỚN HƠN, NHỎ HƠN, KHÁC hoặc GẦN GIỐNG nữa... và JoinIf của tôi viết ra là để phục vụ cho nhu cầu này (gần giống với SUMIF)Cũng như Thầy nói, ai dùng hàm nào cũng được, miễn sao đáp ứng được hiệu quả nhu cầu của mình sử dụng.
Riêng việc đổi chiều dọc thành chiều ngang thì thêm vài phép tính nữa thôi mà Thầy. Quan điểm của em có thể viết thêm sửa đổi sao cho khi sử dụng người dùng cảm thấy đơn giản dễ hiểu, hiệu quả, nhanh chóng, chính xác, còn hàm có viết tràn lan đại hải cũng không sao (đâu ai quan tâm đến hàm SUM của Excel nó được viết thế nào, họ chỉ biết dùng mà thôi).
Cái này như tôi đã nói ở trên: Thêm dấu "=" để so sánh rồi còn gì
Thì dùng hàm JoinTextMột dữ liệu vừa là chuỗi, vừa là số, mà để dấu "=" thì đúng phần số và sai phần chuỗi, Thầy thử nghĩ coi, nếu phải mỗi ô mỗi công thức khác nhau thì sao được hả Thầy?
Na ná nghĩa là *Chuổi* ấy, đương nhiên là so sánh chuổi rồi. Code tôi dùng toán tử Like nên chẳng cần phải suy nghĩ gì nhiều, tự nhiên nó vẫn đạt được như vậy thôi (áp dụng giải thuật trong hàm Filter2DArray)Và việc so sánh na ná giống có lẽ phải dữ liệu bằng chuỗi thôi.
Dĩ nhiên trình độ em được học từ Thầy, nhưng đây là ý tưởng để Thầy hoàn thiện, bổ sung thêm cho nó hoàn chỉnh mà thôi, em không có ý gì đâu ạ.
Một lần nữa em xin cảm ơn Thầy và Anh Nghĩa đã nhiệt tình giúp đỡ!(Đã dời bài đúng box)