Gộp dữ liệu từ nhiều sheets

Liên hệ QC

tuyen_ld

Thành viên mới
Tham gia
31/10/18
Bài viết
19
Được thích
3
Chào các bác. Các bác bổ xung cho em thêm code để điền ô ngày tháng ở sheets"Main" giống trong sheet "Tổng hợp" với
Ngày tháng này lấy ở ô A7 của các sheets cần gộp.
 

File đính kèm

  • Gop data.xls
    316 KB · Đọc: 128
PHP:
Sub SoDongSuDungTrongCacTrang()
Dim Sh As Worksheet, Rng As Range, sRng As Range
Dim DongSD As Long, HangDL As Long, DongCuoi As Long

For Each Sh In ThisWorkbook.Worksheets
    If IsNumeric(Sh.Name) Then
        DongSD = DongSD + Sh.UsedRange.Rows.Count
        MsgBox DongSD, , "Cong Dòn Sô Dòng Su Dung Dên  Trang: " & Sh.Name
        HangDL = HangDL + Sh.[b16].CurrentRegion.Rows.Count
        MsgBox HangDL, , "Cong Dòn  Só Hàng Du Liêu Dén Trang: " & Sh.Name
        Set sRng = Sh.Columns("A:A").Find("*", , xlFormulas, xlWhole)
        If Not sRng Is Nothing Then
            DongCuoi = DongCuoi + sRng.Row
            MsgBox DongCuoi, , "Tông Dòng Có 'Ghi Chú' Dên Trang: '" & Sh.Name
        End If
    End If
Next Sh
End Sub
Dùng 1 vòng lặp cả workbook để xác định số dòng để khai báo mảng.Hơi phí.Thà khai báo lớn nhất luôn.Bác nhỉ.
 
Upvote 0
Dùng 1 vòng lặp cả workbook để xác định số dòng để khai báo mảng.Hơi phí.Thà khai báo lớn nhất luôn.Bác nhỉ.
Thì người ta muốn thế mà.
Ý người ta hỏi không cho bài này mà chỉ tò mò xem có cách không để dùng cho tương lai.
Nhưng cái này đơn giảm mà. Book có bao nhiêu sheet? Hàng ngàn sheet thì cũng chả là bao. Có tính toán gì phức tạp, lâu đâu. Nhưng cái chính là người ta muốn thế, người ta tò mò thôi.
 
Upvote 0
Thì người ta muốn thế mà.
Ý người ta hỏi không cho bài này mà chỉ tò mò xem có cách không để dùng cho tương lai.
Nhưng cái này đơn giảm mà. Book có bao nhiêu sheet? Hàng ngàn sheet thì cũng chả là bao. Có tính toán gì phức tạp, lâu đâu. Nhưng cái chính là người ta muốn thế, người ta tò mò thôi.

Dạ dúng thế, con chỉ tò mò thôi ạ vì thấy các con số gán chết như vậy thì không hay cho người người sử dụng mà không biết đến vba, đây là dữ liệu ít chứ nếu dữ liệu tổng số dòng nhiều hơn 65000 dòng thì lại sửa code tăng thêm con số 65000 lên vài trăm nghìn ạ.

Vậy cách giải quyết là phải sử dụng thêm ít nhất 1 vòng lặp nữa để duyệt qua các sheet ạ. Giờ con đã hiểu

Con xin cảm ơn tất cả các bác và các bạn đã chỉ dẫn ạ.

hehehe con xin phép cười cái ạ,thích quá ạ.
 
Upvote 0
@Nguyễn Hoàng Oanh Thơ
Đã học thêm được Redim chưa. Phải học Luôn Redim Preserve nhé.
Lỡ rồi vận dụng luôn Erase để hoàn thành mảng. Thế là "giỏi VBA"

Mọi người hướng dẫn cho cô ấy lên đỉnh đi
 
Upvote 0
@Nguyễn Hoàng Oanh Thơ
Đã học thêm được Redim chưa. Phải học Luôn Redim Preserve nhé.
Lỡ rồi vận dụng luôn Erase để hoàn thành mảng. Thế là "giỏi VBA"

Mọi người hướng dẫn cho cô ấy lên đỉnh đi
Cảm ơn HeSanbi, nhờ bạn tiếp tục chủ đề mà OT đã hiểu được rõ hơn Redim và bản chất của mảng (trước khi gán giá trị thì cần phải có kích thước cụ thể).Còn về Redim Preserve Erase , OT chưa tìm hiểu. Giỏi thì OT không dám nghĩ đến chỉ hi vọng làm sao đủ để vận dụng được vào nhu cầu công việc của mình thôi ạ. :)
Trong bài toán này với cách khai báo động thêm 1 vòng lặp (bài 18) tộc độ vẫn nhanh hơn cách khai báo gán thẳng giá trị (bài 4).
 
Upvote 0
@Nguyễn Hoàng Oanh Thơ
Thì dịch nó ra tiếng Việt:
Dim : Mù mờ - VBA Array nghĩa là mảng mù mờ
Redim: Sử dụng lại mù mờ
Preserve: Bảo quản
Redim Preserve: Sử dụng lại mảng đang được bảo quản có thể tăng kích thước chiều ngang
Erase: làm rỗng
 
Upvote 0
Số dòng cần thiết? Có cách. Đó là niềm tin. Làm sao chưa xét hết các sheet mà biết được từng sheet có bao nhiêu dòng để tính tổng? Chỉ có bằng niềm tin.

Còn nếu không muốn tính trước số dòng cần thiết thì chỉ còn nước Redim mảng xoay so với mảng sẽ cần khi gặp sheet hợp lệ đầu tiên -> Redim Preserve với các sheet sau -> cuối cùng thì "xoay mảng" hiện hành 90 độ để có mảng cần có. Với cách này thì ở mọi thời điểm, trừ thời điểm xét sheet hợp lệ cuối cùng, cả thánh lẫn người trần tục đều không thể biết số dòng tổng cộng sẽ là bao nhiêu.
Em mượn ý tưởng của bác để thực hiện.
PHP:
Sub Consolidate_Data()
    Dim sArr(), dArr(), Res(), Ws As Worksheet
    Dim I As Long, J As Long, K As Long, lR As Long, t, x As Long
    
    t = Timer
    x = 1
    For Each Ws In ThisWorkbook.Sheets
        With Ws
            If .Name <> "Main" And .Name <> "Tong hop" Then
                lR = .Range("B" & Rows.Count).End(xlUp).Row
                sArr() = .Range("A17:G" & lR).Value
                If x = 1 Then
                    ReDim dArr(1 To UBound(sArr, 2) + 1, 1 To UBound(sArr, 1))
                Else
                    ReDim Preserve dArr(1 To UBound(sArr, 2) + 1, 1 To (UBound(dArr, 2) + UBound(sArr, 1)))
                End If
                
                For I = 1 To UBound(sArr, 1)
                    K = K + 1
                    dArr(1, K) = .Range("A7")
                    For J = 2 To UBound(sArr, 2)
                        dArr(J, K) = sArr(I, J)
                    Next J
                    dArr(UBound(sArr, 2) + 1, K) = .Name
                Next I
                x = x + 1
            End If
        End With
    Next Ws
    
    If K Then
        ReDim Res(1 To UBound(dArr, 2), 1 To UBound(dArr, 1))
        For I = 1 To UBound(dArr, 2)
            For J = 1 To UBound(dArr, 1)
                Res(I, J) = dArr(J, I)
            Next J
        Next I
    End If
    
    With Sheets("Main")
        .Range("A4").CurrentRegion.Offset(1).ClearContents
        .Range("A4").Resize(UBound(Res, 1), UBound(Res, 2)) = Res
    End With
    
    MsgBox "Done in " & (Timer - t) & "s.", vbInformation, "GPE"
End Sub
 
Upvote 0
Bài của Anh @vanthinh3101 chắc ok rồi đó chị OT.
Hình như em nhớ Rows.count xác định số dòng cuối cùng trong 1 trang tính mỗi phiên bản Excel, cũng như tương tự cho Columns.count
 
Upvote 0
GPE này nhiều thành viên cầu toàn nhỉ, tốt, Nhưng như thế là thiếu thực dụng - vì bài toán này quá nhỏ không đáng
 
Upvote 0
@Nguyễn Hoàng Oanh Thơ
Thì dịch nó ra tiếng Việt:
Dim : Mù mờ - VBA Array nghĩa là mảng mù mờ
Redim: Sử dụng lại mù mờ
Preserve: Bảo quản
Redim Preserve: Sử dụng lại mảng đang được bảo quản có thể tăng kích thước chiều ngang
Erase: làm rỗng
Đùa cũng có giới hạn. Đùa đến mức này, người ta ngỡ thật thì là chơi ác.
Từ Dim không hề dính líu đến mù mờ. Nói cho đúng thì nó rất rõ rệt. Chỉ khi dùng loại mảng động (xem giải thích từ động bên dưới) thì nó đưa ra vài uyển chuyển khiến ngừoi lạm dụng sự uyển chuyển này cho rằng đó là mù mờ.

Dim là từ cũ thời thượng (thập niên 1950-60), viết tắt của từ Dimension, có nghĩa là chiều (của mảng). Tiếp đầu ngữ "re" có nghĩa là "làm/đặt lại". Suy ra redim có nghĩa là đặt lại kích cỡ và chiều của mảng.

Mảng được khai báo ở 2 dạng, mảng tĩnh và mảng động. Lúc khia báo mà cho luôn chi tiết chiều và kích cỡ thì nó là mảng tĩnh. Lúc khai báo chưa biết chi tiết thì ngừoi ta chỉ khai báo mảng động, và sau đó dùng Redim để đặt lại chi tiết.

Redim là lệnh đặt lại kích cỡ mảng. Khi được đặt lại kích cỡ, dữ liệu có sẵn trước đó coi như mất.

Redim Preserve là lệnh đặt lại kích cỡ mảng nhưng giữ lại số dữ liệu đã có trong bộ nhớ. Vì mảng là một vùng nhớ liên tục cho nên lệnh này cũng có giới hạn của nó. Đại khái là phần thay đổi phải là chiều cuối cùng của mảng (nếu mảng có 3 chiều thì chỉ chiều thứ 3 mới thay đổi được).

Erase là lệnh xoá mảng. Tuỳ theo loại mảng mà nó xoá như thế nào. Loại mảng tĩnh thì nó xoá trở về trạng thái mới nguyên như lúc mới Dim (0, trống,...). Loại mảng động thì set luôn mảng về Nothing (tức là nếu muốn dùng lại thì phải Redim lại).

Lưu ý: VBA lạm dụng từ Dim để làm lệnh khai báo biến. Nguyên thuỷ thì Dim chỉ dùng để khai báo mảng. Ngôn ngữ BASIC cổ dùng cách khai báo mặc định cho biến (A là số, A$ là chuỗi, ...).

Quan trọng: đáng lẽ bạn Oanh Thơ phải chịu khó tìm thay vì hỏi vu vơ để nghe những câu trả lời bậy bạ. Tất cả những cái này đã từng được giải thích cặn kẽ trong mục chuyên đề "mảng". Bạn batman1 cũng có giải thích rất rõ về cấu trúc và cách hoạt động theo từng chiều cũng như bộ nhớ.
 
Lần chỉnh sửa cuối:
Upvote 0
Đùa cũng có giới hạn. Đùa đến mức này, người ta ngỡ thật thì là chơi ác.
Từ Dim không hề dính líu đến mù mờ. Nói cho đúng thì nó rất rõ rệt. Chỉ khi dùng loại mảng động (xem giải thích từ động bên dưới) thì nó đưa ra vài uyển chuyển khiến ngừoi lạm dụng sự uyển chuyển này cho rằng đó là mù mờ.

Dim là từ cũ thời thượng (thập niên 1950-60), viết tắt của từ Dimension, có nghĩa là chiều (của mảng). Tiếp đầu ngữ "re" có nghĩa là "làm/đặt lại". Suy ra redim có nghĩa là đặt lại kích cỡ và chiều của mảng.

Mảng được khai báo ở 2 dạng, mảng tĩnh và mảng động. Lúc khia báo mà cho luôn chi tiết chiều và kích cỡ thì nó là mảng tĩnh. Lúc khai báo chưa biết chi tiết thì ngừoi ta chỉ khai báo mảng động, và sau đó dùng Redim để đặt lại chi tiết.

Redim là lệnh đặt lại kích cỡ mảng. Khi được đặt lại kích cỡ, dữ liệu có sẵn trước đó coi như mất.

Redim Preserve là lệnh đặt lại kích cỡ mảng nhưng giữ lại số dữ liệu đã có trong bộ nhớ. Vì mảng là một vùng nhớ liên tục cho nên lệnh này cũng có giới hạn của nó. Đại khái là phần thay đổi phải là chiều cuối cùng của mảng (nếu mảng có 3 chiều thì chỉ chiều thứ 3 mới thay đổi được).

Erase là lệnh xoá mảng. Tuỳ theo loại mảng mà nó xoá như thế nào. Loại mảng tĩnh thì nó xoá trở về trạng thái mới nguyên như lúc mới Dim (0, trống,...). Loại mảng động thì set luôn mảng về Nothing (tức là nếu muốn dùng lại thì phải Redim lại).

Lưu ý: VBA lạm dụng từ Dim để làm lệnh khai báo biến. Nguyên thuỷ thì Dim chỉ dùng để khai báo mảng. Ngôn ngữ BASIC cổ dùng cách khai báo mặc định cho biến (A là số, A$ là chuỗi, ...).

Quan trọng: đáng lẽ bạn Oanh Thơ phải chịu khó tìm thay vì hỏi vu vơ để nghe những câu trả lời bậy bạ. Tất cả những cái này đã từng được giải thích cặn kẽ trong mục chuyên đề "mảng". Bạn batman1 cũng có giải thích rất rõ về cấu trúc và cách hoạt động theo từng chiều cũng như bộ nhớ.
Không chừng người ta hiểu như vậy chứ không phải đùa với "Bô lảo" N_H_O_T
 
Upvote 0
Dạ, nhờ có giải thích chi tiết và nhắc nhở của các bác @VetMini và bác @HieuCD mà cháu đã vỡ thêm được một chút nữa ạ.
Cảm ơn các bác nhiều.
OT chúc các bác nhiều sức khỏe ạ.
 
Upvote 0
@Nguyễn Hoàng Oanh Thơ
Làm sao biết 2 người trên là Bác vậy @Nguyễn Hoàng Oanh Thơ
lấy điểm của họ chia cho 10, +10 tức là 1 người 56 và một người 66
Mà quan trọng ai lớn hơn.
Chắc Ai nhiều bài viết hơn. Nhiều lượt thích chắc chắn còn "trẻ"
 
Upvote 0
@Nguyễn Hoàng Oanh Thơ
Làm sao biết 2 người trên là Bác vậy @Nguyễn Hoàng Oanh Thơ
lấy điểm của họ chia cho 10, +10 tức là 1 người 56 và một người 66
Mà quan trọng ai lớn hơn.
Chắc Ai nhiều bài viết hơn. Nhiều lượt thích chắc chắn còn "trẻ"

@HeSanbi
OT biết không phải là vì dựa vào nhiều bài viết hay là dựa vào lượt thích.
Mà dựa vào thông tin của những người mà OT tin tưởng cho biết, với lại qua các bài viết của các bác ấy OT cũng cảm nhận được ít nhiều khi viết về các kinh nghiệm đã từng trải.
Và chuyện này đối với OT cũng không có gì phải để tâm nhiều.
cảm ơn HeSanbi đã thông tin.
 
Upvote 0
...
OT biết không phải là vì dựa vào nhiều bài viết hay là dựa vào lượt thích.
Mà dựa vào thông tin của những người mà OT tin tưởng cho biết, với lại qua các bài viết của các bác ấy OT cũng cảm nhận được ít nhiều khi viết về các kinh nghiệm đã từng trải.
Và chuyện này đối với OT cũng không có gì phải để tâm nhiều.
...
Theo truyền thống người Việt mình thì "bác" là tiếng gọi lịch sự. Như vậy dẫu tôi không lớn tuổi thì cũng chẳng sao. Đối với ngừoi Bắc thì "bác" dùng cả cho phụ nữ.
Nếu bạn dưới 30 và không phải là con út thì khả năng tôi lớn tuổi hơn bố bạn là 50%. Bác batman1 lớn hơn tôi 1 tuổi, và bác HieuCD cũng vậy.
 
Upvote 0
Theo truyền thống người Việt mình thì "bác" là tiếng gọi lịch sự. Như vậy dẫu tôi không lớn tuổi thì cũng chẳng sao. Đối với ngừoi Bắc thì "bác" dùng cả cho phụ nữ.
Nếu bạn dưới 30 và không phải là con út thì khả năng tôi lớn tuổi hơn bố bạn là 50%. Bác batman1 lớn hơn tôi 1 tuổi, và bác HieuCD cũng vậy.

Dạ, vâng! Cách gọi bác là thể hiện tôn trọng và lịch sự.
Oanh Thơ năm nay 30 tuổi và là con đầu lòng.
100% bác hơn tuổi bố con ạ. :)
 
Upvote 0
Upvote 0
Tôi xem Phim miền bắc nghe hay gọi Bố
Sao @Nguyễn Hoàng Oanh Thơ không gọi là Bố.
Tôi đoán là khi nào thân thiết, thường giao tiếp mới gọi "Bố" đúng không
Chứ miền Trung tôi, kêu "chú". Già quên cả tuổi mới gọi bác
Với @Nguyễn Hoàng Oanh Thơ chắc phải kêu "Thím"

Nếu tôi không quên thì chị hoặc anh của bố mẹ thì là bác, còn em thì là chú/cô, cậu/mợ. Ngoài xã hội thì loại hơn tuổi bố mình thì cũng là bác, kém thì là chú. Như vậy theo tôi OT gọi bác VetMini là bác thì chuẩn.
Người dưng nhưng đã thân quen như ruột thịt thì mới gọi là bố.
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu tôi không quên thì chị hoặc anh của bố mẹ thì là bác, còn em thì là chú/cô, cậu/mợ. Ngoài xã hội thì loại hơn tuổi bố mình thì cũng là bác, kém thì là chú. Như vậy theo tôi OT gọi bác VetMini là bác thì chuẩn.
Người dưng nhưng đã thân quen như ruột thịt thì mới gọi là bố.
Ngữ cảnh, bác ơi. Ai mà biết người ta nói cái "Phim miền bắc" đó nó là cái gì? Nó nói về vùng nào, tầng lớp nào? Khung cảnh những lúc đối thoại ấy ra sao?
Tiếng Anh gọi cái kỹ thuật này là "quoting out of context"

Ở miệt dưới người dân quê hay gọi đàn bà lớn tuổi là "má". Nhưng không phải thấy người ta gọi thế là mình gọi theo được. Phải là dân Nam vài chục năm mới nắm vững cách gọi này. Cái từ phát âm ra chỉ cần thay đổi tông (tone/enunciation) một chút, hay đặt lệch vị trí trong câu một chút thì nó nghe thành nghĩa chế diễu ngay.
 
Upvote 0
Web KT
Back
Top Bottom