Các câu hỏi về lọc dữ liệu, lọc với nhiều điều kiện
Các bạn giúp mình 2 bài toán tìm kiếm và lọc các dữ liệu ,vui lòng mở file đính kèm
Một giải pháp cho những ai yêu thích Name
Về phần trích lọc danh sách duy nhất thì trên diển đàn có nói nhiều rồi, tôi chỉ muốn góp phần bài toán trích theo điều kiện (Trần thị)
Đặt 2 name là đủ:listA = $A$3:$A$12 VT =IF(ISERR(SEARCH($E$1,listA)),"",ROW(INDIRECT("1:"&ROWS(listA))))Và cuối cùng có công thức:
C3 =IF(ROW(1:1)>COUNT(VT),"",INDEX(listA,SMALL(VT,ROW(1:1)),1))Kéo fill xuống!
Bạn hoangdanh282vn chú ý: Cẩn thận với hàm INDIRECT vì ko phải khi nào cũng cho kết quả đúng… Bạn hãy thử kéo vùng listA ra khỏi cột A thì sẽ biết liền.. Kết quả sai ngay lập tức
ANH TUẤN
Khóa học SprinGO phù hợp
Thiết kế Tổng đãi ngộ (Total Rewards) theo khung SHRM
Khóa học “Thiết kế Tổng phần thưởng (Total Reward) chuẩn khung SHRM” giúp bạn nắm vững toàn bộ hệ thống đãi ngộ theo chuẩn...
Xem khóa học
Tôi nghĩ có lẽ bạn sai trong phần thiết kế vùng điều kiện… Xem file nha (Chú ý đây là điều kiện OR)
Bằng VBA đây, xin mại dô!
Option Explicit
Sub Search2Columns()
Dim SChu As String: Dim Rng As Range, Cell As Range
Dim lRw As Long, Wf As Long, Ed As Long, Bg As Long
lRw = .End(xlUp).Row
For Wf = 2 To lRw
If Wf < 17 Then Bg = 2 Else Bg = Wf – 15
If lRw – Wf > 15 Then Ed = Wf + 15 Else Ed = lRw
Set Rng = Range(Cells(Bg, "B"), Cells(Ed, "B"))
For Each Cell In Rng
If Cell.Value = Cells(Wf, "C").Value Then _
SChu = SChu & "; " & Cell.Offset(, -1).Value
Next Cell
If Len(SChu) > 0 Then
Cells(Wf, "D") = Mid(SChu, 3): SChu = ""
End If
Next Wf
End Sub
Ver 2.0 xài khi cần tăng tốc bằng phương thức FIND()
Option Explicit
Sub SearchForColumns()
Dim SChu As String, GPE_ As String
Dim MyRng As Range, Rng As Range
Dim lRw As Long, Wf As Long, eD As Long, bG As Long
lRw = .End(xlUp).Row
For Wf = 2 To lRw
If Wf < 17 Then bG = 2 Else bG = Wf – 15
If lRw – Wf > 15 Then eD = Wf + 15 Else eD = lRw
Set MyRng = Range(Cells(bG, "B"), Cells(eD, "B"))
With MyRng
Set Rng = .Find(What:=Cells(Wf, "C"), LookIn:=xlValues)
If Not Rng Is Nothing Then
GPE_ = Rng.Address
Do
SChu = SChu & "; " & Rng.Offset(, -1).Value
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> GPE_
End If
End With
If Len(SChu) > 0 Then
Cells(Wf, "D") = Mid(SChu, 3): SChu = ""
End If
Next Wf
End Sub
Góp 1 cách dùng công thức
Ghép 20 dữ liệu cột A khi dữ liệu cột B giống nhau
(Có thể tăng thêm được nếu có nhu cầu – rất đơn giản)
Tập tẹ tý VBA các bác đừng cười em nhé
Sub boyxin()
Dim Er As Long, Er1 As Long, i As Long, j As Long, Text As String
Er = .End(xlUp).Row
Range("E2:F" & Er).Clear
Range("B1:B" & Er).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range( _
"E1"), Unique:=True
Er1 = .End(xlUp).Row
Range("E1:E" & Er1).Sort Key1:=Range("E2"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
For i = 2 To Er1
Text = ""
For j = 2 To Er
If Cells(j, 2) = Cells(i, 5) Then
Text = Text & Cells(j, 1) & ";"
End If
Next
Cells(i, 6) = Left(Text, Len(Text) – 1)
Next
ActiveSheet.Names("Extract").Delete
End Sub
——————————————-
Mượn file bác SA: Sao bác lọc thêm theo điều kiện gì vậy mà em đọc mãi không hiểu
Mình lọc theo chỉ đạo của BNTT đó mà!
Dò theo cột 'C' với 15 records trước đó & 15 records sau nó; nếu cột 'B' của vùng mà trị nào bằng trị tại C(i) thì chép nối tất tần tật A tương ứng đến ô D(i)
Nhưng khi i<15 hay còn 15 records đến dòng cuối thì vùng khảo sát rút ngắn xuống tương ứng!
Hỏi lại:
a= c HOẶC b = d
hay
a =c VÀ b = d
thêm nữa:
– Tìm được số đúng yêu cầu rồi thì tiếp theo làm gì nữa?
Ẹc… Ẹc… Ít ra phải có file minh họa, chứ như câu hỏi của bạn, tôi có thể trả lời ngay rằng:
Số cần tìm là 780000, 781010, 782020… vân vân —> Dùng công thức cũng kéo fill được hết
bạn dùng advanced Filter để lọc, điều kiện mình lọc trong file là and(a=c,b=d)
Có phải bạn muốn vậy không
Ngoài cách dùng Advanced Filter, tôi nghĩ với bài của bạn dùng AutoFilter thì dể làm hơn
Hãy xem file hướng dẩn tôi đính kèm ở đây (có hình)
(Tôi làm câu 2, các câu khác tương tự)
Ah… yêu cầu của bạn lại phải dùng Advanced Filter mới xong
Bạn làm theo hướng dẩn trong file tôi đính kèm nhé
Ái chà… cái trò này xem bộ ngon à nha! Dùng để LỌC DUY NHẤT kèm TÍNH TỔNG là bá chấy
Theo gợi ý này của volga, tôi làm code như sau:
Sub Test()
Dim Rng As Range
Set Rng = Application.InputBox("Chon vung can tong hop", Type:=8)
Selection.Consolidate "'" & ThisWorkbook.Path & "" & _
ActiveSheet.Name & "'!" & Rng.Address(ReferenceStyle:=xlR1C1), xlSum, False, True, False
End Sub
Mời xem file thử —-> Xem chừng nhanh gọn hơn dùng AF để lọc, rồi lại SUMIF (dài dòng)
Cảm ơn volga rất nhiều về phát hiện này!
Dùng Consolidate sướng thật, nhưng code lượm thượm quá
Sửa lại đây:
Option Explicit
Sub Test()
Dim Src As Range, FullPath As String
Set Src = Application.InputBox("Chon vung can tong hop", Type:=8)
FullPath = Evaluate("=Cell(" & Chr(34) & "Filename" & Chr(34) & ")")
Selection.Consolidate FullPath & "!" & Src.Address(, , 2), 9, , True
End Sub
Ghi chú: số 9 trong code tương đương với Function_Num trong hàm SUBTOTAL —> (1 là AVERAGE… 9 là SUM)
Type:=8 —> Khai báo cho Excel biết đây là Range (Nếu không có nó thì khi gọi InputBox lên, bạn không thể dùng chuột chọn vùng được) —-> Có thể vào của sổ VBE, gõ InputBox, bôi đen nó rồi F1 sẽ thấy
Chr(34) —> là dấu " —> Thí nghiệm gõ thử công thức =CHAR(34) vào 1 cell nào đó sẽ thấy
Thế thì bỏ luôn Src cho gọn:
Sub Test()
With Application.InputBox("Chon vung can tong hop", Type:=8)
Selection.Consolidate .Address(, , 2), 9, , True
End With
End Sub
Tại cái Consolidate nó bắt Address phải là kiểu R1C1 (kiểu thường nó hỏng chịu—> Thử rồi)
Tại khi làm xong, bạn lại làm tiếp, cộng dồn vào dử liệu có sẳn nên nó nhân đôi, nhân 3, nhân 4 là chuyện thường (Đây cũng là phát hiện hay à nha)
Vậy, nếu muốn nó không nhân thì xóa dử liệu vừa tổng hợp đi, làm lại mới (xóa luôn cả Range đang lưu giữ trong Consolidate)
Dữ liệu của bạn gây khó khăn cho việc lọc. Xin góp một vài ý như thế này:
1. Nên tách dòng tên phiếu thành 1 dòng độc lập và lấy nó làm tiêu đề cho các cột luôn thể. Lúc đó có thể đưa chữ "code" xuống dưới để tạo tiêu đề cho cột thứ 2.
2. Nên để cột 1 có tên, ví dụ Qcode chẳng hạn.
Lúc đó bạn chỉ cần dùng autofiter lần lượt trên 2 cột: Qcode và code là OK.
Bạn thử lọc bằng tay ra 1 bảng khác làm ví dụ xem nào (Vì chưa hiểu lắm ý bạn)
Nghĩa là bạn nên thiết kế lại dữ liệu theo hướng này:
QCode|Code|Số Phiếu|Số lượng (Đ.Kiện)
Q01|1|103|1
Q01|1|106|1
Q01|1|107|1
Q01|1|109|1
Q01|1|110|1
Q01|1|112|1
Q01|2|101|1
Q01|2|102|1
Q01|2|104|1
Q01|2|105|1
Q01|2|108|1
…|…|…|…
Không ai thiết kế data theo kiểu của bạn, số phiếu lại cho lên thành cột! Như vậy trong file chỉ có tối đa 255 cột –> 255 phiếu thôi à! Nếu phát sinh thêm phiếu thì sao?
Filter2Criteria
Trong file đính kèm tôi đã sửa đổi 1 ít về cách bố trí các tiêu đề và dùng VBA để giải quyết bài toán của bạn.
Cách dùng như sau:
– Tôi đặt 1 tên dùng làm điểm mốc bắt đầu vùng dữ liệu của bạn (tại A3, tên là Ques). Sau này nếu bạn có muốn thay đổi bảng thì nhớ là giữ lại tên tại điểm bắt đầu của bảng để code hoạt động đúng.
– Trong file tôi chèn 1 nút lệnh để gọi macro (nếu thích thì bạn có thể gán phím nóng để dùng cho nhanh)
– Trước khi nhấn nút, bạn chọn 2 ô liên tiếp chứa điều kiện cần lọc, ví dụ: chọn 2 ô A4:B4 (Q01-code 2) và nhấn nút lệnh. Mã lệnh sẽ lọc dòng và cột đúng như yêu cầu của bạn.
– Nếu muốn hiện lại toàn bộ dữ liệu thì chọn 1 ô bất kỳ, nhấn nút lệnh.
(Ngoài ra, tôi đã freez tại dòng số 2 để bạn dễ theo dõi)
– Bạn xem trong file để test và cho ý kiến nhé.
Rồi, đã tạo lại file giúp bạn.
Có mấy bước như thế này:
1. Chọn ô đầu tiên chứa các Q (vdụ A3), click vào name-box (bạn có biết nó ở đâu không? +-+-+-+) và nhập tên Ques, nhấn Enter
2. Chọn thanh Control Toolbar (cố gắng tìm @#!^%), chọn nút command rồi vẽ lên ô B1
Nhấn D-click vào nút sẽ mở cửa ổ VBE và xuất hiện 2 dòng:
Sub Command1_Click()
End Sub
Gõ thêm vào giữa 2 dòng này: Call Filter2Criteria
Ở của số bên trái, nhấn R-Click, chọn Insert Module, sẽ xuất hiện cửa sổ để viết mã lệnh. Copy cái đoạn code rồi dán vào đó.
Trở lại Excel, click vào biểu tượng hình thước eke trong thanh Control Toolbar để thoát khỏi design mode. Thế là xong.
Bạn copy code này và thay vào code cũ nhé.
(mở file, nhấn Alt-F11, bên trái có dòng Module1, nhấn d-click sẽ thấy code cũ)
Dùng Pivottable bạn nên đặt Thêm một Name động nữa (dùng Offset) để excel tự cập nhật dữ liệu khi ta thêm vào! (vào Insert/Name/Define). Sau đó khi updated dữ liệu xong, bạn phải qua Pivottable, click chuột phải vào nó và chọn Refresh Data.
Bạn xem file đính kèm, mình dùng Pivottable với 1 Name động (dùng Offset).
AutoFilter: Custom – Contains : Vieba
Advanced Filter: từ khoá: *Vieba
Trích ra bản khác thì bạn dùng cái này nè, nó không bình thường đâu: Advanced Filter, trong đó có mục Copy to another location.
Bạn xem File này nhe ,có phải lọc như thế không ?
File của anh Anhtuan1066 .Nhìn dử liệu của bạn thật sự không hiểu !
Thêm cách thứ 2+n
Xài macro này, nếu lười thiết kế:
Option Explicit
Sub FindFilter()
Dim Rng As Range, sRng As Range, rRng As Range
Dim MyAdd As String
Set Rng = Range(, .End(xlUp))
Set sRng = Rng.Find("Vieba", , xlFormulas, xlPart)
If Not sRng Is Nothing Then
MyAdd = sRng.Address: = "KQLoc"
Range(, .End(xlDown)).Clear
Do
.End(xlUp).Offset(1) = sRng.Value
Set sRng = Rng.FindNext(sRng)
Loop While Not sRng Is Nothing And MyAdd <> sRng.Address
End If
End Sub
Từ cần tìm có thể thông qua bàn fím nhập vô biến kiểu chuỗi
Bạn đưa dử liệu thật lên đi.. dù lọc trong sheet hay lọc sang sheet khác gì thì Advanced Filter vẫn làm được tuốt! … Đương nhiên là tự động rồi
(dử liệu ít quá… lười làm lắm —> Sợ bạn ráp vào dử liệu thật không đúng, lại la làng)
Đã dùng VBA thì khỏi công thức —> Xài Consolidate là ăn tiền nhất
Sub Tonghop()
Sheet2.Range("A1").CurrentRegion.Offset(1).ClearContents
With Sheet1.Range("A1").CurrentRegion.Offset(1, 2)
Sheet2.Range("B2").Consolidate "'" & .Parent.Name & "'!" & .Address(, , 2), 9, , 1
End With
With Sheet2.Range("A1").CurrentRegion.SpecialCells(4)
.Value = Evaluate("=ROW(R1:R1000)")
End With
End Sub
Vì Consolidate bắt buộc ta biểu diển địa chỉ vùng dử liệu nguồn theo dạng R1C1 … và nếu dử liệu nguồn nằm tại sheet khác, file khác thì phải ghi rõ đường dẩn nơi chứa dử liệu
Ở trong code của tôi:
– .Parent.Name là tên sheet —> Do phía trên có With Sheet1.Range(gì đó )… —> mà Parent là CHA MẸ —> Vậy cha mẹ của Sheet1.Range( gì đó ) chính là Sheet1
– .Address(, , 2) biểu diển địa chỉ vùng dử liệu theo dạng R1C1
– Số 9 là tổng hợp dử liệu theo kiểu SUM —> tham số này gần giống với tham số trong hàm SUBTOTAL ấy
đại khái là vậy!
Bạn có thể record macro quá trình tổng hợp dử liệu bằng Consolidate rồi xem code để biết thêm chi tiết (tôi cũng làm theo cách này đấy)
Cách đây 1 tháng tôi chưa biết gì về Consolidate cả… May mắn được bạn Volga gợi ý cách dùng.. và tôi thấy nó khá hay khi dùng để tổng hợp số liệu —> Các bạn nghiên cứu thử xem!
Kiến thức trên mạng thì nhiều lắm (không chỉ trên GPE) —> Có điều mọi người phải thừa nhận 1 điều rằng: Chỉ khi nào ta đụng đến 1 vấn đề nào đó có ứng dụng công cụ thì ta sẽ nhớ đến công cụ ấy lâu hơn
Tôi thì chi xài công cụ, hoặc code nào đó mà tôi thật sự lãnh hội được
Hồi đó tôi không đê ý đến Consolidate (dù có rất nhiều tài liệu đề cập) là vì tôi chẳng có gì đê ứng dụng nó cả —> Đến 1 hôm, vừa đúng lúc có 1 bài toán mà khi dùng Consolidate thì nó trở nên đơn giãn đến không ngờ (Và người gợi ý tôi dùng Consolidate cho bài toán ấy chính là bạn Volga)
Bời vậy mới biết: Học, đọc cả ngàn quyển sách mà không ứng dụng cũng bằng thừa
Bạn vào Insert>>Name>>Define sẽ biết "vt" là cái gì liền.
Bạn có thể bấm Ctrl+ F3 sẽ thấy liền .
bài lọc này không hay nữa bạn thử xem link này xem nhe ,nhìn xem những gì anh NDU chỉ nè
[URL='https://www.giaiphapexcel.com/forum/showpost.php?p=131315&postcount=5'%5DLọc
Thân
Lâu rồi không sử dụng Name động với công thức mảng. Gặp bài này hay quá nên làm liền. Bạn xem file nha
lại
Bạn dùng PivotTable để thực hiện bài toán này nhé
Tham khảo trong file đính kèm nhe
Thân
Đối với dữ liệu cửa bạn, cách làm như sau:
1. Điền tháng: Thêm Cột sau cột Q, ghi tiêu đề là tháng. Tại ô R3, gõ công thức MONTH(P3) sau đó copy xuống đến dòng 178
2. Tạo Pivot Table:
– Vào menu DataPivort Table and PivotChart report…
– Bước 1: Chọn Microsoft Office Excel list or database, và chọn PivotTable. Bấm Next
– Bước 2: Chọn vùng dữ liệu. Tại Range: Chọ dữ liệu từ A2 đến R178. Kết quả hiển thị là Sheet1!$A$2:$R$178. Bấm Next
– Bước 3: Chọn nơi hiển thị kết quả: Chọn New worksheet rồi chọn Layout
– Màn hình Layout:
+ Bấm và rê nút Tháng vào vùng PAGE
+ Vùng ROW bạn có thể bấm và rê nút Mã hàng, Tên hàng ,…
+ Vùng COLUMN bạn có thể để Mã đơn vị nếu muốn
+ Vùng DATA, bạn để SL, Thành tiền, … Mặc nhiên là tính tổng. Sau khi để dữ liệu vào, bạn có thể thay đổi công thức và định dạng bằng các nhấp đúp chuột lên nó. Sau đó bấm OK và Finish.
Ngoài ra bạn có thể nghiên cứu thêm phần Option để có kết quả như mong muốn.
Nếu bạn muốn trích dòng hàng nào, trong bảng chi tiết hoặc bảng tổng hợp, bạn chỉ việc đến dòng có số lượng tương ứng bạn nhấp đúp chuột vào ô đó, tự động dữ liệu sẽ được mang sang 1 sheet mới, sau đó bạn muốn làm gì thì làm.
Bạn xem trong file đính kèm coi có đúng ý chưa nhé
Đơn giá là đơn giá tính bình quân nhé
Thân
Bạn vào trang này để tham khảo nhá:
https://www.giaiphapexcel.com/forum/showthread.php?t=6121
Hoặc:
https://www.giaiphapexcel.com/forum/showthread.php?t=6216
Hi vọng bạn sẽ gặt hái nhiều điều ở đó
Thân
Nhìn vào như thế thì trước mắt dùng AutoFilter Cho nhanh đi bạn !
Công thức của bạn quá hay chứ lơ mơ gì
Bạn dùng macro sự kiện sau, như là thêm một tham khảo
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next: Dim Col As Byte
'NhatKy'
If Not Intersect(Target, Columns("D:D")) Is Nothing Then
3 Col = 5 + Choose(Right(Target.Value, 1) + 1, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8)
Target.Offset(, 2).Value = Sheets("QuiUoc").Columns("B:B").Find(Target.Offset(, -2), _
, xlFormulas, xlWhole).Offset(, Col)
ElseIf Not Intersect(Target, Columns("E:e")) Is Nothing Then
6 Col = Switch(Target.Value = "A", 1, Target = "B", 2, Target = "C", 3, Target = "D", 4)
Target.Offset(, 2).Value = Sheets("QuiUoc").Columns("B:B").Find(Target.Offset(, -3), _
, xlFormulas, xlWhole).Offset(, Col)
End If
End SubHướng dẫn sử dụng:
* Bạn Copy macro này & dán vô SheetName có tên là 'NhatKy' (Phải chuột vô thanh SheetName, chọn dòng cuối để mở cửa sổ VBE & . . .
* Để sử dụng hàm Choose() cho ngắn câu lệnh dòng thứ 3, mình đã gán tên (mã) khách hàng biến thiên từ K1. . K10. Như vậy tên trường của 'QuyUoc' từ 'G2..P2' có tên tương ứng là K1. . K10 (Việc này cũng không quan trọng cho lắm,so với việc phải nhập mã khách hàng chỉ là các mã như vậy. Nếu có thêm khách hàng nữa thì phải chuyển đổi khác – ta sẽ tính sau!–=0)
* Khi nhập 1 mã khách hàng đúng tại dòng nào đó của cột 'D', cột 'F' qui chiếu sẽ được cập nhật;
Tương tự như vậy, khi nhập nhà cung cấp vô cột 'E', sẽ có giá trị thích ứng tại cột 'G' với dong tương ứng
Bài này có "nối chuổi" nếu dùng công thức thì sẽ rất cồng kềnh
Tặng bạn 2 hàm tự tạo: 1 cái để trích lọc duy nhất và 1 cái dùng để nối chuổi theo điều kiện!
Function JoinIf(VungDK1 As Range, DK1 As Variant, VungDK2 As Range, DK2 As Variant, VungKQ As Range, Optional PC As String = "") As String
Dim i, Temp As String
For i = 1 To VungKQ.Count
If VungDK1(i) = DK1 And VungDK2(i) = DK2 Then Temp = Temp & PC & VungKQ(i)
Next
JoinIf = Mid(Temp, Len(PC) + 1, Len(Temp))
End Function
Function Unique(Vung As Range, STT As Long) As Variant
Dim i As Long, K As Long
For i = 1 To Vung.Cells.Count
If Vung(i) <> "" Then
If i = Application.WorksheetFunction.Match(Vung(i), Vung, 0) Then
K = K + 1
End If
If K = STT Then Unique = Vung(i): Exit For
End If
Next i
End FunctionXem file đính kèm
———————
Công nhận bác HYen đúng là chuyên gia về Find —> Với Find và FindNext, học hoài vẫn thấy ngu!
Bạn muốn lọc là lọc như thế nào. Căn cứ vào sheet Data, ta sẽ trích lọc dữ liệu theo điều kiện ở một sheet mới hay lọc ngay tại sheet Data luôn. Lọc theo tài khoản là lọc ở bên Nợ hay bên Có.
Nếu chỉ đơn thuần là trích lọc dữ liệu ngay tại sheet Data thì ta chỉ cần dùng Autofilter theo cột Mã đối tượng và Tài khoản là ok rồi. Nếu cần thiết thì có thể dùng VBA để giải quyết yêu cầu của bạn
Bạn nói rõ hơn tí nha.
Mình sẽ hướng dẫn từ xa, bạn làm theo xem sao nha
(*) Dùng chuột chọn 4 dòng đầu tiên của trang tính;
Vô menu Insert để thêm 4 dòng trống;
(*) Bạn copy tiêu đề tại dòng 5 chép sang vùng 'G5:K5'
Sau đó chép vùng 'G5:J5' đến vùng 'G1:J1'
(*) Bạn nhập 'NN_CTVT' vô ô 'G2' & '138822' vô 'I2'
(*) Sau đó vô menu Data -> Fỉlte -> Advanced Fỉlte
Tại ngăn Action ta chọn dòng thứ 2 (Copy to another location)
Tại CS (cửa sổ) Lít range ta nhập $Ạ:$E2156
Tại CS Criteria range ta nhập $G1:$I$1
Ngăn tiếp ta nhập $G5:$K5 & nhấn chọn 'OK'
Chiêm nghiệm kết quả tại vùng dữ liệu mới xuất hiện.
Chúc thành công! –=0
Hi
Bạn xem thử cái này nhe ,lâu quá không sử dụng hơi lúng túng .
Riêng ngay chỗ Validation thì làm như bạn CPH làm là ok ,(Trích lọc ra một ds duy nhất rồi đưa vào Validation)
Thân
Mời bạn xem file này.
Gửi cho bạn file này
Mình dùng 1 cột phụ cho bạn dễ hình dung.
Bạn xem file đính kèm nha
Bạn xem file đình kèm nha.
Bài làm chỉ hướng dẫn thôi. Khi làm bạn có thể kết hợp với hàm Offset để làm cho dữ liệu được tinh gọn và làm cho máy chạy nhanh hơn nếu dữ liệu lớn.
Tôi có 2 cách tùy bạn chọn nhé
Cách 1 :
Vào Menu/Tools/Options, tại tab View bỏ chọn Zero value.
Cách 2 :
Tại F6 sửa thêm công thức sau rồi fill xuống :
Bạn thử lại xem, mình dùng được đấy thôi
Bạn không chỉ rõ chổ lỗi của bạn là gì thì sao mình biết mà sửa được chứ.
RIêng cột STT, dùng hàm if thì bạn nên trả vể rỗng "" thay vì trả về khoảng trắng " ". Như thế sẽ bị lỗi #N/A
Bạn xem lại công thức trong cột H của sheet "NKSUACHUA" xem. Không thể nào cùng một lúc mà ta có thể trích lọc dữ liệu theo điều kiện ở 2 sheet khác nhau được.
Bạn nên thêm một cột I nữa, cột này để dùng cho sheet "THRIENG". Cột H dùng cho sheet "BCSUACHUA".
Bạn dùng công thức này:
Copy công thức xuống.
Lập cho bạn macro khó nhứt, cái còn lại bạn thử sửa từ cái này nha!
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Columns(1)) Is Nothing And Target.Value <> "" Then
Dim Rng As Range, sRng As Range: Dim Dem As Byte
Dim Format_ As String, MyAdd As String
Set Rng = Range(, Target.Offset(9))
5 If IsDate(Target.Value) Then
Format_ = Target.NumberFormat: Rng.NumberFormat = "m/d/yyyy"
7 End If
Set sRng = Rng.Find(Format(Target.Value, "m/d/yyyy"), , xlFormulas, xlWhole)
If sRng Is Nothing Then
MsgBox "Chua Co Trung"
Else
MyAdd = sRng.Address
Do
Dem = 1 + Dem
Set sRng = Rng.FindNext(sRng)
Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
End If
MsgBox Dem & " La So Lan Nhap Trung", , "GPE.COM"
sRng.NumberFormat = Format_
End If
End Sub
Bạn xem trong file kèm nhé.
Làm cho bạn bằng name đây!
Salam dùng RANK còn tôi dùng MATCH –> Có thể ngắn hơn đấy!
bác thay công thức
thành
NHÉ
Các ô ở cột Vùng lọc bạn dùng hàm if( or …..) nên mới bị bạn hãy thay bằng hàm if(and….)như sau :
=IF(AND(MONTH(B11)=BCCN!$E$6,YEAR(B11)=BCCN!$G$6),MAX($I$6:I10)+1,"")
Bạn sai 2 chổ:
OFFSET(ds,,9,,)
Phải sửa lại thành:
OFFSET(ds,,9,,1) —> Resize nó thành 1 cột thôi chứ
và:
ROWS(ds)
Đúng ra phải là:
ROW(ds) —> ROWS và ROW hoàn toàn khác nhau cơ mà
Tuy nhiên nếu là tôi thì tôi thích cái này hơn:
ROW(INDIRECT("1:"&ROWS(DS)))
Nó giúp cho công thức lọc sau này ngắn gọn hơn
Vậy là đặt name được rồi:
DK=IF((OFFSET(ds,,,,1)>=Loc!$F$3)*(OFFSET(ds,,,,1)<=Loc!$I$3)+(OFFSET(ds,,9,,1)=Loc!$H$4),ROW(ds),"")
Cái này hình như là dấu * chứ Bác ndu.
Chưa hiểu lắm! KHÔNG CÓ D/K KHÁCH có phải là khi ta xóa cell KHÁCH đi, đúng không?
Thử xem như thế này được chưa:
Càng lúc yêu cầu càng cao.. cho đến 1 lúc bạn sẽ thấy công thức không thể đáp ứng nổi —> Vậy sao bạn không thử dùng PivotTable hoặc VBA nhỉ?
Cái này dùng sumproduct được mà
Chưa rõ hết ý của bạn
Macro sau sẽ copy toàn bộ các dữ liệu đã tô màu sang Sheet2
Option Explicit
Sub FilterForColor()
Dim Rng As Range, fRng As Range, Clls As Range
Dim eRw As Long: Dim Sh As Worksheet
Set Rng = Range(, .End(xlToLeft))
eRw = .End(xlUp).Row: Set Sh = Sheets("Sheet2")
For Each Clls In Rng
With Clls.Interior
If .ColorIndex > 2 Then
Sh..End(xlToLeft).Offset(, 1).Resize(eRw).Value = Clls.Resize(, eRw).Value
End If
End With
Next Clls
End Sub
Chạy Maro này ở Sheet1. Nhớ sửa lại code cho phù hợp với file dữ liệu thật.
Sub RutTrich()
Dim Data As Range
MyArray = Array("lhdn", "laodong", "nganhkd", "thunhap", "doanhthu", "loinhuan")
For Each Rng In Range(, .End(xlToLeft))
For i = 0 To UBound(MyArray)
If Left(Rng, Len(MyArray(i))) = MyArray(i) Then
If Data Is Nothing Then
Set Data = Rng.Resize(.End(xlUp).Row)
Else
Set Data = Union(Data, Rng.Resize(.End(xlUp).Row))
End If
End If
Next
Next
Data.Copy Sheets("Sheet2").
End Sub
Macro của bạn đây:
Option Explicit
Sub DSDK()
Dim Rng As Range, sRng As Range, Clls As Range, Sh As Worksheet, dRng As Range
Dim eRw As Long, fRw As Long, TTu As Byte
Dim MyAdd As String
Sheets("Data").Select: Set Sh = Sheets("Results")
eRw = .End(xlUp).Row: Set Rng = Range("F1:F" & eRw)
Sh.Range("A5:Z" & eRw + 29).Clear
1 ' Tìm & Chép Theo Loai Hình Dich Vu:'
For Each Clls In Range("AA2:AA" & .End(xlUp).Row)
Set sRng = Rng.Find(Clls.Value, , xlFormulas, xlWhole)
If Not sRng Is Nothing Then
MyAdd = sRng.Address: TTu = TTu + 1
With Sh..End(xlUp)
If TTu > 1 Then
.Offset(1).FormulaR1C1 = "=TCong"
.Offset(2, -1).Value = Choose(TTu, "I", "II", "III", "IV", "V", "VI")
.Offset(2).Value = Clls.Value
Else
.Offset(1, -1).Value = "I"
.Offset(1).Value = Clls.Value
End If
End With
Do
With Sh..End(xlUp).Offset(1, -1)
.Resize(, 18).Value = sRng.Offset(, -5).Resize(, 18).Value
End With
Set sRng = Rng.FindNext(sRng)
Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
End If
Next Clls
eRw = Range("AA2:AA" & .End(xlUp).Row).Rows.Count
Sh.Select
2 'Tô Màu Cho Vui!'
With .Interior
If .ColorIndex < 42 Then
.Resize(, 20).Interior.ColorIndex = .ColorIndex + 1
Else
.Resize(, 20).Interior.ColorIndex = 34
End If
End With
3 ' Dinh Dang & Tính Tong:'
For TTu = 1 To eRw
MyAdd = Choose(TTu, "I", "II", "III", "IV", "V", "VI")
Set sRng = Columns(1).Find(MyAdd)
If Not sRng Is Nothing Then
If sRng = "I" Then
sRng.Resize(, 2).Font.Bold = True
fRw = sRng.Row + 1
Else
sRng.Offset(-1).Resize(2, 2).Font.Bold = True
'14 & 15
sRng.Offset(-1, 13).FormulaR1C1 = "=sum(R[-" & (sRng.Row – fRw) & "]C:RC)"
sRng.Offset(-1, 14).FormulaR1C1 = "=sum(R[-" & (sRng.Row – fRw) & "]C:RC)"
fRw = sRng.Row + 1
End If
End If
Next TTu
End Sub
Tôi có cảm giác dử liệu của bạn nếu dùng PivotTable sẽ nhanh hơn đấy —> Sao bạn không thử xem!
Trong khi chờ đợi, xài lối truyền thống này tiếp đi nha.
Option Explicit
Sub DSDK()
Dim Rng As Range, sRng As Range, Clls As Range, Sh As Worksheet, dRng As Range
Dim eRw As Long, fRw As Long, TTu As Byte
Dim MyAdd As String
Sheets("Data").Select: Set Sh = Sheets("Results")
eRw = .End(xlUp).Row: Set Rng = Range("F1:F" & eRw)
Sh.Range("A5:Z" & eRw + 29).Clear: Application.ScreenUpdating = False
1 ' Tìm & Chép Theo Loai Hình Dich Vu:'
For Each Clls In Range("AA2:AA" & .End(xlUp).Row)
Set sRng = Rng.Find(Clls.Value, , xlFormulas, xlWhole)
If Not sRng Is Nothing Then
MyAdd = sRng.Address: TTu = TTu + 1
With Sh..End(xlUp)
If TTu > 1 Then
.Offset(1).FormulaR1C1 = "=TCong": fRw = 1
End If
.Offset(1 + fRw, -1).Value = Choose(TTu, "I", "II", "III", "IV", "V", "VI")
.Offset(1 + fRw).Value = Clls.Value
End With
Do
With Sh..End(xlUp).Offset(1, -1)
.Resize(, 18).Value = sRng.Offset(, -5).Resize(, 18).Value
End With
Set sRng = Rng.FindNext(sRng)
Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
End If
Next Clls
eRw = Range("AA2:AA" & .End(xlUp).Row).Rows.Count
Sh.Select
2 'Tô Màu Cho Vui!'
With .Interior
If .ColorIndex < 42 Then
.Resize(, 20).Interior.ColorIndex = .ColorIndex + 1
Else
.Resize(, 20).Interior.ColorIndex = 34
End If
End With
3 ' Dinh Dang & Tính Tong:'
For TTu = 1 To eRw
Set sRng = Columns(1).Find(Choose(TTu, "I", "II", "III", "IV", "V", "VI"))
If Not sRng Is Nothing Then
If sRng = "I" Then
sRng.Resize(, 2).Font.Bold = True
fRw = sRng.Row + 1
Else
sRng.Offset(-1).Resize(2, 2).Font.Bold = True
MyAdd = "=sum(R[-" & (sRng.Row – fRw) & "]C:RC)"
39 sRng.Offset(-1, 13).FormulaR1C1 = MyAdd
310 sRng.Offset(-1, 14).FormulaR1C1 = MyAdd
fRw = sRng.Row + 1
End If
End If
Next TTu
4 ' Xu Lí 2 Dòng Cuoi:'
With .End(xlUp).Offset(1)
.Resize(2).FormulaR1C1 = "=TCong": .Resize(2).Font.Bold = True
MyAdd = "=sum(R[-" & (.Row – fRw) & "]C:RC)"
43 .Offset(, 12).FormulaR1C1 = MyAdd: .Offset(, 13).FormulaR1C1 = MyAdd
.Offset(1).Value = .Value & " chung:"
MyAdd = "=sum(R[-" & (.Row – 4) & "]C:RC)/2"
46 .Offset(1, 12).FormulaR1C1 = MyAdd: .Offset(1, 13).FormulaR1C1 = MyAdd
.Offset(1, 12).Resize(, 2).Font.Bold = True
End With
End Sub
(1) Bạn chỉ được giải quyết 2 cột tính tổng là do bạn hoàn toàn đó nha: Trong file đính kèm ban đầu, bạn chỉ tính tổng có 2 cột thôi mà!
Bảo sao làm vậy, làm hơn tổ phí sức (–=0 ?! :-= –=0)
(2) Mình vừa đánh số các dòng lệnh ở bài gần đây của mình & chúng ta xét theo các dòng lệnh có số đó;
Bạn đã thay 2 dòng lệnh 39 & 310 của mình bằng 8 dòng lệnh khác để macro tính tồng cho các vùng miền;
Mình đề xuất 8 dòng lệnh của bạn nên thay bằng các dòng lệnh như sau:
Set dRng = sRng.Offset(-1, 7).Resize(, 8) '*Thay cho 2 dòng lệnh 39 & 310'
For Each Clls In dRng
Clls.FormulaR1C1 = MyAdd
Next Clls
Nhưng dù sao cũng ngợi khen bạn rất nhiều & chắc rằng sau này bạn sẽ bảo trì được đứa con tinh thần của chúng ta 1 cách hoàn hảo! Xin chúc mừng;
(3) Hai dòng lệnh 43 & 46 được thay bằng các câu lệnh sau:
Set dRng = .Offset(, 6).Resize(, 8) '* Dòng tổng của vùng cuối'
For Each Clls In dRng
Clls.FormulaR1C1 = MyAdd
Next Clls&
Set dRng = .Offset(1, 6).Resize(, 8) '* Tổng cộng chung – dòng cuối dữ liệu'
For Each Clls In dRng
Clls.FormulaR1C1 = MyAdd
Next Clls
Bạn thử sức với dòng lệnh để thay cho dòng 47 xem sao
(4) Bạn gọi NDU bằng anh, thì phải gọi mình bằng 'Bác' đó nha! :-= –=0 –=0
Ta có thể 'Đặt thừa số chung' như toán học cơ sở
Bạn có thấy 3 cụm dòng lệnh na ná giống nhau không?
Mình xin nhốt chung chúng vô 1 macro để cần thì gọi cho tiện
Bạn xem cặp macro này ha:
Option Explicit
Sub DSDK()
Dim Rng As Range, sRng As Range, Clls As Range, Sh As Worksheet, dRng As Range
Dim eRw As Long, fRw As Long, TTu As Byte
Dim MyAdd As String
Sheets("Data").Select: Set Sh = Sheets("Results")
eRw = .End(xlUp).Row: Set Rng = Range("F1:F" & eRw)
Sh.Range("A5:Z" & eRw + 29).Clear: Application.ScreenUpdating = False
1 ' Tìm & Chép Theo Loai Hình Dich Vu:'
For Each Clls In Range("AA2:AA" & .End(xlUp).Row)
Set sRng = Rng.Find(Clls.Value, , xlFormulas, xlWhole)
If Not sRng Is Nothing Then
MyAdd = sRng.Address: TTu = TTu + 1
With Sh..End(xlUp)
If TTu > 1 Then
.Offset(1).FormulaR1C1 = "=TCong": fRw = 1
End If
.Offset(1 + fRw, -1).Value = Choose(TTu, "I", "II", "III", "IV", "V", "VI")
.Offset(1 + fRw).Value = Clls.Value
End With
Do
With Sh..End(xlUp).Offset(1, -1)
.Resize(, 18).Value = sRng.Offset(, -5).Resize(, 18).Value
End With
Set sRng = Rng.FindNext(sRng)
Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
End If
Next Clls
eRw = Range("AA2:AA" & .End(xlUp).Row).Rows.Count
Sh.Select
2 'Tô Màu Cho Vui!'
With .Interior
If .ColorIndex < 42 Then
.Resize(, 20).Interior.ColorIndex = .ColorIndex + 1
Else
.Resize(, 20).Interior.ColorIndex = 34
End If
End With
3 ' Dinh Dang & Tính Tong:'
For TTu = 1 To eRw
Set sRng = Columns(1).Find(Choose(TTu, "I", "II", "III", "IV", "V", "VI"))
If Not sRng Is Nothing Then
If sRng = "I" Then
sRng.Resize(, 2).Font.Bold = True
fRw = sRng.Row + 1
Else
sRng.Offset(-1).Resize(2, 2).Font.Bold = True
38 Set dRng = sRng.Offset(-1, 7).Resize(, 8) '*'
TongCong dRng, "=sum(R[-" & (sRng.Row – fRw) & "]C:RC)"
fRw = sRng.Row + 1
End If
End If
Next TTu
4 ' Xu Lí 2 Dòng Cuoi:'
With .End(xlUp).Offset(1)
.Resize(2).FormulaR1C1 = "=TCong": .Resize(2).Font.Bold = True
43 Set dRng = .Offset(, 6).Resize(, 8) '*'
TongCong dRng, "=sum(R[-" & (.Row – fRw) & "]C:RC)"
.Offset(1).Value = .Value & " chung:"
46 Set dRng = .Offset(1, 6).Resize(, 8) '*'
TongCong dRng, "=sum(R[-" & (.Row – 4) & "]C:RC)/2"
.Offset(1, 6).Resize(, 8).Font.Bold = True
End With
End Sub
' * * * * * * * * *
Quá dễ!; Bạn thêm 1 dòng lệnh duy nhất vô macro con (tạm gọi là thế!) dòng lệnh sau
vào phía trên, hay tốt nhất vào phía dưới vòng lặp For. . .Next
Chúc mọi sự như í!
Sao lại không?
Bạn xem các dòng tổng cộng & tổng cộng chung xem sao?
Còn muốn format toàn bộ vùng thì không cần dòng đó nữa; mà là
nhưng e rắng dữ liệu của bạn quá nhiều số không to đùng, chưa chắc thẩm mỹ hơn.
(Dòng lệnh này cho vô cuối macro bự đó nha! –=0 :-= –=0)
Thử code này xem:
Sub Test()
Dim Clls As Range
With Sheet1.Range("A1").CurrentRegion
For Each Clls In .Resize(1)
If Left(Clls, 4) <> "lhdn" Then Clls.EntireColumn.Hidden = True
Next Clls
.SpecialCells(12).Copy: Sheet2.Range("A1").PasteSpecial 3
.EntireColumn.Hidden = False
End With
Application.CutCopyMode = False
End Sub
Bạn tham khảo cách cùi bắp này của DOSNET nhé!
1 cột phụ thôi, dùng công thức này nè:
=SUMPRODUCT(1*(MID($E$3:$E$63,FIND("Tỉnh",$E$3:$E$63),LEN($E$3:$E$63))=MID($E3,FIND("Tỉnh",$E3),LEN($E3))))
Ôi chao —> Tức là nếu có thể thay hàm SUMPRODUCT thành SUMIF thì cứ nên thay —> Còn như không còn cách nào thì cứ xài —> Ai cấm
Bạn dùng 2 cột thì giải thuật cũng như tôi dùng 1 cột thôi —> Tức sẽ bằng nhau về tốc độ —> Và trong trường hợp này tôi chọn cách GỌN NHẤT (gọn ở chổ đở tốn 1 cột)
Hạn chế chứ không phải là bỏ luôn không xài
Trong này có bài nào làm bằng VBA đâu bạn —> Toàn công thức thường
Code và file của bạn chẳng "ăn nhậu" gì với yêu cầu của tác giả cả
Có điều tôi nhìn vào yêu cầu này cũng chả hiểu ý nghĩa của nó là thế nào nữa
Đoán là:
– Cột 1 lấy các giá trị là TEXT
– Cột 2 lấy các giá trị là NUMBER
Hic… chả biết đúng không
Bạn thử code này xem:
Sub Test()
Dim Clls As Range, i As Long, j As Long
Dim Cot1 As Range, Cot2 As Range
On Error GoTo Thoat
Set Cot1 = Application.InputBox("Chon cot 1", Type:=8)
Set Cot2 = Application.InputBox("Chon cot 2", Type:=8)
Cot1.Copy Destination:=
With .Resize(Cot1.Rows.Count)
For Each Clls In Cot2.SpecialCells(2, 1)
i = i + 1
.SpecialCells(2, 1).Areas(j + 1)(i).Value = Clls.Value
If .SpecialCells(2, 1).Areas(j + 1).Count = i Then
j = j + 1: i = 0
End If
Next
End With
Thoat:
End Sub
Chúng ta sẽ làm gì với 2 cột phụ đề này?
(Từ đầu bạn đưa lên luôn cho rồi —> Mất thời gian quá)
Vậy thì thử với code này —> Càng dể:
Sub Test()
Dim Clls As Range, i As Long, j As Long
Dim Cot1 As Range, Cot2 As Range
On Error GoTo Thoat
Set Cot1 = Application.InputBox("Chon cot 1", Type:=8)
Set Cot2 = Application.InputBox("Chon cot 2", Type:=8)
For Each Clls In Cot2.SpecialCells(2, 1)
i = i + 1
Cot1.SpecialCells(2, 1).Areas(j + 1)(i + 1).Value = Clls.Offset(1).Value
If Cot1.SpecialCells(2, 1).Areas(j + 1).Count = i Then
j = j + 1: i = 0
End If
Next
Thoat:
End Sub
Khi hộp InputBox hiện ra, bạn chọn Cot1 là cột A, Cot2 là cột B —> Nói chung code sẽ lấy thời gian ở cột 2 thay vào cột 1
Bạn dùng công thức dưới:
Bạn nên ghép hàm TRIM() vào để loại bỏ các ký tự trống " " thừa khỏi chuỗi. công thức sẽ hoàn chỉnh hơn.
=IF(E2="","",IF(RIGHT(TRIM(E2),8)="doc than","s","m"))
Dùng Maro này thử xem. Gán vào Nút lệnh hoặc 1 sự kiện nào đó.
Bạn xem trong file nhé.
Thì sau khi lọc xong bạn copy qua Sheet KhachHang là được mà. Tôi sửa lại. Bạn xem nhé.
For Each cll In Range(, .End(xlUp)).SpecialCells(xlCellTypeVisible)
If InStr(Str, "," & cll.Value) = 0 Then
Str = Str & "," & cll.Value
Cells(5, R).Value = cll.Value
R = R + 1
End If
NextĐoạn này dùng để trích ngang số phiếu vào dòng 5, từ ô H5. Tôi dùng một chuỗi phụ (Trong Code là biến Str) để kiểm tra xem một số phiếu nào đó đã được trích ngang chưa.
Duyệt qua các Cell hiện ở cột D (Cột số phiếu). Nếu không tìm thấy số phiếu trong chuỗi Str (InStr(Str, "," & cll.Value) = 0) thì trích ngang (Cells(5, R).Value = cll.Value) đồng thời ghép số phiếu đó vào chuỗi Str (Str = Str & "," & cll.Value), Tăng R lên một đơn vị để dịch chuyển sang cột tiếp theo. Đương nhiên các số phiếu đã được trích ngang thì sẽ được ghép vào chuỗi Str và khi có duyệt qua một Cell khác có số phiếu đã được trích ngang thì InStr() sẽ trả về giá trị >0 và không trích ngang số phiếu đó nữa.
If .Value <> "" Then Range(, .End(xlToLeft).Offset(1)).FormulaR1C1 = "=INDEX(R7C3:R65536C3,MATCH(R5C,R7C4:R65536C4,))"
If .Value <> "" Then Range(, Cells(.End(xlUp).Row, .End(xlToLeft).Column)).SpecialCells(xlCellTypeVisible).FormulaR1C1 = "=IF(RC4=R5C,RC7,"""")"Đoạn này dùng để nhập công thức tính ngày giao và số lượng cho vùng trích ngang. Bạn có thể bỏ dòng Sheets("XuatHang")..ClearContents chạy code và xem công thức.
Sheets("KhachHang").Cells.ClearContents
Range(, Cells(.End(xlUp).Row, .End(xlToLeft).Column)).SpecialCells(xlCellTypeVisible).Copy
Sheets("KhachHang").Select
.Select
Selection.PasteSpecial Paste:=xlPasteValuesĐoạn này dùng để xóa dữ liệu cũ ở Sheet KhachHang, Copy các dòng hiện ở Sheet XuatHang dán vào Sheet KhachHang.
Thuật toán nếu diễn đạt bằng lời có lẽ sẽ khó hiểu. Nếu bạn rành về Code, tự đọc code để biết thuật toán sẽ dễ hơn.
Nếu giá trị nhỏ nhất hoặc lớn nhất có trùng thì bạn tính sao? Lấy toàn bộ hay chỉ lấy 1 —> Và nếu lấy 1 thì lấy theo tiêu chí gì?
Ngoài ra có nhiều mặt hàng xuất hiện nhiều lần, vậy ta có cộng số lượng của chúng lại với nhau trước rồi mới so sánh không?
——————–
Ah… sorry, tôi đọc không kỹ yêu cầu: lấy giá trị nhỏ nhất và lớn nhất của mỗi mặt hàng
Bài này bạn dùng Consolidate hoặc Subtotals là nhanh nhất (trong menu Data)
vậy dùng SUBTOTALS đi
Viết cho bạn 1 code tự động luôn
Sub LocMax()
With Range("A1").CurrentRegion
.Subtotal 2, 4, 3, True, False, True
End With
End Sub
Sub LocMin()
With Range("A1").CurrentRegion
.Subtotal 2, 5, 3, True, False, True
End With
End SubNếu khéo tay, bạn có thể gộp 2 code này thành 1
Dể lắm bạn ơi —> Thật ra code trên không phải tôi tự viết… tôi record macro mà ra đấy chứ! (Record quá trình dùng SUBTOTALS)
Bạn cũng làm thử đi, vài lần sẽ quen!
Là vầy:
– Bạn vào menu ToolsMacroRecord new macro
– 1 hộp thoại xuất hiện yêu cầu đặt tên cho macro (bạn có thể không làm gì, cứ OK đại)
– Từ thời điểm này, bạn làm bất cứ điều gì thì record macro sẽ ghi lại thành code (giống như máy ghi âm)
– Giờ bạn có thể dùng SUBTOTALS để thao tác
– Xong quá trình tổng hợp bằng SUBTOTALS, bạn bấm nút tắt record maco đi —> vậy là có được 1 code
Ta có thể thí nghiệm xem macro chạy thế nào bằng cách:
– Remove SUBTOTALS đi, xong bấm Alt + F8, chọn tên macro và bấm nút Run —> Bạn sẽ thấy macro đã làm lại công việc mà bạn vừa làm khi nảy (giống như máy ghi âm phát lại)
Nguyên tắc lọc bằng Advanced Filter, nếu vùng đích và nguồn khác nhau thì điều kiện tiên quyết là ta phải đứng tại sheet đích để gọi Advanced Filter
Cụ thể là:
– Sheet nguồn của bạn là sheet1
– Sheet đích của bạn là sheet2
– Vậy đầu tiên bạn phải chuyển sang sheet2, sau đó mới vào menu DataFilterAdvanced Filter
– Nếu bạn đứng tại sheet1 mà thao tác thì nó sẽ báo lổi
————
Có thể viết thành 1 code, đại khái như sau:
Sub Loc()
Sheet2.Range("A1").CurrentRegion.Clear
With Sheet1.Range("A1").CurrentRegion
.AdvancedFilter 2, Sheet1.Range("F1:I4"), Sheet2.Range("A1")
End With
End Sub
Nếu dử liệu bạn khác hơn, tốt nhất nên đưa file thật lên đây… hoặc ít nhất, nếu file giả lập thì cũng phải cùng cấu trúc với file thật
Cách đơn giản là bạn làm như minhthien321 là dùng Advance Filter. Nếu bạn chưa biết cách sử dụng nó bạn có thể vào đây tham khảo là có thể tự mình làm được
https://www.giaiphapexcel.com/forum/showthread.php?t=11552
Chúc thành công!
Thế thì bạn thử file này xem.
Bạn xem file, nhớ Enable Macro.
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, ) Is Nothing Then Exit Sub
Range("B3").AutoFilter 2,
If = "" Then ActiveSheet.AutoFilterMode = False
End Sub
– Bạn nhập dữ liệu 1 ô nhưng lại muốn dùng nó để lọc cho 1 vùng khác, theo mình dùng macro là gọn nhẹ nhất.
– Nếu muốn dùng cho Sheet khác, bấm Alt F11 –> Click đôi Sheet1 ở cửa sổ bên trái –> Copy đoạn mã –> Click đôi Sheet muốn dùng –> Paste đoạn mã vào.
* Chú ý vùng dữ liệu : ô B1 chứa mã bạn muốn lọc, ô B3 là ô Mã sản phẩm. Nếu trong Sheet mới của bạn, vị trí các ô có thay đổi, hãy sửa lại code cho đúng.
Chắc là bạn này muốn cái bảng tính trông nó pro 1 chút í mà **~****~****~**
Bạn xem trong file nhé. Với yêu cầu mới này không thể sửa code cũ mà phải làm lại theo cách khác.
Private Sub Worksheet_Change(ByVal Target As Range)
If = "" Then
ActiveSheet.AutoFilterMode = False
Exit Sub
End If
If Intersect(Target, ) Is Nothing Then Exit Sub
Range("B3").AutoFilter 2,
If Range("B4", .End(xlUp)).Find() Is Nothing Then
MsgBox "Khong co " & "[ " & & " ] trong danh sach", , "Thong bao"
.ClearContents
End If
End Sub
Anh xem file.
Câu I của bạn đây, xin xem trong file đính kèm
Option Explicit
Sub TongHop()
Dim Sh As Worksheet, Rng As Range, Clls As Range
Dim Dat As Date, Dat0 As Date, Dat9 As Date
Dim sDate As String
Dim Col As Byte, Jj As Byte
Sheets("Data").Select:
Col = Range(, .End(xlToRight)).Columns.Count – 1
ReDim Acc(Col) As Integer
Set Rng = Range(, .End(xlUp))
Set Sh = Sheets("Statement")
Sh..Resize(Sh..CurrentRegion.Rows.Count, 13).Clear
For Each Clls In Rng
If IsDate(Clls.Value) Then
If (Clls.Value <> "" And Month(Clls.Value) <> Month(Dat)) Then
Dat = Clls.Value
Dat0 = DateSerial(Year(Dat), Month(Dat), 1)
Dat9 = DateSerial(Year(Dat), 1 + Month(Dat), 1) – 1
sDate = Format(Dat0, "DD/MM/YY") & "-" & Format(Dat9, "dd/mm/yy")
Sh..End(xlToLeft).Offset(, 1).Value = sDate
For Jj = 0 To Col
If Clls.Row > 3 Then
Sh.Cells(7 + Jj, "iV").End(xlToLeft).Offset(, 1).Value = Acc(Jj)
End If
Acc(Jj) = Clls.Offset(, 2 + Jj).Value
Next Jj
Else
For Jj = 0 To Col
Acc(Jj) = Acc(Jj) + Clls.Offset(, 2 + Jj).Value
Next Jj
End If: End If
Next Clls
For Jj = 0 To Col
Sh.Cells(7 + Jj, "iV").End(xlToLeft).Offset(, 1).Value = Acc(Jj)
Next Jj
With Sh..End(xlToLeft).Offset(, 1)
.Value = "ToTal": .Resize(Col + 1).Font.Bold = True
.HorizontalAlignment = xlCenter
With .Offset(1)
.FormulaR1C1 = "=SUM(RC[-" & (.Column – 3) & "]:RC)"
.AutoFill Destination:=.Resize(Col + 1), Type:=xlFillDefault
.Resize(Col + 1).NumberFormat = "#,##0"
End With: End With
End Sub
Nếu Đông không chịu Đoài thì Đoài phải sang Đông, & ngược lại!
Trong trường hợp đã có macro trên thì nên thêm công đoạn chép tên trường của các cột sau cột 'C' của trang 'Data' sang 'Statement'
Nếu muốn thử sức viết macro khác, thì làm ngược lại.
Bạn muốn như thế này ?
Bạn xem file, mở file ra chọn Enables macros. Vì dùng VBA nên thao tác khoẻ re, muốn cập nhật chỉ cần nhấn nút.
công thức mảng kết thúc bằng ctrl + shift + enter .bạn thử làm đi nhé
Không hiểu ý anh lắm, viết đại code này, anh test thử xem sao cái đã
Chú ý :
Thay đổi –> AutoFilter.
Thay đổi –> Trích phát sinh.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Cll As Range
If Intersect(Target, ) Is Nothing Then Exit Sub
If Target = Then
Range("B3", .End(xlUp)).AutoFilter 2,
Exit Sub
End If
If Target = Then
For Each Cll In Range("B4", .End(xlUp))
If Cll = And Cll.Offset(, 1) = And Cll.Offset(, 2) = Then
MsgBox "Khong co phat sinh"
Exit Sub
End If
Next Cll
MsgBox "Co phat sinh –> Xem Sheet Trich-PS"
Sheets(2)..End(xlUp).Offset(1).Resize(, 3) _
= WorksheetFunction.Transpose()
End If
End Sub
Hãy xem VBA làm điều đó như thế nào!
Sub T3(Jj As Byte)
Dim Clls As Range, Rng0 As Range
Select Case Jj
Case 1
Set Rng = Nothing
For Each Clls In Range(, .End(xlDown))
If Clls.Value = .Value Then
If Rng Is Nothing Then
Set Rng = Clls.Resize(, 4)
Else
Set Rng = Union(Rng, Clls.Resize(, 4))
End If
End If
Next Clls
Case 2
If Not Rng Is Nothing Then
Set Rng0 = Rng.Cells(1, 2).Resize(Rng.Rows.Count)
Set Rng = Nothing
For Each Clls In Rng0
If Clls.Value = .Value Then
If Rng Is Nothing Then
Set Rng = Clls.Offset(, -1).Resize(, 4)
Else
Set Rng = Union(Rng, Clls.Offset(, -1).Resize(, 4))
End If
End If
Next Clls
Else
End If
Case 3
If Not Rng Is Nothing Then
Set Rng0 = Rng.Cells(1, 3).Resize(Rng.Rows.Count)
Set Rng = Nothing
For Each Clls In Rng0
If Clls.Value = .Value Then
If Rng Is Nothing Then
Set Rng = Clls.Offset(, -2).Resize(, 4)
Else
Set Rng = Union(Rng, Clls.Offset(, -2).Resize(, 4))
End If
End If
Next Clls
Else
End If
End Select
End Sub
(Giống như gọi đệ quy, nhỉ?) ; Xin xem thêm trong file đính kèm
Mình rút gọn lại macro T3, như sau
Sub T3(Jj As Byte)
Dim Clls As Range, Rng0 As Range
Select Case Jj
Case 1
Set Rng = Nothing
For Each Clls In Range(, .End(xlDown))
If Clls.Value = .Value Then
If Rng Is Nothing Then
Set Rng = Clls.Resize(, 4)
Else
Set Rng = Union(Rng, Clls.Resize(, 4))
End If
End If
Next Clls
Case 2, 3
If Not Rng Is Nothing Then
Set Rng0 = Rng.Cells(1, Jj).Resize(Rng.Rows.Count) 'jj=2'
Set Rng = Nothing
For Each Clls In Rng0
If Clls.Value = Cells(Jj, "G").Value Then ''
With Clls.Offset(, 1 – Jj) '-1'
If Rng Is Nothing Then
Set Rng = .Resize(, 4)
Else
Set Rng = Union(Rng, .Resize(, 4))
End If
End With
End If
Next Clls
Else
End If
End Select
End Sub
Trong nổ lực 'Đặt thừa số chung'
Sub T3(jj As Byte)
Dim Clls As Range, Rng0 As Range
If jj = 1 Then
Set Rng0 = Range(, .End(xlDown))
Else
Set Rng0 = Rng.Cells(1, jj).Resize(Rng.Rows.Count)
End If
Set Rng = Nothing
For Each Clls In Rng0
If Clls.Value = Cells(jj, "G").Value Then
With Clls.Offset(, 1 – jj)
If Rng Is Nothing Then
Set Rng = .Resize(, 4)
Else
Set Rng = Union(Rng, .Resize(, 4))
End If
End With
End If
Next Clls
End Sub
Có nhiều cách, dùng tạm cái này (vì tôi thấy dữ liệu của bạn có vậy, nếu đầy đủ hơn thì lại khác…):
Bạn xem file đính kèm!
"Unhide công thức" của bác concongia cho bạn đây (Alt+F11 thì sẽ thấy)
Public Function makh(vung As Range) As String
Dim i, j As Integer
For i = 4 To Len(vung)
If Mid(vung, i, 1) = "-" And IsNumeric(Mid(vung, i – 1, 1)) And IsNumeric(Mid(vung, i + 1, 1)) = False Then j = i
Next
makh = Left(vung, j – 1)
End Function
Public Function tenkh(vung As Range) As String
Dim i, j As Integer
For i = 4 To Len(vung)
If Mid(vung, i, 1) = "-" And IsNumeric(Mid(vung, i – 1, 1)) And IsNumeric(Mid(vung, i + 1, 1)) = False Then j = i
Next
tenkh = Right(vung, Len(vung) – j)
End Function
Public Function macv(vung As Range) As String
Dim i, j As Integer
For i = 4 To Len(vung)
If Mid(vung, i, 1) = ":" And IsNumeric(Mid(vung, i – 1, 1)) And IsNumeric(Mid(vung, i + 1, 1)) = False Then j = i
Next
macv = Left(vung, j – 1)
End Function
Public Function congtrinh(vung As Range) As String
Dim i, j As Integer
For i = 4 To Len(vung)
If Mid(vung, i, 1) = ":" And IsNumeric(Mid(vung, i – 1, 1)) And IsNumeric(Mid(vung, i + 1, 1)) = False Then j = i
Next
congtrinh = Right(vung, Len(vung) – j)
End Function
Cách thực hiện:
Nhập định mức bên sheet dinh muc, sau đó qua sheet tien luong copy dòng trên xuống và nhập khối lượng công tứhc sẽ tự tính.
Tôi có chỉnh sửa lại trong file của Bạn để tiện lập công thức, chứ nếu thực hiện như Bạn sẽ khó khăn cho việc liên kết công thức. bạn xem file nhé!
Bạn nói rằng:
Đã tính tuổi (chính xác) thì phải có mốc thời gian bao gồm cả NGÀY, THÁNG, NĂM —> năm hiện tại là 2005, vậy NGÀY là ngày mấy và THÁNG là tháng mấy?
Theo dữ liệu của bạn, tính đến ngày 31/12/2005 thì ai cũng.. <15 tuổi cả —> Vậy nên… khỏi cần lọc luôn
Còn nếu tổng quát hơn (có ai đó > 15 tuổi) thì sẽ dùng Advanced Filter để lọc với cell điều kiện có công thức =DATEDIF(C3,"2005/12/31","Y")<=15
Advanced Filter bạn biết chứ, giống như hình này đây:
1456
Bạn dùng hàm SUMPRODUCT nhé!
Bạn dùng công thức mảng này cho ô G3
Chú ý: Nhập công thức xong kết thúc bằng tổ hợp phím Ctrl + Shift + Enter
Dùng Advanced Filter
– Click vào Copy to another location
– Mục List range: lấy vùng dữ liệu $A$2:$D$9
– Mục Copy to: chọn $A$14:$D$14
– Click vào Unique records only
– OK
Tôi gữi bạn file ví dụ này.
Chú ý
– Công thức tính giá trị màu nằm trong name nha (Menu InsertNameDefine)
– Quy định màu sắc đã được liệt kê tại vùng H1:BK2 cho bạn tham khảo
– Hãy filter cột phụ (Cột D) để lọc theo màu
– Mỗi lần thay đổi màu sắc, hãy bấm F9 để cập nhật giá trị
Thích công thức thì có công thức,
Xem file: