Viết hàm nối mảng (5 người xem)

Liên hệ QC

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

viethung78

Thành viên chính thức
Tham gia
3/6/16
Bài viết
88
Được thích
53
Từ Excel 365 và Excel 2021 có hàm mảng động quá hay. Nhưng hay và thiết thực hơn nhiều nếu nối được các mảng động này mà không phải tạo DataTable và PowerQuery.

Bài toán là có 2 mảng động cùng kích thước ngang, làm sao có thể viết hàm VBA để nối bảng chúng lại với nhau được. Tôi đã cố gắng nhưng chưa đạt được. Rất mong cộng đồng xắn tay trợ giúp. Xin cảm ơn!

1657700866444.png
1657700965447.png
 

File đính kèm

  • Range Union.xlsb
    Range Union.xlsb
    13.8 KB · Đọc: 4
  • 1657700883350.png
    1657700883350.png
    18.4 KB · Đọc: 1
Từ Excel 365 và Excel 2021 có hàm mảng động quá hay. Nhưng hay và thiết thực hơn nhiều nếu nối được các mảng động này mà không phải tạo DataTable và PowerQuery.

Bài toán là có 2 mảng động cùng kích thước ngang, làm sao có thể viết hàm VBA để nối bảng chúng lại với nhau được. Tôi đã cố gắng nhưng chưa đạt được. Rất mong cộng đồng xắn tay trợ giúp. Xin cảm ơn!
Giải pháp khác là Multiple PivotTable, tổng hợp nhiều bảng với nhau.
1657702712604.png
 

File đính kèm

Từ Excel 365 và Excel 2021 có hàm mảng động quá hay. Nhưng hay và thiết thực hơn nhiều nếu nối được các mảng động này mà không phải tạo DataTable và PowerQuery.

Bài toán là có 2 mảng động cùng kích thước ngang, làm sao có thể viết hàm VBA để nối bảng chúng lại với nhau được. Tôi đã cố gắng nhưng chưa đạt được. Rất mong cộng đồng xắn tay trợ giúp. Xin cảm ơn!

View attachment 278791
View attachment 278793
Thử code này xem sao. Code chưa bẩy lỗi và Test hết các trường hợp.
Mã:
Function Union_Example(ParamArray args() As Variant)
    Dim sCell As Range, w As Integer, h As Integer
    Dim Arr, i As Integer, j As Integer, k As Integer
    Dim Rng As Range
    For i = LBound(args) To UBound(args)
        If TypeName(args(i)) = "Range" Then
            If Rng Is Nothing Then
                Set Rng = args(i)
            Else
                Set Rng = Union(Rng, args(i))
            End If
        End If
    Next i
    If Rng Is Nothing Then
       Union_Example = Null
       Exit Function
    End If
    If CheckRange(Rng, w, h) Then
        ReDim Arr(1 To h, 1 To w)
        k = 0
        For Each sCell In Rng.Areas
            For i = 1 To sCell.Rows.Count
                k = k + 1
                For j = 1 To sCell.Columns.Count
                    Arr(k, j) = sCell.Cells(i, j).Value2
                Next j
            Next i
        Next sCell
        Union_Example = Arr
    Else
        Union_Example = Null
    End If
End Function

Function CheckRange(ByVal Rng As Range, w As Integer, h As Integer) As Boolean
    Dim sCell As Range, sCol As Integer
    w = 0: h = 0
    CheckRange = True
    For Each sCell In Rng.Areas
        If sCol = 0 Then
            sCol = sCell.Columns.Count
        ElseIf sCol <> sCell.Columns.Count Then
            CheckRange = False
            Exit Function
        End If
        w = sCol
        h = h + sCell.Rows.Count
    Next sCell
End Function
Public Sub Test()
    Dim Arr
    Arr = Union_Example(Range("A2:B6"), Range("D8:E10"))
    If IsArray(Arr) Then
        Range("N14").Resize(UBound(Arr), UBound(Arr, 2)).Value = Arr
    Else
        MsgBox "Du lieu khong khop giua cac cot"
    End If
End Sub
 
Giải pháp khác là Multiple PivotTable, tổng hợp nhiều bảng với nhau.
View attachment 278799
Dùng Multi Pivot thì dùng Power Query còn hơn anh ạ
Bài đã được tự động gộp:

Thử code này xem sao. Code chưa bẩy lỗi và Test hết các trường hợp.
Mã:
Function Union_Example(ParamArray args() As Variant)
    Dim sCell As Range, w As Integer, h As Integer
    Dim Arr, i As Integer, j As Integer, k As Integer
    Dim Rng As Range
    For i = LBound(args) To UBound(args)
        If TypeName(args(i)) = "Range" Then
            If Rng Is Nothing Then
                Set Rng = args(i)
            Else
                Set Rng = Union(Rng, args(i))
            End If
        End If
    Next i
    If Rng Is Nothing Then
       Union_Example = Null
       Exit Function
    End If
    If CheckRange(Rng, w, h) Then
        ReDim Arr(1 To h, 1 To w)
        k = 0
        For Each sCell In Rng.Areas
            For i = 1 To sCell.Rows.Count
                k = k + 1
                For j = 1 To sCell.Columns.Count
                    Arr(k, j) = sCell.Cells(i, j).Value2
                Next j
            Next i
        Next sCell
        Union_Example = Arr
    Else
        Union_Example = Null
    End If
End Function

Function CheckRange(ByVal Rng As Range, w As Integer, h As Integer) As Boolean
    Dim sCell As Range, sCol As Integer
    w = 0: h = 0
    CheckRange = True
    For Each sCell In Rng.Areas
        If sCol = 0 Then
            sCol = sCell.Columns.Count
        ElseIf sCol <> sCell.Columns.Count Then
            CheckRange = False
            Exit Function
        End If
        w = sCol
        h = h + sCell.Rows.Count
    Next sCell
End Function
Public Sub Test()
    Dim Arr
    Arr = Union_Example(Range("A2:B6"), Range("D8:E10"))
    If IsArray(Arr) Then
        Range("N14").Resize(UBound(Arr), UBound(Arr, 2)).Value = Arr
    Else
        MsgBox "Du lieu khong khop giua cac cot"
    End If
End Sub
CODE NÀY KHI HAI MẢNG NGUỒN Ở SHEET KHÁC NHAU LÀ HÀM BÁO LỖI ANH AH
 
Lần chỉnh sửa cuối:
Dùng Multi Pivot thì dùng Power Query còn hơn anh ạ
Bài đã được tự động gộp:


CODE NÀY KHI HAI MẢNG NGUỒN Ở SHEET KHÁC NHAU LÀ HÀM BÁO LỖI ANH AH
Sửa lại chút.
Mã:
Function Union_Example(ParamArray args() As Variant)
    Dim sCell As Range, Rng As Range, w As Integer, h As Integer
    Dim Arr, i As Integer, j As Integer, k As Integer, n As Integer
    For i = LBound(args) To UBound(args)
        If TypeName(args(i)) = "Range" Then
            For Each sCell In args(i).Areas
                If w < sCell.Columns.Count Then w = sCell.Columns.Count
                h = h + sCell.Rows.Count
            Next sCell
        End If
    Next i
        ReDim Arr(1 To h, 1 To w)
        k = 0
    For i = LBound(args) To UBound(args)
        If TypeName(args(i)) = "Range" Then
            For Each sCell In args(i).Areas
                For n = 1 To sCell.Rows.Count
                    k = k + 1
                    For j = 1 To sCell.Columns.Count
                        Arr(k, j) = sCell.Cells(n, j).Value2
                    Next j
                    'Neu muon bo so 0 thi dung 3 dong lenh duoi day
                    'For j = sCell.Columns.Count + 1 To w
                    '    Arr(k, j) = ""
                    'Next j
                Next n
            Next sCell
        End If
    Next i
    Union_Example = Arr
End Function

Public Sub Test()
    Dim Arr
    Arr = Union_Example(Union(Sheet1.Range("A2:B6"), Sheet1.Range("D8:E10")), Sheet2.Range("C6:E10"))
    Sheet1.Range("N14").Resize(UBound(Arr), UBound(Arr, 2)).Value = Arr
End Sub
 
Sửa lại chút.
Mã:
Function Union_Example(ParamArray args() As Variant)
    Dim sCell As Range, Rng As Range, w As Integer, h As Integer
    Dim Arr, i As Integer, j As Integer, k As Integer, n As Integer
    For i = LBound(args) To UBound(args)
        If TypeName(args(i)) = "Range" Then
            For Each sCell In args(i).Areas
                If w < sCell.Columns.Count Then w = sCell.Columns.Count
                h = h + sCell.Rows.Count
            Next sCell
        End If
    Next i
        ReDim Arr(1 To h, 1 To w)
        k = 0
    For i = LBound(args) To UBound(args)
        If TypeName(args(i)) = "Range" Then
            For Each sCell In args(i).Areas
                For n = 1 To sCell.Rows.Count
                    k = k + 1
                    For j = 1 To sCell.Columns.Count
                        Arr(k, j) = sCell.Cells(n, j).Value2
                    Next j
                    'Neu muon bo so 0 thi dung 3 dong lenh duoi day
                    'For j = sCell.Columns.Count + 1 To w
                    '    Arr(k, j) = ""
                    'Next j
                Next n
            Next sCell
        End If
    Next i
    Union_Example = Arr
End Function

Public Sub Test()
    Dim Arr
    Arr = Union_Example(Union(Sheet1.Range("A2:B6"), Sheet1.Range("D8:E10")), Sheet2.Range("C6:E10"))
    Sheet1.Range("N14").Resize(UBound(Arr), UBound(Arr, 2)).Value = Arr
End Sub
VẪN BỊ LỖI TRƯỜNG HỢP CÁC BẢNG DỮ LIỆU Ở CÁC SHEET KHÁC NHAU ANH AH
 
Nếu đã xài 365 thì xài hàm mảng 365. Định dạng table cho 2 vùng có tên Data1 và Data2

=LET(d_1,Data1,d_2,Data2,r_1,ROWS(d_1),r_2,ROWS(d_2),r_0,r_1+r_2,IF(SEQUENCE(r_0)<=r_1,INDEX(d_1,SEQUENCE(r_1),{1,2}),INDEX(d_2,SEQUENCE(r_0)-r_1,{1,2})))

Nếu có hàm VStack thì càng đơn giản:

=VSTACK(Data1,Data2)

1657768653917.png

1657768682253.png

Nối 3, 4 bảng chỉ cần liệt kê

1657769066365.png
 
Lần chỉnh sửa cuối:
Nếu có hàm VStack thì càng đơn giản:

Còn hàm HSTACK nữa anh.

---
Khoản nối mảng này Google Sheets làm quá hay, chỉ cần liệt kê vào { } là xong. Nối ngang / dọc thì phụ thuộc vào dấu phân cách.

---
Chắc thớt mới nghĩ tới nối dọc xuống, chưa nghĩ ra còn nối rộng sang ngang. :D :D
 
Bạn tham khảo hàm S_ArrayMerge trong tệp dưới:

S_ArrayMerge hỗ trợ cả Sort sau khi nối mảng, nếu bạn gõ thêm hàm nhập tham số là I_Sort, ví dụ:
gõ: =S_ArrayMerge(A1:C100,G1:G100)
gõ: =S_ArrayMerge(I_Sort(1),A1:C100,G1:G100)
gõ: =S_ArrayMerge(I_Sort(1,False,False,False,False),A1:C100,G1:G100)

I_Sort: Index là Cột hoặc hàng, xếp từ nhỏ / lớn, xếp ngang / dọc, đảo mảng, sắp xếp phân biệt hoa thường

Có thể sử dụng S_ArrayMerge ở phiên bản Excel HĐH Windows bất kỳ.
 

File đính kèm

Lần chỉnh sửa cuối:
Nếu đã xài 365 thì xài hàm mảng 365. Định dạng table cho 2 vùng có tên Data1 và Data2

=LET(d_1,Data1,d_2,Data2,r_1,ROWS(d_1),r_2,ROWS(d_2),r_0,r_1+r_2,IF(SEQUENCE(r_0)<=r_1,INDEX(d_1,SEQUENCE(r_1),{1,2}),INDEX(d_2,SEQUENCE(r_0)-r_1,{1,2})))

Nếu có hàm VStack thì càng đơn giản:

=VSTACK(Data1,Data2)
...
Lão già nói chung cho mọi người hay nói riêng với đòi hỏi "hay và thiết thực hơn nhiều nếu..."?
Điều trước thì tốt. Điều sau thì quên đi. Một khi người ta nghĩ tới cái từ "code VBA" rồi là mọi thứ khác chỉ là đồ bỏ. 100 người lên GPE đủ 100.

Thử code này xem sao. Code chưa bẩy lỗi và Test hết các trường hợp.
...
Bạn bị người ta dẫn trước từ "Union" ròi cho nên lạc lối. Ở GPE này, tôi đã đóng băng định kiến: "dân lên đây hỏi bài đều là chủ quan. Không cần phải theo họ".

Khi cần nhóm một nhóm Objects lại, kỹ thuật đơn giản nhất là dùng Collection. Range là Object, một nhóm Ranges dùng Collection là hiệu quả nhất.

---
Khoản nối mảng này Google Sheets làm quá hay, chỉ cần liệt kê vào { } là xong. Nối ngang / dọc thì phụ thuộc vào dấu phân cách.
...
Google Sheets không phải phục vụ dân bí-zi-nịt cho nên tha hồ viết hàm chạy kiểu khoa học. Mà bạn là gốc khoa học cho nên thấy cái gì cũng hợp với mình. Anh Gú này không chịu trách nhiệm nếu bạn hiểu sai.

Anh bạn Joe McDaid của chúng ta bắt buộc phải rõ rệt bên này bên kia. Có nhiều tính năng không thể đâp ứng được vì chúng có khả năng lẫn lộn rồng rắn.
 
Lần chỉnh sửa cuối:
Nếu đã xài 365 thì xài hàm mảng 365. Định dạng table cho 2 vùng có tên Data1 và Data2

=LET(d_1,Data1,d_2,Data2,r_1,ROWS(d_1),r_2,ROWS(d_2),r_0,r_1+r_2,IF(SEQUENCE(r_0)<=r_1,INDEX(d_1,SEQUENCE(r_1),{1,2}),INDEX(d_2,SEQUENCE(r_0)-r_1,{1,2})))

Nếu có hàm VStack thì càng đơn giản:

=VSTACK(Data1,Data2)

View attachment 278832

View attachment 278833

Nối 3, 4 bảng chỉ cần liệt kê

View attachment 278835
Chừng Tháng 3, tháng 4 gì đấy em có đọc được trên mạng về 14 hàm mới của excel 365 như : Textbefore/ Textafter/ textsplit/ Vstack/Hstack/Torow.... nhưng khi em thử tìm trong excel 365 của mình lại không có, có thể chưa được cập nhật hay sao đó. Nhờ anh chỉ giúp em làm sao để cập nhật với ạ. (Em đang dùng lab công ty nên nếu cập nhật thì có cần admin cấp quyền hay tự mình làm được ạ?)
 
Đâu cần hỏi gì.
Gõ vào google: vstack function in excel
Là biết có ở đâu, bao giờ có, làm sao có.
 
Chừng Tháng 3, tháng 4 gì đấy em có đọc được trên mạng về 14 hàm mới của excel 365 như : Textbefore/ Textafter/ textsplit/ Vstack/Hstack/Torow.... nhưng khi em thử tìm trong excel 365 của mình lại không có, có thể chưa được cập nhật hay sao đó. Nhờ anh chỉ giúp em làm sao để cập nhật với ạ. (Em đang dùng lab công ty nên nếu cập nhật thì có cần admin cấp quyền hay tự mình làm được ạ?)
 
Lần chỉnh sửa cuối:
Trời nào? Không thấy tôi nhắc cái tên "Giô" hay sao?
H (horizontal) và V (vertical) rõ ràng là cặp trời sinh từ thuở khai thiên lập địa. Ông Descartes xài Hệ tọa độ vuông góc cũng phải xài 1 cặp trục tọa độ. Quartro và sau đó là Lotus 123 tạo biểu đồ trên máy tính cũng phải có 1 cặp. Hàm VLookup và HLookup cũng có từ xưa xửa xừa xưa.
Tên "Giô" hay "Giếc" gì cũng đâu có sáng tạo ra cái cặp đó cho VStack và HStack?
 
Bạn tham khảo hàm S_ArrayMerge trong tệp dưới:

S_ArrayMerge hỗ trợ cả Sort sau khi nối mảng, nếu bạn gõ thêm hàm nhập tham số là I_Sort, ví dụ:
gõ: =S_ArrayMerge(A1:C100,G1:G100)
gõ: =S_ArrayMerge(I_Sort(1),A1:C100,G1:G100)
gõ: =S_ArrayMerge(I_Sort(1,False,False,False,False),A1:C100,G1:G100)

I_Sort: Index là Cột hoặc hàng, xếp từ nhỏ / lớn, xếp ngang / dọc, đảo mảng, sắp xếp phân biệt hoa thường

Có thể sử dụng S_ArrayMerge ở phiên bản Excel HĐH Windows bất kỳ.
CẢM ƠN ANH ĐÃ TRỢ GIÚP NHÉ
Bài đã được tự động gộp:

Nếu đã xài 365 thì xài hàm mảng 365. Định dạng table cho 2 vùng có tên Data1 và Data2

=LET(d_1,Data1,d_2,Data2,r_1,ROWS(d_1),r_2,ROWS(d_2),r_0,r_1+r_2,IF(SEQUENCE(r_0)<=r_1,INDEX(d_1,SEQUENCE(r_1),{1,2}),INDEX(d_2,SEQUENCE(r_0)-r_1,{1,2})))

Nếu có hàm VStack thì càng đơn giản:

=VSTACK(Data1,Data2)

View attachment 278832

View attachment 278833

Nối 3, 4 bảng chỉ cần liệt kê

View attachment 278835
HÀM NÀY KHÔNG CẦN VBA NÊN TỐT QUÁ. CÓ THỂ DÙNG TRÊN EXCEL ONLINE. RẤT CẢM ƠN ANH.
 
Web KT

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

Back
Top Bottom