lọc không trùng, lấy đơn vị tính theo tên phụ liệu (1 người xem)

Liên hệ QC

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

Rùa Con 1080

Thành Viên Sao Chép 2
Tham gia
4/5/16
Bài viết
351
Được thích
47
Giới tính
Nữ
Chào các Anh, Chị.
Em có file này lọc không trùng tên phụ liệu rồi, giờ em nhờ các Anh, Chị chỉnh code để lấy đơn vị tính theo tên phụ liệu giúp em với.
(Sheet1.Active thì lọc_ chạy module CreatListPL)
 

File đính kèm

Chào các Anh, Chị.
Em có file này lọc không trùng tên phụ liệu rồi, giờ em nhờ các Anh, Chị chỉnh code để lấy đơn vị tính theo tên phụ liệu giúp em với.
(Sheet1.Active thì lọc_ chạy module CreatListPL)
Mình mới lượm được cái này. Bạn thử xem sao nha
Mã:
Sub M_remove()
    Dim Dic As Object, I As Long, sArr()
    Set Dic = CreateObject("scripting.dictionary")
    With Sheets("Sheet1")
        sArr = .Range("A3", .Range("A65535").End(3)).Resize(, 2).Value
        For I = 1 To UBound(sArr)
            Dic.Item(sArr(I, 1)) = Application.Index(sArr, I, 0)
        Next
        .Range("D3:D1000").ClearContents
        .Range("D3").Resize(Dic.Count, UBound(sArr, 2)) = Application.Index(Dic.Items, 0, 0)
        .Range("D3:E" & .Range("D65535").End(3).Row).Sort Key1:=.[D2]
    End With
End Sub
 
Upvote 0
Excel có sẵn công cụ Remove Duplicates. Sử dụng kết hợp với Vlookup là được kết quả như ý.
Mình mới lượm được cái này. Bạn thử xem sao nha
Mã:
Sub M_remove()
    Dim Dic As Object, I As Long, sArr()
    Set Dic = CreateObject("scripting.dictionary")
    With Sheets("Sheet1")
        sArr = .Range("A3", .Range("A65535").End(3)).Resize(, 2).Value
        For I = 1 To UBound(sArr)
            Dic.Item(sArr(I, 1)) = Application.Index(sArr, I, 0)
        Next
        .Range("D3:D1000").ClearContents
        .Range("D3").Resize(Dic.Count, UBound(sArr, 2)) = Application.Index(Dic.Items, 0, 0)
        .Range("D3:E" & .Range("D65535").End(3).Row).Sort Key1:=.[D2]
    End With
End Sub
Sao bạn không add ĐVT vào Item luôn mà phải dùng Index rồi xử lý lại.

Ngoài ra, Một số dòng cùng tên nhưng khác ĐVT và một số dòng khác chỉ khác chữ thường - hoa. Tùy theo nhu cầu nên kiểm tra kết hợp tên và ĐVT đồng thời cân nhắc thiết lập
CompareMode cho Dictionary.
 
Upvote 0
Excel có sẵn công cụ Remove Duplicates. Sử dụng kết hợp với Vlookup là được kết quả như ý.

Sao bạn không add ĐVT vào Item luôn mà phải dùng Index rồi xử lý lại.

Ngoài ra, Một số dòng cùng tên nhưng khác ĐVT và một số dòng khác chỉ khác chữ thường - hoa. Tùy theo nhu cầu nên kiểm tra kết hợp tên và ĐVT đồng thời cân nhắc thiết lập
CompareMode cho Dictionary.
Dạ. Hôm trước em có đọc 1 bài họ dùng hàm Index nên đang làm thử thầy ạ./
 
Upvote 0
Vậy nhờ anh huuthang_bd viết code add ĐVT vào Item cho em học hỏi với.
 
Upvote 0
Đây này bạn @Rùa Con 1080
Mã:
Public Sub CreatList()
    Dim sArr(), dArr(), I As Long, K As Long
    Dim Dic As Object, Tem As String
    Set Dic = CreateObject("Scripting.Dictionary")
    With Sheet1
        sArr = .Range("A3", .Range("B65536").End(3)).Value
        ReDim dArr(1 To UBound(sArr, 1), 1 To 2)
        For I = 1 To UBound(sArr, 1)
            Tem = sArr(I, 1) & "#" & sArr(I, 2)
            If Not Dic.Exists(Tem) Then
                K = K + 1
                Dic.Add Tem, K
                dArr(K, 1) = sArr(I, 1): dArr(K, 2) = sArr(I, 2)
            End If
        Next I
        .Range("D3:D1000").ClearContents
        .Range("D3").Resize(K, 2) = dArr
        .Range("D3:E" & .Range("D65535").End(3).Row).Sort Key1:=.[D2]
    End With
    Set Dic = Nothing
End Sub
 
Upvote 0
Vậy nhờ anh huuthang_bd viết code add ĐVT vào Item cho em học hỏi với.
Thì vầy thôi
PHP:
Sub CreatListPL()
  Dim Darr(), Dic As Object, i As Long, LastR As Long
  LastR = Sheet1.Range("A65500").End(xlUp).Row
  If LastR > 1 Then
    Darr = Sheet1.Range("A3:B" & LastR).Value
    Set Dic = CreateObject("Scripting.Dictionary")
   
    For i = 1 To UBound(Darr)
      Dic(Darr(i, 1)) = Darr(i, 2)
    Next
    With Sheet1
      .Range("D3:D1000").ClearContents
      .Range("D3").Resize(Dic.Count) = Application.Transpose(Dic.keys)
      .Range("E3").Resize(Dic.Count) = Application.Transpose(Dic.Items)
      .Range("D3").Resize(Dic.Count, 2).Sort .[D3], 1, Header:=xlNo
    End With
    Set Dic = Nothing
  End If
End Sub
 
Upvote 0
Cám ơn Anh huuthang_bd và Chị PacificPR nhiều.
 
Upvote 0
Xin các Anh,Chị giúp em lần nữa:
Lọc không trùng xong, nạp vào mảng tạm, và lấy mảng tạm này làm List cho ComboBox trên UserForm có 2 cột[Tên Phụ liệu và ĐVT] thì chỉnh code làm sao để nạp vào ComboBox đó ah?
 
Upvote 0
Xin các Anh,Chị giúp em lần nữa:
Lọc không trùng xong, nạp vào mảng tạm, và lấy mảng tạm này làm List cho ComboBox trên UserForm có 2 cột[Tên Phụ liệu và ĐVT] thì chỉnh code làm sao để nạp vào ComboBox đó ah?
Bạn kiểm tra file xem sao
 

File đính kèm

Upvote 0
Xin các Anh,Chị giúp em lần nữa:
Lọc không trùng xong, nạp vào mảng tạm, và lấy mảng tạm này làm List cho ComboBox trên UserForm có 2 cột[Tên Phụ liệu và ĐVT] thì chỉnh code làm sao để nạp vào ComboBox đó ah?
Thật ra vấn đề lọc duy nhất và sort mảng 2 chiều có đầy trên GPE rồi.
Nếu bạn muốn lọc vào 1 mảng tạm thì buộc bạn phải viết nó thành 1 hàm.
Gửi bạn hàm tôi viết trước đây (tuy chưa hoàn hảo nhưng tạm dùng được):
1> Code trong Module:
Mã:
Option Compare Text
Function Sort2DArray(ByVal Source2D, ByVal ColIndex As Long, Optional ByVal Order As Boolean = False)
  Dim aSrc, tmp
  Dim oArrList As Object
  Dim lR As Long, lC As Long, idx As Long, lPos As Long
  Dim lFstRow As Long, lEndRow As Long, lFstCol As Long, lEndCol As Long
  aSrc = Source2D
  lFstRow = LBound(aSrc, 1): lEndRow = UBound(aSrc, 1)
  lFstCol = LBound(aSrc, 2): lEndCol = UBound(aSrc, 2)
  Set oArrList = CreateObject("System.Collections.ArrayList")
  For lR = lFstRow To lEndRow
    tmp = aSrc(lR, ColIndex)
    oArrList.Add tmp
  Next
  oArrList.Sort
  If Order Then oArrList.Reverse
  ReDim aPos(oArrList.Count - 1)
  ReDim aDes(lFstRow To lEndRow, lFstCol To lEndCol)
  For lR = lFstRow To lEndRow
    tmp = aSrc(lR, ColIndex)
    idx = oArrList.IndexOf(tmp, 0)
    lPos = idx + lFstRow + aPos(idx)
    For lC = lFstCol To lEndCol
      aDes(lPos, lC) = aSrc(lR, lC)
    Next
    aPos(idx) = aPos(idx) + 1
  Next
  Sort2DArray = aDes
End Function
Function Unique2DArray(ByVal Source2D, Optional ByVal ColIndex As Variant = 1)
  Dim aSrc, aCol, tmp As String, cItem
  Dim lR As Long, lC As Long, n As Long
  Dim lFstRow As Long, lEndRow As Long, lFstCol As Long, lEndCol As Long
  Dim oArrList As Object
  Set oArrList = CreateObject("System.Collections.ArrayList")
  aSrc = Source2D: aCol = ColIndex
  If Not IsArray(aCol) Then aCol = Array(aCol)
  lFstRow = LBound(aSrc, 1): lEndRow = UBound(aSrc, 1)
  lFstCol = LBound(aSrc, 2): lEndCol = UBound(aSrc, 2)
  ReDim aDes(lFstCol To lEndCol, lFstRow To lFstRow)
  n = lFstRow - 1
  For lR = lFstRow To lEndRow
    tmp = vbNullString
    If Len(CStr(aSrc(lR, lFstRow))) Then
      If TypeName(aSrc(lR, lFstRow)) <> "Error" Then
        For Each cItem In aCol
           tmp = tmp & vbBack & UCase(aSrc(lR, cItem))
        Next
        If Not oArrList.Contains(tmp) Then
          n = n + 1
          oArrList.Add tmp
          ReDim Preserve aDes(lFstCol To lEndCol, lFstRow To n)
          For lC = lFstCol To lEndCol
            aDes(lC, n) = aSrc(lR, lC)
          Next
        End If
      End If
    End If
  Next
  If n Then Unique2DArray = Transpose2DArray(aDes)
End Function

Function Transpose2DArray(ByVal Source2D)
  Dim aSrc
  Dim lR As Long, lC As Long
  Dim lFstRow As Long, lEndRow As Long, lFstCol As Long, lEndCol As Long
  aSrc = Source2D
  lFstRow = LBound(aSrc, 1): lEndRow = UBound(aSrc, 1)
  lFstCol = LBound(aSrc, 2): lEndCol = UBound(aSrc, 2)
  ReDim aDes(lFstCol To lEndCol, lFstRow To lEndRow)
  For lR = lFstRow To lEndRow
    For lC = lFstCol To lEndCol
      aDes(lC, lR) = aSrc(lR, lC)
    Next
  Next
  Transpose2DArray = aDes
End Function
2> Code trong form của bạn
Mấy hàm trên tuy dài nhưng mặc kệ nó đi, bạn chỉ cần biết áp dụng trong form thế này là được:
Mã:
Private Sub UserForm_Initialize()
  Dim arr1, arr2
  arr1 = Unique2DArray(Sheet1.Range("A3:B1000")) ''<-- lọc duy nhất ra mảng arr1
  If IsArray(arr1) Then
    arr2 = Sort2DArray(arr1, 1)  ''<-- sort arr1 ra thành arr2
    If IsArray(arr2) Then Me.ComboBox1.List = arr2  ''<--- nạp arr2 vào combobox
  End If
End Sub
----------------------
Nói thêm rằng: Code bạn viết trong file lọc ra không chính xác đâu nha. Bạn có thể dùng công cụ Remove Duplicate để kiểm chứng, kết quả 76 dòng là chính xác trong khi code của bạn cho ra 86 dòng
 

File đính kèm

Upvote 0
Em đoán bạn ấy sẽ cần cái đó nên dùng hàm của thầy ạ. Hị hì
Tuy nhiên phải xem lại nha! Vì phần lọc duy nhất của bạn chưa chính xác.
Ngoài ra bạn nên viết nó thành 1 hàm thay vì cho vào sự kiện trong form, bởi như vậy thì mức độ tùy biến sẽ cao hơn (người ta có thể lọc duy nhất ở bất kỳ đâu, gán kết quả vào bất kỳ đâu)
 
Upvote 0
Thầy Tuấn, Nếu máy cài win 8/8.1/10 thì sẽ bị lỗi Automation của CreateObject("System.Collections.ArrayList"), khắc phục bằng cách cài gói tích hợp NetFramwork 2.0 + 3.5
Thật ra vấn đề lọc duy nhất và sort mảng 2 chiều có đầy trên GPE rồi.
Nếu bạn muốn lọc vào 1 mảng tạm thì buộc bạn phải viết nó thành 1 hàm.
Gửi bạn hàm tôi viết trước đây (tuy chưa hoàn hảo nhưng tạm dùng được):
1> Code trong Module:
Mã:
Option Compare Text
Function Sort2DArray(ByVal Source2D, ByVal ColIndex As Long, Optional ByVal Order As Boolean = False)
  Dim aSrc, tmp
  Dim oArrList As Object
  Dim lR As Long, lC As Long, idx As Long, lPos As Long
  Dim lFstRow As Long, lEndRow As Long, lFstCol As Long, lEndCol As Long
  aSrc = Source2D
  lFstRow = LBound(aSrc, 1): lEndRow = UBound(aSrc, 1)
  lFstCol = LBound(aSrc, 2): lEndCol = UBound(aSrc, 2)
  Set oArrList = CreateObject("System.Collections.ArrayList")
  For lR = lFstRow To lEndRow
    tmp = aSrc(lR, ColIndex)
    oArrList.Add tmp
  Next
  oArrList.Sort
  If Order Then oArrList.Reverse
  ReDim aPos(oArrList.Count - 1)
  ReDim aDes(lFstRow To lEndRow, lFstCol To lEndCol)
  For lR = lFstRow To lEndRow
    tmp = aSrc(lR, ColIndex)
    idx = oArrList.IndexOf(tmp, 0)
    lPos = idx + lFstRow + aPos(idx)
    For lC = lFstCol To lEndCol
      aDes(lPos, lC) = aSrc(lR, lC)
    Next
    aPos(idx) = aPos(idx) + 1
  Next
  Sort2DArray = aDes
End Function
Function Unique2DArray(ByVal Source2D, Optional ByVal ColIndex As Variant = 1)
  Dim aSrc, aCol, tmp As String, cItem
  Dim lR As Long, lC As Long, n As Long
  Dim lFstRow As Long, lEndRow As Long, lFstCol As Long, lEndCol As Long
  Dim oArrList As Object
  Set oArrList = CreateObject("System.Collections.ArrayList")
  aSrc = Source2D: aCol = ColIndex
  If Not IsArray(aCol) Then aCol = Array(aCol)
  lFstRow = LBound(aSrc, 1): lEndRow = UBound(aSrc, 1)
  lFstCol = LBound(aSrc, 2): lEndCol = UBound(aSrc, 2)
  ReDim aDes(lFstCol To lEndCol, lFstRow To lFstRow)
  n = lFstRow - 1
  For lR = lFstRow To lEndRow
    tmp = vbNullString
    If Len(CStr(aSrc(lR, lFstRow))) Then
      If TypeName(aSrc(lR, lFstRow)) <> "Error" Then
        For Each cItem In aCol
           tmp = tmp & vbBack & UCase(aSrc(lR, cItem))
        Next
        If Not oArrList.Contains(tmp) Then
          n = n + 1
          oArrList.Add tmp
          ReDim Preserve aDes(lFstCol To lEndCol, lFstRow To n)
          For lC = lFstCol To lEndCol
            aDes(lC, n) = aSrc(lR, lC)
          Next
        End If
      End If
    End If
  Next
  If n Then Unique2DArray = Transpose2DArray(aDes)
End Function
[/QUOTE]
 
Upvote 0
Thầy Tuấn, Nếu máy cài win 8/8.1/10 thì sẽ bị lỗi Automation của CreateObject("System.Collections.ArrayList"), khắc phục bằng cách cài gói tích hợp NetFramwork 2.0 + 3.5
Thực ra bạn có thể dùng Dictionary để lọc duy nhất chứ không cần phải mất thời gian với Arraylist.
Chỉ vì trong topic này có yêu cầu sort, mà vụ sort này dùng Arraylist sẽ gọn hơn (nhưng không hẳn nhanh hơn) nên nhân tiện đang viết code sort tôi dùng nó viết code lọc duy nhất luôn
Các bạn nếu không muốn cài NetFramwork thì có thể dùng cách khác (có đầy)
 
Upvote 0
Web KT

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

Back
Top Bottom