Xoá trùng dữ liệu trong 1 ô bằng VBA (1 người xem)

Liên hệ QC

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

Toto beo

Thành viên mới
Tham gia
30/3/18
Bài viết
2
Được thích
0
Giới tính
Nữ
Nghề nghiệp
Data analyst
Chào mọi người,

Mình có đoạn dữ liệu như thế này:
A1: destop (xuống dòng)
destop
A2: destop
mobile
destop
Mình muốn viết code VBA để xoá dữ liệu trùng trong mỗi ô. Tức là kết quả thu được sẽ là
A1: destop
A2: destop
mobile
Mong được sự giúp đỡ của moi nguoi. Cam on moi ng nhieu
 

File đính kèm

  • Capture.PNG
    Capture.PNG
    6.4 KB · Đọc: 10
Chào mọi người,

Mình có đoạn dữ liệu như thế này:
A1: destop (xuống dòng)
destop
A2: destop
mobile
destop
Mình muốn viết code VBA để xoá dữ liệu trùng trong mỗi ô. Tức là kết quả thu được sẽ là
A1: destop
A2: destop
mobile
Mong được sự giúp đỡ của moi nguoi. Cam on moi ng nhieu
Dùng chương trình Ms.Paint đơn giản để xóa những từ trùng trên là nhanh nhất
Lý do: vì file dang PNG là file hình nên phải dùng Paint là nhẹ nhất
 
Upvote 0
Chào mọi người,

Mình có đoạn dữ liệu như thế này:
A1: destop (xuống dòng)
destop
A2: destop
mobile
destop
Mình muốn viết code VBA để xoá dữ liệu trùng trong mỗi ô. Tức là kết quả thu được sẽ là
A1: destop
A2: destop
mobile
Mong được sự giúp đỡ của moi nguoi. Cam on moi ng nhieu
Function Rduplicate(ByVal Rng As Range, ByVal Delimiter As String)
Dim dic As Object, Tmp, i As Long, Str As String
Set dic = CreateObject("Scripting.Dictionary")
Tmp = Split(Rng, Delimiter)
For i = LBound(Tmp) To UBound(Tmp)
If Tmp(i) <> Empty Then
If Not dic.Exists(Trim(Tmp(i))) Then dic.Add Trim(Tmp(i)), ""
End If
Next i
If dic.Count Then
Rduplicate = Join(dic.Keys, Delimiter)
End If
End Function
C1=Rduplicate(A1,CHAR(10))
 
Lần chỉnh sửa cuối:
Upvote 0
Function Rduplicate(ByVal Rng As Range, ByVal Delimiter As String)
Dim dic As Object, Tmp, i As Long, Str As String
Set dic = CreateObject("Scripting.Dictionary")
Tmp = Split(Rng, Delimiter)
For i = LBound(Tmp) To UBound(Tmp)
If Tmp(i) <> Empty Then
If Not dic.Exists(Trim(Tmp(i))) Then dic.Add Trim(Tmp(i)), ""
End If
Next i
If dic.Count Then
Rduplicate = Join(dic.Keys, Delimiter)
End If
End Function
C1=Rduplicate(A1,CHAR(10))
Có vài vấn đề với Delimiter
1> Không có Delimiter trong chuỗi. Dạng đầu vào là "zbcabbzc" phải được biến thành "zbca"
2> Delimiter bị gõ thừa (giống như khoảng trắng thừa trong chuỗi). Dạng đầu vào "z,,,b,,,c,a,b,b,,,z,c" phải được biến thành "a,b,c,z"
-----------------------
Nhớ không lầm thì bài toán này được giải quyết cách đây rất nhiều năm rồi
 
Upvote 0
If Tmp(i) <> Empty Then
If Not dic.Exists(Trim(Tmp(i))) Then dic.Add Trim(Tmp(i)), ""
End If

Nếu muốn viết ngắn hơn thì viết như vầy:
If Tmp(i) <> Empty Then dic(Trim(Tmp(i)) = ""
Theo nguyên tắc của VBscript Dictionary, nếu key chưa có thì dic tự động add vào; nếu đã có thì dic sẽ đổi giá trị item của nó. (bạn không cần item nên khong sao cả)

Tuy nhiên, điều đáng lưu ý là code này tuy ngắn hơn nhưng chưa hẳn đã hiệu quả hơn. Vì nó ép đổi item cho nên công việc update luôn luôn thực hiện. Code nguyên thủy của bạn thì dic xét key trước khi thực hiện update.
Như vậy nên dùng cái nào? nếu bạn dự đoán rằng số key duplicate thấp thì dùng code gọn. Nếu số duplicate cao thì dùng code dài.
Đây là một ví dụ điển hình cho bạn thấy ngắn gọn không có nghĩa là hiệu quả. Và cách chọn lựa code cho hiệu quả lắm khi cũng tùy thuộc vào tình trạng dữ liệu mà nó được sử dụng.

(thực sự, nếu tôi viết code bài này thì tôi cứ cộng thẳng từng đoạn chuỗi và dùng hàm Instr để tìm duplicate. Nếu chuỗi ngắn thì cách này hiệu quả hơn vì không phải tạo dựng cái dic)

Chú thích thêm: nếu là tôi thì tôi tập bỏ thói quen dùng biến tên là tmp. Trong code của bạn cái key kia khong hẳn đã là temporary. Dùng tên như thế không đúng. Tên tmp thường dùng để chuyển đổi dữ liệu giữa 2 biến:
tmp = a
a = b
b = tmp
Vì khong rõ rệt nhiệm vụ cho nên người đọc cũng có cảm tưởng bạn dùng tmp để chỉ temperature (nhiệt độ)
(hình như tháng trước có 1 bạn cũng nhắc tới điều này. Trong bài ấy có ý muốn giúp các bạn sửa đổi phong cách viết code. Nhưng vì thói quen của các bạn ở đây chỉ chuyên về "hiệu quả" cho nên bạn ấy không đề cập đến việc sì tin viết code nữa. Và hình như bạn ấy đã rút lui khỏi diễn đàn - chán nản chăng?)
 
Lần chỉnh sửa cuối:
Upvote 0
Ah! Ngoài ra thì có 1 chuyện không kém phần quan trọng là CompareMode. Hay nói ngắn gọn là phải cân nhắc việc phân biệt HOA thường cho chuỗi.
"z,B,c,a,b" sẽ được biến thành "z,B,c,a" hay "z,B,c,a,b"? Đây chắc chắn nên là 1 tùy chọn trong UDF
 
Upvote 0
Đếm trùng thì còn có thể nói chuyện hoa thường chứ xóa trùng thì dùng cái gì để biết dạng nào chỉnh hơn mà xóa hay giữ?
nGUYỄN vĂN a và Nguyễn Văn A thì giữ cái nào?
 
Upvote 0
Function Rduplicate(ByVal Rng As Range, ByVal Delimiter As String)
Dim dic As Object, Tmp, i As Long, Str As String
Set dic = CreateObject("Scripting.Dictionary")
Tmp = Split(Rng, Delimiter)
For i = LBound(Tmp) To UBound(Tmp)
If Tmp(i) <> Empty Then
If Not dic.Exists(Trim(Tmp(i))) Then dic.Add Trim(Tmp(i)), ""
End If
Next i
If dic.Count Then
Rduplicate = Join(dic.Keys, Delimiter)
End If
End Function
C1=Rduplicate(A1,CHAR(10))
M dùng code bạn chạy đc rồi. Cảm ơn bạn lắm lắm
 
Upvote 0
Đếm trùng thì còn có thể nói chuyện hoa thường chứ xóa trùng thì dùng cái gì để biết dạng nào chỉnh hơn mà xóa hay giữ?
nGUYỄN vĂN a và Nguyễn Văn A thì giữ cái nào?
Vậy theo bạn thì nGUYỄN vĂN aNguyễn Văn A là.. mấy người? Dù máy tính nó có nói đó là 2 người thì tôi vẫn cho là 1 mà thôi. Tùy theo chuỗi ấy là gì, nếu là tên người thì phân biệt HOA thường gì chứ? Khi ấy dù có lấy nGUYỄN vĂN a hay Nguyễn Văn A thì vẫn là chú "đó" thôi
Bởi vậy tôi mới cho rằng nên cho CompareMode vào hàm như 1 tùy chọn
 
Upvote 0
Vậy theo bạn thì nGUYỄN vĂN aNguyễn Văn A là.. mấy người? Dù máy tính nó có nói đó là 2 người thì tôi vẫn cho là 1 mà thôi. ...

Nếu sẵn sàng xóa Nguyễn Văn A vì đã có ngUYỄN vĂN a rồi thì thà chuyển tất cả thành NGUYỄN VĂN A cho nó đồng bộ.
Căn bản thì dùng lối phân biệt hoa thường. Khi có khả năng không phân biệt thì nhét thêm hàm chuyển đổi.
B1 = HamLoaiTrung(HamDoiHoaThuong(A1))
 
Upvote 0
Nếu sẵn sàng xóa Nguyễn Văn A vì đã có ngUYỄN vĂN a rồi thì thà chuyển tất cả thành NGUYỄN VĂN A cho nó đồng bộ.
Căn bản thì dùng lối phân biệt hoa thường. Khi có khả năng không phân biệt thì nhét thêm hàm chuyển đổi.
B1 = HamLoaiTrung(HamDoiHoaThuong(A1))
Nhưng ai mà biết người ta có muốn phân biệt HOA thường hay không nên phải cho tùy chọn chứ bạn
Dictionay cũng hoạt động theo cách này đấy thôi (cho người ta tùy ý chọn CompareMode)
Ý tôi là: Viết code tổng quát, thà rằng Optional byVal CompareMode = gì gì đó, người ta không truyền vào thì lấy theo mặc định đã khai báo trước
 
Upvote 0
Web KT

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

Back
Top Bottom