Xin mã VBA như hàm Vloopkup nhưng lấy được cả formats , comments của ô được tìm kiếm

Liên hệ QC

kienphamiuh

Thành viên chính thức
Tham gia
8/12/18
Bài viết
66
Được thích
11
-em có 1 vấn đề nhờ các anh chị trong group giúp ạ
-em có 1 File excel ( sheep 1 là "thông tin", sheep 2 là "file tổng")
+ em sử dụng làm Vlookup để lấy thông tin từ "file tổng" chuyển qua file " thông tin" dựa vào Mã HV
+ Vấn đề em gặp là Vlookup chỉ lấy được giá trị mà không lấy đc: màu sắc của ô ( ô được tô màu vàng ), comment, màu sắc của chữ ( chữ màu đỏ ).
- em mong anh chị giúp tạo 1 hàm Xlookup có chức năng như Vlookup nhưng lấy được giá trị và cả (màu sắc của ô,comment, màu sắc của chữ ) , còn nếu không thể làm 1 hàm như Xlookup anh chị giúp em viết code lấy giá trị và màu sắc của ô,comment, màu sắc của chữ dựa vào mã HV trong file " thông tin" ạ
vd: =Xlookup ( X, Y ,Z ,0 or 1)
X là Giá trị dùng để dò tìm
Y là Bảng giá trị dò
Z là Thứ tự của cột cần lấy dữ liệu trên bảng giá trị dò
0 là giá trị tuyệt đối
X Y Z là các giá trị mình nhập ( linh động như ham vlookup ), mong các anh chị giúp, em cảm ơn nhiều " trong code có giải thích code thì càng tốt ạ "

em có viết 1 đoan VBA như sau :
Function Xlookup(cn As String)
Xlookup = Sheet2.Range("a:a").Find(cn).Offset(, 1).Value
End Function
nhưng nhựơc điểm là không linh động cột cần lấy, mỗi lần lấy phải vào code sửa offset và không lấy được màu sắc của ô,comment, màu sắc của chữ ( còn thua xài vlookup nữa anh chị ạ :(( )
 

File đính kèm

  • file.xlsx
    12.5 KB · Đọc: 18
Híc , nhờ bạn xem giúp ạ!

OT vốn chậm hiểu và tính lại hay quên nếu không phiền nhờ bạn giải thích thêm code ở bài 56
Lúc đặt biến tôi quên đặt Data-Type. Byref cần khai báo Data Type khớp nhau . OT tự đặt nhé . A$ = A As String thì AVeDay As String
OT viết code, lại cần giải thích, hơi khó hiểu...
 
Upvote 0
Lúc đặt biến tôi quên đặt Data-Type. Byref cần khai báo Data Type khớp nhau . OT tự đặt nhé . A$ = A As String thì AVeDay As String
OT viết code, lại cần giải thích, hơi khó hiểu...
Dạ, OT sẽ tìm hiểu thêm theo những gợi ý của bạn ạ.
cảm ơn bạn nhiều.
 
Upvote 0
Theo OT hiểu,khai báo biến kiểu ByVal có nghĩa là các thay đổi của biến này chỉ có giá trị sử dụng trong riêng trong sub,kết thúc thủ tục biến sẽ trả về giá trị ban đầu.Khai báo biến kiểu ByRef thì khi kết thúc sub, nếu giá trị của biến bị thay đổi thì biến sẽ nhận giá trị mới này.
Về kiểu truyền tham số ByVal - truyền giá trị và ByRef - truyền reference thì bạn hiểu đúng. Còn ai hỏi sao trong procedure bạn dùng Byval thì bạn trả lời là do bạn không có nhu cầu dùng ByRef, thế thôi. Còn tại sao bạn lại dùng ByRef thì cũng trả lời là do tôi có nhu cầu như thế. Tôi muốn giá trị của biến được thay đổi trong procedure, và tôi sẽ dùng biến đó tiếp theo. Đại loại là thế. Tôi dùng cái này vì có nhu cầu, không dùng cái kia vì không có nhu cầu. Thế thôi.
 
Lần chỉnh sửa cuối:
Upvote 0
@Nguyễn Hoàng Oanh Thơ
Khai báo Byval là bắt buộc. Khi biến từ hàm gọi - bắt buộc không đổi khi truyền vào đối số của một hàm khác.
Byval và Byref rất quan trọng. Nếu trong một hàm gọi truyền biến vào rất nhiều nhiều nhiều hàm khác mà người viết code không chú trọng. Thì sẽ không biết vì sao kết quả không đúng. Vì nếu không đặt là Byval thì mặc định sẽ là Byref. Byref sẽ trả về biến có thay đổi giá trị của nó.

Khai báo Byref đơn giản là:
Hàm gọi có x = 0. Truyền x vào đối số là Byref hàm khác, trong hàm khác này cho giá trị biến nhận x tăng lên
Thì hàm đang gọi có x sẽ tăng.

Thường khi viết một hai hàm thì không thấy vấn đề. Chứ nhiều thì sẽ có vấn đề lớn nếu không chú trọng Byval và Byref
 
Lần chỉnh sửa cuối:
Upvote 0
Những điều bạn nói tới ở bài #58 nằm trong kỹ thuật quản lý mô đun code của lập trình.

Từ khóa Private giới hạn visibility (khả năng được người khác thấy, cho phép người khác thấy) của một Sub/Module/Biến/hay Type (tức là những gì khai báo) trong vòng một mô đun.

Trên nguyên tắc, code chỉ có thể sử dụng cái mà nó "thấy", tức là không bị che đi. Đối với code, các vật mà nó thấy là visible.

Đối với code bên trong một mô đun thì những cái mà nó "thấy" được gồm:
1. trong cùng mô đun:
- các biến và type được khai báo trong mô đun theo tầm vực toàn cuc (global), bất kể private hay public
- các sub và function khai báo trong mô đun, bất kể private hay public
2. ngoài mô đun (khai báo trong mô đun khác)
- các biến và type được khai báo theo tầm vực toàn cuc (global), và public
- các sub và function khai báo public
3. những đối tượng được Referenced (tạm gác cái này)

Những cái mà nó không thấy được bao gồm:
- các biến được khai báo bên trong Sub hoặc Function khác, bất kể cùng mô đun hay khác mô đun
- các biến được khai báo trong mô đun khác, và với từ khóa Private

Và một điều rất quan trọng, tuy rất ít khi xảy ra là trường hợp bị che khuất bởi cái khác trùng tên.
Nếu hai mô đun có hai sub/fucntion/biến public và toàn cục trùng tên nhau thì mạnh thằng nào xài của thằng nấy.

ByVal / ByRef
Trong kỹ thuật quản lý code thì từ khóa byVal dùng để Sub/Function "hứa" với code gọi nó là "tôi chỉ copy trị ấy về xài, chứ cái bạn đưa vào luôn còn đó"
Ví dụ, bạn đưa cho tôi một cái Sub dài vài trăm dòng, nếu không thấy từ khóa ByVal thì tôi phải cẩn thận rằng cái biến mà tôi nạp vào làm tham có thể bị thay đổi. Nếu thấy từ khóa ByVal thì tôi yên tâm.
Mặt khác, ByRef thường dùng để lấy kết quả trả về của Sub/Hàm (lưu ý từ thường không có nghĩa là luôn luôn)

Điển hình của việc này là bài toán giải phương trình bậc 2:
Function NghiemPTBac2(byVal a, byVal b, byVal c, byRef x1, byRef x2) ' tạm không nói đến kiểu cho gọn
Nhìn vào cái khai báo này, tôi biết ngay là tôi có thể nạp 3 tham đầu thoải mái mà không sợ bị mất. Hai tham kế đó tôi đoán được là kết quả trả về (chỉ đoán thôi, người viết code chân chính luôn luôn có dòng chú thích diễn giải mục đích và giới hạn các tham)
 
Lần chỉnh sửa cuối:
Upvote 0
Về kiểu truyền tham số ByVal - truyền giá trị và ByRef - truyền reference thì bạn hiểu đúng. Còn ai hỏi sao trong procedure bạn dùng Byval thì bạn trả lời là do bạn không có nhu cầu dùng ByRef, thế thôi. Còn tại sao bạn lại dùng ByRef thì cũng trả lời là do tôi có nhu cầu như thế. Tôi muốn giá trị của biến được thay đổi trong procedure, và tôi sẽ dùng biến đó tiếp theo. Đại loại là thế. Tôi dùng cái này vì có nhu cầu, không dùng cái kia vì không có nhu cầu. Thế thôi.

Những điều bạn nói tới ở bài #58 nằm trong kỹ thuật quản lý mô đun code của lập trình.

Từ khóa Private giới hạn visibility (khả năng được người khác thấy, cho phép người khác thấy) của một Sub/Module/Biến/hay Type (tức là những gì khai báo) trong vòng một mô đun.

Trên nguyên tắc, code chỉ có thể sử dụng cái mà nó "thấy", tức là không bị che đi. Đối với code, các vật mà nó thấy là visible.

Đối với code bên trong một mô đun thì những cái mà nó "thấy" được gồm:
1. trong cùng mô đun:
- các biến và type được khai báo trong mô đun theo tầm vực toàn cuc (global), bất kể private hay public
- các sub và function khai báo trong mô đun, bất kể private hay public
2. ngoài mô đun (khai báo trong mô đun khác)
- các biến và type được khai báo theo tầm vực toàn cuc (global), và public
- các sub và function khai báo public
3. những đối tượng được Referenced (tạm gác cái này)

Những cái mà nó không thấy được bao gồm:
- các biến được khai báo bên trong Sub hoặc Function khác, bất kể cùng mô đun hay khác mô đun
- các biến được khai báo trong mô đun khác, và với từ khóa Private

Và một điều rất quan trọng, tuy rất ít khi xảy ra là trường hợp bị che khuất bởi cái khác trùng tên.
Nếu hai mô đun có hai sub/fucntion/biến public và toàn cục trùng tên nhau thì mạnh thằng nào xài của thằng nấy.

ByVal / ByRef
Trong kỹ thuật quản lý code thì từ khóa byVal dùng để Sub/Function "hứa" với code gọi nó là "tôi chỉ copy trị ấy về xài, chứ cái bạn đưa vào luôn còn đó"
Ví dụ, bạn đưa cho tôi một cái Sub dài vài trăm dòng, nếu không thấy từ khóa ByVal thì tôi phải cẩn thận rằng cái biến mà tôi nạp vào làm tham có thể bị thay đổi. Nếu thấy từ khóa ByVal thì tôi yên tâm.
Mặt khác, ByRef thường dùng để lấy kết quả trả về của Sub/Hàm (lưu ý từ thường không có nghĩa là luôn luôn)

Điển hình của việc này là bài toán giải phương trình bậc 2:
Function NghiemPTBac2(byVal a, byVal b, byVal c, byRef x1, byRef x2) ' tạm không nói đến kiểu cho gọn
Nhìn vào cái khai báo này, tôi biết ngay là tôi có thể nạp 3 tham đầu thoải mái mà không sợ bị mất. Hai tham kế đó tôi đoán được là kết quả trả về (chỉ đoán thôi, người viết code chân chính luôn luôn có dòng chú thích diễn giải mục đích và giới hạn các tham)

Dạ,con cảm ơn hai Bác Siwtom & VetMini nhiều ạ.
Chúc hai Bác nhiều sức khỏe.
 
Upvote 0
Upvote 0
Mười ông Thầy có chừng một ông đủ trình độ lý thuyết quản lý mô đun thôi.
Mà dạy cũng chẳng mấy học sinh muốn học.

@Cô Oanh Thơ: ở bài trên, bài #65, trong đoạn giữa tôi có nhắc kỹ "Và một điều rất quan trọng, tuy rất ít khi xảy ra..." không phải là không có lý do.
Nhưng không thấy bạn hay ai hỏi tới - thất vọng.
 
Upvote 0
Mười ông Thầy có chừng một ông đủ trình độ lý thuyết quản lý mô đun thôi.
Mà dạy cũng chẳng mấy học sinh muốn học.

@Cô Oanh Thơ: ở bài trên, bài #65, trong đoạn giữa tôi có nhắc kỹ "Và một điều rất quan trọng, tuy rất ít khi xảy ra..." không phải là không có lý do.
Nhưng không thấy bạn hay ai hỏi tới - thất vọng.

Híc Bác VetMini ơi, suốt từ đêm qua đến chiều con mới ngồi máy ạ.
Con cảm ơn Bác,chắc chắn con sẽ đọc lại nhiều lần bài này nữa ạ.
 
Upvote 0
Híc mình xin lỗi, còn thiếu, bạn sửa tiếp:
Mã:
csdl = .Range("B4:J" & lastRow).Value
thành:
Mã:
csdl = .Range("B4:L" & lastRow).Value
Sửa:
Mã:
If Not format Then shDest.Range("J12").Resize(UBound(result), 6).Value = result
Thành:
Mã:
If Not format Then shDest.Range("J12").Resize(UBound(result), 4).Value = result

Mã:
Private Sub sGPE(Optional ByVal format As Boolean = False)
Dim lastRow As Long, r1 As Long, r2 As Long, shSrc As Worksheet, shDest As Worksheet, csdl(), data(), result(), text As String
    Set shDest = Worksheets("FILE GUI")
    With shDest
'        xoa ket qua cu
        lastRow = .Cells(Rows.Count, "J").End(xlUp).Row
        If lastRow >= 12 Then
            With .Range("J12:K" & lastRow)
                .Clear
                .Borders.LineStyle = xlContinuous
            End With
        End If
        lastRow = .Cells(Rows.Count, "B").End(xlUp).Row
'        neu khong co du lieu thi ket thuc cuoc choi, nguoc lai lay vao mang data
        If lastRow < 12 Then Exit Sub
        data = .Range("B12:B" & lastRow + 1).Value
'        mang ket qua
        If Not format Then ReDim result(1 To UBound(data) - 1, 1 To 4)
    End With
    Set shSrc = Worksheets("DANH SACH TONG")
    With shSrc
        lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
'        neu khong co du lieu thi ket thuc cuoc choi, nguoc lai lay vao mang csdl
        If lastRow < 4 Then Exit Sub
        csdl = .Range("A4:L" & lastRow).Value
    End With
    For r1 = 1 To UBound(data) - 1
        text = data(r1, 1)
        For r2 = 1 To UBound(csdl)
            If csdl(r2, 1) = text Then
                If format Then
                    shSrc.Cells(3 + r2, "I").Resize(, 4).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 9)
                    result(r1, 2) = csdl(r2, 10)
                    result(r1, 3) = csdl(r2, 11)
                    result(r1, 4) = csdl(r2, 12)
                End If
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then shDest.Range("J12").Resize(UBound(result), 4).Value = result
End Sub

Sub test()
'    chi lay gia tri
     sGPE
'    lay gia tri va format
'    sGPE True
End Sub
Thanks Ms. Oanh Thơ.

Mình làm thành công rồi!
 
Upvote 0
Web KT
Back
Top Bottom