Thử món này xem sao:Em có ví dụ này nhờ mọi người xem và thiết lập cho em. Câu hỏi cụ thể trong file đính kèm!
Download file
Liệu có giải pháp nào không?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim VL As String, Cll As Range
If Target.Count > 1 Or Intersect(Target, Range([A2], [A100].End(xlUp))) Is Nothing Then Exit Sub
For Each Cll In Sheet1.Range(Sheet1.[A1], Sheet1.[A10000].End(xlUp))
If Cll.Value = Target.Value Then
VL = VL & vbCr & Cll.Offset(, 1) & " | " & Cll.Offset(, 2)
End If
Next
If Len(VL) > 0 Then MsgBoxUni VL, , "Ma san pham " & Target.Value
End Sub
Mình nghĩ hiện kết quả vào 1 Comment hoặc cái gì đó tương tự sẽ hay hơn ---> MsgBox cứ bấm hoài, mỏi tay lắmThử món này xem sao:
Trong file có sử dụng hàm MsgBoxUni của anh Nguyễn Duy Tuân. Cảm ơn anh!PHP:Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim VL As String, Cll As Range If Target.Count > 1 Or Intersect(Target, Range([A2], [A100].End(xlUp))) Is Nothing Then Exit Sub For Each Cll In Sheet1.Range(Sheet1.[A1], Sheet1.[A10000].End(xlUp)) If Cll.Value = Target.Value Then VL = VL & vbCr & Cll.Offset(, 1) & " | " & Cll.Offset(, 2) End If Next If Len(VL) > 0 Then MsgBoxUni VL, , "Ma san pham " & Target.Value End Sub
Nếu lượng dữ liệu lớn thì có lẽ thay vòng For-Next thành vòng Do-While và set biến Cll bởi phương thức Find sẽ nhanh hơn.
Theo gợi ý của bác ndu, em làm ra cái này. Bác cho ý kiến nhé:Mình nghĩ hiện kết quả vào 1 Comment hoặc cái gì đó tương tự sẽ hay hơn ---> MsgBox cứ bấm hoài, mỏi tay lắm
(bấm vào đúng vùng hoạt động thì Add và hiện comment, ngược lại thì xóa comment)
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim Cll As Range, n As Long, VL As String, i As Integer
[A:A].ClearComments
If Target.Count > 1 Or Intersect(Target, Range([A2], [A10000].End(xlUp))) Is Nothing Then Exit Sub
VL = ""
With Sheet1
On Error GoTo AddCom
Set Cll = .[A:A].Find(Target.Value, .[A1], , xlWhole)
n = Cll.Row
Do
i = i + 1
VL = VL & Chr(10) & Cll.Offset(, 1) & " | " & Cll.Offset(, 2)
Set Cll = .[A:A].Find(Target.Value, Cll, , xlWhole)
Loop Until Cll.Row = n
End With
AddCom:
With Target
.AddComment
.Comment.Visible = True
.Comment.Text VL
.Comment.Shape.Height = 25 + 10 * i
End With
End Sub
Theo mình, đã dùng Find nên dùng thêm FindNext cho gọn hơn.Nguyên văn bởi nghiaphuc
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim Cll As Range, n As Long, VL As String, i As Integer
[A:A].ClearComments
If Target.Count > 1 Or Intersect(Target, Range([A2], [A10000].End(xlUp))) Is Nothing Then Exit Sub
VL = ""
With Sheet1
On Error GoTo AddCom
Set Cll = .[A:A].Find(Target.Value, .[A1], , xlWhole)
n = Cll.Row
Do
i = i + 1
VL = VL & Chr(10) & Cll.Offset(, 1) & " | " & Cll.Offset(, 2)
Set Cll = .[A:A].Find(Target.Value, Cll, , xlWhole)
Loop Until Cll.Row = n
End With
AddCom:
With Target
.AddComment
.Comment.Visible = True
.Comment.Text VL
.Comment.Shape.Height = 25 + 10 * i
End With
End Sub
Theo gợi ý của bác ndu, em làm ra cái này. Bác cho ý kiến nhé:
(đang dùng máy trên trường nên không có Excel 2007 --> làm đại 1 file trên Excel 2003, hình như là có cấu trúc giống file của NH_DK)PHP:Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim Cll As Range, n As Long, VL As String, i As Integer [A:A].ClearComments If Target.Count > 1 Or Intersect(Target, Range([A2], [A10000].End(xlUp))) Is Nothing Then Exit Sub VL = "" With Sheet1 On Error GoTo AddCom Set Cll = .[A:A].Find(Target.Value, .[A1], , xlWhole) n = Cll.Row Do i = i + 1 VL = VL & Chr(10) & Cll.Offset(, 1) & " | " & Cll.Offset(, 2) Set Cll = .[A:A].Find(Target.Value, Cll, , xlWhole) Loop Until Cll.Row = n End With AddCom: With Target .AddComment .Comment.Visible = True .Comment.Text VL .Comment.Shape.Height = 25 + 10 * i End With End Sub
Theo góp ý của anh tintam7251 (sử dụng FindNext), mình sửa lại code như vầy, Ngọc xem đúng ý chưa nhé:Anh ơi, thế này thì đúng ý em rùi. Cho em hỏi thêm nhé: Em muốn phần trên cùng của comment nó hiện thêm Mã vật liệu - Tên vật liệu (có thể hiện luôn thông tin ở ô tiêu đề)?
Cám ơn anh nhiều!
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim Cll As Range, n As Long, VL As String, i As Integer
[A:A].ClearComments
If Target.Count > 1 Or Intersect(Target, Range([A2], [A10000].End(xlUp))) Is Nothing Then Exit Sub
With Sheet1
VL = .[B1] & " | " & .[C1] 'Tiêu đề của Comment: Mã vật liệu - Tên vật liệu'
On Error GoTo AddCom
Set Cll = .[A:A].Find(Target.Value, .[A1], , xlWhole)
n = Cll.Row
Do
i = i + 1
VL = VL & Chr(10) & Cll.Offset(, 1) & " | " & Cll.Offset(, 2)
Set Cll = .[A:A].FindNext(Cll)
Loop Until Cll.Row = n
End With
AddCom:
With Target
.AddComment
.Comment.Visible = True
.Comment.Text VL
.Comment.Shape.TextFrame.AutoSize = True 'Tự động chỉnh kích thước Comment tùy thuộc nội dung'
End With
End Sub
Theo góp ý của anh tintam7251 (sử dụng FindNext), mình sửa lại code như vầy, Ngọc xem đúng ý chưa nhé:
PHP:Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim Cll As Range, n As Long, VL As String, i As Integer [A:A].ClearComments If Target.Count > 1 Or Intersect(Target, Range([A2], [A10000].End(xlUp))) Is Nothing Then Exit Sub With Sheet1 VL = .[B1] & " | " & .[C1] 'Tiêu đề của Comment: Mã vật liệu - Tên vật liệu' On Error GoTo AddCom Set Cll = .[A:A].Find(Target.Value, .[A1], , xlWhole) n = Cll.Row Do i = i + 1 VL = VL & Chr(10) & Cll.Offset(, 1) & " | " & Cll.Offset(, 2) Set Cll = .[A:A].FindNext(Cll) Loop Until Cll.Row = n End With AddCom: With Target .AddComment .Comment.Visible = True .Comment.Text VL .Comment.Shape.TextFrame.AutoSize = True 'Tự động chỉnh kích thước Comment tùy thuộc nội dung' End With End Sub
Mình nghĩ đến việc thay Comment bởi 1 Listbox hay 1 Listview động. Mỗi lần chọn trong vùng chỉ định thì khởi tạo Listbox/Listview (nạp dữ liệu thỏa mãn), sau đó cho hiện lên tại ô chọn (sử dụng các thuộc tính Top, Left, Visible). Ngược lại thì ẩn Listbox/Listview. Tuy nhiên, với Listbox thì có lẽ cũng không cải thiện được về mặt thẩm mỹ, còn Listview thì thú thật là mình hoàn toàn mù tịt, chưa dùng bao giờ, hình như Listview không hiển thị được tiếng Việt Unicode mà phải chuyển mã sang TCVN-3.Như vậy thì Ok rùi anh ah. Nhưng cho em hởi thêm chút xíu nữa ha: Em muốn thông tin của từng cột hiện đúng cột của nó? Vì thực tế còn có những mã, tên, ... nếu cứ để như thế này thì sẽ nhìn rất xấu ah?
Tôi có chiêu này (không dùng listbox hay listview) dùng CopyPicture, xem thử thế nào nhaMình nghĩ đến việc thay Comment bởi 1 Listbox hay 1 Listview động. Mỗi lần chọn trong vùng chỉ định thì khởi tạo Listbox/Listview (nạp dữ liệu thỏa mãn), sau đó cho hiện lên tại ô chọn (sử dụng các thuộc tính Top, Left, Visible). Ngược lại thì ẩn Listbox/Listview. Tuy nhiên, với Listbox thì có lẽ cũng không cải thiện được về mặt thẩm mỹ, còn Listview thì thú thật là mình hoàn toàn mù tịt, chưa dùng bao giờ, hình như Listview không hiển thị được tiếng Việt Unicode mà phải chuyển mã sang TCVN-3.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim sArray, Arr
On Error Resume Next
Target.Parent.Pictures.Delete
If Target.Column = 1 And Target.Count = 1 And Target.Value <> "" Then
With Sheet1
.Range("L:N").ClearContents
sArray = .Range(.[A1], .[A65536].End(xlUp)).Resize(, 3)
Arr = Filter2DArray(sArray, 1, Target(1, 1).Value, True)
.Range("L1").Resize(UBound(Arr, 1), 3) = Arr
.Range("L1").CurrentRegion.CopyPicture
Target.Parent.Paste Target.Offset(, 1)
End With
Target.Select
Application.ScreenUpdating = True
End If
End Sub
Chú ý chổ màu đỏ này:Thế này OK lắm sư phụ ah! Giờ em muốn thêm 2 cột nữa trong phần sheet Data (cột số lượng và cột ghi chú). Tất nhiên 2 cột này cũng có mặt trong phần xem rùi (sheet info). Sư phụ sửa thêm phần code dùm em nhé! Em vẫn chưa sửa được ah!
Cám ơn sư phụ nhiều!
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim sArray, Arr
On Error Resume Next
Target.Parent.Pictures.Delete
If Target.Column = 1 And Target.Row > 1 And Target.Count = 1 And Target.Value <> "" Then
With Sheet1
.[COLOR=#ff0000][B]Range("L:N")[/B][/COLOR].ClearContents
sArray = .Range(.[A1], .[A65536].End(xlUp)).Resize(, [COLOR=#ff0000][B]3[/B][/COLOR])
Arr = Filter2DArray(sArray, 1, Target(1, 1).Value, True)
.Range("L1").Resize(UBound(Arr, 1), [COLOR=#ff0000][B]3[/B][/COLOR]) = Arr
.Range("L1").CurrentRegion.CopyPicture
Target.Parent.Paste Target.Offset(, 1)
End With
Target.Select
Application.ScreenUpdating = True
End If
End Sub
Chú ý chổ màu đỏ này:
Sửa số 3 thành số 5 thì ra 5 cột thôiMã:Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim sArray, Arr On Error Resume Next Target.Parent.Pictures.Delete If Target.Column = 1 And Target.Row > 1 And Target.Count = 1 And Target.Value <> "" Then With Sheet1 .[COLOR=#ff0000][B]Range("L:N")[/B][/COLOR].ClearContents sArray = .Range(.[A1], .[A65536].End(xlUp)).Resize(, [COLOR=#ff0000][B]3[/B][/COLOR]) Arr = Filter2DArray(sArray, 1, Target(1, 1).Value, True) .Range("L1").Resize(UBound(Arr, 1), [COLOR=#ff0000][B]3[/B][/COLOR]) = Arr .Range("L1").CurrentRegion.CopyPicture Target.Parent.Paste Target.Offset(, 1) End With Target.Select Application.ScreenUpdating = True End If End Sub
Range("L:N") sửa thành Range("L")
Đương nhiên bạn phải trang trí lại vùng tạm (bên sheet Data) cho kết quả ở Info được đẹp hơn
Sửa lại code như vầy là OK:Em không muốn hiện cột mã sản phẩm? Em tìm mãi mà sửa không được. Phiền sư phụ chỉ dùm em thêm chút nữa nha!
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim sArray, Arr
On Error Resume Next
Target.Parent.Pictures.Delete
[COLOR=#ff0000]If Target.Count > 1 Or Intersect(Target, [A:A], UsedRange) Is Nothing Then Exit Sub
If Target.Row > 1 And Target.Value <> "" Then
[/COLOR] With Sheet1
.Range("L:[COLOR=#ff0000]P[/COLOR]").ClearContents
sArray = .Range(.[A1], .[A65536].End(xlUp)).Resize(, [COLOR=#ff0000]5[/COLOR])
Arr = Filter2DArray(sArray, 1, Target(1, 1).Value, True)
.Range("L1").Resize(UBound(Arr, 1), [COLOR=#ff0000]5[/COLOR]) = Arr
[COLOR=#ff0000].Range(.[M1], .[M65536].End(xlUp)).Resize(, 4)[/COLOR].CopyPicture
Target.Parent.Paste Target.Offset(, 1)
End With
Target.Select
Application.ScreenUpdating = True
End If
End Sub
[COLOR=#ff0000]On Error Resume Next[/COLOR]
If Target.Column = 1 And Target.Row > 1 And Target.Count = 1 And [COLOR=#ff0000]Target.Value <> ""[/COLOR] Then
If Target.Column = 1 And Target.Row > 1 And Target.Count = 1 And Target.Value <> "" Then
If Target.Count > 1 Or Intersect(Target, [A:A], UsedRange) Is Nothing Then Exit Sub
If Target.Row > 1 And Target.Value <> "" Then
Trời đất ơi, cái này quá đơn giản mà bạn!Em không muốn hiện cột mã sản phẩm? Em tìm mãi mà sửa không được. Phiền sư phụ chỉ dùm em thêm chút nữa nha!
.Range("L1").CurrentRegion.Resize(, 4).Offset(, 1).CopyPicture
With .Range("L1").CurrentRegion
Intersect(.Cells, .Offset(, 1)).CopyPicture
End With
Quả thật có sơ sót trong quá trình suy luận logic... Tuy nhiên khi viết code tôi ít khi thích Exit Sub (dù cũng có xài), nên tôi sẽ sửa thế này:@ndu: Trong code của bác, có 2 câu này:
Do đó, nếu em chọn một vùng bất kỳ trên sheet Info, chỉ cần Target.Count > 1 thì toàn bộ biểu thức logic này sẽ bị lỗi (vì không xác định được Target.Value) và nó sẽ nhảy qua câu lệnh kế tiếp --> kết quả hổng đẹp.Mã:[COLOR=#ff0000]On Error Resume Next[/COLOR] If Target.Column = 1 And Target.Row > 1 And Target.Count = 1 And [COLOR=#ff0000]Target.Value <> ""[/COLOR] Then
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim sArray, Arr
On Error Resume Next
Target.Parent.Pictures.Delete
If Target.Count = 1 Then
If Target.Column = 1 And Target.Row > 1 And Target.Value <> "" Then
With Sheet1
.Range("L1").CurrentRegion.ClearContents
sArray = .Range(.[A1], .[A65536].End(xlUp)).Resize(, [COLOR=#0000cd][B]5[/B][/COLOR])
Arr = Filter2DArray(sArray, 1, Target(1, 1).Value, True)
[COLOR=#ff0000][B]If TypeName(Arr) = "Variant()" Then[/B][/COLOR]
.Range("L1").Resize(UBound(Arr, 1), UBound(Arr, 2)) = Arr
With .Range("L1").CurrentRegion
Intersect(.Cells, .Offset(, 1)).CopyPicture
End With
Target.Parent.Paste Target.Offset(, 1)
End If
End With
Target.Select
Application.ScreenUpdating = True
End If
End If
End Sub