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

Liên hệ QC

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

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

Nếu là Hàm UDF trong VBA thì không thể áp dụng thay đổi màu sắc, định dạng format của cell
 
Upvote 0
-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ị ạ :(( )

Code ở bài này, bạn chưa dùng được ạ:
https://www.giaiphapexcel.com/diendan/threads/chuyên-đề-giải-đáp-những-thắc-mắc-về-code-vba.83698/page-86#post-895669
----------------
Oanh Thơ (OT) góp ý thêm: bạn đừng viết tắt nhé và đừng nửa tiếng Anh nửa tiếng Việt nhé, đại loại như:

Gửi lại bạn tập tin lần trước
 

File đính kèm

Upvote 0
Code ở bài này, bạn chưa dùng được ạ:
https://www.giaiphapexcel.com/diendan/threads/chuyên-đề-giải-đáp-những-thắc-mắc-về-code-vba.83698/page-86#post-895669
----------------
Oanh Thơ (OT) góp ý thêm: bạn đừng viết tắt nhé và đừng nửa tiếng Anh nửa tiếng Việt nhé, đại loại như:


Gửi lại bạn tập tin lần trước
mình sẽ rút kinh nghiệm, giờ mình muốn sửa lại Sheep khác , cột khác thì phải sửa khúc nào trong code bạn :)
 
Upvote 0
Code ở bài này, bạn chưa dùng được ạ:
https://www.giaiphapexcel.com/diendan/threads/chuyên-đề-giải-đáp-những-thắc-mắc-về-code-vba.83698/page-86#post-895669
----------------
Oanh Thơ (OT) góp ý thêm: bạn đừng viết tắt nhé và đừng nửa tiếng Anh nửa tiếng Việt nhé, đại loại như:


Gửi lại bạn tập tin lần trước
Đạt chuẩn rồi đó.
Tiếp tục với "Sheep" đi. Khi bạn không còn "thấy" gì thì bạn sẽ không còn "sợ" gì.
 
Upvote 0
Trong Microsoft Excel lại có vụ vặt lông cừu sao?

Vấn đề của chủ thớt không phải là hàm u dờ ép nào cả, vấn đề ở chỗ thiết kế cấu trúc dữ liệu và cách ghi nhận dữ liệu.

Thay vì mỏi tay tô màu lòe loẹt, chèn ghi chú loằng nhoằng thì chèn thêm 3 cái cột nữa. Vậy có ngon lành như thịt cừu không?

[cột màu nền ô này] [cột ghi chú này] [cột màu chữ này]

Rồi vlookup() thì được xơi thịt cừu nướng.

---
Trường hợp dữ liệu đã có cần xử lý thì xử lý những thứ đó ghi ra 3 cột là giải quyết xong.
 
Upvote 0
Trong Microsoft Excel lại có vụ vặt lông cừu sao?

Vấn đề của chủ thớt không phải là hàm u dờ ép nào cả, vấn đề ở chỗ thiết kế cấu trúc dữ liệu và cách ghi nhận dữ liệu.

Thay vì mỏi tay tô màu lòe loẹt, chèn ghi chú loằng nhoằng thì chèn thêm 3 cái cột nữa. Vậy có ngon lành như thịt cừu không?

[cột màu nền ô này] [cột ghi chú này] [cột màu chữ này]

Rồi vlookup() thì được xơi thịt cừu nướng.

---
Trường hợp dữ liệu đã có cần xử lý thì xử lý những thứ đó ghi ra 3 cột là giải quyết xong.
em cũng muốn làm như vậy cho dễ bác ạ nhưng khổ cái file chính của em nó đã nhiều cột lắm rồi :(
 
Upvote 0
Excel (từ phiên bản 2007) có mười sáu ngàn ba trăm tám mươi bốn cột!
dạ ý em là file nhiều cột nhìn rối mắt ạ, anh có thể chỉ em cách thay thế cột khác và sheet khác trong code được không anh
Theo kiến thức cùi bắp của em mới đc học là

Sub FindAndCopyPase()
Dim lastRow As Long, i As Long, varKey As Variant
Dim c As Range, shtData As Worksheet, shtKQ As Worksheet
Set shtData = ThisWorkbook.Worksheets("Sheet2") //qui định shtdata là sheet2
Set shtKQ = ThisWorkbook.Worksheets("Sheet1") //qui định shtKQ là sheet1
With shtKQ
lastRow = .Range("A" & .Rows.Count).End(xlUp).Row // tìm dòng cuối
varKey = .Range("A2:A" & lastRow) // vị trí ô bắt đầu được copy thì phải
End With
With shtData // còn phần này em bó tay :)
For i = LBound(varKey) To UBound(varKey)
Set c = .Columns("A").Find(What:=varKey(i, 1), _
After:=.Range("A1"), LookIn:=xlValues, _
LookAt:=xlWhole, SearchDirection:=xlNext)
If c Is Nothing Then
shtKQ.Cells(i + 1, 2).Value = "#N/A"
Else
c.Resize(1, 2).Offset(0, 1).Copy Destination:=shtKQ.Cells(i + 1, 2)
End If
Next i
End With
End Sub
 
Upvote 0
mình sẽ rút kinh nghiệm, giờ mình muốn sửa lại Sheep khác , cột khác thì phải sửa khúc nào trong code bạn :)
Xin chào kienphamiuh,
Bạn điều chỉnh các tên sheet và tên cột trong Sub Chay_FindAndCopyPase nhé, những chỗ còn lại khoan vội để ý:
Mã:
Option Explicit
'Call FindAndCopyPase(ThamSo1, ThamSo2, ThamSo3, ThamSo4)
                    'ThamSo1:   Sheet 1
                    'ThamSo2:   Cot Chua tu khoa tim kiem trong sheet1
                    'ThamSo3:   Sheet 2
                    'ThamSo4:   Cot Chua tu khoa tim kiem trong sheet2

Sub Chay_FindAndCopyPase()
    Call FindAndCopyPase("Sheet1", "A", "Sheet2", "A")
End Sub

Sub FindAndCopyPase(shtKQ As String, colKeyKQ As String, shtData As String, colKeyData As String)

    Dim lastRow As Long, i As Long, varKey As Variant, c As Range
    Const dongdau As Integer = 2
    With Sheets(shtKQ)
        lastRow = .Range(colKeyKQ & .Rows.Count).End(xlUp).Row
        varKey = .Range(colKeyKQ & dongdau & ":" & colKeyKQ & lastRow)
    End With
    With Sheets(shtData)
        For i = LBound(varKey) To UBound(varKey)
            Set c = .Columns(colKeyData).Find(What:=varKey(i, 1), _
                After:=.Range(colKeyData & 1), LookIn:=xlValues, _
                LookAt:=xlWhole, SearchDirection:=xlNext)
            If c Is Nothing Then
                Sheets(shtKQ).Cells(i + 1, 2).Value = "#N/A"
            Else
                c.Resize(1, 2).Offset(0, 1).Copy Destination:=Sheets(shtKQ).Cells(i + 1, 2)
            End If
        Next i
    End With
End Sub
 
Upvote 0
Bạn nhận xét rất đúng file ở bài #1.

Những gì là code, là công thức thì cho vào cái chỗ chuyên chứa nó.

View attachment 209072
anh giải thích giúp em đoạn code bạn Oanh viết được không ạ
Mã:
With shtData
For i = LBound(varKey) To UBound(varKey)
Set c = .Columns("A").Find(What:=varKey(i, 1), _
After:=.Range("A1"), LookIn:=xlValues, _
LookAt:=xlWhole, SearchDirection:=xlNext)
If c Is Nothing Then
shtKQ.Cells(i + 1, 2).Value = "#N/A"
Else
c.Resize(1, 2).Offset(0, 1).Copy Destination:=shtKQ.Cells(i + 1, 2)
End If
Next i
End With
End Sub
 
Upvote 0
Đạt chuẩn rồi đó.
Tiếp tục với "Sheep" đi. Khi bạn không còn "thấy" gì thì bạn sẽ không còn "sợ" gì.

Xin chào thầy ạ :D
Bài đã được tự động gộp:

anh giải thích giúp em đoạn code bạn Oanh viết được không ạ
Mã:
With shtData
For i = LBound(varKey) To UBound(varKey)
Set c = .Columns("A").Find(What:=varKey(i, 1), _
After:=.Range("A1"), LookIn:=xlValues, _
LookAt:=xlWhole, SearchDirection:=xlNext)
If c Is Nothing Then
shtKQ.Cells(i + 1, 2).Value = "#N/A"
Else
c.Resize(1, 2).Offset(0, 1).Copy Destination:=shtKQ.Cells(i + 1, 2)
End If
Next i
End With
End Sub

Oanh Thơ mới học code nên giải thích có thể bạn và những người khác chưa hiểu code này sẽ không hiểu. híc:
Mã:
With shtData 'là "Sheet2"
For i = LBound(varKey) To UBound(varKey) ' bắt đầu từ dòng 2 đến dòng cuối trong cột A

Set c = .Columns("A").Find(What:=varKey(i, 1), _
After:=.Range("A1"), LookIn:=xlValues, _
LookAt:=xlWhole, SearchDirection:=xlNext) ' gán cho biến c một ô tìm kiếm được trong cột A của sheet2
If c Is Nothing Then ' nếu không tìm thấy C
shtKQ.Cells(i + 1, 2).Value = "#N/A" ' trả về "#N/A" giống như vlookup không tìm thấy từ khóa trong bảng tìm kiếm
Else ' nếu tìm thấy
c.Resize(1, 2).Offset(0, 1).Copy Destination:=shtKQ.Cells(i + 1, 2)  ' từ ô tìm kiếm được quét sang phải 1 cột,và nhảy thêm 1 cột nữa rồi copy vùng này sau đó đặt con trỏ tại dòng i cột 2 rồi pase.
End If
Next i
End With
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Si tình thôi chứ ghê gớm gì.
tim khắc sâu ảnh em.
Chả thấy lôgíc gì cả. Vào GPE hỏi bài mà tự dưng "tim khắc sâu ảnh em" là thế nào bác? :D

Chắc đang yêu mê mệt nên buột miệng chăng?

Tôi cho là "Tớ không sành ăn ếch GPE". Đại loại là: "Tớ còn gà món ếch xào của GPE lắm, các ấy thông cảm cho nhé".
 
Upvote 0
Xin góp ý với chủ bài đăng 1 ý về mã HV (Học viên?) của bạn, như sau:
Mã HV của cả danh sách nên có độ dài bằng nhau; (Nhất là trong Excel tài lanh trong chuyện kí tự đại diện)
Ví dụ, ta nên bắt đầu mã HV từ 9999 cho HV đầu tiên trong danh sách
Chuyện bạn muốn trong bài đúng là không thể xài VLOOPKUP() hay udfVLOOKUP() nào được.
Họa chăng chỉ có thể là macro, nhưng chắc mệt lắm & xin báo trước là mình không thể đâu nha!
 
Upvote 0
Xin góp ý với chủ bài đăng 1 ý về mã HV (Học viên?) của bạn, như sau:
Mã HV của cả danh sách nên có độ dài bằng nhau; (Nhất là trong Excel tài lanh trong chuyện kí tự đại diện)
Ví dụ, ta nên bắt đầu mã HV từ 9999 cho HV đầu tiên trong danh sách
Chuyện bạn muốn trong bài đúng là không thể xài VLOOPKUP() hay udfVLOOKUP() nào được.
Họa chăng chỉ có thể là macro, nhưng chắc mệt lắm & xin báo trước là mình không thể đâu nha!
- Cảm ơn anh đã góp ý, nếu mã HV em viết thành ABC/0001 hoặc ABC/1762 có được không anh, vì " mã HV " sẽ nhỏ hơn 9999 .
- Như bài này nếu lúc mình dùng Function để tìm kiếm dựa vào " mã HV " sau đó dùng Sub/macro để lấy định dạng và comment thì có ổn không anh ?
 
Lần chỉnh sửa cuối:
Upvote 0
Xin chào kienphamiuh,
Bạn điều chỉnh các tên sheet và tên cột trong Sub Chay_FindAndCopyPase nhé, những chỗ còn lại khoan vội để ý:
Mã:
Option Explicit
'Call FindAndCopyPase(ThamSo1, ThamSo2, ThamSo3, ThamSo4)
                    'ThamSo1:   Sheet 1
                    'ThamSo2:   Cot Chua tu khoa tim kiem trong sheet1
                    'ThamSo3:   Sheet 2
                    'ThamSo4:   Cot Chua tu khoa tim kiem trong sheet2

Sub Chay_FindAndCopyPase()
    Call FindAndCopyPase("Sheet1", "A", "Sheet2", "A")
End Sub

Sub FindAndCopyPase(shtKQ As String, colKeyKQ As String, shtData As String, colKeyData As String)

    Dim lastRow As Long, i As Long, varKey As Variant, c As Range
    Const dongdau As Integer = 2
    With Sheets(shtKQ)
        lastRow = .Range(colKeyKQ & .Rows.Count).End(xlUp).Row
        varKey = .Range(colKeyKQ & dongdau & ":" & colKeyKQ & lastRow)
    End With
    With Sheets(shtData)
        For i = LBound(varKey) To UBound(varKey)
            Set c = .Columns(colKeyData).Find(What:=varKey(i, 1), _
                After:=.Range(colKeyData & 1), LookIn:=xlValues, _
                LookAt:=xlWhole, SearchDirection:=xlNext)
            If c Is Nothing Then
                Sheets(shtKQ).Cells(i + 1, 2).Value = "#N/A"
            Else
                c.Resize(1, 2).Offset(0, 1).Copy Destination:=Sheets(shtKQ).Cells(i + 1, 2)
            End If
        Next i
    End With
End Sub

- Oanh Thơ hôm nay minh cho code vào file chính nhưng mình sửa code lại nó không chạy được, bạn coi giúp mình file này sửa code lại giúp mình với:
- Mục đích của file là lấy gia trị + màu sách+ comment của 2 cột ( I và J ) số điện thoại từ sheet " DANH SACH TONG " sang file " FILE GUI " cột ( J và K ) dựa vào cột MHV của " FILE GUI " để dò tim bên file " DANH SACH TONG "
- Bạn giải thích code cho mình hiểu với
đây là code mình sửa lại nhưng không chạy đuược
Mã:
Option Explicit
'Call FindAndCopyPase(ThamSo1, ThamSo2, ThamSo3, ThamSo4)
                    'ThamSo1:   Sheet 1
                    'ThamSo2:   Cot Chua tu khoa tim kiem trong sheet1
                    'ThamSo3:   Sheet 2
                    'ThamSo4:   Cot Chua tu khoa tim kiem trong sheet2

Sub Chay_FindAndCopyPase()
    Call FindAndCopyPase("FILE GUI", "B", "DANH SACH TONG", "A")
End Sub

Sub FindAndCopyPase(shtKQ As String, colKeyKQ As String, shtData As String, colKeyData As String)

    Dim lastRow As Long, i As Long, varKey As Variant, c As Range
    Const dongdau As Integer = 12
    With Sheets(shtKQ)
        lastRow = .Range(colKeyKQ & .Rows.Count).End(xlUp).Row
        varKey = .Range(colKeyKQ & dongdau & ":" & colKeyKQ & lastRow)
    End With
    With Sheets(shtData) 'minh khong biet sua phan nay sao cho dung
        For i = LBound(varKey) To UBound(varKey)
            Set c = .Columns(colKeyData).Find(What:=varKey(i, 1), _
                After:=.Range(colKeyData & 1), LookIn:=xlValues, _
                LookAt:=xlWhole, SearchDirection:=xlNext)
            If c Is Nothing Then
                Sheets(shtKQ).Cells(i + 1, 2).Value = "#N/A"
            Else
                c.Resize(1, 2).Offset(0, 1).Copy Destination:=Sheets(shtKQ).Cells(i + 1, 2)
            End If
        Next i
    End With
End Sub
 

File đính kèm

Upvote 0
- Oanh Thơ hôm nay minh cho code vào file chính nhưng mình sửa code lại nó không chạy được, bạn coi giúp mình file này sửa code lại giúp mình với:
- Mục đích của file là lấy gia trị + màu sách+ comment của 2 cột ( I và J ) số điện thoại từ sheet " DANH SACH TONG " sang file " FILE GUI " cột ( J và K ) dựa vào cột MHV của " FILE GUI " để dò tim bên file " DANH SACH TONG "
- Bạn giải thích code cho mình hiểu với
đây là code mình sửa lại nhưng không chạy đuược
Mã:
Option Explicit
'Call FindAndCopyPase(ThamSo1, ThamSo2, ThamSo3, ThamSo4)
                    'ThamSo1:   Sheet 1
                    'ThamSo2:   Cot Chua tu khoa tim kiem trong sheet1
                    'ThamSo3:   Sheet 2
                    'ThamSo4:   Cot Chua tu khoa tim kiem trong sheet2

Sub Chay_FindAndCopyPase()
    Call FindAndCopyPase("FILE GUI", "B", "DANH SACH TONG", "A")
End Sub

Sub FindAndCopyPase(shtKQ As String, colKeyKQ As String, shtData As String, colKeyData As String)

    Dim lastRow As Long, i As Long, varKey As Variant, c As Range
    Const dongdau As Integer = 12
    With Sheets(shtKQ)
        lastRow = .Range(colKeyKQ & .Rows.Count).End(xlUp).Row
        varKey = .Range(colKeyKQ & dongdau & ":" & colKeyKQ & lastRow)
    End With
    With Sheets(shtData) 'minh khong biet sua phan nay sao cho dung
        For i = LBound(varKey) To UBound(varKey)
            Set c = .Columns(colKeyData).Find(What:=varKey(i, 1), _
                After:=.Range(colKeyData & 1), LookIn:=xlValues, _
                LookAt:=xlWhole, SearchDirection:=xlNext)
            If c Is Nothing Then
                Sheets(shtKQ).Cells(i + 1, 2).Value = "#N/A"
            Else
                c.Resize(1, 2).Offset(0, 1).Copy Destination:=Sheets(shtKQ).Cells(i + 1, 2)
            End If
        Next i
    End With
End Sub
Bạn sửa lại tiêu đề bài viết: Bỏ "tks ae GPE"
Sheet "DANH SACH TONG" làm gì có cột MHV?
Nếu cột B cả 2 sheet đều là MHV thì xem file này.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
cảm ơn mọi người trong GPE đã giúp đỡ mình, nhất là bạn Oanh Thơ, mình đã dựa vào code của Oanh Thơ và sửa lại thành công rồi ạ, cảm ơn mọi người rất nhiều !!
Bài đã được tự động gộp:

Bạn sửa lại tiêu đề bài viết: Bỏ "tks ae GPE"
Sheet "DANH SACH TONG" làm gì có cột MHV?
Nếu cột B cả 2 sheet đều là MHV thì xem file này.
cảm ơn anh, code anh viết rất dễ hiểu và ngắn
 
Upvote 0
Cho hỏi nếu tôi có các sheet giống nhau cấu trúc nhưng cột Điểm TL ở các sheet khác nhau. Tôi muốn gộp lại vào sheet tổng hợp thì làm sao?
 

File đính kèm

Upvote 0
Cho hỏi nếu tôi có các sheet giống nhau cấu trúc nhưng cột Điểm TL ở các sheet khác nhau. Tôi muốn gộp lại vào sheet tổng hợp thì làm sao?
- Bạn coi file này ổn không, bạn vào sheet4 bấm vào nút tổng hợp file , thì sẽ có file tổng hợp 3 sheet của bạn, nhưng mỗi lần bạn tổng hợp file thì phải xoá sheet tên "Tong Hop" đi vì nếu để sheet này sẽ bị trùng tên với sheet tổng hợp tiếp theo code sẽ ko chạy.
- Các anh chị coi code này có cần thêm bớt gì không ạ
Mã:
Sub tong_hop_du_lieu()
    Dim shAll As Worksheet
    Dim sh As Worksheet
    Dim count As Integer
    Dim lastrow As Long
    
    Set shAll = Worksheets.Add
    shAll.Name = "Tong Hop"
    
    For Each sh In Worksheets
        If sh.Name <> shAll.Name Then
            count = count + 1
            If count = 1 Then
                sh.Range("A1:N" & sh.Range("A" & Rows.count).End(xlUp).Row).Copy _
                shAll.Range("A1")
            Else
                sh.Range("A2:N" & sh.Range("A" & Rows.count).End(xlUp).Row).Copy _
                shAll.Range("A" & lastrow + 1)
            End If
            lastrow = shAll.Range("A" & Rows.count).End(xlUp).Row
        End If
    Next sh
End Sub
 

File đính kèm

Upvote 0
- Bạn coi file này ổn không, bạn vào sheet4 bấm vào nút tổng hợp file , thì sẽ có file tổng hợp 3 sheet của bạn, nhưng mỗi lần bạn tổng hợp file thì phải xoá sheet tên "Tong Hop" đi vì nếu để sheet này sẽ bị trùng tên với sheet tổng hợp tiếp theo code sẽ ko chạy.
- Các anh chị coi code này có cần thêm bớt gì không ạ
Mã:
Sub tong_hop_du_lieu()
    Dim shAll As Worksheet
    Dim sh As Worksheet
    Dim count As Integer
    Dim lastrow As Long
  
    Set shAll = Worksheets.Add
    shAll.Name = "Tong Hop"
  
    For Each sh In Worksheets
        If sh.Name <> shAll.Name Then
            count = count + 1
            If count = 1 Then
                sh.Range("A1:N" & sh.Range("A" & Rows.count).End(xlUp).Row).Copy _
                shAll.Range("A1")
            Else
                sh.Range("A2:N" & sh.Range("A" & Rows.count).End(xlUp).Row).Copy _
                shAll.Range("A" & lastrow + 1)
            End If
            lastrow = shAll.Range("A" & Rows.count).End(xlUp).Row
        End If
    Next sh
End Sub
Bài đã được tự động gộp:

Không được rồi!
Vì cột L có dữ liệu của 3 sheet phải được gộp lại mới đúng
 
Upvote 0
Bài đã được tự động gộp:

Không được rồi!
Vì cột L có dữ liệu của 3 sheet phải được gộp lại mới đúng
phải được gộp lại là sao anh, chưa hiểu lắm ?
Bài đã được tự động gộp:

Bài đã được tự động gộp:

Không được rồi!
Vì cột L có dữ liệu của 3 sheet phải được gộp lại mới đúng
ý anh là các dòng có dữ liệu ở cột L sẽ được gộp lại thành 1 sheet khác đúng không ?
 
Upvote 0
Cho hỏi nếu tôi có các sheet giống nhau cấu trúc nhưng cột Điểm TL ở các sheet khác nhau. Tôi muốn gộp lại vào sheet tổng hợp thì làm sao?
tất cả các sheet đều giống nhau nên sheet TongHop là có sẵn, Code chỉ lấy dữ liệu cột L của các sheet về TongHop.
 

File đính kèm

Upvote 0
Cảm ơn nhiều nhé
 
Upvote 0
Xin chào thầy ạ :D
Bài đã được tự động gộp:



Oanh Thơ mới học code nên giải thích có thể bạn và những người khác chưa hiểu code này sẽ không hiểu. híc:
Mã:
With shtData 'là "Sheet2"
For i = LBound(varKey) To UBound(varKey) ' bắt đầu từ dòng 2 đến dòng cuối trong cột A

Set c = .Columns("A").Find(What:=varKey(i, 1), _
After:=.Range("A1"), LookIn:=xlValues, _
LookAt:=xlWhole, SearchDirection:=xlNext) ' gán cho biến c một ô tìm kiếm được trong cột A của sheet2
If c Is Nothing Then ' nếu không tìm thấy C
shtKQ.Cells(i + 1, 2).Value = "#N/A" ' trả về "#N/A" giống như vlookup không tìm thấy từ khóa trong bảng tìm kiếm
Else ' nếu tìm thấy
c.Resize(1, 2).Offset(0, 1).Copy Destination:=shtKQ.Cells(i + 1, 2)  ' từ ô tìm kiếm được quét sang phải 1 cột,và nhảy thêm 1 cột nữa rồi copy vùng này sau đó đặt con trỏ tại dòng i cột 2 rồi pase.
End If
Next i
End With
End Sub
Xin chào Ms. Oanh Thơ

Bạn có thể cho mình hỏi với đoạn Code trên thì làm sao để copy giá trị thôi không copy format và công thức
 
Upvote 0
Xin chào Ms. Oanh Thơ

Bạn có thể cho mình hỏi với đoạn Code trên thì làm sao để copy giá trị thôi không copy format và công thức

Xin chào Nguyentu95, bạn lấy code và file ở bài này của thầy Ba Tê nhé:

https://www.giaiphapexcel.com/diendan/threads/xin-mã-vba-như-hàm-vloopkup-nhưng-lấy-được-cả-formats-comments-của-ô-được-tìm-kiếm.139556/#post-895976


bỏ dòng:
Cll.Offset(, 7).Resize(, 2).Copy Rng.Offset(, 8) ' Lay ca format + value
thay thành:
Cll.Offset(, 7).Resize(, 2).Copy
Rng.Offset(, 8).PasteSpecial xlPasteValues

Mã:
Option Explicit

Public Sub sGPE()
Dim sRng As Range, dRng As Range, Cll As Range, Rng As Range, Txt As String
Set sRng = Sheets("DANH SACH TONG").Range("B4", Sheets("DANH SACH TONG").Range("B4").End(xlDown))
Set dRng = Sheets("FILE GUI").Range("B12", Sheets("FILE GUI").Range("B12").End(xlDown))
For Each Rng In dRng
    Txt = Rng.Value
    For Each Cll In sRng
        If Cll.Value = Txt Then
             Rem Cll.Offset(, 7).Resize(, 2).Copy Rng.Offset(, 8) ' Lay ca format + value
             Cll.Offset(, 7).Resize(, 2).Copy
             Rng.Offset(, 8).PasteSpecial xlPasteValues
            Exit For
        End If
    Next Cll
Next Rng
End Sub

Nếu bạn muốn lấy value không thì dùng mảng thì tốc độ nhanh hơn code nhiều. Về mảng OT đang tìm hiểu bạn có thể gửi file kèm và nêu mong muốn nên đây để mọi người xem và giúp cho bạn.
 
Upvote 0
Nếu bạn đang học viết code thì:
- Luôn phải xóa kết quả cũ. Trong bài mà bạn cho link bạn thử như sau: nhấn GPE -> bạn có kết quả trong J12:K29 -> sau một thời gian xóa đi, nhập lại, sửa thì cột B trong sheet FILE GUI chỉ có 3 dòng dữ liệu B12:B14 -> nhấn GPE -> bạn vẫn có 18 kết quả trong J12:K29
Bạn không biết đâu là kết quả mới, đâu là kết quả cũ.
Tất nhiên người nhập liệu khi xóa chì còn 3 dòng dữ liệu B12:B14 thì anh ta nên tự xóa cả các kết quả trong J:K. Nhưng đấy là việc của anh ta. Anh ta có thể làm mà cũng có thể không. Người viết code hãy làm nhiệm vụ của bản thân mình và đừng bao giờ giả thiết là anh nhập liệu luôn ý thức được trách nhiệm của mình, luôn tỉnh táo, luôn không nhầm lẫn. Việc của người ta thì để người ta làm, việc của mình thì mình làm, đừng giả thiết là người khác sẽ chuẩn, sẽ có trách nhiệm.

- Người viết code không được phép giả thiết là dữ liệu luôn liên tục, không có dòng trống. Dùng xlDown? Nếu 'DANH SACH TONG'!B7 = rỗng thì sau khi chạy GPE sẽ thiếu kết quả. Tương tự khi vd. 'FILE GUI'!B15 = rỗng.
Dữ liệu liên tục thì tốt nhưng là người viết code thì không được phép mặc định như thế.

- Người viết code không được phép giả thiết là luôn có dữ liệu. Nếu cột B trong 'FILE GUI' hoặc/và 'DANH SACH TONG' không có dữ liệu thì dRng hoặc/và sRng sẽ có hàng triệu dòng. Lúc đó thì nhấn GPE rồi đi nhậu.

Tóm lại người viết code nên lường được những trường hợp dữ liệu, những sự cố có thể có và xử lý chúng. Càng lường được nhiều tình huống càng tốt. Trên đây tôi chỉ liệt kê ra 3 vấn đề mà người viết code bắt buộc phải xử lý.

Bạn tham khảo code ở dưới. Code dài hơn code ở link vì:
- gộp 2 trường hợp: chỉ lấy giá trị, và lấy giá trị và format.
- xóa kết quả cũ, xử lý trường hợp không có dữ liệu, và khi dữ liệu không liên tục.

Gán cho nút GPE macro test
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 2)
    End With
    Set shSrc = Worksheets("DANH SACH TONG")
    With shSrc
        lastRow = .Cells(Rows.Count, "B").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("B4:J" & 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(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8)
                    result(r1, 2) = csdl(r2, 9)
                End If
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then shDest.Range("J12").Resize(UBound(result), 2).Value = result
End Sub

Sub test()
'    chi lay gia tri
    sGPE
'    lay gia tri va format
'    sGPE True
End Sub
 
Upvote 0
Nếu bạn đang học viết code thì:
- Luôn phải xóa kết quả cũ. Trong bài mà bạn cho link bạn thử như sau: nhấn GPE -> bạn có kết quả trong J12:K29 -> sau một thời gian xóa đi, nhập lại, sửa thì cột B trong sheet FILE GUI chỉ có 3 dòng dữ liệu B12:B14 -> nhấn GPE -> bạn vẫn có 18 kết quả trong J12:K29
Bạn không biết đâu là kết quả mới, đâu là kết quả cũ.
Tất nhiên người nhập liệu khi xóa chì còn 3 dòng dữ liệu B12:B14 thì anh ta nên tự xóa cả các kết quả trong J:K. Nhưng đấy là việc của anh ta. Anh ta có thể làm mà cũng có thể không. Người viết code hãy làm nhiệm vụ của bản thân mình và đừng bao giờ giả thiết là anh nhập liệu luôn ý thức được trách nhiệm của mình, luôn tỉnh táo, luôn không nhầm lẫn. Việc của người ta thì để người ta làm, việc của mình thì mình làm, đừng giả thiết là người khác sẽ chuẩn, sẽ có trách nhiệm.

- Người viết code không được phép giả thiết là dữ liệu luôn liên tục, không có dòng trống. Dùng xlDown? Nếu 'DANH SACH TONG'!B7 = rỗng thì sau khi chạy GPE sẽ thiếu kết quả. Tương tự khi vd. 'FILE GUI'!B15 = rỗng.
Dữ liệu liên tục thì tốt nhưng là người viết code thì không được phép mặc định như thế.

- Người viết code không được phép giả thiết là luôn có dữ liệu. Nếu cột B trong 'FILE GUI' hoặc/và 'DANH SACH TONG' không có dữ liệu thì dRng hoặc/và sRng sẽ có hàng triệu dòng. Lúc đó thì nhấn GPE rồi đi nhậu.

Tóm lại người viết code nên lường được những trường hợp dữ liệu, những sự cố có thể có và xử lý chúng. Càng lường được nhiều tình huống càng tốt. Trên đây tôi chỉ liệt kê ra 3 vấn đề mà người viết code bắt buộc phải xử lý.

Bạn tham khảo code ở dưới. Code dài hơn code ở link vì:
- gộp 2 trường hợp: chỉ lấy giá trị, và lấy giá trị và format.
- xóa kết quả cũ, xử lý trường hợp không có dữ liệu, và khi dữ liệu không liên tục.

Gán cho nút GPE macro test
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 2)
    End With
    Set shSrc = Worksheets("DANH SACH TONG")
    With shSrc
        lastRow = .Cells(Rows.Count, "B").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("B4:J" & 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(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8)
                    result(r1, 2) = csdl(r2, 9)
                End If
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then shDest.Range("J12").Resize(UBound(result), 2).Value = result
End Sub

Sub test()
'    chi lay gia tri
    sGPE
'    lay gia tri va format
'    sGPE True
End Sub

Con chào bác Siwtom,
Cảm ơn bác nhiều vì đã chia sẻ kinh nghiệm và chỉ dẫn cho con biết thêm cách kết hợp sử dụng mảng ạ.
Kính chúc bác ngày mới vui khỏe.
 
Upvote 0
Upvote 0
Xin chào Nguyentu95, bạn lấy code và file ở bài này của thầy Ba Tê nhé:

https://www.giaiphapexcel.com/diendan/threads/xin-mã-vba-như-hàm-vloopkup-nhưng-lấy-được-cả-formats-comments-của-ô-được-tìm-kiếm.139556/#post-895976


bỏ dòng:

thay thành:


Mã:
Option Explicit

Public Sub sGPE()
Dim sRng As Range, dRng As Range, Cll As Range, Rng As Range, Txt As String
Set sRng = Sheets("DANH SACH TONG").Range("B4", Sheets("DANH SACH TONG").Range("B4").End(xlDown))
Set dRng = Sheets("FILE GUI").Range("B12", Sheets("FILE GUI").Range("B12").End(xlDown))
For Each Rng In dRng
    Txt = Rng.Value
    For Each Cll In sRng
        If Cll.Value = Txt Then
             Rem Cll.Offset(, 7).Resize(, 2).Copy Rng.Offset(, 8) ' Lay ca format + value
             Cll.Offset(, 7).Resize(, 2).Copy
             Rng.Offset(, 8).PasteSpecial xlPasteValues
            Exit For
        End If
    Next Cll
Next Rng
End Sub

Nếu bạn muốn lấy value không thì dùng mảng thì tốc độ nhanh hơn code nhiều. Về mảng OT đang tìm hiểu bạn có thể gửi file kèm và nêu mong muốn nên đây để mọi người xem và giúp cho bạn.
Rất vui khi được ban giúp đỡ,
Cảm ơn Ms. Oanh Thơ nhiều!

Công việc của mình liên quan đến Vlookup khá nhiều và phải copy-paste dữ liệu từ sheet A qua Sheet B để làm báo cáo so sánh, mình có học qua 1 khóa VBA cơ bản nên cũng chưa có nắm được mong học tập được từ bạn nhiều!
Mình gửi kèm file liên quan đến công việc hàng ngày của mình và trình bày để mong nhận được sự giúp đỡ như sau:

- I: Lấy dữ liệu từ dạng Value từ sheet 1 qua sheet 2 và sheet 3 với điều kiện dò tìm theo tên đầu mục nằm trong 1 cột được lựa chọn từ Box hiện lên mỗi khi chạy code. ( Với file mình gửi thì cột dò tìm ở sheet 1 là "B", dò tìm với cột "C" ở sheet 2, sheet 3, nếu trùng thì lấy dữ liệu Value từ cột C=>H của sheet 1 điền vô dòng tương ứng ở Sheet 2, 3 ). Vấn đề nữa là Sheet 1 của mình có dữ liệu về số thay đổi trong cột D => H thì làm sao để Sheet 2,3 tự cập nhật được điều này mà không cần chạy lại Code VBA?

- II: Trong trường hợp mình có 1 file như file kết quả sau khi chạy Code VBA ở yêu cầu I làm thế nào để lấy dữ liệu ở cả 2 sheet 2 và 3 ở cột "D" để điền vô cột "I" của sheet 1 vẫn với điều kiện dò tìm là tên đầu mục ở cột C sheet 2,3 trùng với tên đầu mục ở cột B sheet 1 thì lấy Value để thực hiện công tác so sánh?
 

File đính kèm

Upvote 0
Nếu bạn đang học viết code thì:
- Luôn phải xóa kết quả cũ. Trong bài mà bạn cho link bạn thử như sau: nhấn GPE -> bạn có kết quả trong J12:K29 -> sau một thời gian xóa đi, nhập lại, sửa thì cột B trong sheet FILE GUI chỉ có 3 dòng dữ liệu B12:B14 -> nhấn GPE -> bạn vẫn có 18 kết quả trong J12:K29
Bạn không biết đâu là kết quả mới, đâu là kết quả cũ.
Tất nhiên người nhập liệu khi xóa chì còn 3 dòng dữ liệu B12:B14 thì anh ta nên tự xóa cả các kết quả trong J:K. Nhưng đấy là việc của anh ta. Anh ta có thể làm mà cũng có thể không. Người viết code hãy làm nhiệm vụ của bản thân mình và đừng bao giờ giả thiết là anh nhập liệu luôn ý thức được trách nhiệm của mình, luôn tỉnh táo, luôn không nhầm lẫn. Việc của người ta thì để người ta làm, việc của mình thì mình làm, đừng giả thiết là người khác sẽ chuẩn, sẽ có trách nhiệm.

- Người viết code không được phép giả thiết là dữ liệu luôn liên tục, không có dòng trống. Dùng xlDown? Nếu 'DANH SACH TONG'!B7 = rỗng thì sau khi chạy GPE sẽ thiếu kết quả. Tương tự khi vd. 'FILE GUI'!B15 = rỗng.
Dữ liệu liên tục thì tốt nhưng là người viết code thì không được phép mặc định như thế.

- Người viết code không được phép giả thiết là luôn có dữ liệu. Nếu cột B trong 'FILE GUI' hoặc/và 'DANH SACH TONG' không có dữ liệu thì dRng hoặc/và sRng sẽ có hàng triệu dòng. Lúc đó thì nhấn GPE rồi đi nhậu.

Tóm lại người viết code nên lường được những trường hợp dữ liệu, những sự cố có thể có và xử lý chúng. Càng lường được nhiều tình huống càng tốt. Trên đây tôi chỉ liệt kê ra 3 vấn đề mà người viết code bắt buộc phải xử lý.

Bạn tham khảo code ở dưới. Code dài hơn code ở link vì:
- gộp 2 trường hợp: chỉ lấy giá trị, và lấy giá trị và format.
- xóa kết quả cũ, xử lý trường hợp không có dữ liệu, và khi dữ liệu không liên tục.

Gán cho nút GPE macro test
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 2)
    End With
    Set shSrc = Worksheets("DANH SACH TONG")
    With shSrc
        lastRow = .Cells(Rows.Count, "B").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("B4:J" & 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(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8)
                    result(r1, 2) = csdl(r2, 9)
                End If
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then shDest.Range("J12").Resize(UBound(result), 2).Value = result
End Sub

Sub test()
'    chi lay gia tri
    sGPE
'    lay gia tri va format
'    sGPE True
End Sub
Dạ, Hay quá
Cảm ơn Thầy nhiều, kính chúc thầy nhiều sức khỏe!
 
Upvote 0
Xin chào Nguyentu95, bạn lấy code và file ở bài này của thầy Ba Tê nhé:

https://www.giaiphapexcel.com/diendan/threads/xin-mã-vba-như-hàm-vloopkup-nhưng-lấy-được-cả-formats-comments-của-ô-được-tìm-kiếm.139556/#post-895976


bỏ dòng:

thay thành:


Mã:
Option Explicit

Public Sub sGPE()
Dim sRng As Range, dRng As Range, Cll As Range, Rng As Range, Txt As String
Set sRng = Sheets("DANH SACH TONG").Range("B4", Sheets("DANH SACH TONG").Range("B4").End(xlDown))
Set dRng = Sheets("FILE GUI").Range("B12", Sheets("FILE GUI").Range("B12").End(xlDown))
For Each Rng In dRng
    Txt = Rng.Value
    For Each Cll In sRng
        If Cll.Value = Txt Then
             Rem Cll.Offset(, 7).Resize(, 2).Copy Rng.Offset(, 8) ' Lay ca format + value
             Cll.Offset(, 7).Resize(, 2).Copy
             Rng.Offset(, 8).PasteSpecial xlPasteValues
            Exit For
        End If
    Next Cll
Next Rng
End Sub

Nếu bạn muốn lấy value không thì dùng mảng thì tốc độ nhanh hơn code nhiều. Về mảng OT đang tìm hiểu bạn có thể gửi file kèm và nêu mong muốn nên đây để mọi người xem và giúp cho bạn.
Hi Ms. Oanh Thơ

Với Code này khi 1 trong 2 sheet có 1 dòng trống ở giữa thì file chỉ cho ra kết quả tới dòng trước dòng trống và dừng Code. Bạn có thể sửa cho Code chạy hết khi có dòng chống.
 

File đính kèm

Upvote 0
Hi Ms. Oanh Thơ

Với Code này khi 1 trong 2 sheet có 1 dòng trống ở giữa thì file chỉ cho ra kết quả tới dòng trước dòng trống và dừng Code. Bạn có thể sửa cho Code chạy hết khi có dòng chống.
Bạn thử thay lại như thế này xem sao
Mã:
Set sRng = Sheets("DANH SACH TONG").Range("B4", Sheets("DANH SACH TONG").Range("B65535").End(xlUp))
Set dRng = Sheets("FILE GUI").Range("B12", Sheets("FILE GUI").Range("B65535").End(xlUp))
 

File đính kèm

Upvote 0
Hi Ms. Oanh Thơ

Với Code này khi 1 trong 2 sheet có 1 dòng trống ở giữa thì file chỉ cho ra kết quả tới dòng trước dòng trống và dừng Code. Bạn có thể sửa cho Code chạy hết khi có dòng chống.
Tôi viết rất rõ
- Người viết code không được phép giả thiết là dữ liệu luôn liên tục, không có dòng trống. Dùng xlDown? Nếu 'DANH SACH TONG'!B7 = rỗng thì sau khi chạy GPE sẽ thiếu kết quả. Tương tự khi vd. 'FILE GUI'!B15 = rỗng
Bạn đã đọc vì
Mã:
Dạ, Hay quá
Thế bạn đọc có hiểu không mà vẫn cứ dùng xlDown? Bó tay.
 
Upvote 0
@Nguyễn Hoàng Oanh Thơ vậy code của bạn với PacificPR code nào tốt hơn ta?, mình thấy code đang xài vẫn ok chưa phat sinh gì, thấy mấy anh chị viết hoan mang quá.

Hi code của bạn PacificPR tốt hơn code của OT nhiều bạn à vì bạn ấy rất giỏi code.

Mà Oanh Thơ cũng không biết bạn đang sử dụng code nào của OT nữa, nếu bạn lấy code ở bài 12 thì yên tâm không bị lỗi như bài 34 ạ. Nếu bạn cảm thấy hoag mang thì có thể tạo dòng trống xen kẽ sau đó chạy code có thể biết được mà.

Bạn tham khảo thêm bài 29 nhé, có 2 cách cho bạn lựa chọn đó, lấy dữ liệu có cả format hoặc là chỉ value không.
 
Lần chỉnh sửa cuối:
Upvote 0
Hi code của bạn PacificPR tốt hơn code của OT nhiều bạn à vì bạn ấy rất giỏi code.

Mà Oanh Thơ cũng không biết bạn đang sử dụng code nào của OT nữa, nếu bạn lấy code ở bài 12 thì yên tâm không bị lỗi như bài 34 ạ. Nếu bạn cảm thấy hoag mang thì có thể tạo dòng trống xen kẽ sau đó chạy code có thể biết được mà.

Bạn tham khảo thêm bài 29 nhé, có 2 cách cho bạn lựa chọn đó, lấy dữ liệu có cả format hoặc là chỉ value không.
- OT ơi ! Bài 29 của anh Batman1 là cột B "FILE GUI" so sánh với cột B "DANH SACH TONG", giờ mình muốn sửa thành cột A "DANH SACH TONG" thì phải sửa khúc nào nhỉ :)
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn chạy "Sub test" nhé,code hỏi điều kiện lấy: nếu muốn lấy fromat và giá trị chọn yes, còn chỉ mỗi giá trị không thì chọn No, hủy bỏ chọn cancel:
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 2)
    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:J" & 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(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8)
                    result(r1, 2) = csdl(r2, 9)
                End If
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then shDest.Range("J12").Resize(UBound(result), 2).Value = result
End Sub

Sub test()
    Select Case Application.Assistant.DoAlert("Giaiphapexcel.com", TbaoLuachon, msoAlertButtonYesNoCancel, msoAlertIconWarning, 0, 0, False)
        Case vbYes:       sGPE True   'lay gia tri va format
        Case vbNo:        sGPE        'chi lay gia tri
        Case vbCancel:    Exit Sub    'thoat khong lam gi
    End Select
End Sub

Function TbaoLuachon()
    TbaoLuachon = "B" & ChrW(7841) & "n c" & ChrW(243) & " mu" & ChrW(7889) & "n l" & ChrW(7845) & "y c" & ChrW(7843) & " Format kh" & ChrW(244) & "ng?"
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn chạy "Sub test" nhé,code hỏi điều kiện lấy: nếu muốn lấy fromat và giá trị chọn yes, còn chỉ mỗi giá trị không thì chọn No, hủy bỏ chọn cancel:
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 2)
    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:J" & 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(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8)
                    result(r1, 2) = csdl(r2, 9)
                End If
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then shDest.Range("J12").Resize(UBound(result), 2).Value = result
End Sub

Sub test()
    Select Case Application.Assistant.DoAlert("Giaiphapexcel.com", TbaoLuachon, msoAlertButtonYesNoCancel, msoAlertIconWarning, 0, 0, False)
        Case vbYes:       sGPE True   'lay gia tri va format
        Case vbNo:        sGPE        'chi lay gia tri
        Case vbCancel:    Exit Sub    'thoat khong lam gi
    End Select
End Sub

Function TbaoLuachon()
    TbaoLuachon = "B" & ChrW(7841) & "n c" & ChrW(243) & " mu" & ChrW(7889) & "n l" & ChrW(7845) & "y c" & ChrW(7843) & " Format kh" & ChrW(244) & "ng?"
End Function
Cảm ơn OT mình biết phải sửa code lại thế nào rồi :)
 
Upvote 0
@Nguyễn Hoàng Oanh Thơ bạn cho mình hỏi đoạn code result(r1, 1) = csdl(r2, 8) và result(r1, 2) = csdl(r2, 9) nó có ý nghĩa gì vậy bạn ?
Mã:
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(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8) // câu này với câu dưới mang ý nghĩa gì, số 8,9 có công dụng gì ạ ?
                    result(r1, 2) = csdl(r2, 9)
                End If
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then shDest.Range("J12").Resize(UBound(result), 2).Value = result
 
Upvote 0
@Nguyễn Hoàng Oanh Thơ bạn cho mình hỏi đoạn code result(r1, 1) = csdl(r2, 8) và result(r1, 2) = csdl(r2, 9) nó có ý nghĩa gì vậy bạn ?
Mã:
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(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8) // câu này với câu dưới mang ý nghĩa gì, số 8,9 có công dụng gì ạ ?
                    result(r1, 2) = csdl(r2, 9)
                End If
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then shDest.Range("J12").Resize(UBound(result), 2).Value = result

Xin chào kienphamiuh,
OT cũng chưa nắm chắc kiến thức về mảng cũng như về khái niệm về các từ ngữ của mảng nên tạm thời OT viết theo cách OT hiểu nhé:

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 ' dua du lieu cua sheet"FILE GUI" vao mang data
'        mang ket qua
        If Not format Then ReDim result(1 To UBound(data) - 1, 1 To 2) ' neu khong lay format thi khai bao kich thuoc cua mang result
        '1 To 2: chieu tu trai sang fai la co 2 cot (tuong uong voi cot J(cot1) va K(cot2) tren sheet"FILE GUI")
    'result la mang ghi ket qua so sanh duoc
    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:J" & lastRow).Value ' dua du lieu cua sheet"DANH SACH TONG" vao mang csdl
    End With
    For r1 = 1 To UBound(data) - 1 'duyet gia tri trong mang data
        text = data(r1, 1) 'moi vong lap gan gia tri tim dc vao bien text (bien tam thoi hay con goi la trung gian)
        '1: cot dau tien trong mang data,tuong ung voi cot B tren sheet"FILE GUI"
        For r2 = 1 To UBound(csdl) 'duyet gia tri trong mang csdl
            If csdl(r2, 1) = text Then 'neu tim duoc gia tri trong mang csdl(r2, 1) = text
            '1: cot dau tien trong mang csdl,tuong ung voi cot A tren sheet"DANH SACH TONG"
                If format Then 'Neu lay ca format
                    shSrc.Cells(3 + r2, "I").Resize(, 2).Copy shDest.Cells(11 + r1, "J")
                    'bat dau tu dong 3 , cot I trong sheet "DANH SACH TONG" + voi thu tu cua giatri tim duoc trong mang csdl
                    'Resize(, 2) : tu cot I que't sang phai 1 cot se thanh I:J dong 3+r2
                Else
                    'xet trong mang csdl tuong duong voi xet trong sheet"DANH SACH TONG"
                    result(r1, 1) = csdl(r2, 8) ' tinh tu cot A den J tuong ung voi 1,2,...9 (cot 8 = H)
                    result(r1, 2) = csdl(r2, 9) ' tinh tu cot A den J tuong ung voi 1,2,...9 (cot 9 = I)
                End If
                Exit For
            End If
        Next r2
    Next r1
    'neu khong lay format thi se dua mang result xuong bat dau tu o J12
    If Not format Then shDest.Range("J12").Resize(UBound(result), 2).Value = result
End Sub

result(r1, 1) = csdl(r2, 8) // câu này với câu dưới mang ý nghĩa gì, số 8,9 có công dụng gì ạ ?
result(r1, 2) = csdl(r2, 9)
Bạn thử thay số 8 thành số 9 và thay số 9 thành số 10 ở 2 dòng trên thì khi chạy Sub tes:
Mã:
Sub test()
    Select Case Application.Assistant.DoAlert("Giaiphapexcel.com", TbaoLuachon, msoAlertButtonYesNoCancel, msoAlertIconWarning, 0, 0, False)
        Case vbYes:       sGPE True   'lay gia tri va format
        Case vbNo:        sGPE        'chi lay gia tri
        Case vbCancel:    Exit Sub    'thoat khong lam gi
    End Select
End Sub
sẽ thấy kết quả giá trị trả về khi chọn yes hoặc no đều như nhau.
Chỉ khác nhau về lấy format và không lấy format.

Bạn muốn hiểu rõ về mảng thì có thể hỏi thêm bác Siwtom, người viết đoạn code trên ở bài 29:
https://www.giaiphapexcel.com/diendan/threads/xin-mã-vba-như-hàm-vloopkup-nhưng-lấy-được-cả-formats-comments-của-ô-được-tìm-kiếm.139556/page-2#post-900311

Hoặc tham gia chủ đề này, để được những người có kiến thức sâu về chuyên môn giúp đỡ. OT cũng đang hỏi và hỏi ở chủ đề này:
https://www.giaiphapexcel.com/diendan/threads/các-câu-hỏi-về-mảng-trong-vba-array.46834/
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu bạn đang học viết code thì:
- Luôn phải xóa kết quả cũ. Trong bài mà bạn cho link bạn thử như sau: nhấn GPE -> bạn có kết quả trong J12:K29 -> sau một thời gian xóa đi, nhập lại, sửa thì cột B trong sheet FILE GUI chỉ có 3 dòng dữ liệu B12:B14 -> nhấn GPE -> bạn vẫn có 18 kết quả trong J12:K29
Bạn không biết đâu là kết quả mới, đâu là kết quả cũ.
Tất nhiên người nhập liệu khi xóa chì còn 3 dòng dữ liệu B12:B14 thì anh ta nên tự xóa cả các kết quả trong J:K. Nhưng đấy là việc của anh ta. Anh ta có thể làm mà cũng có thể không. Người viết code hãy làm nhiệm vụ của bản thân mình và đừng bao giờ giả thiết là anh nhập liệu luôn ý thức được trách nhiệm của mình, luôn tỉnh táo, luôn không nhầm lẫn. Việc của người ta thì để người ta làm, việc của mình thì mình làm, đừng giả thiết là người khác sẽ chuẩn, sẽ có trách nhiệm.

- Người viết code không được phép giả thiết là dữ liệu luôn liên tục, không có dòng trống. Dùng xlDown? Nếu 'DANH SACH TONG'!B7 = rỗng thì sau khi chạy GPE sẽ thiếu kết quả. Tương tự khi vd. 'FILE GUI'!B15 = rỗng.
Dữ liệu liên tục thì tốt nhưng là người viết code thì không được phép mặc định như thế.

- Người viết code không được phép giả thiết là luôn có dữ liệu. Nếu cột B trong 'FILE GUI' hoặc/và 'DANH SACH TONG' không có dữ liệu thì dRng hoặc/và sRng sẽ có hàng triệu dòng. Lúc đó thì nhấn GPE rồi đi nhậu.

Tóm lại người viết code nên lường được những trường hợp dữ liệu, những sự cố có thể có và xử lý chúng. Càng lường được nhiều tình huống càng tốt. Trên đây tôi chỉ liệt kê ra 3 vấn đề mà người viết code bắt buộc phải xử lý.

Bạn tham khảo code ở dưới. Code dài hơn code ở link vì:
- gộp 2 trường hợp: chỉ lấy giá trị, và lấy giá trị và format.
- xóa kết quả cũ, xử lý trường hợp không có dữ liệu, và khi dữ liệu không liên tục.

Gán cho nút GPE macro test
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 2)
    End With
    Set shSrc = Worksheets("DANH SACH TONG")
    With shSrc
        lastRow = .Cells(Rows.Count, "B").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("B4:J" & 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(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8)
                    result(r1, 2) = csdl(r2, 9)
                End If
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then shDest.Range("J12").Resize(UBound(result), 2).Value = result
End Sub

Sub test()
'    chi lay gia tri
    sGPE
'    lay gia tri va format
'    sGPE True
End Sub
Anh ơi em dò tìm dữ liệu lớn hơn 100 dữ liệu máy tính bị giật giật, trắng màng hình excel ( bị lag ) rồi tầm 5s sau mới ra giá trị tìm, anh có thể làm tăng tốc độ chạy hoặc cho code chạy bớt " lag " được ko ạ
vì sheet "danh sach tong" tầm hơn 4000 dòng, em do tìm tầm 120 dữ liệu bên sheet " file gui" thì nó bị vậy, ko biết có phải máy tính em cũ rồi nên nó bị vậy ko ạ
 
Lần chỉnh sửa cuối:
Upvote 0
Đính kèm tập tin giật giật ấy lên.
em có 1 chút việc nên giờ mới gửi cho anh mong anh thông cảm, anh coi qua file giúp em ! tình hình là máy tính cty em đời cũ, lọc tầm 200 mã nv là nó bị đứng tầm 7-10s, sau khi lọc xong máy tính chạy rất chậm kiểu bị " lag " , anh có thể chỉnh code cho chạy nhanh và bớt lag được ko ? cảm ơn anh !
 

File đính kèm

Upvote 0
em có 1 chút việc nên giờ mới gửi cho anh mong anh thông cảm, anh coi qua file giúp em ! tình hình là máy tính cty em đời cũ, lọc tầm 200 mã nv là nó bị đứng tầm 7-10s, sau khi lọc xong máy tính chạy rất chậm kiểu bị " lag " , anh có thể chỉnh code cho chạy nhanh và bớt lag được ko ? cảm ơn anh !
--------------------------------
 
Upvote 0
Đấy là tôi viết cho cấu trúc dữ liệu cũ

Bạn thử xem
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, rng As Range
    Application.ScreenUpdating = False
   
    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
'        xac dinh dong cuoi co du lieu trong cot B (MHV) tai sheet FILE GUI
        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
'        chi lay 1 cot MHV. Lay du ra 1 dong
        data = .Range("B12:B" & lastRow + 1).Value
'        mang ket qua - chi cho truong hop lay gia tri. Khi lay ca Format thi khong dung mang result
        If Not format Then ReDim result(1 To UBound(data) - 1, 1 To 2)
    End With
    Set shSrc = Worksheets("DANH SACH TONG")
    With shSrc
'        xac dinh dong cuoi co du lieu trong cot B (MHV) tai sheet DANH SACH TONG
        lastRow = .Cells(Rows.Count, "B").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
'        lay tu cot MHV toi cot SDT BA
        csdl = .Range("B4:J" & lastRow).Value
    End With
'    duyet tung dong cua mang data (cot 1. Mang data cung chi co 1 cot) de lay MHV. Khong xet dong lay du vi the UBound(data) - 1
    For r1 = 1 To UBound(data) - 1
'        MHV hien hanh trong sheet FILE GUI
        text = data(r1, 1)
'        duyet tung dong cua mang csdl
        For r2 = 1 To UBound(csdl)
'            xet xem MHV hien hanh trong sheet DANH SACH TONG co y het MHV hien hanh trong sheet FILE GUI hay khong
            If csdl(r2, 1) = text Then
'                MHV hien hanh trong sheet DANH SACH TONG y het MHV hien hanh trong sheet FILE GUI
                If format Then
'                    Can lay ca Format, vay them 2 cell tren sheet DANH SACH TONG nam o cot I:J vao Range rng
'                    2 cell nay nam o dong 3 + r2 tren sheet DANH SACH TONG. Tai sao? Mang csdl duoc lay tu dong 4 tren sheet tro xuong.
'                    Dong 4 tren sheet tuong ung voi dong 1 trong mang csdl. Vi the dong r2 trong mang csdl tuong ung voi dong 3 + r2 tren sheet
                    If rng Is Nothing Then
'                        rng chua duoc thiet lap, vay lay 2 cell lam rng
                        Set rng = shSrc.Cells(3 + r2, "I").Resize(, 2)
                    Else
'                        rng da duoc thiet lap, vay them 2 cell vao Range rng
                        Set rng = Union(rng, shSrc.Cells(3 + r2, "I").Resize(, 2))
                    End If
                Else
'                    nhap SDT ME lay tu mang csdl tai dong hien hanh r2 cot 8 vao dong hien hanh r1 cot 1. Tai sao cot 8?
'                    Mang csdl duoc lay tu cot B (MHV) toi cot J (SDT CHA). Cot 1 trong mang csdl la MHV thi
'                    SDT ME phai nam o cot 8 cua mang csdl
                    result(r1, 1) = csdl(r2, 8)
'                    nhap SDT CHA lay tu mang csdl tai dong hien hanh r2 cot 9 vao dong hien hanh r1 cot 2. Tai sao cot 9?
'                    Mang csdl duoc lay tu cot B (MHV) toi cot J (SDT CHA). Cot 1 trong mang csdl la MHV thi
'                    SDT CHA phai nam o cot 9 cua mang csdl
                    result(r1, 2) = csdl(r2, 9)
                End If
'                Da tim thay MHV trong mang csdl va da xu ly nen thoat khoi vong lap duyet mang csdl
                Exit For
            End If
        Next r2
    Next r1
    If Not format Then
'        chi lay gia tri thi dap mang result vao sheet FILE GUI
        shDest.Range("J12").Resize(UBound(result), 2).Value = result
    Else
'        neu lay ca Format thi copy nhom cac Range "con" sang sheet FILE GUI, xuat phat tu cell J12
        rng.Copy shDest.Range("J12")
    End If
   
    Application.ScreenUpdating = True
End Sub

Sub test()
'    chi lay gia tri
'    sGPE
'    lay gia tri va format
    sGPE True
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Đấy là tôi viết cho cấu trúc dữ liệu cũ

Bạn thử xem
Mã:
           result(r1, 1) = csdl(r2, 8)
           result(r1, 2) = csdl(r2, 9)
Trong trường hợp em muốn lấy dữ liệu dạng Value ở 4 cột 1 lúc ( SĐT 1=> SĐT 4) sang file gửi thì sửa lại đoạn lệnh này thế nào anh?
 

File đính kèm

Upvote 0
Bạn sửa như sau xem đúng không ạ:
Mã:
If Not format Then ReDim result(1 To UBound(data) - 1, 1 To 2)
thành:
Mã:
If Not format Then ReDim result(1 To UBound(data) - 1, 1 To 4)
Sửa đoạn:
Mã:
                    shSrc.Cells(3 + r2, "I").Resize(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8)
                    result(r1, 2) = csdl(r2, 9)
                End If
thành:

Mã:
                    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)
 
Upvote 0
Bạn sửa như sau xem đúng không ạ:
Mã:
If Not format Then ReDim result(1 To UBound(data) - 1, 1 To 2)
thành:
Mã:
If Not format Then ReDim result(1 To UBound(data) - 1, 1 To 4)
Sửa đoạn:
Mã:
                    shSrc.Cells(3 + r2, "I").Resize(, 2).Copy shDest.Cells(11 + r1, "J")
                Else
                    result(r1, 1) = csdl(r2, 8)
                    result(r1, 2) = csdl(r2, 9)
                End If
thành:

Mã:
                    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)    ' LỖI NẾU CHỈ LẤY VALUE
                    result(r1, 4) = csdl(r2, 12)
Trường hợp lấy cả Format thì ok, nhưng lấy Value thì nó vẫn không chạy và báo lỗi ở dòng mình tô đỏ? Bạn sửa lại giúp mình
 

File đính kèm

Upvote 0
Trường hợp lấy cả Format thì ok, nhưng lấy Value thì nó vẫn không chạy và báo lỗi ở dòng mình tô đỏ? Bạn sửa lại giúp mình
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
 
Lần chỉnh sửa cuối:
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
Vì sao lại viết Macro trên ở chế độ "riêng tư" Private?
Vì sao phải thêm Byval, nếu để Byref , nếu không để ?
Vậy OT?
 
Upvote 0
Vì sao lại viết Macro trên ở chế độ "riêng tư" Private?
Vì sao phải thêm Byval, nếu để Byref , nếu không để ?
Vậy OT?
Xin chào HeSanbi , phải chăng bạn muốn kiểm tra kiến thức của OT xem tới đâu?
Cảm ơn bạn đã quan tâm ạ :)
Private trong trường hợp này phạm vi nội bộ trong cùng module với sub gọi test để gọi,
nếu thêm Private cái này ở đầu thì khi tạo nút gán macro người dùng không thể nhìn thấy tên sub mà trước đó có Private .

Còn:
Vì sao phải thêm Byval, nếu để Byref , nếu không để ?
OT vừa mới tìm hiểu thêm ở đây:
https://www.giaiphapexcel.com/diendan/threads/bài-9-function-and-sub.130769/#post-821864
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.
Trong trường hợp này OT thử:
Mã:
Private Sub sGPE(Optional format As Boolean = False)
Mã:
Private Sub sGPE(Optional ByRef format As Boolean = False)
Kết quả cũng không có gì khác nhau cả. o_O
Bạn có thể giải thích thêm được không ạ?
 
Upvote 0
Xin chào HeSanbi , phải chăng bạn muốn kiểm tra kiến thức của OT xem tới đâu?
Cảm ơn bạn đã quan tâm ạ :)
Private trong trường hợp này phạm vi nội bộ trong cùng module với sub gọi test để gọi,
nếu thêm Private cái này ở đầu thì khi tạo nút gán macro người dùng không thể nhìn thấy tên sub mà trước đó có Private .

Còn:

OT vừa mới tìm hiểu thêm ở đây:
https://www.giaiphapexcel.com/diendan/threads/bài-9-function-and-sub.130769/#post-821864
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.
Trong trường hợp này OT thử:
Mã:
Private Sub sGPE(Optional format As Boolean = False)
Mã:
Private Sub sGPE(Optional ByRef format As Boolean = False)
Kết quả cũng không có gì khác nhau cả.
Bạn có thể giải thích thêm được không ạ?
Hỏi chơi không ngờ Thật

Private là không thể dùng được ở bất kì một VBProject nào khác cả ngoài nơi nó đứng. Trừ khi gọi một Public Hàm hoặc Public Sub
Nằm cùng với Private, và Public này lại được gọi ở một nơi khác
Byval khi gọi lại biến thì biến không đổi. Byref ngược lại. Không để gì thì mặc định là Byref
Hãy thử ví dụ bên dưới

PHP:
Sub LayTrongToiDiNay(optional Byref A$)
    A = "Nguyen Hoang Oanh Tho"
End Sub

Sub LayTrongToiDiNay2(optional Byval A$)
    A = "Nguyen Hoang Oanh Tho là ai"
End Sub

Sub ADauRoi()
    Dim AVeDay$, AVeDay2$
    AVeDay = "Nguyen Hoang Oanh Tho on GPE"
    LayTrongToiDiNay AVeDay
    'Call LayTrongToiDiNay(AVeDay)
    MsgBox AVeDay
    AVeDay2 = "Toi Van la Nguyen Hoang Oanh Tho"
    Call LayTrongToiDiNay2(AVeDay2)
    MsgBox AVeDay2

End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
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

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

Back
Top Bottom