Nhờ code vba trích lọc dữ liệu (1 người xem)

Liên hệ QC

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

giaiphapexcel00

Thành viên mới
Tham gia
19/7/17
Bài viết
5
Được thích
0
Giới tính
Nam
Em có bảng tính như sau: sheet1 và sheet2. Em muốn trích lọc tên KH, với điều kiện Loại hàng trên 1 khách hàng mua, nghĩa là sau khi countif xong, nếu lớn hơn 1 sẽ trích lọc ra tên KH từ sheet1. Loại hàng chỉ có 1 khách mua hoặc không có khách mua sẽ không cần trích lọc tên KH. Nhờ các anh chị giúp đỡ nhé.
 

File đính kèm

Em hiểu rồi, cám ơn anh!!!
Dùng thêm mảng Arr1, code đúng chuẩn mực và minh bạch
Không dùng thêm mảng Arr1, bạn có thể tùy biến theo 2 cách:
_ Khai báo Arr2 dư 1 cột, cột cuối lưu tạm tên khách hàng đầu tiên
_ Dùng Item để lưu số thứ tự và tên khách hàng đầu tiên theo nhiều cách như:
.Add arr3(num1, num4), Array(num2 , arr3(num1, 1))
Dĩ nhiên code sẽ kém minh bạch hơn
Chúc bạn 1 ngày vui
 
Lần chỉnh sửa cuối:
Upvote 0
Dùng thêm mảng Arr1, code đúng chuẩn mực và minh bạch
Không dùng thêm mảng Arr1, bạn có thể tùy biến theo 2 cách:
_ Khai báo Arr2 dư 1 cột, cột cuối lưu tạm tên khách hàng đầu tiên
_ Dùng Item để lưu số thứ tự và tên khách hàng đầu tiên theo nhiều cách như:
.Add arr3(num1, num4), Array(num2 , arr3(num1, 1))
Dĩ nhiên code sẽ kém minh bạch hơn
Chúc bạn 1 ngày vui
Vâng các cách này đều ổn nếu >1, nhưng em nghĩ nếu >n... thì các cách trên sẽ khó hơn là cho chạy mảng bình thường sau đó duyệt lại với arr2(,2)>n!!!
 
Upvote 0
Vâng các cách này đều ổn nếu >1, nhưng em nghĩ nếu >n... thì các cách trên sẽ khó hơn là cho chạy mảng bình thường sau đó duyệt lại với arr2(,2)>n!!!
Nếu n là 1 số cố định như n=3 chẳng hạn thì code vẫn như vậy, chỉ cần tăng cột của Arr2, tăng số phần tử của Array lên
 
Upvote 0
Code dùng dictionary với item là mảng
Thực ra trong code này, tôi đặt mảng là 1 chuỗi để dễ dò số khách hàng. Vì đề bài chỉ kê khai món hàng có trên 1 người mua.
Nếu đề bài là liệt kê tất cả món hàng thì dùng mảng boolean hay integer tổng quát hơn. Code đại khái cũng vậy. Chỉ cần để ý chỗ dựng cái template (mẫu) thì dùng Redim custTemplate(1 to numCust) As Boolean

Mã:
Sub tt()
Dim numCust As Integer, numCol As Integer, iRow As Integer, iCol As Integer
Dim itemName As String, custTemplate As String
Dim aIn As Variant, custArray As Variant
Dim dic As Object
numCust = Sheets("sheet1").Range("a2").CurrentRegion.Rows.Count - 1
aIn = Sheets("sheet1").Range("a2").CurrentRegion.Offset(1).Resize(numCust)
custTemplate = String(numCust, "0")
Set dic = CreateObject("scripting.dictionary")
For iCol = 2 To UBound(aIn, 2)
    For iRow = 1 To numCust
        itemName = Trim(CStr(aIn(iRow, iCol)))
        If itemName <> "" Then
            ' nhet vao dic
            ' If Not dic.exists(itemName) Then dic.Add itemName, custTemplate
            custArray = dic(itemName)
            If IsEmpty(custArray) Then custArray = custTemplate
            Mid(custArray, iRow, 1) = "1" ' ghi khach hang mua mon nay
            dic(itemName) = custArray
        End If
    Next iRow
Next iCol
' bat dau lap mang dau ra
Dim aOut() As Variant, oRow As Integer
ReDim aOut(0 To dic.Count, 0 To numCust)
oRow = 0
For iRow = 1 To numCust ' ghi ten khach hang (hang doc bay gio thannh ngang)
    aOut(oRow, iRow) = Trim(CStr(aIn(iRow, 1)))
Next iRow
For iRow = 0 To dic.Count - 1
    custArray = dic.items()(iRow)
    If Len(Replace(custArray, "0", "")) >= 2 Then ' toi thieu 2 khach hang
        oRow = oRow + 1
        aOut(oRow, 0) = dic.keys()(iRow)
        For iCol = 1 To numCust
            If Mid(custArray, iCol, 1) = "1" Then aOut(oRow, iCol) = "X"
        Next iCol
    End If
Next iRow
Sheets("sheet2").Range("a10").Resize(oRow, numCust + 1) = aOut
Set dic = Nothing
End Sub

Chú thích sửa sai code:
Lúc pót code trên, tôi chưa xét kỹ kết quả. Code bị lỗi là lúc xuất ra thiếu hết 1 dòng. Toi quên mất là mảng đầu ra chỉ số bắt đầu từ 0. Vì vậy câu xuất mảng ra sheet kết quả phải sửa lại là:
Sheets("sheet2").Range("a10").Resize(oRow + 1, numCust + 1) = aOut
 
Lần chỉnh sửa cuối:
Upvote 0
Vâng, vậy sẽ dùng thêm vòng lặp duyệt qua arr1 hoặc các các cột thừa của arr2 để đưa vào lại arr2!!
Nếu n nhỏ như n=3 hoặc 4 thì gán trực tiếp không cần dùng for, dể hiểu và code cũng không dài hơn (for phải mất 3 dòng lệnh), nếu n lớn thì dùng for của cột với dòng đã xác định theo Item
 
Upvote 0
Code dùng mảng và arraylist để sort mảng
Lưu ý là code sẽ khựng lại 1 chút (khoảng nửa giây) khi chạy code arraylist lần đầu tiên, vì hệ thống phải chờ dot net đưa code arraylist vào bộ nhớ. Những lần chạy sau sẽ bình thường vì khong cần đưa vào nữa.

Mã:
Sub ttt()
' dung arraylist cho de sort
Const DELIM = "|" ' ky hieu ngan cac phan chuoi
Dim numCust As Integer, iRow As Integer, iCol As Integer
Dim itemName As String
Dim aIn As Variant
Dim aList As Object
numCust = Sheets("sheet1").Range("a2").CurrentRegion.Rows.Count - 1
aIn = Sheets("sheet1").Range("a2").CurrentRegion.Offset(1).Resize(numCust)
Set aList = CreateObject("system.collections.arraylist")
For iCol = 2 To UBound(aIn, 2)
    For iRow = 1 To numCust
        itemName = Trim(CStr(aIn(iRow, iCol)))
        If itemName <> "" Then
            ' nhet vao
            aList.Add itemName & DELIM & CStr(iRow)
        End If
    Next iRow
Next iCol
aList.Add String(20, Chr(255)) & DELIM & "1" ' dat them 1 phan tu cuoi de duyet cho de hon
aList.Sort
' bat dau lap mang dau ra
Dim aOut() As Variant, oRow As Integer, itemArray As Variant, custCount As Integer
ReDim aOut(0 To aList.Count, 0 To numCust)
oRow = 0
For iRow = 1 To numCust ' ghi ten khach hang (hang doc bay gio thannh ngang)
    aOut(oRow, iRow) = Trim(CStr(aIn(iRow, 1)))
Next iRow
itemName = ""
oRow = 1
For iRow = 0 To aList.Count - 1
    itemArray = Split(aList.Item(iRow), DELIM)
    If itemArray(0) <> itemName Then
        ' If itemName <> "" Then
        ' neu hoi du dieu kien in ra thi chuan bi dong moi
        ' neu khong du dieu kien thi dong moi se chong len dong cu
        If custCount >= 2 Then oRow = oRow + 1
        For iCol = 1 To numCust ' chuan bi dong moi
            aOut(oRow, iCol) = ""
        Next iCol
        itemName = itemArray(0)
        custCount = 0
        aOut(oRow, 0) = itemName
    End If
    aOut(oRow, CInt(itemArray(1))) = "X"
    custCount = custCount + 1
Next iRow
Sheets("sheet2").Range("a16").Resize(oRow, numCust + 1) = aOut
Set aList = Nothing
End Sub
 
Upvote 0
Hi anh/chị @eke_rula, code chạy khoảng trên trăm khách hàng và trên trăm mặt hàng là bị chậm hoặc đơ chạy không được luôn. Có cách nào khắc phục không ạ?
 
Upvote 0
Upvote 0
Bạn lấy code của anh Vetmini chạy đi bạn(bài #25,#27), code mình chưa hoàn chỉnh!!!

Tôi cũng chạy luôn. 100x100 là 10000 phát sinh. Với con số đó thì pivot vô tư. Tuy nhiên, pivot chỉ xảy ra khi dữ liệu đã được xếp thẳng thành bảng có quy củ (tiếng nhà nghề CSDL gọi là theo đúng chuẩn bậc 1 - First normalised form).
Cái bảng rối như bòng bong trên thì máy đơ là chuyện bình thường.
 
Upvote 0
Hi anh/chị @eke_rula, code chạy khoảng trên trăm khách hàng và trên trăm mặt hàng là bị chậm hoặc đơ chạy không được luôn. Có cách nào khắc phục không ạ?
Bạn chạy thử code
Mã:
Sub GPE()
Dim Darr(), Arr(), Key As String, RowsIn As Long, ColsIn As Long, ColsOut As Long
Dim i As Long, j As Long, k As Long, ik As Long, n As Long
With Sheets("sheet1")
  RowsIn = .Range("A60000").End(xlUp).Row - 2
  ColsIn = .Range("A3").CurrentRegion.Columns.Count
  Darr = .Range("A3").Resize(RowsIn, ColsIn).Value
End With
ColsOut = RowsIn + 3
ReDim Arr(1 To 10000, 1 To ColsOut)
With CreateObject("scripting.dictionary")
  For i = 1 To RowsIn
    For j = 2 To ColsIn
      Key = Darr(i, j)
      If Key = Empty Then GoTo Tiep 'Du lieu theo cot khong duoc co Cell trong xen giua
      If Not .exists(Key) Then
        k = k + 1
        .Add Key, k
        Arr(k, 1) = Key: Arr(k, 2) = 1: Arr(k, ColsOut) = Darr(i, 1)
      Else
        ik = .Item(Key)
        n = Arr(ik, 2) + 1
        Arr(ik, 2) = n
        If n = 2 Then Arr(ik, 3) = Arr(ik, ColsOut)
        Arr(ik, n + 2) = Darr(i, 1)
      End If
Tiep:
    Next j
  Next i
End With
Sheets("sheet2").Range("A3").Resize(k, ColsOut - 1) = Arr
End Sub
 
Upvote 0
Web KT

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

Back
Top Bottom