So sánh nội dung của 2 sheet, xuất kết quả không trùng sang sheet khác

Liên hệ QC

hanbro

Thành viên mới
Tham gia
2/5/12
Bài viết
6
Được thích
0
Xin chào các bạn, xin nhờ các bạn giúp mình so sánh ID hai sheet 1 và 2, nếu kết quả không trùng ở cả 2 sheet thì xuất sang sheet 3 như hình với.
Rất mong nhận được sự giúp đỡ từ mọi người.
Xin cảm ơn!
P/s: Mình cũng đã thử mấy bài gần giống giống trên diễn đàn nhưng không áp dụng được.

2022-04-29_130149.png
 

File đính kèm

  • SS ID.xlsx
    10.5 KB · Đọc: 19
Xin chào các bạn, xin nhờ các bạn giúp mình so sánh ID hai sheet 1 và 2, nếu kết quả không trùng ở cả 2 sheet thì xuất sang sheet 3 như hình với.
Rất mong nhận được sự giúp đỡ từ mọi người.
Xin cảm ơn!
P/s: Mình cũng đã thử mấy bài gần giống giống trên diễn đàn nhưng không áp dụng được.

2022-04-29_130149.png
Thử code.
Mã:
Sub asda()
    Dim i As Long, lr As Long, dic As Object, dk As String, arr, data, kq, a As Long
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet1")
         lr = .Range("A" & Rows.Count).End(xlUp).Row
         arr = .Range("A2:B" & lr).Value
         For i = 1 To UBound(arr)
             dk = arr(i, 1) & "A"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
             End If
         Next i
    End With
    With Sheets("sheet2")
         lr = .Range("A" & Rows.Count).End(xlUp).Row
         data = .Range("A2:B" & lr).Value
         ReDim kq(1 To UBound(arr) + UBound(data), 1 To 2)
         For i = 1 To UBound(data)
             dk = data(i, 1) & "A"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
                a = a + 1
                kq(a, 1) = data(i, 1)
                kq(a, 2) = data(i, 2)
             End If
             dk = data(i, 1) & "B"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
             End If
         Next i
         For i = 1 To UBound(arr)
             dk = arr(i, 1) & "B"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
                a = a + 1
                kq(a, 1) = arr(i, 1)
                kq(a, 2) = arr(i, 2)
             End If
        Next i
   End With
   With Sheets("sheet3")
        .Range("A2:B1000").ClearContents
        If a Then .Range("A2:B2").Resize(a).Value = kq
   End With
   Set dic = Nothing
End Sub
 
Upvote 0
Thử code.
Mã:
Sub asda()
    Dim i As Long, lr As Long, dic As Object, dk As String, arr, data, kq, a As Long
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet1")
         lr = .Range("A" & Rows.Count).End(xlUp).Row
         arr = .Range("A2:B" & lr).Value
         For i = 1 To UBound(arr)
             dk = arr(i, 1) & "A"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
             End If
         Next i
    End With
    With Sheets("sheet2")
         lr = .Range("A" & Rows.Count).End(xlUp).Row
         data = .Range("A2:B" & lr).Value
         ReDim kq(1 To UBound(arr) + UBound(data), 1 To 2)
         For i = 1 To UBound(data)
             dk = data(i, 1) & "A"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
                a = a + 1
                kq(a, 1) = data(i, 1)
                kq(a, 2) = data(i, 2)
             End If
             dk = data(i, 1) & "B"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
             End If
         Next i
         For i = 1 To UBound(arr)
             dk = arr(i, 1) & "B"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
                a = a + 1
                kq(a, 1) = arr(i, 1)
                kq(a, 2) = arr(i, 2)
             End If
        Next i
   End With
   With Sheets("sheet3")
        .Range("A2:B1000").ClearContents
        If a Then .Range("A2:B2").Resize(a).Value = kq
   End With
   Set dic = Nothing
End Sub
Chạy đúng y, cảm ơn rất nhiều.
 
Upvote 0
Thử code.
Mã:
Sub asda()
    Dim i As Long, lr As Long, dic As Object, dk As String, arr, data, kq, a As Long
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet1")
         lr = .Range("A" & Rows.Count).End(xlUp).Row
         arr = .Range("A2:B" & lr).Value
         For i = 1 To UBound(arr)
             dk = arr(i, 1) & "A"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
             End If
         Next i
    End With
    With Sheets("sheet2")
         lr = .Range("A" & Rows.Count).End(xlUp).Row
         data = .Range("A2:B" & lr).Value
         ReDim kq(1 To UBound(arr) + UBound(data), 1 To 2)
         For i = 1 To UBound(data)
             dk = data(i, 1) & "A"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
                a = a + 1
                kq(a, 1) = data(i, 1)
                kq(a, 2) = data(i, 2)
             End If
             dk = data(i, 1) & "B"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
             End If
         Next i
         For i = 1 To UBound(arr)
             dk = arr(i, 1) & "B"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
                a = a + 1
                kq(a, 1) = arr(i, 1)
                kq(a, 2) = arr(i, 2)
             End If
        Next i
   End With
   With Sheets("sheet3")
        .Range("A2:B1000").ClearContents
        If a Then .Range("A2:B2").Resize(a).Value = kq
   End With
   Set dic = Nothing
End Sub
Cái này sheet 1 cho vào dic.xong qua sheet 2 cái nào có trong dic rồi thì remove. Chưa có cho vào dic có ổn không anh nhỉ?
 
Upvote 0
Thử code.
Mã:
Sub asda()
    Dim i As Long, lr As Long, dic As Object, dk As String, arr, data, kq, a As Long
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet1")
         lr = .Range("A" & Rows.Count).End(xlUp).Row
         arr = .Range("A2:B" & lr).Value
         For i = 1 To UBound(arr)
             dk = arr(i, 1) & "A"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
             End If
         Next i
    End With
    With Sheets("sheet2")
         lr = .Range("A" & Rows.Count).End(xlUp).Row
         data = .Range("A2:B" & lr).Value
         ReDim kq(1 To UBound(arr) + UBound(data), 1 To 2)
         For i = 1 To UBound(data)
             dk = data(i, 1) & "A"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
                a = a + 1
                kq(a, 1) = data(i, 1)
                kq(a, 2) = data(i, 2)
             End If
             dk = data(i, 1) & "B"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
             End If
         Next i
         For i = 1 To UBound(arr)
             dk = arr(i, 1) & "B"
             If Not dic.exists(dk) Then
                dic.Add dk, ""
                a = a + 1
                kq(a, 1) = arr(i, 1)
                kq(a, 2) = arr(i, 2)
             End If
        Next i
   End With
   With Sheets("sheet3")
        .Range("A2:B1000").ClearContents
        If a Then .Range("A2:B2").Resize(a).Value = kq
   End With
   Set dic = Nothing
End Sub
[/QUOTE]
anh ơi, nếu muốn mở rộng vùng so sánh và lấy dữ liệu thì sửa ở chỗ nào ạ
Bài đã được tự động gộp:

anh ơi, nếu muốn mở rộng vùng so sánh và lấy dữ liệu thì sửa ở chỗ nào ạ
em sửa được vùng lấy dữ liệu rồi ạ, nếu mình muốn lấy dự liệu trùng nhau thì sửa như thế nào ạ, e cảm ơn :D
 
Lần chỉnh sửa cuối:
Upvote 0
Thì nó vẫn chỉ lấy được dữ liệu không có bên sheet2.còn bên sheet1 thì làm sao.
Da. Cám ơn anh đã phản hồi. Ngồi vọc vạch theo suy nghĩ của mình.
Thấy ra kết quả. Nhưng chẳng biết đúng hay sai nữa
Mã:
Option Explicit

Sub Abc()
Dim dic As Object, Arr(), Res(1 To 100000, 1 To 2)
Dim sArr(), i&, k&, Key, iR
Set dic = CreateObject("scripting.dictionary")
With Sheet1
    iR = .Range("A" & Rows.Count).End(3).Row
    Arr = .Range("A2:B" & iR).Value
    For i = 1 To UBound(Arr)
        If dic.exists(Arr(i, 1)) = False Then
            dic.Item(Arr(i, 1)) = i
        End If
    Next
End With
With Sheet2
    iR = .Range("A" & Rows.Count).End(3).Row
    sArr = .Range("A2:B" & iR).Value
    For i = 1 To UBound(sArr)
        If dic.exists(sArr(i, 1)) = True Then
            dic.Remove (sArr(i, 1))
        Else
         k = k + 1
         Res(k, 1) = sArr(i, 1)
         Res(k, 2) = sArr(i, 2)
        End If
    Next
    For Each Key In dic.keys
    k = k + 1
        Res(k, 1) = Key
        Res(k, 2) = Arr(dic.Item(Key), 2)
    Next
End With
If k Then
Sheet3.Range("C2:D1000").ClearContents
Sheet3.Range("C2").Resize(k, 2).Value = Res
End If
End Sub
 
Upvote 0
Da. Cám ơn anh đã phản hồi. Ngồi vọc vạch theo suy nghĩ của mình.
Thấy ra kết quả. Nhưng chẳng biết đúng hay sai nữa
Mã:
Option Explicit

Sub Abc()
Dim dic As Object, Arr(), Res(1 To 100000, 1 To 2)
Dim sArr(), i&, k&, Key, iR
Set dic = CreateObject("scripting.dictionary")
With Sheet1
    iR = .Range("A" & Rows.Count).End(3).Row
    Arr = .Range("A2:B" & iR).Value
    For i = 1 To UBound(Arr)
        If dic.exists(Arr(i, 1)) = False Then
            dic.Item(Arr(i, 1)) = i
        End If
    Next
End With
With Sheet2
    iR = .Range("A" & Rows.Count).End(3).Row
    sArr = .Range("A2:B" & iR).Value
    For i = 1 To UBound(sArr)
        If dic.exists(sArr(i, 1)) = True Then
            dic.Remove (sArr(i, 1))
        Else
         k = k + 1
         Res(k, 1) = sArr(i, 1)
         Res(k, 2) = sArr(i, 2)
        End If
    Next
    For Each Key In dic.keys
    k = k + 1
        Res(k, 1) = Key
        Res(k, 2) = Arr(dic.Item(Key), 2)
    Next
End With
If k Then
Sheet3.Range("C2:D1000").ClearContents
Sheet3.Range("C2").Resize(k, 2).Value = Res
End If
End Sub
Nếu dữ liệu sheet2 bị trùng thì tèo :p
Thử không dùng dic xem sao
 
Upvote 0
Nếu dữ liệu sheet2 bị trùng thì tèo :p
Thử không dùng dic xem sao
Cám ơn thầy. Đoạn không dùng dic. Em cũng chưa nghĩ ra được không dùng dic. Mà không sort thì sẽ làm thế nào. Nhưng để em thử xem theo cách em nghĩ thế nào
 
Upvote 0
Da. Cám ơn anh đã phản hồi. Ngồi vọc vạch theo suy nghĩ của mình.
Thấy ra kết quả. Nhưng chẳng biết đúng hay sai nữa
Mã:
Option Explicit

Sub Abc()
Dim dic As Object, Arr(), Res(1 To 100000, 1 To 2)
Dim sArr(), i&, k&, Key, iR
Set dic = CreateObject("scripting.dictionary")
With Sheet1
    iR = .Range("A" & Rows.Count).End(3).Row
    Arr = .Range("A2:B" & iR).Value
    For i = 1 To UBound(Arr)
        If dic.exists(Arr(i, 1)) = False Then
            dic.Item(Arr(i, 1)) = i
        End If
    Next
End With
With Sheet2
    iR = .Range("A" & Rows.Count).End(3).Row
    sArr = .Range("A2:B" & iR).Value
    For i = 1 To UBound(sArr)
        If dic.exists(sArr(i, 1)) = True Then
            dic.Remove (sArr(i, 1))
        Else
         k = k + 1
         Res(k, 1) = sArr(i, 1)
         Res(k, 2) = sArr(i, 2)
        End If
    Next
    For Each Key In dic.keys
    k = k + 1
        Res(k, 1) = Key
        Res(k, 2) = Arr(dic.Item(Key), 2)
    Next
End With
If k Then
Sheet3.Range("C2:D1000").ClearContents
Sheet3.Range("C2").Resize(k, 2).Value = Res
End If
End Sub
Nếu xóa rồi mà nó lại xuất hiện thêm lần nữa thì sao nhỉ.
Bài đã được tự động gộp:

Sort dữ liệu trước tốc độ sẽ nhanh hơn nhiều
Sort lại dùng công cụ excel nếu data của họ không muốn thay đổi thì sao anh.Mà không dùng Dictionary thì dùng mảng à anh.
 
Upvote 0
Cám ơn thầy. Đoạn không dùng dic. Em cũng chưa nghĩ ra được không dùng dic. Mà không sort thì sẽ làm thế nào. Nhưng để em thử xem theo cách em nghĩ thế nào
Nếu không dùng dic thì phải chạy vòng lặp trong mảng kết quả đến lúc chạy, xem có hay chưa.
 
Upvote 0
Nếu xóa rồi mà nó lại xuất hiện thêm lần nữa thì sao nhỉ.
Bài đã được tự động gộp:


Sort lại dùng công cụ excel nếu data của họ không muốn thay đổi thì sao anh.Mà không dùng Dictionary thì dùng mảng à anh.
Lưu dữ liệu gốc vào mảng, sort và xử lý xong trả lại dữ liệu gốc, hoặc sort bằng VBA
Anh Hiếu hay có bài dùng Hàm instr với array.Tôi nghĩ 2 cách đấy cũng nhanh nếu dữ liệu ít.
ID là số nguyên, tạo mảng dùng ID làm thứ tự dòng là cách sort và lấy dữ liệu trùng hoặc thiếu đơn giản và nhanh nhất
 
Upvote 0
Cách 1:
- Copy bảng 1 vào bảng 3.
- Copy bảng 2 vào nối tiếp.
- Sort theo ID
- Đọc bảng, cái nào giống trước hoặc sau nó thì đánh dấu X vào cột dư cuối.
- Sort theo cột dư.
- Đọc ngược bảng, xoá những dòng có X. Đến khi gặp trống thì dừng.
- Xoá cột dư.

Cách 2:
- Sort bảng 2
- Lập một mảng Long (a) có số phần tử bằng số dòng của bảng 2
- Lập một mảng ID, Name (b) có số dòng bằng tổng số dòng của 1 và 2
- Đọc bảng 1, dùng hàm Match để dò bảng 2. (dò theo gần đúng rồi kiểm lại rất nhanh)
- - Nếu thấy Match thì đánh dấu phần tử ở a = 1. Nếu không thấy match thì chép vào b.
- Đọc mảng a, phần tử nào bằng 0 thì chép dòng tương ứng nó từ bảng 2 vào b.
- Chép mảng b xuống thành bảng 3.
 
Upvote 0
Lưu dữ liệu gốc vào mảng, sort và xử lý xong trả lại dữ liệu gốc, hoặc sort bằng VBA

ID là số nguyên, tạo mảng dùng ID làm thứ tự dòng là cách sort và lấy dữ liệu trùng hoặc thiếu đơn giản và nhanh nhất
Anh viết code em xem ạ.
 
Upvote 0
Cách 1:
- Copy bảng 1 vào bảng 3.
- Copy bảng 2 vào nối tiếp.
- Sort theo ID
- Đọc bảng, cái nào giống trước hoặc sau nó thì đánh dấu X vào cột dư cuối.
- Sort theo cột dư.
- Đọc ngược bảng, xoá những dòng có X. Đến khi gặp trống thì dừng.
- Xoá cột dư.

Cách 2:
- Sort bảng 2
- Lập một mảng Long (a) có số phần tử bằng số dòng của bảng 2
- Lập một mảng ID, Name (b) có số dòng bằng tổng số dòng của 1 và 2
- Đọc bảng 1, dùng hàm Match để dò bảng 2. (dò theo gần đúng rồi kiểm lại rất nhanh)
- - Nếu thấy Match thì đánh dấu phần tử ở a = 1. Nếu không thấy match thì chép vào b.
- Đọc mảng a, phần tử nào bằng 0 thì chép dòng tương ứng nó từ bảng 2 vào b.
- Chép mảng b xuống thành bảng 3.
Cách 2 đọc thấy rối nùi bác ơi. Chắc tôi phải mở máy tính dò từng dòng để thử mới được.
 
Upvote 0
Cần gì code.
Bạn dùng hàm MIN và MAX để tìm số ID nhỏ nhất và lớn nhất. Đặt mảng:
Dim a(idMin To idMax) As Long
Đọc lần lượt 2 bảng, a(ID) = a(ID) + 1
Duyệt mảng, cái nào bằng 1 thì nó là chỉ có ở 1 trong 2 bảng.

Trường hợp chính bảng 1 hoặc 2 có ID trùng thì hơi rắc rối hơn một chút. Bạn phải dùng con toán bit:
- Nếu id từ bảng 1 thì a(ID) = a(ID) AND 1, từ bảng 2 thì AND 2
- Khi duyệt lại mảng, chỗ nào bằng 1 hoặc 2 là chỉ có trong 1 bảng, 3 là có trong hai bảng.

Chỉnh sửa: lại lầm nữa, tuổi già lẩm cẩm.
Ở trên tôi nói dùng AND là sai. Dùng OR mới đúng.
Nguyên tắc: AND dùng để xét, OR dùng để cài.
 
Lần chỉnh sửa cuối:
Upvote 0
Cách 1:
- Copy bảng 1 vào bảng 3.
- Copy bảng 2 vào nối tiếp.
- Sort theo ID
- Đọc bảng, cái nào giống trước hoặc sau nó thì đánh dấu X vào cột dư cuối.
- Sort theo cột dư.
- Đọc ngược bảng, xoá những dòng có X. Đến khi gặp trống thì dừng.
- Xoá cột dư.

Cách 2:
- Sort bảng 2
- Lập một mảng Long (a) có số phần tử bằng số dòng của bảng 2
- Lập một mảng ID, Name (b) có số dòng bằng tổng số dòng của 1 và 2
- Đọc bảng 1, dùng hàm Match để dò bảng 2. (dò theo gần đúng rồi kiểm lại rất nhanh)
- - Nếu thấy Match thì đánh dấu phần tử ở a = 1. Nếu không thấy match thì chép vào b.
- Đọc mảng a, phần tử nào bằng 0 thì chép dòng tương ứng nó từ bảng 2 vào b.
- Chép mảng b xuống thành bảng 3.
Tại sao cách 2 lại phải sort trước anh nhỉ.Để cho hàm match nó chạy nhanh hơn à.
Bài đã được tự động gộp:

Cần gì code.
Bạn dùng hàm MIN và MAX để tìm số ID nhỏ nhất và lớn nhất. Đặt mảng:
Dim a(idMin To idMax) As Long
Đọc lần lượt 2 bảng, a(ID) = a(ID) + 1
Duyệt mảng, cái nào bằng 1 thì nó là chỉ có ở 1 trong 2 bảng.

Trường hợp chính bảng 1 hoặc 2 có ID trùng thì hơi rắc rối hơn một chút. Bạn phải dùng con toán bit:
- Nếu id từ bảng 1 thì a(ID) = a(ID) AND 1, từ bảng 2 thì AND 2
- Khi duyệt lại mảng, chỗ nào bằng 1 hoặc 2 là chỉ có trong 1 bảng, 3 là có trong hai bảng.
Hì cái này thì thuật toán nó vẫn giống Dictionary.Chẳng qua là nó duyệt duy nhất bằng mảng thôi.Nhưng em thấy bài của anh Hiếu cần kết hợp với sort để nó nhanh hơn.Có thể duyệt chạy song song được 2 mảng 1 vòng lặp là có kết quả ấy.
 
Lần chỉnh sửa cuối:
Upvote 0
Tại sao cách 2 lại phải sort trước anh nhỉ.Để cho hàm match nó chạy nhanh hơn à.
Match với tham thứ 3 là 1 dùng phép dò nhị phân, rất nhanh. Nhưng vì nó dò gần đúng cho nên khi ra vị trí rồi thì phải lấy từ vị trí ấy ra để xét lại có chính xác. Tuy phải làm vậy nhưng vẫn hiệu quả hơn cách dò với tham là 0. Trừ phi dữ kiệu rất ít.
 
Upvote 0
Web KT

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

Back
Top Bottom