Chuyển dữ liệu từ 1 sheet sang nhiều sheet theo điều kiện? (2 người xem)

Liên hệ QC

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

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.
 

File đính kèm

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
 
Upvote 0
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ộ)
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
Híc!!!!!!!!
 
Upvote 0
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

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.
 
Upvote 0
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ộ)
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
Híc!!!!!!!!

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!
 
Upvote 0
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!

Bạn tự chỉnh code lại dưới dòng Next I
PHP:
Next I 
            .Range("C4").Resize(1000, 3).ClearContents 
            If K > 0 Then .Range("C4").Resize(K, 3) = dArr
Thành như vầy thử coi.
PHP:
Next I
            If K > 0 Then
                .Range("C4").Resize(1000, 3).ClearContents
                .Range("C4").Resize(K, 3) = dArr
            End If
Có hàng trăm sheet "không liên quan" thì code chạy "vớ vẫn" mệt luôn.
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn tự chỉnh code lại dưới dòng Next I
PHP:
Next I 
            .Range("C4").Resize(1000, 3).ClearContents 
            If K > 0 Then .Range("C4").Resize(K, 3) = dArr
Thành như vầy thử coi.
PHP:
Next I
            If K > 0 Then
                .Range("C4").Resize(1000, 3).ClearContents
                .Range("C4").Resize(K, 3) = dArr
            End If
Có hàng trăm sheet "không liên quan" thì code chạy "vớ vẫn" mệt luôn.

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é!
 
Upvote 0
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ý.
 
Lần chỉnh sửa cuối:
Upvote 0
---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ý.

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 ạ.
 
Upvote 0
...
Có hàng trăm sheet "không liên quan" thì code chạy "vớ vẫn" mệt luôn.

Có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.
 
Upvote 0
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 ạ.

Nếu có nhiều OR và quá nhiều sheet "không liên quan" thì nên tạo 1 bảng danh sách các sheet cần lấy dữ liệu (bằng cách nào đó), số vòng lặp = đúng danh sách, ít "mệt mõi" hơn.
 
Upvote 0
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.
 
Upvote 0
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.

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
 
Upvote 0
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".
 
Upvote 0
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).
 
Upvote 0
Hi, Oanh Thơ xin cảm ơn tất cả các bạn nhiều vì đã quan tâm đến đóng góp và giúp đỡ cho bài viết này này của Oanh Thơ ạ.

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).

Cảm ơn bạn đã góp ý ạ.
File thực của Oanh Thơ xin lỗi vì không thể up lên đây được ạ rất mong các bạn thông cảm ạ.
Còn về lý do tại sao Oanh Thơ lại bố trí dữ liệu như vậy, Oanh Thơ xin giải thích thêm ạ.

Sheet Data mục đích để lưu trữ các thông tin dữ liệu cơ sở liên quan đến thông tin của từng người,mỗi người 1 dòng ...
Các sheet bộ phận thì có cấu trúc fom mẫu giống nhau về số dòng số cột để nhập các dữ liệu liên quan của từng người trong 1 tháng ở các cột tiếp theo,
mỗi người sẽ có tất cả 8 hạng mục (8 dòng) các dòng khác không đưa dữ liệu thông tin nhân viên vào nên Oanh Thơ để nhỏ là để các bạn dễ nhìn xuống các dòng dưới .
Và hàng tháng do danh sách ở sheet data có sự thay đổi vì vậy Oanh Thơ mới phải cập nhật lại nhân viên ở sheet data đưa vào các sheet bộ phận này.
Vài trăm sheet thì không đến nhưng tổng thể gộp đủ các bộ phận và các tổ vào cũng đến gần 40 sheet đó ạ.
Và các Sheet này đã được tạo sẵn từ trước ạ.

Cảm ơn bạn nhiều,
Oanh Thơ
 
Upvote 0
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.

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ơ
 
Upvote 0
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".

Hi dạ vâng, đúng thế ạ.
Code trên của bạn Oanh Thơ sẽ giữ lại để dùng cho trường hợp khác ạ. :{}:
Rất mong nhận được thêm sự hỗ trợ của bạn.
Cảm ơn các bạn nhiều,
 
Upvote 0
Có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.
làm tương tự, dùng Dictionary thay sheet tạm
Mã:
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
 
Upvote 0
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ơ

Lúc đề nghị dùng ADO, tôi quên mất là đề bài này chỉ đơn giản "lọc ra và chép lại" (trừ cái phần thêm 8 dòng trống).
Ngay cái từ "lọc ra và chép lại" đã hàm ý nghĩa advanced filter. Vì vậy cách làm của bạn ndu ở bài #13 là đúng nhất rồi.
ADO chỉ lợi hơn khi bạn cần gom thu (vd tổng các hàng gióng nhau) hay tính toán thêm cột gì đó.
 
Upvote 0
Web KT

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

Back
Top Bottom