Hoàng Nhật Phương
Thành viên gắn bó



- Tham gia
- 5/11/15
- Bài viết
- 1,895
- Được thích
- 1,219
Xin chào tất cả các bạn,
Như tiêu đề Oanh Thơ đã nêu, cụ thể bài toán Oanh Thơ đã viết trong file đính kèm ạ.
Rất mong nhận được sự giúp đỡ từ các bạn.
xin cảm ơn.
Có vấn đề cần làm rõ: Các sheet SX, QC, Kho, KT đã có sẵn hay ban đầu chỉ có sheet Data và bạn muốn code lọc rồi tạo ra các sheet con luôn? Bởi:
- Nếu chỉ cần lọc ra 4 sheet con, bất kể cột bộ phận trong sheet Data có bao nhiêu phần tử thì vòng lập chỉ duyệt qua 4 lần là xong
- Nếu các sheet con chưa sẵn, yêu cầu có bao nhiêu bộ phân thì lọc ra bấy nhiêu sheet, khi ấy vòng lập buộc phải chạy qua toàn bộ các phần tử trong cột bộ phận rồi phải thêm nhiệm vụ chèn sheet... vân... vân...
------------------
Hỏi rõ, làm 1 lần cho đở mất công. Nói chung bài này trên GPE chắc cũng được hỏi cả 100 lần rồi ----> For Next + Dictionary + Advanced Filter là cách dễ ăn nhất
Public Sub GPE()
Dim Ws As Worksheet, sArr(), dArr(), I As Long, K As Long, R As Long, Txt As String
With Sheets("Data")
sArr = .Range("C9", .Range("C65536").End(xlUp)).Resize(, 4).Value
R = UBound(sArr)
End With
For Each Ws In ThisWorkbook.Worksheets
If Ws.Name <> "Data" Then
With Ws
Txt = UCase(.Name): K = -7
ReDim dArr(1 To R * 8, 1 To 3)
For I = 1 To R
If UCase(sArr(I, 2)) = Txt Then
K = K + 8
dArr(K, 1) = sArr(I, 1)
dArr(K, 2) = sArr(I, 2)
dArr(K, 3) = sArr(I, 4)
End If
Next I
.Range("C4").Resize(1000, 3).ClearContents
If K > 0 Then .Range("C4").Resize(K, 3) = dArr
End With
End If
Next Ws
End Sub
Có vấn đề cần làm rõ: Các sheet SX, QC, Kho, KT đã có sẵn hay ban đầu chỉ có sheet Data và bạn muốn code lọc rồi tạo ra các sheet con luôn? Bởi:
- Nếu chỉ cần lọc ra 4 sheet con, bất kể cột bộ phận trong sheet Data có bao nhiêu phần tử thì vòng lập chỉ duyệt qua 4 lần là xong
- Nếu các sheet con chưa sẵn, yêu cầu có bao nhiêu bộ phân thì lọc ra bấy nhiêu sheet, khi ấy vòng lập buộc phải chạy qua toàn bộ các phần tử trong cột bộ phận rồi phải thêm nhiệm vụ chèn sheet... vân... vân...
------------------
Hỏi rõ, làm 1 lần cho đở mất công. Nói chung bài này trên GPE chắc cũng được hỏi cả 100 lần rồi ----> For Next + Dictionary + Advanced Filter là cách dễ ăn nhất
Chắc "chủ nhân" phải làm sẵn các sheet con thôi (vì phải Format các dòng "rí rí"...ngộ ngộ)
Híc!!!!!!!!PHP:Public Sub GPE() Dim Ws As Worksheet, sArr(), dArr(), I As Long, K As Long, R As Long, Txt As String With Sheets("Data") sArr = .Range("C9", .Range("C65536").End(xlUp)).Resize(, 4).Value R = UBound(sArr) End With For Each Ws In ThisWorkbook.Worksheets If Ws.Name <> "Data" Then With Ws Txt = UCase(.Name): K = -7 ReDim dArr(1 To R * 8, 1 To 3) For I = 1 To R If UCase(sArr(I, 2)) = Txt Then K = K + 8 dArr(K, 1) = sArr(I, 1) dArr(K, 2) = sArr(I, 2) dArr(K, 3) = sArr(I, 4) End If Next I .Range("C4").Resize(1000, 3).ClearContents If K > 0 Then .Range("C4").Resize(K, 3) = dArr End With End If Next Ws End Sub
Hihi, Một lần nữa Oanh Thơ lại được bạn giúp đỡ cảm ơn bạn nhiều nhé. Avata của bạn nhìn dễ thương và ấn tượng quá ah.
Oanh Thơ đã chạy thử code của bạn, đối với file đính kèm Oanh Thơ thì kết quả rất OK rồi ạ.
Nhưng Khi Oanh Thơ thêm 1 sheet khác Sheet này không phải là sheet bộ phận hay liên quan gì đến sheet Data cả chỉ là 1 sheet dữ liệu khác thôi ạ.
Sau đó Oanh Thơ chạy code của bạn thì lập tức có một vùng dữ liệu trong sheet này bị mất.
Bạn có thể xử lý lại giúp Oanh Thơ dữ liệu chỉ đưa vào các Sheet có tên bộ phận giống với trường bộ phận trong Sheet Data không ạ, còn các Sheet khác không liên quan ạ.
Xin cảm bạn và diễn đàn nhiều!
Next I
.Range("C4").Resize(1000, 3).ClearContents
If K > 0 Then .Range("C4").Resize(K, 3) = dArr
Next I
If K > 0 Then
.Range("C4").Resize(1000, 3).ClearContents
.Range("C4").Resize(K, 3) = dArr
End If
Bạn tự chỉnh code lại dưới dòng Next I
Thành như vầy thử coi.PHP:Next I .Range("C4").Resize(1000, 3).ClearContents If K > 0 Then .Range("C4").Resize(K, 3) = dArr
Có hàng trăm sheet "không liên quan" thì code chạy "vớ vẫn" mệt luôn.PHP:Next I If K > 0 Then .Range("C4").Resize(1000, 3).ClearContents .Range("C4").Resize(K, 3) = dArr End If
Cảm ơn bạn, ưng quá rồi ! hihi
Bạn cho hỏi thêm K đóng vai trò gì vậy ạ, bạn có thể giải thích cho Oanh Thơ hiểu thêm sự thay đổi này được không ạ.
Với code của bạn trong khi chờ đợi kết quả Oanh Thơ thử sửa lại thành :
If Ws.Name = "SX" Or Ws.Name = "QC" Or Ws.Name = "KT" Or Ws.Name = "Kho" Then
Oanh Thơ thấy kết quả cũng OK ạ.
Cảm ơn bạn nhiều nhé!
---K là số lượng (dòng) dữ liệu tìm được thỏa điều kiện ứng với tên Sheet.
Do bảng kết quả của bạn mỗi 1 dòng dữ liệu dán vào kết quả cách nhau 8 dòng "rí rí" nên khi tìm được 1 dòng thì phải cho K công thêm 8.
K mà <=0 thì chẳng làm gì cả.
---Vì chuyện này mà bài #2 Ndu... phải hỏi bạn có "bi nhiêu" sheet kết quả, nếu chỉ 4 sheet thì bạn OR 4 cái là xong. Nếu có 20 sheet kết quả thì bạn phải OR 20 cái!
Tùy trường hợp mà có cách xử lý.
...
Có hàng trăm sheet "không liên quan" thì code chạy "vớ vẫn" mệt luôn.
Ahihi,
Cảm ơn bạn nhiều , dù là Oanh Thơ chưa hiểu lắm nhưng cảm thấy rất hứng thú.
Đúng là với file thực của Oanh Thơ thì nhiều Or lắm ạ..
Một lần nữa cảm ơn bạn ạ.
Ui, người nổi tiếng!
Oanh Thơ cảm ơn bạn nhiều vì đã quan tâm ạ.
Vâng đúng là các sheet bộ phận SX, QC, Kho, KT là có sẵn từ trước bạn ạ.
Công việc chỉ là đổ dữ liệu từ sheet Data vào đúng các sheet bộ phận này bạn ạ.
Rất mong bạn giúp đỡ!
Xin cảm ơn.
Sub Main()
Dim wksData As Worksheet, wksSub As Worksheet
Dim aWksName, shItem
Set wksData = Worksheets("Data")
wksData.Range("IV1").Value = wksData.Range("D7").Value
aWksName = Array("SX", "QC", "Kho", "KT")
For Each shItem In aWksName
Set wksSub = Worksheets(CStr(shItem))
wksSub.Range("C4:E10000").Clear
wksData.Range("IV2").Value = CStr(shItem)
wksData.Range("C7:F10000").AdvancedFilter 2, wksData.Range("IV1:IV2"), wksSub.Range("C3:E3")
Next
wksData.Range("IV1:IV2").Clear
End Sub
Nếu vậy thì quá dễ, chỉ cần For Next + Advanced Filter là xong:
Mã:Sub Main() Dim wksData As Worksheet, wksSub As Worksheet Dim aWksName, shItem Set wksData = Worksheets("Data") wksData.Range("IV1").Value = wksData.Range("D7").Value aWksName = Array("SX", "QC", "Kho", "KT") For Each shItem In aWksName Set wksSub = Worksheets(CStr(shItem)) wksSub.Range("C4:E10000").Clear wksData.Range("IV2").Value = CStr(shItem) wksData.Range("C7:F10000").AdvancedFilter 2, wksData.Range("IV1:IV2"), wksSub.Range("C3:E3") Next wksData.Range("IV1:IV2").Clear End Sub
Cũng còn thiếu 1 "chiện", mỗi dòng dữ liệu khi dán vào kết quả sẽ cách nhau 8 dòng "rí rí leo nheo".
Nếu tôi theo dõi là chuyện khác, muốn làm cái gì đó thì cứ thêm, sửa, xóa vào sheet Data vậy là xong chuyện, muốn cái gì nữa thì tính tiếp chứ không ai để sẳn mỗi thứ 1 sheet chi cho rắc rối, nhất là cái vụ Insert thêm 8 dòng nữa chẳng biết để làm gì?????
Nếu vài trăm sheet thì không lẽ làm thủ công (đặt mỗi sheet 1 tên).
Nếu tổng số sheet là số lớn so với số sheet cần lọc ra. Nói cách khác là nếu chỉ cần lấy ra vài sheets thì có thể dùng ADO để lọc và sort luôn.
Nếu số sheet cần lấy ra rất nhỏ (không hơn 5 sheets) thì có thể dùng vòng lặp gọi từng lệnh SQL lọc theo tên mỗi sheet là giản dị nhất.
Nếu vậy thì quá dễ, chỉ cần For Next + Advanced Filter là xong:
Mã:Sub Main() Dim wksData As Worksheet, wksSub As Worksheet Dim aWksName, shItem Set wksData = Worksheets("Data") wksData.Range("IV1").Value = wksData.Range("D7").Value aWksName = Array("SX", "QC", "Kho", "KT") For Each shItem In aWksName Set wksSub = Worksheets(CStr(shItem)) wksSub.Range("C4:E10000").Clear wksData.Range("IV2").Value = CStr(shItem) wksData.Range("C7:F10000").AdvancedFilter 2, wksData.Range("IV1:IV2"), wksSub.Range("C3:E3") Next wksData.Range("IV1:IV2").Clear End Sub
Cũng còn thiếu 1 "chiện", mỗi dòng dữ liệu khi dán vào kết quả sẽ cách nhau 8 dòng "rí rí leo nheo".
làm tương tự, dùng Dictionary thay sheet tạmCóp py sang sheet tạm, sort theo tên sheet đầu ra, đọc dữ liệu vào array, xoá sheet tạm.
Bây giờ có thể đọc từ đầu đến cuối. Sheet nào xong mới sang sheet kia. Dữ liệu nào không có tên sheet thì bỏ qua.
Sub GPE()
Dim Ws As Worksheet, Darr(), Dic As Object, i As Long, R As Long, Tmp As String
Darr = Sheets("Data").Range("C9:F" & Sheets("Data").Range("C65500").End(xlUp).Row).Value
Set Dic = CreateObject("scripting.dictionary")
For i = 1 To UBound(Darr)
If Not Dic.exists(Darr(i, 2)) And Darr(i, 2) <> "" Then
Dic.Add Darr(i, 2), 1
Dic.Add Darr(i, 2) & "#" & 1, Array(Darr(i, 1), Darr(i, 2), Darr(i, 4))
Else
Dic.Item(Darr(i, 2)) = Dic.Item(Darr(i, 2)) + 1
Tmp = Darr(i, 2) & "#" & Dic.Item(Darr(i, 2))
Dic.Add Tmp, Array(Darr(i, 1), Darr(i, 2), Darr(i, 4))
End If
Next i
For Each Ws In ThisWorkbook.Worksheets
Tmp = Ws.Name
If Dic.exists(Tmp) Then
R = Dic.Item(Tmp)
ReDim Darr(1 To R * 8, 1 To 3)
For i = 1 To R
Darr((i - 1) * 8 + 1, 1) = Dic.Item(Tmp & "#" & i)(0)
Darr((i - 1) * 8 + 1, 2) = Dic.Item(Tmp & "#" & i)(1)
Darr((i - 1) * 8 + 1, 3) = Dic.Item(Tmp & "#" & i)(2)
Next i
Ws.Range("C4").Resize(1000, 3).ClearContents
Ws.Range("C4").Resize(R * 8, 3) = Darr
End If
Next Ws
Set Dic = Nothing: Set Ws = Nothing: Erase Darr
End Sub
Xin chào Vetmini, cảm ơn bạn đã quan tâm đến chủ đề này ạ.
Nếu bạn có hứng thú,rất mong bạn giúp đỡ cho bài toàn này của Oanh Thơ bằng code cụ thể theo giải pháp của bạn đề cập được không ạ?
Cảm ơn bạn nhiều,
Oanh Thơ