Xây dựng hàm nối chuỗi ký tự theo nhiều cột, dòng và loại bỏ ô trống

Liên hệ QC

Pham Dinh Ca

Thành viên mới
Tham gia
22/10/17
Bài viết
46
Được thích
1
Giới tính
Nam
Nghề nghiệp
Thất Nghiệp
Gửi ACE trong diễn đàn!

Mình có 1 bài toán ntn:

Mong các cao nhân giúp đỡ là viết hàm nào có thể cho ra kết quả như bảng đưa ra và có thể áp dụng như 1 hàm mảng

Và tất nhiên sẽ thực hiện trên googlesheet


1595919674010.png
Xin cảm ơn ạ
 
Gửi ACE trong diễn đàn!

Mình có 1 bài toán ntn:

Mong các cao nhân giúp đỡ là viết hàm nào có thể cho ra kết quả như bảng đưa ra và có thể áp dụng như 1 hàm mảng

Và tất nhiên sẽ thực hiện trên googlesheet


View attachment 241945
Xin cảm ơn ạ
PHP:
Option Explicit
Function JoinText(ByVal Delimiter As String, ParamArray Arrays()) As String
  Dim aTmp, arrDes(), Item, tmp As String
  Dim idx As Long, n As Long
  'On Error Resume Next
  For idx = LBound(Arrays) To UBound(Arrays)
    aTmp = Arrays(idx)
    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 arrDes(1 To n)
        arrDes(n) = tmp
      End If
    Next
  Next
  If n Then JoinText = Join(arrDes, Delimiter)
End Function
Function UniqueList(ParamArray sArray())
  Dim Item, tmpArr, SubArr, tmp
  'On Error Resume Next
  With CreateObject("Scripting.Dictionary")
    For Each SubArr In sArray
      tmpArr = SubArr
      If Not IsArray(tmpArr) Then tmpArr = Array(tmpArr)
      For Each Item In tmpArr
        If TypeName(Item) <> "Error" Then
          tmp = CStr(Item)
          If Len(tmp) Then
            If Not .Exists(tmp) Then .Add tmp, ""
          End If
        End If
      Next
    Next
    If .Count Then UniqueList = .Keys
  End With
End Function
Function JoinIf(ByVal Delimiter As String, ByVal CriteriaArray, ByVal Criteria, Optional ByVal TargetArray) As String
  Dim arrDes()
  Dim arrTmpCrit    As Variant
  Dim arrTmpDest    As Variant
  Dim strCrit       As Variant
  Dim strDest       As Variant
  Dim dic           As Object
  Dim bComp         As Boolean
  Dim idx           As Long
  Dim dTmpVal       As Double
 
  Set dic = CreateObject("Scripting.Dictionary")
  If IsMissing(TargetArray) Then TargetArray = CriteriaArray
  arrTmpCrit = ConvertTo1DArray(CriteriaArray)
  arrTmpDest = ConvertTo1DArray(TargetArray)
  If (Not IsArray(arrTmpCrit)) Or (Not IsArray(arrTmpDest)) Then Exit Function
  'On Error Resume Next
  bComp = (InStr("<>=", Left(Criteria, 1)) > 0)
  For idx = LBound(arrTmpDest) To UBound(arrTmpDest)
    strCrit = arrTmpCrit(idx): strDest = arrTmpDest(idx)
    If TypeName(strCrit) <> "Error" Then
      If TypeName(strDest) <> "Error" Then
        If bComp And Len(Criteria) Then
          dTmpVal = CDbl(arrTmpCrit(idx))
          If Evaluate(dTmpVal & Criteria) Then
            If Not dic.Exists(strDest) Then dic.Add strDest, ""
          End If
        Else
          If (Left(Criteria, 1) = "!") Then
            If Not (UCase(strCrit) Like UCase(Mid(Criteria, 2))) Then
              If Not dic.Exists(strDest) Then dic.Add strDest, ""
            End If
          Else
            If (UCase(strCrit) Like UCase(Criteria)) Then
              If Not dic.Exists(strDest) Then dic.Add strDest, ""
            End If
          End If
        End If
      End If
    End If
  Next
  If dic.Count Then
    arrDes = dic.Keys
    JoinIf = Join(arrDes, Delimiter)
  End If
  'If Err.Number Then MsgBox Err.Description
End Function
Private Function ConvertTo1DArray(ByVal SourceArray)
  Dim arrDest()
  Dim arrSrc    As Variant
  Dim Item      As Variant
  Dim idx       As Long
  'On Error Resume Next
  arrSrc = SourceArray
  If Not IsArray(arrSrc) Then arrSrc = Array(arrSrc)
  For Each Item In arrSrc
    idx = idx + 1
    ReDim Preserve arrDest(1 To idx)
    arrDest(idx) = Item
  Next
  ConvertTo1DArray = arrDest
  'If Err.Number Then MsgBox Err.Description
End Function
PHP:
=JoinText(",",IF(D3:I3>0,$D$2:$I$2&"-"&D3:I3,1/0))
 
PHP:
Option Explicit
Function JoinText(ByVal Delimiter As String, ParamArray Arrays()) As String
  Dim aTmp, arrDes(), Item, tmp As String
  Dim idx As Long, n As Long
  'On Error Resume Next
  For idx = LBound(Arrays) To UBound(Arrays)
    aTmp = Arrays(idx)
    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 arrDes(1 To n)
        arrDes(n) = tmp
      End If
    Next
  Next
  If n Then JoinText = Join(arrDes, Delimiter)
End Function
Function UniqueList(ParamArray sArray())
  Dim Item, tmpArr, SubArr, tmp
  'On Error Resume Next
  With CreateObject("Scripting.Dictionary")
    For Each SubArr In sArray
      tmpArr = SubArr
      If Not IsArray(tmpArr) Then tmpArr = Array(tmpArr)
      For Each Item In tmpArr
        If TypeName(Item) <> "Error" Then
          tmp = CStr(Item)
          If Len(tmp) Then
            If Not .Exists(tmp) Then .Add tmp, ""
          End If
        End If
      Next
    Next
    If .Count Then UniqueList = .Keys
  End With
End Function
Function JoinIf(ByVal Delimiter As String, ByVal CriteriaArray, ByVal Criteria, Optional ByVal TargetArray) As String
  Dim arrDes()
  Dim arrTmpCrit    As Variant
  Dim arrTmpDest    As Variant
  Dim strCrit       As Variant
  Dim strDest       As Variant
  Dim dic           As Object
  Dim bComp         As Boolean
  Dim idx           As Long
  Dim dTmpVal       As Double

  Set dic = CreateObject("Scripting.Dictionary")
  If IsMissing(TargetArray) Then TargetArray = CriteriaArray
  arrTmpCrit = ConvertTo1DArray(CriteriaArray)
  arrTmpDest = ConvertTo1DArray(TargetArray)
  If (Not IsArray(arrTmpCrit)) Or (Not IsArray(arrTmpDest)) Then Exit Function
  'On Error Resume Next
  bComp = (InStr("<>=", Left(Criteria, 1)) > 0)
  For idx = LBound(arrTmpDest) To UBound(arrTmpDest)
    strCrit = arrTmpCrit(idx): strDest = arrTmpDest(idx)
    If TypeName(strCrit) <> "Error" Then
      If TypeName(strDest) <> "Error" Then
        If bComp And Len(Criteria) Then
          dTmpVal = CDbl(arrTmpCrit(idx))
          If Evaluate(dTmpVal & Criteria) Then
            If Not dic.Exists(strDest) Then dic.Add strDest, ""
          End If
        Else
          If (Left(Criteria, 1) = "!") Then
            If Not (UCase(strCrit) Like UCase(Mid(Criteria, 2))) Then
              If Not dic.Exists(strDest) Then dic.Add strDest, ""
            End If
          Else
            If (UCase(strCrit) Like UCase(Criteria)) Then
              If Not dic.Exists(strDest) Then dic.Add strDest, ""
            End If
          End If
        End If
      End If
    End If
  Next
  If dic.Count Then
    arrDes = dic.Keys
    JoinIf = Join(arrDes, Delimiter)
  End If
  'If Err.Number Then MsgBox Err.Description
End Function
Private Function ConvertTo1DArray(ByVal SourceArray)
  Dim arrDest()
  Dim arrSrc    As Variant
  Dim Item      As Variant
  Dim idx       As Long
  'On Error Resume Next
  arrSrc = SourceArray
  If Not IsArray(arrSrc) Then arrSrc = Array(arrSrc)
  For Each Item In arrSrc
    idx = idx + 1
    ReDim Preserve arrDest(1 To idx)
    arrDest(idx) = Item
  Next
  ConvertTo1DArray = arrDest
  'If Err.Number Then MsgBox Err.Description
End Function
PHP:
=JoinText(",",IF(D3:I3>0,$D$2:$I$2&"-"&D3:I3,1/0))
PHP:
Option Explicit
Function JoinText(ByVal Delimiter As String, ParamArray Arrays()) As String
  Dim aTmp, arrDes(), Item, tmp As String
  Dim idx As Long, n As Long
  'On Error Resume Next
  For idx = LBound(Arrays) To UBound(Arrays)
    aTmp = Arrays(idx)
    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 arrDes(1 To n)
        arrDes(n) = tmp
      End If
    Next
  Next
  If n Then JoinText = Join(arrDes, Delimiter)
End Function
Function UniqueList(ParamArray sArray())
  Dim Item, tmpArr, SubArr, tmp
  'On Error Resume Next
  With CreateObject("Scripting.Dictionary")
    For Each SubArr In sArray
      tmpArr = SubArr
      If Not IsArray(tmpArr) Then tmpArr = Array(tmpArr)
      For Each Item In tmpArr
        If TypeName(Item) <> "Error" Then
          tmp = CStr(Item)
          If Len(tmp) Then
            If Not .Exists(tmp) Then .Add tmp, ""
          End If
        End If
      Next
    Next
    If .Count Then UniqueList = .Keys
  End With
End Function
Function JoinIf(ByVal Delimiter As String, ByVal CriteriaArray, ByVal Criteria, Optional ByVal TargetArray) As String
  Dim arrDes()
  Dim arrTmpCrit    As Variant
  Dim arrTmpDest    As Variant
  Dim strCrit       As Variant
  Dim strDest       As Variant
  Dim dic           As Object
  Dim bComp         As Boolean
  Dim idx           As Long
  Dim dTmpVal       As Double

  Set dic = CreateObject("Scripting.Dictionary")
  If IsMissing(TargetArray) Then TargetArray = CriteriaArray
  arrTmpCrit = ConvertTo1DArray(CriteriaArray)
  arrTmpDest = ConvertTo1DArray(TargetArray)
  If (Not IsArray(arrTmpCrit)) Or (Not IsArray(arrTmpDest)) Then Exit Function
  'On Error Resume Next
  bComp = (InStr("<>=", Left(Criteria, 1)) > 0)
  For idx = LBound(arrTmpDest) To UBound(arrTmpDest)
    strCrit = arrTmpCrit(idx): strDest = arrTmpDest(idx)
    If TypeName(strCrit) <> "Error" Then
      If TypeName(strDest) <> "Error" Then
        If bComp And Len(Criteria) Then
          dTmpVal = CDbl(arrTmpCrit(idx))
          If Evaluate(dTmpVal & Criteria) Then
            If Not dic.Exists(strDest) Then dic.Add strDest, ""
          End If
        Else
          If (Left(Criteria, 1) = "!") Then
            If Not (UCase(strCrit) Like UCase(Mid(Criteria, 2))) Then
              If Not dic.Exists(strDest) Then dic.Add strDest, ""
            End If
          Else
            If (UCase(strCrit) Like UCase(Criteria)) Then
              If Not dic.Exists(strDest) Then dic.Add strDest, ""
            End If
          End If
        End If
      End If
    End If
  Next
  If dic.Count Then
    arrDes = dic.Keys
    JoinIf = Join(arrDes, Delimiter)
  End If
  'If Err.Number Then MsgBox Err.Description
End Function
Private Function ConvertTo1DArray(ByVal SourceArray)
  Dim arrDest()
  Dim arrSrc    As Variant
  Dim Item      As Variant
  Dim idx       As Long
  'On Error Resume Next
  arrSrc = SourceArray
  If Not IsArray(arrSrc) Then arrSrc = Array(arrSrc)
  For Each Item In arrSrc
    idx = idx + 1
    ReDim Preserve arrDest(1 To idx)
    arrDest(idx) = Item
  Next
  ConvertTo1DArray = arrDest
  'If Err.Number Then MsgBox Err.Description
End Function
PHP:
=JoinText(",",IF(D3:I3>0,$D$2:$I$2&"-"&D3:I3,1/0))
Cái này là Google Sheets, còn code của Bạn là VBA. Trong Google Sheets có hàm Textjoin cũng như vậy. =ArrayFormula(TextJoin(",",True,IF(D3:I3<>"",D$2:I$2&"-"&D3:I3,)))
Bài đã được tự động gộp:

Còn nếu Bạn muốn 1 công thức cho cả mảng thì dùng công thức sau:
=ArrayFormula(REGEXREPLACE(Trim(Transpose(Query(Transpose(if( D3:I5<>"",D2:I2&"-"&D3:I5&","," ")),,99999))),",$",""))
 
Lần chỉnh sửa cuối:
Cái này là Google Sheets, còn code của Bạn là VBA. Trong Google Sheets có hàm Textjoin cũng như vậy. =ArrayFormula(TextJoin(",",True,IF(D3:I3<>"",D$2:I$2&"-"&D3:I3,)))
Bài đã được tự động gộp:

Còn nếu Bạn muốn 1 công thức cho cả mảng thì dùng công thức sau:
=ArrayFormula(REGEXREPLACE(Trim(Transpose(Query(Transpose(if( D3:I5<>"",D2:I2&"-"&D3:I5&","," ")),,99999))),",$",""))
Xin cảm ơn bạn nhiều
Công thức mảng bạn đã đưa rất hiệu quả với mình.
 
Web KT
Back
Top Bottom