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ơ



Chỉnh lại code bài #3, cho nó chạy "vớ vẫn" một chút chắc cũng không lâu.Oanh Thơ xin cảm ơn hai bạn: VetMini & HieuCD đã góp ý và giúp đỡ cho Oanh Thơ ạ.
Oanh Thơ đã chạy thử code trên của bạn HieuCD kết quả cũng đã OK rồi ạ. Cảm ơn bạn nhé!
Oanh Thơ đang vướng mắc 1 trường hợp nữa (bài toán 2) cũng tương tự như bài toán Oanh Thơ đã nêu ở bài 1.
Cũng là lấy dữ liệu từ Sheet Data đưa vào các sheet có sẵn ạ.
bài toán 2 những điểm khác so với bài toán 1 như sau ạ.
+ Dữ liệu lấy từ các Sheet Data đưa vào các sheet bộ phận điều kiện là tên của các Sheet bộ phận có thay đổi không trùng với tên trong trường bộ phận tại sheet Data nữa vì có thêm "ABC " đằng trước.
+ Dữ liệu lấy từ bảng theo dòng nhưng đưa vào các sheet bộ phận theo cột.
+ Số cột của mỗi người là 1 cột không phải như 8 cột như bài toán 1
Cụ thể câu hỏi và kết quả Oanh Thơ xin nêu cụ thể trong file kèm.
Kính mong nhận thêm được sự giúp đỡ của các bạn ạ.
Trân trọng cảm ơn.
Oanh Thơ
Public Sub GPE()
Dim Ws As Worksheet, sArr(), dArr(), I As Long, Col 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): Col = 0
ReDim dArr(1 To 2, 1 To R)
For I = 1 To R
If "ABC " & UCase(sArr(I, 2)) = Txt Then
Col = Col + 1
dArr(1, Col) = sArr(I, 4)
dArr(2, Col) = sArr(I, 1)
End If
Next I
.Range("D3:D4").Resize(, 1000).ClearContents
If Col > 0 Then .Range("D3:D4").Resize(, Col) = dArr
End With
End If
Next Ws
End Sub



Chỉnh lại code bài #3, cho nó chạy "vớ vẫn" một chút chắc cũng không lâu.
PHP:Public Sub GPE() Dim Ws As Worksheet, sArr(), dArr(), I As Long, Col 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): Col = 0 ReDim dArr(1 To 2, 1 To R) For I = 1 To R If "ABC " & UCase(sArr(I, 2)) = Txt Then Col = Col + 1 dArr(1, Col) = sArr(I, 4) dArr(2, Col) = sArr(I, 1) End If Next I .Range("D3:D4").Resize(, 1000).ClearContents If Col > 0 Then .Range("D3:D4").Resize(, Col) = dArr End With End If Next Ws End Sub





bạn chạy code mớiOanh Thơ xin cảm ơn hai bạn: VetMini & HieuCD đã góp ý và giúp đỡ cho Oanh Thơ ạ.
Oanh Thơ đã chạy thử code trên của bạn HieuCD kết quả cũng đã OK rồi ạ. Cảm ơn bạn nhé!
Oanh Thơ đang vướng mắc 1 trường hợp nữa (bài toán 2) cũng tương tự như bài toán Oanh Thơ đã nêu ở bài 1.
Cũng là lấy dữ liệu từ Sheet Data đưa vào các sheet có sẵn ạ.
bài toán 2 những điểm khác so với bài toán 1 như sau ạ.
+ Dữ liệu lấy từ các Sheet Data đưa vào các sheet bộ phận điều kiện là tên của các Sheet bộ phận có thay đổi không trùng với tên trong trường bộ phận tại sheet Data nữa vì có thêm "ABC " đằng trước.
+ Dữ liệu lấy từ bảng theo dòng nhưng đưa vào các sheet bộ phận theo cột.
+ Số cột của mỗi người là 1 cột không phải như 8 cột như bài toán 1
Cụ thể câu hỏi và kết quả Oanh Thơ xin nêu cụ thể trong file kèm.
Kính mong nhận thêm được sự giúp đỡ của các bạn ạ.
Trân trọng cảm ơn.
Oanh Thơ
Sub GPE()
Dim Ws As Worksheet, Darr(), Dic As Object, i As Long, C As Long, Tmp As String
Darr = Sheets("Data").Range("C8:F" & Sheets("Data").Range("C65500").End(xlUp).Row).Value
Set Dic = CreateObject("scripting.dictionary")
For i = 1 To UBound(Darr)
If Darr(i, 2) <> "" Then
Tmp = "ABC " & Darr(i, 2)
If Not Dic.exists(Tmp) Then
Dic.Add Tmp, 1
Dic.Add Tmp & "#" & 1, Array(Darr(i, 1), Darr(i, 4))
Else
Dic.Item(Tmp) = Dic.Item(Tmp) + 1
Tmp = Tmp & "#" & Dic.Item(Tmp)
Dic.Add Tmp, Array(Darr(i, 1), Darr(i, 4))
End If
End If
Next i
For Each Ws In ThisWorkbook.Worksheets
Tmp = Ws.Name
If Dic.exists(Tmp) Then
C = Dic.Item(Tmp)
ReDim Darr(1 To 2, 1 To C)
For i = 1 To C
Darr(1, i) = Dic.Item(Tmp & "#" & i)(1)
Darr(2, i) = Dic.Item(Tmp & "#" & i)(0)
Next i
Ws.Range("D3").Resize(2, 1000).ClearContents
Ws.Range("D3").Resize(2, C) = Darr
End If
Next Ws
Set Dic = Nothing: Set Ws = Nothing: Erase Darr
End Sub
Ahihi, Tuyệt cú mèo rồi!
Ah bài toán 2 này của Oanh Thơ các cột liền nhau xin hỏi bạn ndu96081631 có thể áp dụng được phương pháp giống bài13 của bạn được không ạ?
Cảm ơn các bạn nhiều nhiều.
Oanh Thơ



Hi, vẫn là cái tên chưa thân nhưng quen quen, Xin cảm ơn bạn HieuCD rất nhiều ạ.bạn chạy code mớiMã:Sub GPE() Dim Ws As Worksheet, Darr(), Dic As Object, i As Long, C As Long, Tmp As String Darr = Sheets("Data").Range("C8:F" & Sheets("Data").Range("C65500").End(xlUp).Row).Value Set Dic = CreateObject("scripting.dictionary") For i = 1 To UBound(Darr) If Darr(i, 2) <> "" Then Tmp = "ABC " & Darr(i, 2) If Not Dic.exists(Tmp) Then Dic.Add Tmp, 1 Dic.Add Tmp & "#" & 1, Array(Darr(i, 1), Darr(i, 4)) Else Dic.Item(Tmp) = Dic.Item(Tmp) + 1 Tmp = Tmp & "#" & Dic.Item(Tmp) Dic.Add Tmp, Array(Darr(i, 1), Darr(i, 4)) End If End If Next i For Each Ws In ThisWorkbook.Worksheets Tmp = Ws.Name If Dic.exists(Tmp) Then C = Dic.Item(Tmp) ReDim Darr(1 To 2, 1 To C) For i = 1 To C Darr(1, i) = Dic.Item(Tmp & "#" & i)(1) Darr(2, i) = Dic.Item(Tmp & "#" & i)(0) Next i Ws.Range("D3").Resize(2, 1000).ClearContents Ws.Range("D3").Resize(2, C) = Darr End If Next Ws Set Dic = Nothing: Set Ws = Nothing: Erase Darr End Sub
Câu trả lời là ĐƯỢC!
Cũng giống như cách làm bằng tay thôi: Lọc bằng Advanced Filter sang vùng tạm, copy/paste transpose sang các sheet
Xong!






hic ngại quá

Oanh Thơ xin trân trọng cảm ơn các bạn và diễn đàn đã giúp đỡ Oanh Thơ thực hiện được bài toán 1 và 2 trong chủ đề này ạ.
Hiện tại với chủ đề này Oanh Thơ vẫn còn một vướng mắc nữa đó bài toán 3 này ạ...hic ngại quá
Câu hỏi và kết quả mong muốn Oanh Thơ đã nêu trong file đính kèm ạ.
Kính mong các bạn tiếp tục giúp đỡ ạ.
Trân trọng cảm ơn.
Oanh Thơ
"a" ở file thật là giống nhau hay khác nhau? và đã có sẵn dữ liệu "a" ứng với 31 ngày? Đã tạo 31 ngày ứng với tháng đó? Có cần tạo tự động số ngày tương ứng với tháng chỉ định?Không làm mất dữ liệu ở các vùng và các sheet không liên quan (không làm mất chữ a)



"a" ở file thật là giống nhau hay khác nhau? và đã có sẵn dữ liệu "a" ứng với 31 ngày? Đã tạo 31 ngày ứng với tháng đó? Có cần tạo tự động số ngày tương ứng với tháng chỉ định?
Các sheet bộ phận (KT,SX,Kho,QC) có sẵn? Đã lập sẵn Họ Tên | Bộ Phận | Mã Số | Item?
Với mỗi mã số luôn có 8 dòng và 3 items?
Không cần file thật, dữ liệu minh họa tương tự file thật là được (minh họa "a" hết thì khó hiểu)Cảm ơn befaint đã quan tâm ạ,rất xin lỗi các bạn vì điều kiện không cho phép nên Oanh Thơ không gửi đc file thật lên đây rất mong các bạn thông cảm.
Oanh Thơ xin giải thích từng trường hợp của bạn ạ:
+ "a" mục đích chỉ là hiển thị các vùng đó có dữ liệu,các dữ liệu có khác nhau, thay đổi có hoặc không tùy theo từng ngày.
+ 31 ngày này là cố định 31 cột, form mẫu có sẵn 31 cột tương ứng với 31 ngày. nếu tháng nào có 30 ngày thì form mẫu vẫn có đủ 31 cột nhưng cột thứ 30 để trắng không có gì.
+ Các sheet bộ phận (KT,SX,Kho,QC) có sẵn Đã lập sẵn Họ Tên | Bộ Phận | Mã Số | Item.
+ Với mỗi mã số luôn có 8 dòng tương ứng với 8 hạng mục mà Oanh Thơ đã nêu ở bài16 trong cùng chủ đề.
https://www.giaiphapexcel.com/forum...hiều-sheet-theo-điều-kiện&p=764148#post764148
3Item(3 dòng) 1,2,3 sẽ tự động lấy từ Sheet Data2 sang còn lại các 5 dòng còn lại là dữ liệu nhập tay theo ngày.
Rất mong nhận được sự trợ giúp của bạn và diễn đàn.
Trân trọng cảm ơn.
Oanh Thơ.



Không cần file thật, dữ liệu minh họa tương tự file thật là được (minh họa "a" hết thì khó hiểu)
Có thể nói rõ hơn về quy trình nhập dữ liệu vào sheet "Data2" và sheet bộ phận không? Ban đầu gồm dữ liệu nào? Nhập dữ liệu tiếp vào như nào? Cái nào trước/ sau? (vì nếu còn cập nhật dữ liệu vào các sheet bộ phận nhiều hơn 1 lần?)
(1) Nhập vào file mà bạn đã đính kèm phải không? Hay mỗi bộ phận một file để tự nhập dữ liệu vào?Hi befaint,
Về quy trình nhập dữ liệu thì là thế này. Mỗi thành viên ở các sheet bộ phận có 8 dòng. 4 dòng đầu là nhập dữ liệu cho từng người theo ngày. (1)
Sau đấy cứ 1 tuần hoặc nửa tháng (không cụ thể là bao nhiêu ngày thậm trí là cuối tháng cũng được) dữ liệu sẽ tổng hợp từ nhiều tệp tin bên ngoài khác (2) đưa hết vào tệp tin đính kèm trong sheet data2 với các trường mã số và các dữ liệu của 5item như đã minh họa.
Bước cuối cùng là từ sheet data2 đưa dữ liệu của 3item vào các dòng màu vàng trong sheet bộ phận.
Sheet data2 gọi là sheet trung gian để tổng hợp dữ liệu từ nhiều tệp tin. Nghĩa là bước này thực hiện xong thì sheet data2 mới có dữ liệu để đưa đến những sheet bộ phận được bạn ạ.
code chỉ thay thế Hàm Vlookup như trong file mẩuOanh Thơ xin trân trọng cảm ơn các bạn và diễn đàn đã giúp đỡ Oanh Thơ thực hiện được bài toán 1 và 2 trong chủ đề này ạ.
Hiện tại với chủ đề này Oanh Thơ vẫn còn một vướng mắc nữa đó bài toán 3 này ạ...hic ngại quá
Câu hỏi và kết quả mong muốn Oanh Thơ đã nêu trong file đính kèm ạ.
Kính mong các bạn tiếp tục giúp đỡ ạ.
Trân trọng cảm ơn.
Oanh Thơ
Sub GPE()
Dim Darr(), Sarr(), Arr(), Tarr(), Dic As Object, Ws, i As Long, k As Byte, j As Byte
Darr = Sheets("Data2").Range("F9:FE" & Sheets("Data2").Range("F65500").End(xlUp).Row).Value
Set Dic = CreateObject("scripting.dictionary")
For i = 1 To UBound(Darr)
If Darr(i, 1) <> "" And Not Dic.exists(Darr(i, 1)) Then Dic.Add Darr(i, 1), i
Next i
Ws = Array("SX", "QC", "Kho", "KT") 'Khai báo tên các Sheet
Tarr = Sheets(Ws(0)).Range("H3:AL3").Value
For k = LBound(Ws) To UBound(Ws)
ReDim Arr(1 To 3, 1 To 31)
Sarr = Sheets(Ws(k)).Range("E1:E" & Sheets(Ws(k)).Range("E65500").End(xlUp).Row).Value
For i = 4 To UBound(Sarr) Step 8
If Sarr(i, 1) <> "" And Dic.exists(Sarr(i, 1)) Then
For n = 1 To UBound(Arr)
For j = 1 To UBound(Arr, 2)
If Tarr(1, j) > 0 Then Arr(n, j) = Darr(Dic.Item(Sarr(i, 1)), (Tarr(1, j) - 1) * 5 + n + 1)
Next j
Next n
Sheets(Ws(k)).Range("H" & i + 3).Resize(3, 31) = Arr
End If
Next i
Next k
Set Dic = Nothing
End Sub
Oanh Thơ xin trân trọng cảm ơn các bạn và diễn đàn đã giúp đỡ Oanh Thơ thực hiện được bài toán 1 và 2 trong chủ đề này ạ.
Hiện tại với chủ đề này Oanh Thơ vẫn còn một vướng mắc nữa đó bài toán 3 này ạ...hic ngại quá
Câu hỏi và kết quả mong muốn Oanh Thơ đã nêu trong file đính kèm ạ.
Kính mong các bạn tiếp tục giúp đỡ ạ.
Trân trọng cảm ơn.
Oanh Thơ
Bạn nhận xét quá chuẩn, mình không rỏ dữ liệu ở sheet Data2 và cột ngày từng sheet như thế nào nên lưỡng lự và code không hợp lý,Anh HieuCD,
Sao anh không chuyển dòng
ra ngoài vòng lặp.Mã:ReDim Arr(1 To 3, 1 To 31)
Tarr = Sheets(Ws(0)).Range("H3:AL3").Value
ReDim Arr(1 To 3, 1 To 31)
For k = LBound(Ws) To UBound(Ws)
Sarr = Sheets(Ws(k)).Range("E1:E" & Sheets(Ws(k)).Range("E65500").End(xlUp).Row).Value
For i = 4 To UBound(Sarr) Step 8 [COLOR=#000000]
If Sarr(i, 1) <> "" And Dic.exists(Sarr(i, 1)) Then[/COLOR]
For k = LBound(Ws) To UBound(Ws)
Tarr = Sheets(Ws(k)).Range("H3:AL3").Value
ReDim Arr(1 To 3, 1 To 31)
Sarr = Sheets(Ws(k)).Range("E1:E" & Sheets(Ws(k)).Range("E65500").End(xlUp).Row).Value
For i = 4 To UBound(Sarr) Step 8
[COLOR=#000000] If Sarr(i, 1) <> "" And Dic.exists(Sarr(i, 1)) Then[/COLOR]
Sub GPE1()
Dim Darr(), Arr(), Ws, i As Long, n As Byte, k As Integer, j As Byte
Ws = Array("SX", "QC", "Kho", "KT") 'Khai báo tên các Sheet
For k = LBound(Ws) To UBound(Ws)
Darr = Sheets(Ws(k)).Range("E1:AL" & Sheets(Ws(k)).Range("E65500").End(xlUp).Row + 7).Value
For i = 4 To UBound(Darr) Step 8
If Darr(i, 1) <> "" Then
ReDim Arr(1 To 3, 1 To 31)
For n = 1 To UBound(Arr)
For j = 1 To UBound(Arr, 2)
If Darr(3, j + 3) > 0 Then Arr(n, j) = Darr(i, 1) & "/Itiem" & n & "-" & Darr(3, j + 3)
Next j
Next n
Sheets(Ws(k)).Range("H" & i + 3).Resize(3, 31) = Arr
End If
Next i
Next k
End Sub
Bạn nhận xét quá chuẩn, mình không rỏ dữ liệu ở sheet Data2 và cột ngày từng sheet như thế nào nên lưỡng lự và code không hợp lý,
nếu dữ liệu đầy đủ và đồng nhất thì Redim Arr nên đưa ra khỏi vòng lập
Mã:Tarr = Sheets(Ws(0)).Range("H3:AL3").Value ReDim Arr(1 To 3, 1 To 31) For k = LBound(Ws) To UBound(Ws) Sarr = Sheets(Ws(k)).Range("E1:E" & Sheets(Ws(k)).Range("E65500").End(xlUp).Row).Value For i = 4 To UBound(Sarr) Step 8 [COLOR=#000000] If Sarr(i, 1) <> "" And Dic.exists(Sarr(i, 1)) Then[/COLOR]
còn nếu dữ liệu các sheet lung tung lúc có lúc không thì phải cẩn thận hơn
Mã:For k = LBound(Ws) To UBound(Ws) Tarr = Sheets(Ws(k)).Range("H3:AL3").Value ReDim Arr(1 To 3, 1 To 31) Sarr = Sheets(Ws(k)).Range("E1:E" & Sheets(Ws(k)).Range("E65500").End(xlUp).Row).Value For i = 4 To UBound(Sarr) Step 8 [COLOR=#000000] If Sarr(i, 1) <> "" And Dic.exists(Sarr(i, 1)) Then[/COLOR]
cám ơn bạn, vụ khai báo dim, redim mình còn lúng túng, các kiểu dữ liệu chưa hiểu hết, đặc biệt là dùng ReDim Preserve để thay đổi kích thước mảng lúc được lúc khôngRedim có 2 mục đích, 1 là để đổi số phần tử của mảng động (dynamic array), 2 là để chuyển giá trị về mặc định (trong trường hợp này là trống vì dữ liệu variant)
Đặt Redim trong vòng lặp bảo đảm không bị ảnh hưởng tàn dư của những lần trước.
Trong trường hợp không cần reset mảng, và nếu số phần tử cũng cố định. Thì dùng mảng tĩnh (static array) là đúng hơn.
Dim Arr(1 to 3, 1 to 31)
Với dữ liệu + yêu cầu như trong file, tôi thấy bạn dùng VLOOKUP vậy là quá ổn rồi (với lại hàm này cũng khá "nhẹ"). Code trong trường hợp này vô cùng nguy hiểm, bởi chỉ sai 1 chút là xem như bạn hết cơ hội quay đầuOanh Thơ xin trân trọng cảm ơn các bạn và diễn đàn đã giúp đỡ Oanh Thơ thực hiện được bài toán 1 và 2 trong chủ đề này ạ.
Hiện tại với chủ đề này Oanh Thơ vẫn còn một vướng mắc nữa đó bài toán 3 này ạ...hic ngại quá
Câu hỏi và kết quả mong muốn Oanh Thơ đã nêu trong file đính kèm ạ.
Kính mong các bạn tiếp tục giúp đỡ ạ.
Trân trọng cảm ơn.
Oanh Thơ






Với dữ liệu + yêu cầu như trong file, tôi thấy bạn dùng VLOOKUP vậy là quá ổn rồi (với lại hàm này cũng khá "nhẹ"). Code trong trường hợp này vô cùng nguy hiểm, bởi chỉ sai 1 chút là xem như bạn hết cơ hội quay đầu
Nói chung code hay công thức, chọn cái nào là tùy vào chuyện ta kiểm soát được mức độ chính xác của kết quả
-------------------------
Kinh nghiệm của tôi là vậy, có gì không đúng xem như tôi chưa nói gì cả



(1) Nhập vào file mà bạn đã đính kèm phải không? Hay mỗi bộ phận một file để tự nhập dữ liệu vào?
(2) Gửi file đó lên xem như nào?
Mỗi bộ phận có một danh sách "Mã số" tương ứng? Có sẵn danh sách này rồi chứ?
Có thể bỏ qua bước trung gian không? Hay nhất thiết phải có bước này?
công việc chỉ là đưa dữ liệu từ sheet data2 sang các sheet bộ phận trong cùng 1 tệp tin bạn ạ.Không biết bạn tổng hợp từ các file đó vào sheet "Data2" như nào? Hỏi vậy để định làm luôn cả phần đó...Còn vấn đề 2. Bước trung gian ở đây là Oanh Thơ đã lấy dữ liệu từ nhiều tệp tin mỗi tệp tin là dữ liệu của 1 tổ hoặc 1 bộ phận (có rất nhiều tệp tin) và dữ liệu được đưa hết vào sheet data2 đó ạ.
...
trên từng sheet có đủ dữ liệu để xử lý, tại sao phải lấy dữ liệu từ Data2?Hi, thật bất ngờ!
Oanh Thơ xin cảm ơn tất cả các bạn rất nhiều vì những ngày cuối năm bộn rộn mà các bạn vẫn dành thời gian để tham gia diễn đàn giúp đỡ Oanh Thơ và mọi người.
Hôm nay Oanh Thơ phải dọn dẹp nhà cửa nên giờ mới thông tin đến các bạn được kính mong các bạn thông cảm ạ.
Oanh Thơ đã thử code của bài 34 và bài 36 code chạy trên file mẫu gửi lên lẹ quá , kết quả rất đúng với ý của Oanh Thơ.
Nhưng khi áp dụng vào file thật thì Oanh Thơ không sử dụng được do có một chút thay đổi về thứ tự dòng cột
và tiêu đề ngày 1 đến 31 trong các sheet bộ phận là định dạng ngày tháng năm.
Oanh Thơ xin gửi file đã sửa lại thứ tự dòng cột và định dạng tiêu đề ngày tháng ở các sheet bộ phận để các bạn xem giúp Oanh Thơ ạ.
Sub GPE_1()
Dim dArr(), sArr(), Arr(), tArr(), Dic As Object, Ws, I As Long, k As Byte, J As Byte, N
dArr = Sheets("Data2").Range("B14:FC" & Sheets("Data2").Range("B65500").End(xlUp).Row).Value
Set Dic = CreateObject("scripting.dictionary")
For I = 1 To UBound(dArr)
If dArr(I, 1) <> "" And Not Dic.Exists(dArr(I, 1)) Then Dic.Add dArr(I, 1), I
Next I
Ws = Array("SX", "QC", "Kho", "KT") 'Khai báo tên các Sheet
For k = LBound(Ws) To UBound(Ws)
tArr = Sheets(Ws(k)).Range("J14:AN14").Value
ReDim Arr(1 To 3, 1 To 31)
sArr = Sheets(Ws(k)).Range("G1:G" & Sheets(Ws(k)).Range("G65500").End(xlUp).Row).Value
For I = 15 To UBound(sArr) Step 8
If sArr(I, 1) <> "" And Dic.Exists(sArr(I, 1)) Then
For N = 1 To UBound(Arr)
For J = 1 To UBound(Arr, 2)
If tArr(1, J) > 0 Then Arr(N, J) = dArr(Dic.Item(sArr(I, 1)), (Day(tArr(1, J)) - 1) * 5 + N + 3)
Next J
Next N
Sheets(Ws(k)).Range("J" & I + 3).Resize(3, 31) = Arr
End If
Next I
Next k
Set Dic = Nothing
End Sub



Không biết bạn tổng hợp từ các file đó vào sheet "Data2" như nào? Hỏi vậy để định làm luôn cả phần đó...



@Nguyễn Hoàng Oanh Thơ,
(1) Vậy mọi thứ đã đầy đủ rồi
(2) hình như lỗi chính tả...
(3)Hình như thiếu cái gì đó \Mã:filename = ThisWorkbook.Path & [COLOR=#0000ff]"" [/COLOR]& bo_phan(index) & ".xls"



trên từng sheet có đủ dữ liệu để xử lý, tại sao phải lấy dữ liệu từ Data2?Mã:Sub GPE_1() Dim dArr(), sArr(), Arr(), tArr(), Dic As Object, Ws, I As Long, k As Byte, J As Byte, N dArr = Sheets("Data2").Range("B14:FC" & Sheets("Data2").Range("B65500").End(xlUp).Row).Value Set Dic = CreateObject("scripting.dictionary") For I = 1 To UBound(dArr) If dArr(I, 1) <> "" And Not Dic.Exists(dArr(I, 1)) Then Dic.Add dArr(I, 1), I Next I Ws = Array("SX", "QC", "Kho", "KT") 'Khai báo tên các Sheet For k = LBound(Ws) To UBound(Ws) tArr = Sheets(Ws(k)).Range("J14:AN14").Value ReDim Arr(1 To 3, 1 To 31) sArr = Sheets(Ws(k)).Range("G1:G" & Sheets(Ws(k)).Range("G65500").End(xlUp).Row).Value For I = 15 To UBound(sArr) Step 8 If sArr(I, 1) <> "" And Dic.Exists(sArr(I, 1)) Then For N = 1 To UBound(Arr) For J = 1 To UBound(Arr, 2) If tArr(1, J) > 0 Then Arr(N, J) = dArr(Dic.Item(sArr(I, 1)), (Day(tArr(1, J)) - 1) * 5 + N + 3) Next J Next N Sheets(Ws(k)).Range("J" & I + 3).Resize(3, 31) = Arr End If Next I Next k Set Dic = Nothing End Sub
Oanh Thơ chưa hiểu ý bạn lắm ạ, nếu Oanh Thơ trả lời không đúng ý bạn mong bạn giải thích thêm ạ.trên từng sheet có đủ dữ liệu để xử lý, tại sao phải lấy dữ liệu từ Data2?
....................
Bạn cho hỏi thêm trong trường hợp Oanh Thơ chỉ lấy dữ liệu của Item2 và Item3 thôi mà không lấy dữ liệu của Item1 nữa thì code phải thay đổi chỗ nào ạ.
Sở dĩ Item1 là dữ liệu có thể phải sửa lại bằng tay nên sau khi điều chỉnh lại Oanh Thơ không cho cập nhật từ sheet data2 sang nữa bạn ạ.
................
Public Sub GPE_2()
Dim Dic As Object, sArr(), dArr(), tArr(), Tem As Long, iTm As Long
Dim I As Long, iK As Long, J As Long, Col As Long, N As Long, Rws As Long
Set Dic = CreateObject("Scripting.Dictionary")
With Sheets("Data2")
tArr = .Range("G1", .Range("G1").End(xlToRight)).Value
sArr = .Range("B14", .Range("B65536").End(xlUp)).Resize(, 158).Value
End With
For I = 1 To UBound(sArr)
Dic.Item(sArr(I, 1)) = I
Next I
For N = 1 To UBound(tArr, 2)
With Sheets(tArr(1, N))
Rws = .Range("G65536").End(xlUp).Row
For iK = 15 To Rws Step 8
Tem = .Range("G" & iK): Col = 0
If Dic.Exists(Tem) Then
iTm = Dic.Item(Tem)
ReDim dArr(1 To 2, 1 To 31)
For J = 5 To 158 Step 5
Col = Col + 1
dArr(1, Col) = sArr(iTm, J)
dArr(2, Col) = sArr(iTm, J + 1)
Next J
.Range("J" & iK + 4).Resize(2, 31) = dArr
End If
Next iK
End With
Next N
Set Dic = Nothing
MsgBox "Da thuc hien xong.", , "GiaiPhapExcel"
End Sub



Hình như bạn không khoái cái Sub dài "thoòng" này.
Nó không dình liếu gì với cái tiêu đề là Number hay Date. Cứ từ cột 1 đến 31 mà "phang".
PHP:Public Sub GPE_2() Dim Dic As Object, sArr(), dArr(), tArr(), Tem As Long, iTm As Long Dim I As Long, iK As Long, J As Long, Col As Long, N As Long, Rws As Long Set Dic = CreateObject("Scripting.Dictionary") With Sheets("Data2") tArr = .Range("G1", .Range("G1").End(xlToRight)).Value sArr = .Range("B14", .Range("B65536").End(xlUp)).Resize(, 158).Value End With For I = 1 To UBound(sArr) Dic.Item(sArr(I, 1)) = I Next I For N = 1 To UBound(tArr, 2) With Sheets(tArr(1, N)) Rws = .Range("G65536").End(xlUp).Row For iK = 15 To Rws Step 8 Tem = .Range("G" & iK): Col = 0 If Dic.Exists(Tem) Then iTm = Dic.Item(Tem) ReDim dArr(1 To 2, 1 To 31) For J = 5 To 158 Step 5 Col = Col + 1 dArr(1, Col) = sArr(iTm, J) dArr(2, Col) = sArr(iTm, J + 1) Next J .Range("J" & iK + 4).Resize(2, 31) = dArr End If Next iK End With Next N Set Dic = Nothing MsgBox "Da thuc hien xong.", , "GiaiPhapExcel" End Sub
của bạn ,như đã nêu ở bài 41 vì Oanh Thơ chưa biết cách vận dụng cho file thật của mình thôi ạ.Sub dài "thoòng"

