Cần sự giúp đỡ để lọc dữ liệu!!!

Liên hệ QC

sontvxd10

Thành viên mới
Tham gia
2/9/07
Bài viết
16
Được thích
2
Chào tất cả các bạn trong 4f. Mình mới tập tành sử dụng VBA nên rất cần sự chỉ giáo của các bạn.
Cụ thể là yêu cầu của mình như sau:


Mình muốn đánh dấu (*) vào cột K ở những hàng có giá trị lớn nhất, nhỏ nhất và trung bình ở cột C cụ thể ở trong hình này là:
Với B1 là các giá trị: 0.11, 1.8 và 3.49
Với B10 là: 0.11, 0.9 và 1.8.
Mình cũng đã thư làm 1 đoạn code để điều khiển cái Button như sau:

Private Sub CommandButton1_Click()

Dim i, j, n As Integer
Dim max, min, tb As Double
n = 4
Do While Cells(n, "B") <> ""
n = n + 1
Loop
n = n - 1
i = 4
j = 4
Cells(j, "K") = "*"
'danh dau * cac gia tri can thiet
For i = j To n
If Cells(i, "B") = Cells(i + 1, "B") Then
If Cells(j, "D") <= Cells(i + 1, "D") Then
Cells(j, "K") = "*"
min = Cells(j, "D")
End If
If Cells(j, "D") >= Cells(i + 1, "D") Then
Cells(j, "K") = "*"
max = Cells(j, "D")
End If
tb = max + min
If Cells(j, "D") = tb Then
Cells(j, "K") = "*"
End If
Else
j = i + 1
Cells(j, "K") = "*"
End If
Next i
End Sub

Nhưng khi chạy nó chỉ đánh dấu (*) tùm lum.**~**
Rất mong các bạn cho ý kiến. Cảm ơn nhiều!!

 
F ương án đề xuất của mình với bạn là vầy:

Khai báo thêm 1 biến đối tượng WF &

Set WF=Application.WorkSheetFunction;

Rồi tính trị MAX , MIN cũng như hàm trung bình tại cột 'C" nhờ vào hàm MAX() & MIN(),. . trong Excel

Dùng fương thức FIND() hay duyệt toàn cột so với 3 trị tìm được là OK thôi;

Sẽ có rắc rối khi trị trung bình tìm được bằng hàm sẽ không trùng với trị nào trên cột cả.


Có gì khó khăn fát biểu tiếp nha


Còn mình xin lưu í bạn 1 số điều sau:

(*) Khai báo các biến tường minh hơn;

không fải
PHP:
 Dim i, j, n As Integer
Dim max, min, tb As Double
Mà fải là :
Mã:
Dim i As Long, j As Long, n As Long
Dim maX As Long, miN As Long, tB As Double
(*) Thường thì mình không xài i & n làm biến, mà thay vào đó là Ww hay zZ, fF (lí do ư: Bàn fím sẽ hư đều ở các fím)



Chúc bạn tiến bộ!
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Khai báo thêm 1 biến đối tượng WF &

Set WF=Application.WorkSheetFunction;

Rồi tính trị MAX , MIN cũng như hàm trung bình tại cột 'C" nhờ vào hàm MAX() & MIN(),. . trong Excel

Dùng fương thức FIND() hay duyệt toàn cột so với 3 trị tìm được là OK thôi;

Sẽ có rắc rối khi trị trung bình tìm được bằng hàm sẽ không trùng với trị nào trên cột cả.
Cảm ơn các ý kiến của bạn. Để mình bơi tiếp xem sao đã. Khi nào đuối thì nhờ bạn vứt phao vậy. Còn cái vụ mòn phím thì chắc ko sao.
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn các ý kiến của bạn. Để mình bơi tiếp xem sao đã. Khi nào đuối thì nhờ bạn vứt phao vậy. Còn cái vụ mòn phím thì chắc ko sao.
Mình thử bơi "zí" bạn một phát xem sao
Thật ra không biết tính trung bình ra mần răng nữa nên làm đại, nếu trật thì thì bạn nhờ ....bác Sa_QD làm nhé
Với dữ liệu hiện tại đã được sắp xếp như thế thì thử code này xem sao
Mã:
Public Sub tim()
Dim Vung As Range, Wf, iMax As Double, iMin As Double, iMid As Double, VgDem As Range, I As Long, Bd As Long, A As Long
Set Wf = Application.WorksheetFunction:  Set Vung = Range([a4], [a50000].End(xlUp))
    For I = 1 To Vung.Rows.Count
        If Vung(I) = Vung(I + 1) Then
            Bd = Wf.Match(Vung(I), Vung, 0) + 3
            Set VgDem = Cells(Bd, 1).Resize(Wf.CountIf(Vung, Vung(I))).Offset(, 2)
            iMax = Wf.max(VgDem): iMin = Wf.min(VgDem): iMid = Wf.Median(VgDem)
                If Vung(I).Offset(, 2) = iMax Or Vung(I).Offset(0, 2) = iMin Or Vung(I).Offset(0, 2) = iMid Then Vung(I).Offset(, 10) = "*"
                A = A + 1
        Else
                    If Vung(I) = Vung(I - 1) And Vung(I) <> Vung(I + 1) Then Vung(I).Offset(, 10) = "*"
                    A = A + 1
        End If
Next
End Sub
Chưa nghĩ cách nào khác cho gọn và chạy nhanh hơn, làm đại lấy trớn đi ......đã, tối tính tiếp
Thân
 
Upvote 0
Mình thử bơi "zí" bạn một phát xem sao
Thật ra không biết tính trung bình ra mần răng nữa nên làm đại, nếu trật thì thì bạn nhờ ....bác Sa_QD làm nhé
Với dữ liệu hiện tại đã được sắp xếp như thế thì thử code này xem sao
Chưa nghĩ cách nào khác cho gọn và chạy nhanh hơn, làm đại lấy trớn đi ......đã, tối tính tiếp
Thân

Bó tay với bác. Quá Pro luôn. Em cóp vô chạy thấy quá ổn luôn. Mấy hàm bác dùng em vẫn chưa hiểu hết để tối em mò lại xem.
Hê hê, Em chỉ là tay ngang mới tự mò. Cả chiều bơi đc từng này đây bác
Mã:
Dim i, n, dau, cuoi As Integer
Dim max, min, tb As Double
n = 4
Do While Cells(n, "A") <> ""
    n = n + 1
    Loop
    n = n - 1
    i = 4
    dau = 4
    For i = 4 To n
        If Cells(i, "A") = Cells(i + 1, "A") Then
        cuoi = i + 1
        Else
        min = Application.WorksheetFunction.min(Range(Cells(dau, "C"), Cells(cuoi, "C")))
        max = Application.WorksheetFunction.max(Range(Cells(dau, "C"), Cells(cuoi, "C")))
        tb = (max + min) / 2
        Cells(dau - 1, "K") = min
        Cells(dau, "K") = tb
        Cells(dau + 1, "K") = max
        End If
        dau = cuoi
    Next i
End Sub
Em muốn dùng giá trị "dau" và "cuoi" để giới hạn vùng tìm max và min. Nhưng khi chạy thì giá trị đầu nó không nhận như mình mong muốn. Bác thử xem và góp ý xem đoạn Code này của em có dùng đc không? Và nếu dùng phải chỉnh sửa ra sao?
 
Upvote 0
Hix vẫn ko đủ bác ơi. Em chạy code của bác thì thấy ở B15 vẫn không đánh đc dấu (*) ở giá trị trung bình. Bác thử ktra lại xem file excell em đã úp ở phần trên đó. Nhân tiện bác cho em hỏi là vai trò của biến "A" trong đoạn Code của bác làm gì vậy??
 
Lần chỉnh sửa cuối:
Upvote 0
Hix vẫn ko đủ bác ơi. Em chạy code của bác thì thấy ở B15 vẫn không đánh đc dấu (*) ở giá trị trung bình. Bác thử ktra lại xem file excell em đã úp ở phần trên đó. Nhân tiện bác cho em hỏi là vai trò của biến "A" trong đoạn Code của bác làm gì vậy??
Hihi, thì mình đã nói với bạn mình không biết cái "thằng" trung bình mặt mũi ra sao mà nên làm đại
"Bi" giờ thì biết rồi, bạn sửa cái "thằng" iMid tí xong chạy lại thử xem
iMid = Wf.Round((iMax + iMin) / 2, 3)
Thân
Biến A để cố định cell đầu tiên trong vùng dữ liệu muốn đếm
 
Upvote 0
. . mình không biết cái "thằng" trung bình mặt mũi ra sao mà nên làm đại
"Bi" giờ thì biết rồi, bạn sửa cái "thằng" iMid tí xong chạy lại thử xem
iMid = Wf.Round((iMax + iMin) / 2, 3)
Thân

Tính như vậy thì biến iMid là giá trị trung đoạn, chứ đâu fải trung bình đâu ta?!

Tính trung bình có thể 1 trong 2 cách iMid = Sum (LoopkUpRange)/Count(LookUpRange)
Hay dùng hàm của excel chứ bộ?
 
Upvote 0
Tính như vậy thì biến iMid là giá trị trung đoạn, chứ đâu fải trung bình đâu ta?!

Tính trung bình có thể 1 trong 2 cách iMid = Sum (LoopkUpRange)/Count(LookUpRange)
Hay dùng hàm của excel chứ bộ?
Híc, nhìn "zô" trong bài của chủ topic thấy tính cái gọi là trung bình như "zị" đó bác ơi
"Trung bình" là tên gọi thôi mà, còn tính mần sao thì ăn thua mình giao với nhau thôi
Híc
 
Upvote 0
Ah đúng rồi. Em hiểu rồi. Ý của em là tb ở đây là (max+min)/2 chứ không phải là "tổng các phần tử"/"số phần tử". Ô B15 không đánh "*" đc là do nó không tìm đc trị tb khi dùng hàm median(). Đọc đoạn Code của bác concogia tưởng biến A không có vai trò gì em bỏ đi. Thấy vẫn chạy bt. Nếu cứ bỏ đi thì có vấn đề gì không bác. Nhân tiện em hỏi thêm luôn. Đó là khi lọc ra thì có những đoạn nó ra 4 trị iMid. Nhưng em chỉ muốn lấy 2 giá trị ứng với 2 giá trị max và min của cột I. Thì cách giải quyết tốt nhất là ra sao nhỉ 2 bác??
 
Upvote 0
Ah đúng rồi. Em hiểu rồi. Ý của em là tb ở đây là (max+min)/2 chứ không phải là "tổng các phần tử"/"số phần tử". Ô B15 không đánh "*" đc là do nó không tìm đc trị tb khi dùng hàm median(). Đọc đoạn Code của bác concogia tưởng biến A không có vai trò gì em bỏ đi. Thấy vẫn chạy bt. Nếu cứ bỏ đi thì có vấn đề gì không bác. Nhân tiện em hỏi thêm luôn. Đó là khi lọc ra thì có những đoạn nó ra 4 trị iMid. Nhưng em chỉ muốn lấy 2 giá trị ứng với 2 giá trị max và min của cột I. Thì cách giải quyết tốt nhất là ra sao nhỉ 2 bác??
Câu 1- Bỏ biến A đi thì cell đầu của vung tham chiếu để tìm Max, Min...sẽ chạy theo I ==> kết quả ra "trật lấc"
Câu 2- Cái này khó quá bạn nhờ Thầy của mình là Thầy Ptm hoặc Thầy Sa_DQ làm giúp nhé
Thân
 
Upvote 0
Ah đúng rồi. Em hiểu rồi. Ý của em là tb ở đây là (max+min)/2 chứ không phải là "tổng các phần tử"/"số phần tử". Ô B15 không đánh "*" đc là do nó không tìm đc trị tb khi dùng hàm median(). Đọc đoạn Code của bác concogia tưởng biến A không có vai trò gì em bỏ đi. Thấy vẫn chạy bt. Nếu cứ bỏ đi thì có vấn đề gì không bác. Nhân tiện em hỏi thêm luôn. Đó là khi lọc ra thì có những đoạn nó ra 4 trị iMid. Nhưng em chỉ muốn lấy 2 giá trị ứng với 2 giá trị max và min của cột I. Thì cách giải quyết tốt nhất là ra sao nhỉ 2 bác??
Cho tôi hỏi với A=B15 và xét theo cột B (Loc)
1/ Max = 3.49
2/ Min = 0.11
3/ Danh sach duy nhất là 12 số
4/ Và median(danh sach duy nhất) = 2.325
Vậy lấy số hạng thứ 6 = 2.25 hay số 7=2.4. Trướng hợp như với B1 thì dễ hơn vì có 5 số hạng => số giữa là số thứ 3= 1.8.
Bạn cụ thể hơn vấn đề này. Với lại những cột khác kg có tham gia thì mình kg nên đưa vào yêu cầu, nhìn vào sẽ rối.
 
Upvote 0
Cho tôi hỏi với A=B15 và xét theo cột B (Loc)
1/ Max = 3.49
2/ Min = 0.11
3/ Danh sach duy nhất là 12 số
4/ Và median(danh sach duy nhất) = 2.325
Vậy lấy số hạng thứ 6 = 2.25 hay số 7=2.4. Trướng hợp như với B1 thì dễ hơn vì có 5 số hạng => số giữa là số thứ 3= 1.8.
Bạn cụ thể hơn vấn đề này. Với lại những cột khác kg có tham gia thì mình kg nên đưa vào yêu cầu, nhìn vào sẽ rối.

Không phải bác ơi. Em chỉ lấy trị TB tức là : (Max+min)/2 thôi. Ứng với B15 là: (3.49+0.11)/2 là 1.8 đó.
 
Upvote 0
À há! Hai chàng này định áp đặt lệ làng lên fép vua ư?

(SPAM 1 cái & nhờ MODs/SMODs ngang qua đây xóa dùm & Rất cảm ơn!)

Thuật ngữ Trung bình đã đi vào lòng người rồi & không ăn nhập gì với định nghĩa của hai cha cả!

Đúng ra đó là giá trị trung bình cộng của cực trị. Thà dài dòng, nhưng không lấn chiếm lòng lề đường tẹo nào.

Như hai bạn, riết rồi 'E' lên nằm trên 'A' trong chuỗi chữ cái mất thôi!
 
Upvote 0
Cảm ơn bác đã sửa dùm. Tại em quen cứ thấy giữa giữa là gọi trung bình thôi.
 
Upvote 0
Em chỉ lấy giá trị (max + min)/2 bác ah. Với B10 thì là 0.995 là không có nên em cũng không cần lấy. Em là dân kết cấu xây dựng. Cái B10 là cái dầm consol nên chỉ cần giá trị đầu và cuối thôi.
 
Upvote 0
Em chỉ lấy giá trị (max + min)/2 bác ah. Với B10 thì là 0.995 là không có nên em cũng không cần lấy. Em là dân kết cấu xây dựng. Cái B10 là cái dầm consol nên chỉ cần giá trị đầu và cuối thôi.
Vậy là nếu (max + min)/2 mà không có trong cột Loc tương ứng thì không lấy. Chỉ lấy max và min thôi. Hiểu yêu cầu thì dễ làm hơn.
Bạn đổi tên sh Nguồn thành "data" và dùng code sau thử.
PHP:
Option Explicit
Dim Dic As Object, sTmp As String
Dim endR As Long, i As Long, s As Long, k As Long
Dim Arr01, Arr02, Arr, ArrKQ
Sub Danhdau()
Set Dic = CreateObject("Scripting.Dictionary")
With Sheets("Data")
  endR = .Cells(65000, 1).End(xlUp).Row
  Arr01 = .Range("A2:A" & endR)
  Arr02 = .Range("C2:C" & endR)
End With
ReDim Arr(1 To endR - 1, 1 To 4)
s = 0
For i = 1 To endR - 1
  sTmp = Arr01(i, 1)
  If Not Dic.Exists(sTmp) Then
    s = s + 1
    Dic.Add sTmp, s
    Arr(s, 1) = sTmp
  End If
  k = Dic.Item(sTmp)
  If Arr(k, 2) = "" Or Arr(k, 2) > Arr02(i, 1) Then Arr(k, 2) = Arr02(i, 1) 'min
  If Arr(k, 3) < Arr02(i, 1) Then Arr(k, 3) = Arr02(i, 1) 'max
  Arr(k, 4) = (Arr(k, 2) + Arr(k, 3)) / 2
Next i
'Lay nhung dong thoa'
ReDim ArrKQ(1 To UBound(Arr), 1 To 1)
For i = 1 To UBound(Arr)
  sTmp = Arr01(i, 1)
  If Dic.Exists(sTmp) Then
    k = Dic.Item(sTmp)
    If Arr02(i, 1) = Arr(k, 2) Or Arr02(i, 1) = Arr(k, 3) Or Arr02(i, 1) = Arr(k, 4) Then
      ArrKQ(i, 1) = "x"
    End If
  End If
Next i
Sheets("Data").Select
Range("K2").Resize(i - 1, 1) = ArrKQ
Erase Arr01, Arr02, Arr, ArrKQ: Set Dic = Nothing
End Sub
Code này là học từ file TransferData của NDU về lấy max, min và TB.
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom