Tổng hợp số liệu bằng Dicitionay (1 người xem)

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

canguocs

Thành viên hoạt động
Tham gia
28/6/14
Bài viết
100
Được thích
7
PHP:
[CODE]Sub TH()
Dim Dic As Object, sArr(), dArr(1 To 10000, 1 To 14), N As Long, I As Long, K As Long, Tem As String
Dim Ws As Worksheet
Set Dic = CreateObject("Scripting.Dictionary")
For Each Ws In Worksheets
    If Ws.Name <> "T_HOP" Then
        sArr = Ws.Range("B3", Ws.Range("B65000").End(3)).Resize(, 2).Value2
            For I = 1 To UBound(sArr, 1)
                Tem = UCase(sArr(I, 1))
                If Not Dic.Exists(Tem) Then
                    K = K + 1
                    Dic.Add Tem, ""
                    dArr(K, 1) = K
                    dArr(K, 2) = sArr(I, 1)
                    For N = 3 To 14
                        dArr(K, N) = sArr(I, 2)
                    Next
              
                End If
            Next
    End If
Next
Ws.[B3].Resize(I, 2).Value = sArr
Sheets("T_HOP").[A4:N5000].ClearContents
Sheets("T_HOP").[A4].Resize(K - 1, 14).Value = dArr


Set Dic = Nothing
End Sub


[/CODE]
Em có file cần tổng hợp bảng lương 12 tháng vào sheet T_HOP
em dùng Dic chạy Debug thấy sai, nhưng chưa biết sửa thế nào cho hợp lý.
Nhờ anh chị và các bạn giúp đỡ
 

File đính kèm

Lần chỉnh sửa cuối:
Mã:
Ws.[B3].Resize(I, 2).Value = sArr
- Câu lệnh này có lẽ là hơi thừa vì dữ liệu trong các sheet vẫn y nguyên nên không cần phải khôi phục.
- Tham biến Ws lúc này nằm ngoài vòng lặp.
 
Upvote 0
Trong macro bạn tạo vòng lặp duyệt lần lượt từng trang tính (ngoại trừ trang tổng hợp); Điều này là cần thiết;
Nhưng tiếp theo, ở từng trang tính về lương các tháng, bạn lại duyệt theo [Số thứ tự]
Tuy nhiên số TT của 1 nhân viên qua các tháng không cố định sẽ làm bạn cộng của anh chàng này vô nàng kia!

Như là mình thì trước tiên mình cần tạo thêm 1 trường mã NV ở tất thẩy các trang tính. (Trường mã này sẽ được tạo ở tất thẩy các trang tính;

Công việc của macro là :

1./ Tạo vòng lặp (ngoài) duyệt toàn bộ các mã nhân viên tại trang 'T_Hop', từ đầu chí cuối;

2./ Tạo vòng lặp duyệt tất cả các trang tính có Left(Sh.Name,5)="Tháng"
(Hay Isnumeric(Right(Sh.Name,2) )
Điều kiện là mã của vòng lặp ngoài=mã của vòng lặp trong thì cộng thêm số tiền lương của tháng đó vô biến mảng, như

dArr(K, CByte(Right(Sh.name,2))) = sArr(I, 2)
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
Public Sub TH_QUY()
Dim Dic As Object, Thang(), sArr(), dArr(1 To 10000, 1 To 14), N As Long, I As Long, K As Long, Tem As String
Set Dic = CreateObject("Scripting.Dictionary")
Thang = Range("A3:N3").Value
For N = 3 To 14
    With Sheets(Thang(1, N))
        sArr = .Range(.[B3], .[B3].End(xlDown)).Resize(, 2).Value
    End With
    For I = 1 To UBound(sArr, 1)
        Tem = UCase(sArr(I, 1))
        If Not Dic.Exists(Tem) Then
            K = K + 1
            Dic.Add Tem, K
            dArr(K, 1) = K
            dArr(K, 2) = sArr(I, 1)
            dArr(K, N) = sArr(I, 2)
        Else
            dArr(Dic.Item(Tem), N) = sArr(I, 2)
        End If
    Next I
Next N
[A4].Resize(K, 14) = dArr ' dArr tren cung phai bang 6
Set Dic = Nothing
End Sub
Nếu sửa thế này em thấy cũng ok ah
 
Upvote 0
Trong macro bạn tạo vòng lặp duyệt lần lượt từng trang tính (ngoại trừ trang tổng hợp); Điều này là cần thiết;
Nhưng tiếp theo, ở từng trang tính về lương các tháng, bạn lại duyệt theo [Số thứ tự]
Tuy nhiên số TT của 1 nhân viên qua các tháng không cố định sẽ làm bạn cộng của anh chàng này vô nàng kia!

Như là mình thì trước tiên mình cần tạo thêm 1 trường mã NV ở tất thẩy các trang tính. (Trường mã này sẽ được tạo ở tất thẩy các trang tính;

Công việc của macro là :

1./ Tạo vòng lặp (ngoài) duyệt toàn bộ các mã nhân viên tại trang 'T_Hop', từ đầu chí cuối;

2./ Tạo vòng lặp duyệt tất cả các trang tính có Left(Sh.Name,5)="Tháng"
(Hay Isnumeric(Right(Sh.Name,2) )
Điều kiện là mã của vòng lặp ngoài=mã của vòng lặp trong thì cộng thêm số tiền lương của tháng đó vô biến mảng, như

dArr(K, CByte(Right(Sh.name,2))) = sArr(I, 2)
Duyệt vòng lặp ngoài đúng là em ko nghĩ được tới , vì kiến thức còn giới hạn, Nếu được Thấy có thể giúp em học hỏi thêm ah
 
Upvote 0
BÀi 5 đã giải quyết được vấn đề nhưng em muốn tìm hiểu giải theo cách Bài #1 , nhờ anh chị giúp đỡ
 
Upvote 0
BÀi 5 đã giải quyết được vấn đề nhưng em muốn tìm hiểu giải theo cách Bài #1 , nhờ anh chị giúp đỡ
Làm lại code dựa theo bài 1
Code cũ
Mã:
Option Explicit
Sub TH()
Dim Dic As Object, sArr(), dArr(1 To 10000, 1 To 14), N As Long, I As Long, K As Long, Tem As String
Dim Ws As Worksheet
Set Dic = CreateObject("Scripting.Dictionary")
For Each Ws In Worksheets
    If Ws.Name <> "T_HOP" Then
        sArr = Ws.Range("B3", Ws.Range("B65000").End(3)).Resize(, 2).Value2
            For I = 1 To UBound(sArr, 1)
                Tem = UCase(sArr(I, 1))
                If Not Dic.Exists(Tem) Then
                    K = K + 1
                    Dic.Add Tem, ""
                    dArr(K, 1) = K
                    dArr(K, 2) = sArr(I, 1)
                    [I]For N = 3 To 14[/I]          'Bỏ vòng lặp này
[I]                        dArr(K, N) = sArr(I, 2)
                    Next
[/I]              
                End If
            Next
    End If
Next
Ws.[B3].Resize(I, 2).Value = sArr     'Bỏ câu này
Sheets("T_HOP").[A4:N5000].ClearContents
Sheets("T_HOP").[A4].Resize(K - 1, 14).Value = dArr

Set Dic = Nothing
End Sub

Sửa thế này xem sao
Mã:
Sub TH_SC()
Dim Dic As Object, sArr(), dArr(1 To 10000, 1 To 14), N As Long, I As Long, K As Long, Tem As String 
Dim Ws As Worksheet
Set Dic = CreateObject("Scripting.Dictionary")
For Each Ws In Worksheets
If Ws.Name <> "T_HOP" Then
N = N + 1                         'Đưa biến N lên đây vì mỗi lần chuyển sheet là sang cột mới của dArr
sArr = Ws.Range("B3", Ws.Range("B65000").End(3)).Resize(, 2).Value2
For I = 1 To UBound(sArr, 1)
Tem = UCase(sArr(I, 1))

If Not Dic.Exists(Tem) Then  'Nếu Dic chưa có Tem
K = K + 1
Dic.Add Tem, K
dArr(K, 1) = K
dArr(K, 2) = sArr(I, 1)
dArr(K, N + 2) = sArr(I, 2)
Else                                  'Nếu Dic đã có Tem
dArr(Dic.Item(Tem), N + 2) = sArr(I, 2)
End If
Next I
End If
Next Ws
Sheets("T_HOP").[A4:N5000].ClearContents
Sheets("T_HOP").[A4].Resize(K - 1, 14).Value = dArr

Set Dic = Nothing
End Sub
Bạn kiểm tra xem sao
 
Lần chỉnh sửa cuối:
Upvote 0
Làm lại code dựa theo bài 1
Sửa thế này xem sao
Mã:
Sub TH_SC()
Dim Dic As Object, sArr(), dArr(1 To 10000, 1 To 14), N As Long, I As Long, K As Long, Tem As String 
Dim Ws As Worksheet
Set Dic = CreateObject("Scripting.Dictionary")
For Each Ws In Worksheets
If Ws.Name <> "T_HOP" Then
N = N + 1                         'Đưa biến N lên đây vì mỗi lần chuyển sheet là sang cột mới của dArr
sArr = Ws.Range("B3", Ws.Range("B65000").End(3)).Resize(, 2).Value2
For I = 1 To UBound(sArr, 1)
Tem = UCase(sArr(I, 1))

If Not Dic.Exists(Tem) Then  'Nếu Dic chưa có Tem
K = K + 1
Dic.Add Tem, K
dArr(K, 1) = K
dArr(K, 2) = sArr(I, 1)
dArr(K, N + 2) = sArr(I, 2)
Else                                  'Nếu Dic đã có Tem
dArr(Dic.Item(Tem), N + 2) = sArr(I, 2)
End If
Next I
End If
Next Ws
Sheets("T_HOP").[A4:N5000].ClearContents
Sheets("T_HOP").[A4].Resize(K - 1, 14).Value = dArr

Set Dic = Nothing
End Sub
Bạn kiểm tra xem sao
Code này có 2 vấn đề:
1) Sai:
Sheets("T_HOP").[A4].Resize(K - 1, 14).Value = dArr
phải là:
Sheets("T_HOP").[A4].Resize(K, 14).Value = dArr
2) Không an toàn:
Trong bảng tổng hợp thì các tháng xếp theo thứ tự thì ok, nhưng trong file vì lý do nào đó các sheet không theo thứ tự từ 1 đến 12 thì code này "tèo". Có thể tránh trường hợp này bằng cách gán giá trị số trong tên Sheet vào biến N ( đây chỉ là một cách)
Thân
 
Upvote 0
Code này có 2 vấn đề:
1) Sai:

phải là:

2) Không an toàn:
Trong bảng tổng hợp thì các tháng xếp theo thứ tự thì ok, nhưng trong file vì lý do nào đó các sheet không theo thứ tự từ 1 đến 12 thì code này "tèo". Có thể tránh trường hợp này bằng cách gán giá trị số trong tên Sheet vào biến N ( đây chỉ là một cách)
Thân
Quả là đúng vậy.
Thấy chủ thớt vẫn có ý sử dụng theo hướng của bài 1 nên cũng chỉ sửa lại một vài chỗ tính toán mà không hiệu chỉnh các câu lệnh còn lại ( Nhất là tại mục 2).
Thanks!
 
Upvote 0
Làm lại code dựa theo bài 1
Code cũ
Mã:
Option Explicit
Sub TH()
Dim Dic As Object, sArr(), dArr(1 To 10000, 1 To 14), N As Long, I As Long, K As Long, Tem As String
Dim Ws As Worksheet
Set Dic = CreateObject("Scripting.Dictionary")
For Each Ws In Worksheets
    If Ws.Name <> "T_HOP" Then
        sArr = Ws.Range("B3", Ws.Range("B65000").End(3)).Resize(, 2).Value2
            For I = 1 To UBound(sArr, 1)
                Tem = UCase(sArr(I, 1))
                If Not Dic.Exists(Tem) Then
                    K = K + 1
                    Dic.Add Tem, ""
                    dArr(K, 1) = K
                    dArr(K, 2) = sArr(I, 1)
                    [I]For N = 3 To 14[/I]          'Bỏ vòng lặp này
[I]                        dArr(K, N) = sArr(I, 2)
                    Next
[/I]              
                End If
            Next
    End If
Next
Ws.[B3].Resize(I, 2).Value = sArr     'Bỏ câu này
Sheets("T_HOP").[A4:N5000].ClearContents
Sheets("T_HOP").[A4].Resize(K - 1, 14).Value = dArr

Set Dic = Nothing
End Sub

Sửa thế này xem sao
Mã:
Sub TH_SC()
Dim Dic As Object, sArr(), dArr(1 To 10000, 1 To 14), N As Long, I As Long, K As Long, Tem As String 
Dim Ws As Worksheet
Set Dic = CreateObject("Scripting.Dictionary")
For Each Ws In Worksheets
If Ws.Name <> "T_HOP" Then
N = N + 1                         'Đưa biến N lên đây vì mỗi lần chuyển sheet là sang cột mới của dArr
sArr = Ws.Range("B3", Ws.Range("B65000").End(3)).Resize(, 2).Value2
For I = 1 To UBound(sArr, 1)
Tem = UCase(sArr(I, 1))

If Not Dic.Exists(Tem) Then  'Nếu Dic chưa có Tem
K = K + 1
Dic.Add Tem, K
dArr(K, 1) = K
dArr(K, 2) = sArr(I, 1)
dArr(K, N + 2) = sArr(I, 2)
Else                                  'Nếu Dic đã có Tem
dArr(Dic.Item(Tem), N + 2) = sArr(I, 2)
End If
Next I
End If
Next Ws
Sheets("T_HOP").[A4:N5000].ClearContents
Sheets("T_HOP").[A4].Resize(K - 1, 14).Value = dArr

Set Dic = Nothing
End Sub
Bạn kiểm tra xem sao
Ok, em cảm ơn bác, lúc đầu em đã đưa biến N lên nhưng chưa đúng cách
 
Upvote 0
Code này có 2 vấn đề:
1) Sai:

phải là:

2) Không an toàn:
Trong bảng tổng hợp thì các tháng xếp theo thứ tự thì ok, nhưng trong file vì lý do nào đó các sheet không theo thứ tự từ 1 đến 12 thì code này "tèo". Có thể tránh trường hợp này bằng cách gán giá trị số trong tên Sheet vào biến N ( đây chỉ là một cách)
Thân

Em cảm ơn Thầy nhiều nhé
 
Upvote 0
BÀi 5 đã giải quyết được vấn đề nhưng em muốn tìm hiểu giải theo cách Bài #1 , nhờ anh chị giúp đỡ

Sao nhìn code quen quen.
Viết lại như vầy xem sao:
PHP:
Sub TH()
Dim Dic As Object, sArr(), dArr(1 To 1000, 1 To 14), I As Long
Dim Ws As Worksheet, Col As Long, K As Long, Tem As String
Set Dic = CreateObject("Scripting.Dictionary")
For Each Ws In Worksheets
    If IsNumeric(Right(Ws.Name, 1)) Then
        Col = Right(Ws.Name, 2) + 2
        sArr = Ws.Range("B3", Ws.Range("B65536").End(xlUp)).Resize(, 2).Value
            For I = 1 To UBound(sArr, 1)
                Tem = UCase(sArr(I, 1))
                If Not Dic.Exists(Tem) Then
                    K = K + 1
                    Dic.Add Tem, K
                    dArr(K, 1) = K
                    dArr(K, 2) = sArr(I, 1)
                    dArr(K, Col) = sArr(I, 2)
                Else
                    dArr(Dic.Item(Tem), Col) = sArr(I, 2)
                End If
            Next I
    End If
Next
With Sheets("T_HOP")
    .[A4:N1000].ClearContents
    .[A4].Resize(K, 14).Value = dArr
End With
Set Dic = Nothing
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Sao nhìn code quen quen.
Viết lại như vầy xem sao:
PHP:
Sub TH()
Dim Dic As Object, sArr(), dArr(1 To 1000, 1 To 14), I As Long
Dim Ws As Worksheet, Col As Long, K As Long, Tem As String
Set Dic = CreateObject("Scripting.Dictionary")
For Each Ws In Worksheets
    If IsNumeric(Right(Ws.Name, 1)) Then
        Col = Right(Ws.Name, 2) + 2
        sArr = Ws.Range("B3", Ws.Range("B65536").End(xlUp)).Resize(, 2).Value
            For I = 1 To UBound(sArr, 1)
                Tem = UCase(sArr(I, 1))
                If Not Dic.Exists(Tem) Then
                    K = K + 1
                    Dic.Add Tem, K
                    dArr(K, 1) = K
                    dArr(K, 2) = sArr(I, 1)
                    dArr(K, Col) = sArr(I, 2)
                Else
                    dArr(Dic.Item(Tem), Col) = sArr(I, 2)
                End If
            Next I
    End If
Next
With Sheets("T_HOP")
    .[A4:N1000].ClearContents
    .[A4].Resize(K, 14).Value = dArr
End With
Set Dic = Nothing
End Sub
Đương nhiên là quen rồi Thầy, của Thầy mà, sau em chế thành 12 tháng ah. Em cảm ơn Thầy nhé. Bién Col or N do em đưa lên trên rồi nhưng sai cách nên không ra. Thầy gán giá trị số vào biến N nên đã giải quyết được tình huống của Thầy concogia roài
 
Lần chỉnh sửa cuối:
Upvote 0

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

Back
Top Bottom