Tổng hợp dữ liệu theo điều kiện? (1 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 bạn,
Như tiêu đề O.Thơ đã nêu ở trên và điều kiện cụ thể O,Thơ viết chi tiết trong file đính kèm rồi ạ.
Rất mong nhận được sự trợ giúp của các bạn.
O.Thơ xin cảm ơn rất nhiều.

 

File đính kèm

Bạn cần chạy macro có nội dung như sau:
PHP:
Option Explicit
Sub TongHop()
 Dim Sh As Worksheet
 Dim Rws As Long, J As Long, W As Long, Col As Byte
 With Sheets("TongHop")
    Rws = .[B5].CurrentRegion.Rows.Count
    .[B5].Resize(Rws, 9).ClearContents
    W = 4
    For Each Sh In ThisWorkbook.Worksheets
        If Sh.Name <> "TongHop" Then
            Col = Sh.UsedRange.Columns.Count + 2
            For J = 3 To Sh.UsedRange.Rows.Count
                If Sh.Cells(J, "A").End(xlToRight).Column < Col Then
                    W = W + 1
                    .Cells(W, "B").Value = Sh.Name
                    .Cells(W, "C").Resize(, Col).Value = Sh.Cells(J, "B").Resize(, Col).Value
                End If
            Next J
        End If
    Next Sh
 End With
End Sub
 
Upvote 0
Xin chào tất các bạn,
Như tiêu đề O.Thơ đã nêu ở trên và điều kiện cụ thể O,Thơ viết chi tiết trong file đính kèm rồi ạ.
Rất mong nhận được sự trợ giúp của các bạn.
O.Thơ xin cảm ơn rất nhiều.


nghĩ trưa góp thêm bạn một đoạn code
Mã:
Sub tonghop()
Dim ws As Worksheet
Dim arr(1 To 60000, 1 To 7) As Variant
Dim i, j, k As Long
Dim rng, v As Range

For Each ws In Worksheets
    With ws
    If ws.Name <> "TongHop" Then
        On Error Resume Next
        Set rng = .[b3:G60000].SpecialCells(2)
        If Err Then GoTo next_step
        On Error GoTo 0
        rw = 0
        For Each v In rng
            If rw <> v.Row Then k = k + 1
            arr(k, 1) = ws.Name
            arr(k, v.Column) = v
            rw = v.Row
        Next
next_step:
    End If
    End With
Next
If k Then
With Sheets("TongHop")
    .[b5:h6000].ClearContents
    .[b5:h5].Resize(k) = arr
End With
End If
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Xin phép góp ý một tí:
Code bài #2: Nếu ngoài vùng dữ liệu cần lấy trên sheet còn dữ liệu khác thì không áp dụng được.
Code bài #3: Nếu dữ liệu dạng như bên dưới thì kết quả sẽ sai:
[TABLE="width: 384"]
[TR]
[TD="class: xl63, width: 64, align: left"]Du lieu 1
[/TD]
[TD="class: xl63, width: 64, align: left"]Du lieu 2
[/TD]
[TD="class: xl63, width: 64, align: left"]Du lieu 3[/TD]
[TD="class: xl63, width: 64, align: left"]Du lieu 4[/TD]
[TD="class: xl63, width: 64, align: left"]Du lieu 5[/TD]
[TD="class: xl63, width: 64, align: left"]Du lieu 6[/TD]
[/TR]
[TR]
[TD="class: xl63"] [/TD]
[TD="class: xl63, align: left"]fg[/TD]
[TD="class: xl63, align: left"]fg[/TD]
[TD="class: xl63"] [/TD]
[TD="class: xl63, align: left"]fg[/TD]
[TD="class: xl63, align: left"]fg[/TD]
[/TR]
[TR]
[TD="class: xl63"] [/TD]
[TD="class: xl63, align: left"]fg[/TD]
[TD="class: xl63, align: left"]fg[/TD]
[TD="class: xl63"] [/TD]
[TD="class: xl63, align: left"]fg[/TD]
[TD="class: xl63, align: left"]fg
[/TD]
[/TR]
[/TABLE]

Theo tôi thì bài này nếu dữ liệu thưa thớt thì dùng Find, ngược lại thì cứ duyệt qua từng dòng.
 
Upvote 0
Code duyệt qua từng dòng:
PHP:
Sub TongHop()
Dim Sh As Worksheet, ArrData, ArrResult(), i As Long, j As Long, k As Long, Check As Boolean
Me.Range("B5:H65536").ClearContents
ReDim ArrResult(0 To &H10000, 0 To 6)
For Each Sh In ThisWorkbook.Sheets
    If Sh.Name <> Me.Name Then
        ArrData = Sh.Range("B3:G25").Value
        For i = 1 To UBound(ArrData, 1)
            Check = False
            For j = 1 To UBound(ArrData, 2)
                If Not IsEmpty(ArrData(i, j)) Then
                    Check = True
                    ArrResult(k, j) = ArrData(i, j)
                End If
            Next
            If Check Then
                ArrResult(k, 0) = Sh.Name
                k = k + 1
            End If
        Next
    End If
Next
If k > 0 Then Me.Range("B5").Resize(k, 7).Value = ArrResult
End Sub
 
Upvote 0
Xin chào tất các bạn,
Như tiêu đề O.Thơ đã nêu ở trên và điều kiện cụ thể O,Thơ viết chi tiết trong file đính kèm rồi ạ.
Rất mong nhận được sự trợ giúp của các bạn.
O.Thơ xin cảm ơn rất nhiều.

1 cách nữa
Mã:
Public Sub TongHop()
Dim Ws As Worksheet, Nguon As Range, Cll As Range, i, kq(1 To 65000, 1 To 7)
With CreateObject("scripting.dictionary")
For Each Ws In Worksheets
If Ws.Name <> "TongHop" Then
'Set Nguon = Ws.Range("B3", "G" & Ws.UsedRange.Rows.Count).SpecialCells(2)
'Sửa lại bên dưới
Set Nguon = Ws.Range("B3", "G" & Ws.UsedRange.Rows.Count + 2)
For Each Cll In Nguon
If Cll.Value <> "" Then
.Item(Ws.Name & Cll.Row) = ""
kq(.Count, 1) = Ws.Name
kq(.Count, Cll.Column) = Cll.Value
End If
Next Cll
End If
Next Ws
Sheet1.Range("J5", "P" & .Count + 4).ClearContents
Sheet1.Range("J5", "P" & .Count + 4) = kq
Sheet1.Range("J5", "P" & .Count + 4).Borders.LineStyle = 1
End With
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
1 cách nữa
Mã:
Public Sub TongHop()
Dim Ws As Worksheet, Nguon As Range, Cll As Range, i, kq(1 To 65000, 1 To 7)
With CreateObject("scripting.dictionary")
For Each Ws In Worksheets
If Ws.Name <> "TongHop" Then
Set Nguon = Ws.Range("B3", "G" & Ws.UsedRange.Rows.Count).SpecialCells(2)
For Each Cll In Nguon
If Cll.Value <> "" Then
.Item(Ws.Name & Cll.Row) = ""
kq(.Count, 1) = Ws.Name
kq(.Count, Cll.Column) = Cll.Value
End If
Next Cll
End If
Next Ws
Sheet1.Range("J5", "P" & .Count + 4).ClearContents
Sheet1.Range("J5", "P" & .Count + 4) = kq
Sheet1.Range("J5", "P" & .Count + 4).Borders.LineStyle = 1
End With
End Sub
Code này sai gần giống bài #3 nhưng hậu quả sẽ nghiêm trọng hơn. Bạn thử test với trường hợp ở bài #4 sẽ thấy sai.
 
Upvote 0
Code này sai gần giống bài #3 nhưng hậu quả sẽ nghiêm trọng hơn. Bạn thử test với trường hợp ở bài #4 sẽ thấy sai.
Sửa thế này thấy đúng, không biết vì sao
Mã:
Set Nguon = Ws.Range("B3", "G" & Ws.UsedRange.Rows.Count).SpecialCells(2)
--->
Set Nguon = Ws.Range("B3", "G" & Ws.UsedRange.Rows.Count + 2).SpecialCells(2)
---
Sửa lại cho sát hơn
Mã:
Set Nguon = Ws.Range("B3", "G" & Ws.UsedRange.Rows.Count + 2)
 
Lần chỉnh sửa cuối:
Upvote 0
Code này sai gần giống bài #3 nhưng hậu quả sẽ nghiêm trọng hơn. Bạn thử test với trường hợp ở bài #4 sẽ thấy sai.
vậy thử macro này xem có bị sai không--=0


PHP:
Sub Tonghop()
Dim sh As Worksheet, i As Long
Application.ScreenUpdating = False
Sheets("TongHop").Range("5:10000").Clear
For Each sh In Worksheets
If sh.Name <> "TongHop" Then
  sh.Range("A3:A" & sh.UsedRange.Rows.Count).Value = sh.Name
   sh.[A3].CurrentRegion.Offset(1).Copy
   Sheets("TongHop").Range("B10000").End(3).Offset(1).PasteSpecial (12)
   sh.Range("A:A").Clear
End If
Next
For i = 1 To 6
Sheets("TongHop").Range("O1").Offset(i, i - 1).Value = "<>"
Next
With Sheets("TongHop")
.Range("O1:T1").Value = Range("C4:H4").Value
.Range("B4:H10000").AdvancedFilter 2, Range("O1:T7"), Range("AA5"), False
.Range("B4:H10000").Value = Range("AA5:AG10000").Value
.Range("N:AG").Clear
.Range("B4").CurrentRegion.Borders.LineStyle = 1
.Range("B4").Select
End With
Application.ScreenUpdating = True
End Sub
 
Upvote 0
Bạn cần chạy macro có nội dung như sau:
Em cũng bon chen cùng bác SA_DQ. Nhờ 2 cuốn sách của bác mà cũng biết ghi macro--=0
Mã:
Sub Tonghop2()
Dim Sh As Worksheet, T As Double, I As Integer
Dim Crits As Range, Dest As Range, Data As Range
T = Timer
Application.ScreenUpdating = False
    Sheet1.Range("C4", Range("C4").End(2)).Copy: Range("O1").PasteSpecial (12)
For I = 1 To Sheet1.Range("O1").CurrentRegion.Columns.Count
    Sheet1.Range("O1").Offset(I, I - 1).Value = "<>"
Next
Sheet1.Range("A5:K10000").Clear
For Each Sh In Worksheets
  If Sh.Name <> "TongHop" Then
     Sh.Range("A3:A" & Sh.UsedRange.Rows.Count + 10).Value = Sh.Name
     Sh.Range("A2") = "Sheet"
     Set Data = Sh.Range("A2").CurrentRegion
     Set Crits = Sheet1.Range("O1").CurrentRegion
     Set Dest = Sheet1.Range("B10000").End(3).Offset(1)
        Data.AdvancedFilter 2, Crits, Dest, False
    Sh.Range("A:A").Clear
  End If
Next
With Sheet1
    .Range("N:AG").Clear
    .Range("B4").CurrentRegion.Borders.LineStyle = 1
    .Range("B4").CurrentRegion.AutoFilter 1, "Sheet"
    .Range("B4").CurrentRegion.Offset(1).Delete Shift:=xlUp
    .Range("B4").CurrentRegion.AutoFilter
    .Range("B4").Select
End With
Application.ScreenUpdating = True
[A1] = Timer - T
End Sub
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Oanh Thơ xin cảm ơn tất cả các bạn nhiều nhé,
Nhờ có các bạn mà vấn đề khó khăn của Oanh Thơ đã được giải quyết ... hihi

Trân trọng
 
Upvote 0
Xin chào tất cả các bạn,
Nhờ các bạn giúp đỡ Oanh Thơ ví dụ trong tập tin gửi kèm với ạ.
 

File đính kèm

Upvote 0
Mã:
Public Sub GPE()
Dim DicTH As Object, KH As String, Tem As String, I As Long, J As Long, K As Long
Dim ArrTH, ArrDL, ArrDM, TCong As String, DicDL As Object, ArrKQ, Thang As Long
Set DicTH = CreateObject("Scripting.Dictionary")
Set DicDL = CreateObject("Scripting.Dictionary")
TCong = "T" & ChrW(7893) & "ng c" & ChrW(7897) & "ng:"
With Sheet3
    ArrTH = .Range("A8:W20").Value
End With
With Sheet1
    ArrDM = .Range("A8:A" & .Range("B" & Rows.Count).End(3).Row).Resize(, 6).Value
End With
With Sheet2
    ArrDL = .Range("D6", .Range("D" & Rows.Count).End(3)).Resize(, 50).Value
    Thang = Month(.[D2].Value)
End With
ReDim ArrKQ(1 To UBound(ArrDM), 1 To UBound(ArrTH, 2))
For I = 1 To UBound(ArrTH)
    If ArrTH(I, 1) = Empty And ArrTH(I, 2) <> TCong Then
        KH = ArrTH(I, 2)
    End If
        Tem = KH & "#" & ArrTH(I, 2) & "#" & ArrTH(I, 4)
        If Not DicTH.Exists(Tem) Then
            DicTH.Add Tem, I
        End If
Next
For I = 1 To UBound(ArrDL)
    If Len(ArrDL(I, 1)) Then
        Tem = ArrDL(I, 2) & "#" & ArrDL(I, 1) & "#" & ArrDL(I, 3)
        If Not DicDL.Exists(Tem) Then
            DicDL.Add Tem, I
        End If
    End If
Next
For I = 1 To UBound(ArrDM)
    If ArrDM(I, 1) = Empty And ArrDM(I, 2) <> TCong Then
        KH = ArrDM(I, 2)
    End If
    For J = 1 To 6
        ArrKQ(I, J) = ArrDM(I, J)
    Next
    For J = 12 To UBound(ArrTH, 2)
            ArrKQ(1, J) = ArrTH(1, J)
    Next
        Tem = KH & "#" & ArrDM(I, 2) & "#" & ArrDM(I, 4)
        If DicTH.Exists(Tem) Then
            For J = 12 To UBound(ArrTH, 2)
                ArrKQ(I, J) = ArrTH(DicTH.Item(Tem), J)
            Next
        End If
        If DicDL.Exists(Tem) Then
            ArrKQ(I, 11 + Thang) = ArrDL(DicDL.Item(Tem), 50)
        End If
Next
Range("A35").Resize(UBound(ArrDM), UBound(ArrTH, 2)).Value = ArrKQ
End Sub

Xin chào hpkhuong,

Code của bạn chạy ra kết quả đúng ý Oanh Thơ rồi, thật lợi hại.
Cảm ơn bạn rất nhiều.
 
Upvote 0
Xin chào hpkhuong,
nếu có thể bạn có thể giải thích giúp code trên theo cách gọi "kiểu nông dân" này được không? :rolleyes:
https://www.giaiphapexcel.com/diendan/threads/lọc-và-đưa-dữ-liệu-mới-ra-1-wordbook-riêng.138155/#post-884863

Cảm ơn bạn nhiều
Thế viết code kiểu thành phổ ở trên bạn không hiểu à? Tôi thấy code trên viết nó dài thôi chứ có câu lệnh nào phức tạp đâu.
 
Upvote 0
Xin chào tất cả các bạn,
Nhờ các bạn giúp đỡ Oanh Thơ ví dụ trong tập tin gửi kèm với ạ.
Thử với code
Mã:
Sub GPE()
  Dim Res(), DuLieu(), TongHop()
  Dim khStr As String, iKey As String
  Dim i As Long, ik As Long, j As Long, sCol As Long, jCol As Long
  Dim Ngay As Date
 
  With Sheets("DU_LIEU")
    i = .Range("E1000000").End(xlUp).Row
    DuLieu = .Range("E6:BA" & i).Value
    Ngay = .Range("D2").Value
  End With
  With Sheets("TONG_HOP")
    i = .Range("B8").End(xlDown).Row
    sCol = .Range("AAA8").End(xlToLeft).Column
    On Error Resume Next
    jCol = Application.Match(Ngay, .Range("A8").Resize(, sCol).Value, 0)
    On Error GoTo 0
    TongHop = .Range("A8:A" & i).Resize(, sCol).Value
    .Range("A9:A" & i).Resize(, sCol).ClearContents
  End With
  With Sheets("DMSP")
    i = .Range("B8").End(xlDown).Row
    Res = .Range("A9:A" & i).Resize(, sCol).Value
  End With

  With CreateObject("scripting.dictionary")
    For i = 2 To UBound(Res) - 1
      If Len(Res(i, 3)) > 0 Then
        If Len(Res(i - 1, 3)) = 0 Then khStr = Res(i - 1, 2)
        .Item(khStr & "#" & Res(i, 4)) = i
      End If
    Next i
    For i = 2 To UBound(TongHop) - 1
      If Len(TongHop(i, 3)) > 0 Then
        If Len(TongHop(i - 1, 3)) = 0 Then khStr = TongHop(i - 1, 2)
        ik = .Item(khStr & "#" & TongHop(i, 4))
        If ik Then
          For j = 12 To sCol
            If Len(TongHop(i, j)) Then Res(ik, j) = TongHop(i, j)
          Next j
        End If
      End If
    Next i
    If jCol Then
      For i = 1 To UBound(DuLieu) Step 8
        ik = .Item(DuLieu(i, 1) & "#" & DuLieu(i, 2))
        If ik Then Res(ik, jCol) = DuLieu(i, 49)
      Next i
    End If
  End With
  Sheets("TONG_HOP").Range("A9").Resize(UBound(Res), UBound(Res, 2)) = Res
End Sub
 
Upvote 0
Thế viết code kiểu thành phổ ở trên bạn không hiểu à? Tôi thấy code trên viết nó dài thôi chứ có câu lệnh nào phức tạp đâu.

Xin chào giaiphap,

Dạ, Oanh Thơ(OT) cũng không biết kiểu nào là thành phố kiểu nào là nông dân.
OT chỉ cảm thấy thích cái kiểu code có comment giải thích giống của bạn mà OT đã trích dẫn link ở trên để hi vong được hiểu thêm một chút về code thôi ạ. OT thấy bạn gọi đó là kiểu nông dân, còn OT thơ thì không nghĩ là nông dân nên mới để trong ngoặc kép "".
Nếu có vấn đề gì không phải thành thật xin lỗi và mong bạn bỏ qua.

Rất mong nhận được sự giúp đỡ của bạn.
 
Lần chỉnh sửa cuối:
Upvote 0
Xin chào hpkhuong,HieuCD

Cảm ơn 2 bạn đã giúp đỡ. OT đã ứng dụng được code của 2 bạn vào file thật của mình.
Hiện tại đang không gặp phải vấn đề gì cả.
Tuy nhiên có một vấn để như sau, file hiện tại sau này có thể thay đổi thêm cột hoặc bớt cột.

Ví dụ đối với trong tập tin gửi kèm tại shees("TONG_HOP") và sheet ("DMSP")
OT đã thêm một cột màu vàng. Dữ liệu ở cột này có thể không theo một tiêu chuẩn hay qui định nào cả (nghĩa là không đưa vào điều kiện để kiểm tra trong code).
Như vậy code của 2 bạn sẽ cần chỉnh ở đâu ạ.
 

File đính kèm

Upvote 0
Khi bạn làm nhà, bạn có cần bản vẽ không? Có cần làm móng không? Hay đụng đâu xây đó?

Dạ, khi làm nhà thì có cần bản vẽ có cần làm móng , xin lỗi hpkhuong T_T
Đó là chỉ ý tưởng phòng trừ sau này khi phát sinh vì dữ liệu nguồn thì nhiều cột nhưng hiện tại form mẫu mới chỉ yêu cầu có vậy và OT hỏi hỏi thêm.. nếu không phiền nhờ bạn xem giúp ạ.
 
Upvote 0
Xin chào hpkhuong,HieuCD

Cảm ơn 2 bạn đã giúp đỡ. OT đã ứng dụng được code của 2 bạn vào file thật của mình.
Hiện tại đang không gặp phải vấn đề gì cả.
Tuy nhiên có một vấn để như sau, file hiện tại sau này có thể thay đổi thêm cột hoặc bớt cột.

Ví dụ đối với trong tập tin gửi kèm tại shees("TONG_HOP") và sheet ("DMSP")
OT đã thêm một cột màu vàng. Dữ liệu ở cột này có thể không theo một tiêu chuẩn hay qui định nào cả (nghĩa là không đưa vào điều kiện để kiểm tra trong code).
Như vậy code của 2 bạn sẽ cần chỉnh ở đâu ạ.
Giá trị trong cột màu vàng sheet "TONG HOP" không đổi hay hay bê từ sheet "DMSP" qua
 
Upvote 0
Web KT

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

Back
Top Bottom