Tăng tốc đoạn code dò tìm theo điều kiện thời gian

Liên hệ QC

Haffaz Aladeen

Thành viên mới
Tham gia
11/7/18
Bài viết
41
Được thích
5
Chào cả nhà ạ.

Em đang làm thử 1 file excel có chức năng lọc tìm dữ liệu ở sheet "DATA CD", kiểm tra thời gian update nếu lớn hơn thời gian update của dữ liệu ở sheet "DATA" thì sẽ cập nhật cột Tiến độ.
Tuy nhiên thời gian chạy khá lâu, nên nhờ mọi người giúp em thử có cách nào nhanh hơn không ạ.

Em giải thích hơi khó kiểu, mọi người xem code trong file đính kèm giúp em.
Em cảm ơn!
 

File đính kèm

  • DT.xls
    1 MB · Đọc: 33
Chào cả nhà ạ.

Em đang làm thử 1 file excel có chức năng lọc tìm dữ liệu ở sheet "DATA CD", kiểm tra thời gian update nếu lớn hơn thời gian update của dữ liệu ở sheet "DATA" thì sẽ cập nhật cột Tiến độ.
Tuy nhiên thời gian chạy khá lâu, nên nhờ mọi người giúp em thử có cách nào nhanh hơn không ạ.

Em giải thích hơi khó kiểu, mọi người xem code trong file đính kèm giúp em.
Em cảm ơn!
Bạn thử với cái này:

Mã:
Sub NhapCongDoan()
    Dim i1 As Range
    Dim t1, t0, t As Long
    
    On Error Resume Next
    'With Sheet14
    '    n1 = .Cells(.Rows.Count, "B").End(xlUp).Row
    'End With
    Set Rng = Sheet1.Range(Sheet1.[B3], Sheet1.[B15000].End(xlUp))
    Set Rng1 = Sheet3.Range(Sheet3.[C2], Sheet3.[C60000].End(xlUp))
        't0 = Sheet1.Range("C1").Value
    
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual
    
        For Each i1 In Rng1
            t1 = Format(i1.Offset(, 5), "0.0000000000")
            t0 = Format(Rng.Find(i1.Value, LookIn:=xlValues, lookat:=xlWhole).Offset(, 4).Value, "0.0000000000")
            cd1 = i1.Offset(, 3).Value
            If t1 > t0 Then
                Rng.Find(i1.Value, LookIn:=xlValues, lookat:=xlWhole).Offset(, 3).Value = cd1
                Rng.Find(i1.Value, LookIn:=xlValues, lookat:=xlWhole).Offset(, 4).Value = i1.Offset(, 5).Value
                    'Format(t1, "dd/mm/yy hh:mm:ss")
            End If
        Next i1
        
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Application.ScreenUpdating = True
    't1 = sheet14.Range("B" & i1).Find(
End Sub
 
Upvote 0
Hay quá anh ạ, mấy dòng này cũng có nghe nói, mà em chưa thử nghiệm bao giờ. Không ngờ nhanh hơn nhiều thế
Em cảm ơn nhé.

Ngoài ra thì còn cách nào khác nữa không anh nhỉ?
Có lẽ là còn, nhưng chăc làm cái này tôi hiện không rảnh, để người khác xem và giúp bạn nhé.
 
Upvote 0
Chào cả nhà ạ.

Em đang làm thử 1 file excel có chức năng lọc tìm dữ liệu ở sheet "DATA CD", kiểm tra thời gian update nếu lớn hơn thời gian update của dữ liệu ở sheet "DATA" thì sẽ cập nhật cột Tiến độ.
Tuy nhiên thời gian chạy khá lâu, nên nhờ mọi người giúp em thử có cách nào nhanh hơn không ạ.

Em giải thích hơi khó kiểu, mọi người xem code trong file đính kèm giúp em.
Em cảm ơn!
Bạn ơi,
Bạn có thể giải thích mong muốn của bạn rõ ràng là gì được không?
Nhìn code của bạn tôi chỉ hiểu được là tìm thời gian bên ở sheet "DATA CD" của mã sOder rồi kiểm tra xem bên sheet Data thời gian này có lớn hơn với thời gian tìm kiếm đã cho trước của mã số oder đó hay không nếu lớn hơn thì update thông tin theo sheet "DATA CD".
Code của bạn có phải chỉ làm vậy thôi đúng không?
Ví dụ trong sheet "DATA CD" bạn có đến 8 giá trị "435" phải duyệt hết từng 8 giá trị này xem giá trị nào có thời gian hoàn thành lớn nhất và lớn hơn thời gian của số oder bên sheet data thì điền sang ?
1629292981906.png

Nhưng điểm vấn đề là,trong sheet data bạn lại có 2 dòng số oder "435":
1629293123683.png

Mà trong khi code của bạn thi luôn tìm kiếm giá trị i1.Value = "435"
Mã:
        t1 = Format(i1.Offset(, 5), "0.0000000000")
        t0 = Format(Rng.Find(i1.Value, LookIn:=xlValues, lookat:=xlWhole).Offset(, 4).Value, "0.0000000000")
        If t1 < t0 Then
Phải chăng nó luôn tìm thấy dòng 329 (dòng trước) để so sánh và điền kết quả vào dòng 329 này nếu thời gian lớn hơn , còn dòng 813 không quan tâm?
 
Upvote 0
Bạn ơi,
Bạn có thể giải thích mong muốn của bạn rõ ràng là gì được không?
Nhìn code của bạn tôi chỉ hiểu được là tìm thời gian bên ở sheet "DATA CD" của mã sOder rồi kiểm tra xem bên sheet Data thời gian này có lớn hơn với thời gian tìm kiếm đã cho trước của mã số oder đó hay không nếu lớn hơn thì update thông tin theo sheet "DATA CD".
Code của bạn có phải chỉ làm vậy thôi đúng không?
Ví dụ trong sheet "DATA CD" bạn có đến 8 giá trị "435" phải duyệt hết từng 8 giá trị này xem giá trị nào có thời gian hoàn thành lớn nhất và lớn hơn thời gian của số oder bên sheet data thì điền sang ?
Đúng là như thế đó bạn. Do file của mình còn nhiều thứ hơn, nên mình rút gọn dữ liệu lại chỉ lấy 3 số đó. Chứ theo nguyên tắc thì cột Số Order không được trùng nhau đâu bạn ạ
Bài đã được tự động gộp:

Ai biết cách nào khác giúp em với ạ
 
Upvote 0
bạn hỏi cách khác làm gì vậy? Code trên có vấn đề gì sao?
 
Upvote 0
Đúng là như thế đó bạn. Do file của mình còn nhiều thứ hơn, nên mình rút gọn dữ liệu lại chỉ lấy 3 số đó. Chứ theo nguyên tắc thì cột Số Order không được trùng nhau đâu bạn ạ
Bài đã được tự động gộp:

Ai biết cách nào khác giúp em với ạ
Bạn kiểm tra lại nhé:
Mã:
Option Explicit

Sub update_tiendo()

    Dim shCD As Worksheet, shData As Worksheet, time_1 As Double, time_2 As Double
    Dim r As Long, i As Long, sTienDo As String, sOder As String, arrCD(), arrData()

    Set shCD = ThisWorkbook.Worksheets("DATA CD")
    r = shCD.Cells(shCD.Rows.Count, "C").End(xlUp).Row
    If r < 2 Then Exit Sub
    arrCD = shCD.Range("C2:C" & r).Resize(, 7).Value
    
    Set shData = ThisWorkbook.Worksheets("DATA")
    r = shData.Cells(shData.Rows.Count, "B").End(xlUp).Row
    If r < 3 Then Exit Sub
    arrData = shData.Range("B3:F" & r).Resize(, 5).Value
    
    Dim dic As New Scripting.Dictionary
    
    For i = LBound(arrData, 1) To UBound(arrData, 1)
        sOder = arrData(i, 1)
        If Not dic.Exists(sOder) Then
            dic.Add sOder, i
        End If
    Next i
    
    For i = LBound(arrCD, 1) To UBound(arrCD, 1)
        sOder = arrCD(i, 1)
        If dic.Exists(sOder) Then
            r = dic.Item(sOder)
            sTienDo = arrCD(i, 4)
            time_1 = arrCD(i, 6)
            time_2 = arrData(r, 5)
            If time_1 > time_2 Then
                arrData(r, 5) = time_1
                arrData(r, 4) = sTienDo
            End If
        End If
    Next i
    
    shData.Range("B3").Resize(UBound(arrData, 1), UBound(arrData, 2)).Value = arrData
    
End Sub
 
Upvote 0
Hay quá anh ạ, mấy dòng này cũng có nghe nói, mà em chưa thử nghiệm bao giờ. Không ngờ nhanh hơn nhiều thế
Em cảm ơn nhé.

Ngoài ra thì còn cách nào khác nữa không anh nhỉ?
Không biết kết quả có đúng không? bạn thử test lại kết quả xem thế nào
Mã:
Sub ABC()
    Dim Dic As Object, Arr(), sArr(), iR&, i&, Key, J&, T, Res()
    Set Dic = CreateObject("scripting.dictionary")
    With Sheets("DATA")
        iR = .Range("B" & Rows.Count).End(3).Row
        Arr = .Range("B3:F" & iR).Value
    End With
    ReDim Res(1 To UBound(Arr, 1), 1 To 2)
    For i = 1 To UBound(Arr, 1)
        Key = Arr(i, 1) & "|" & Arr(i, 2) & "|" & Arr(i, 4)
        If Dic.exists(Key) = False Then
            Dic.Item(Key) = i
            Res(i, 1) = Arr(i, 4)
            Res(i, 2) = Arr(i, 5)
        End If
    Next
    With Sheets("DATA CD")
        iR = .Range("C" & Rows.Count).End(3).Row
        sArr = .Range("C2:I" & iR).Value
        For i = 1 To UBound(sArr, 1)
            Key = sArr(i, 1) & "|" & sArr(i, 2) & "|" & sArr(i, 4)
            If Dic.exists(Key) Then
                J = Dic.Item(Key)
                If Format(sArr(i, 6), "0.0000000000") > Format(Arr(J, 5), "0.0000000000") Then
                    Res(J, 2) = sArr(i, 6)
                End If
            End If
        Next
    End With
    Sheet1.Range("G3").Resize(UBound(Arr, 1), 2).Value = Res
End Sub
 
Upvote 0
Bạn kiểm tra lại nhé:
Cột thời gian update thì đã chạy đúng rồi, nhưng có một số vị trí bị thay đổi dữ liệu như ở cột Số Order và mã hàng đó anh
Không biết kết quả có đúng không? bạn thử test lại kết quả xem thế nào
Kết quả quá hoàn hảo ạ. Em cảm ơn mọi người nhiều.

Giờ thì từ từ nghiền ngẫm code thôi. Nhưng cho em hỏi 1 vấn đề là: Tại sao 2 code đều dùng scriping.Dictionary, nhưng của anh Hoàng Nhật Phương lại phải add thư viện, nhưng của anh buiquangthuan thì không nhỉ?
 
Upvote 0
Kết quả quá hoàn hảo ạ. Em cảm ơn mọi người nhiều.

Giờ thì từ từ nghiền ngẫm code thôi. Nhưng cho em hỏi 1 vấn đề là: Tại sao 2 code đều dùng scriping.Dictionary, nhưng của anh Hoàng Nhật Phương lại phải add thư viện, nhưng của anh buiquangthuan thì không nhỉ?
Kết quả đúng á. Sao mình so sánh với cái code cũ của bạn chạy nó có cái chệch. Làm theo dạng trúng thì trúng chẳng trúng thì trượt. Code cua Anh Thơ logic giống y chang của mình. Cái khởi tạo dictionary thì mỗi người viết 1 cách. Nếu trong tool VBA mà chưa kích vô cái scripting ...... Gì đó thì hình như của anh thơ sẽ chạy được sao ấy.
 
Upvote 0
Cột thời gian update thì đã chạy đúng rồi, nhưng có một số vị trí bị thay đổi dữ liệu như ở cột Số Order và mã hàng đó anh

Kết quả quá hoàn hảo ạ. Em cảm ơn mọi người nhiều.

Giờ thì từ từ nghiền ngẫm code thôi. Nhưng cho em hỏi 1 vấn đề là: Tại sao 2 code đều dùng scriping.Dictionary, nhưng của anh Hoàng Nhật Phương lại phải add thư viện, nhưng của anh buiquangthuan thì không nhỉ?
À mà em tìm thấy tài liệu của anh Kyo trên diễn đàn về scriping.Dictionary rồi ạ
Bài đã được tự động gộp:

Kết quả đúng á. Sao mình so sánh với cái code cũ của bạn chạy nó có cái chệch. Làm theo dạng trúng thì trúng chẳng trúng thì trượt. Code cua Anh Thơ logic giống y chang của mình. Cái khởi tạo dictionary thì mỗi người viết 1 cách. Nếu trong tool VBA mà chưa kích vô cái scripting ...... Gì đó thì hình như của anh thơ sẽ chạy được sao ấy.
Bị lệch là do file mẫu của em bị sai đó anh, đúng là cột Số Order phải không có dữ liệu trùng nhau. Nếu sửa dữ liệu lại thì kết quả giống nhau ạ
 
Lần chỉnh sửa cuối:
Upvote 0
Cột thời gian update thì đã chạy đúng rồi, nhưng có một số vị trí bị thay đổi dữ liệu như ở cột Số Order và mã hàng đó anh
......
Giờ thì từ từ nghiền ngẫm code thôi.
Bạn thử lại:
Mã:
Option Explicit     '// Them dong nay de kiem soat cac bien co duoc din nghia day hay khong?
Sub Capnhat_Thoigian()                                  '// Ten thu tuc
    '//Khai bao bien
    Dim dic As Object, arrCD(), arrData(), rData As Range, sKey As String, r As Long, i As Long
    With ThisWorkbook.Worksheets("DATA CD")             '// Lam viec voi Sheet "DATA CD"
        r = .Cells(.Rows.Count, "C").End(xlUp).Row      '// Xac dinh dong cuoi trong co C
        If r < 2 Then Exit Sub                          '// Thoat neu khong co du lieu
        '// Gan du lieu vao arrCD tu C2 den dong cuoi cua cot C quet sang phai 7 cot
        arrCD = .Range("C2:C" & r).Resize(, 7).Value2
    End With                                            '//Ket thuc lam viec voi Sheet "DATA CD"
    With ThisWorkbook.Worksheets("DATA")                '// Lam viec voi Sheet "DATA"
        r = .Cells(.Rows.Count, "B").End(xlUp).Row      '// Xac dinh dong cuoi trong co B
        If r < 3 Then Exit Sub                          '// Thoat neu khong co du lieu
        '// Gan du lieu vao arrData tu B3 den dong cuoi cua cot B quet sang phai 5 cot
        arrData = .Range("B3:F" & r).Resize(, 5).Value2
        Set rData = .Range("B3") 'Gan B3 vao bien rData cho gon de xuong duoi khong phai viet lai ten sheet
    End With                                            '//Ket thuc lam viec voi Sheet "DATA"
    '//Khoi tao DIC
    Set dic = CreateObject("Scripting.Dictionary")
    '// Bat dau duyet tu vi tri dau tien den vi tri cuoi cung theo chieu thu 1 mang arrData
    '// tu tren xuong duoi tuong ung tren bang tinh tu B3:B3157 sheet Data
    For i = LBound(arrData, 1) To UBound(arrData, 1)
        '//Tim kiem theo 3 tieu chi : so oder / ma hang / tien do
        'sKey = arrData(i, 1) & "|" & arrData(i, 2) & arrData(i, 4)
        sKey = arrData(i, 1)                            '//Tim kiem theo 1 tieu chi : so oder
        '//Neu trong DIC chua ton tai sKey,gan sKey vao DIC va ghi nho vi tri thu i
        If Not dic.Exists(sKey) Then dic.Add sKey, i
    Next i                                              '// Ket thuc vong lap (dong cuoi cung)
    '// Bat dau duyet tu vi tri dau tien den vi tri cuoi cung theo chieu thu 1 mang arrData
    '// tu tren xuong duoi tuong ung tren bang tinh tu C2:C4233 sheet "DATA CD"
    For i = LBound(arrCD, 1) To UBound(arrCD, 1)
    '//Tim kiem theo 3 tieu chi : so oder / ma hang / tien do
        '//sKey = arrCD(i, 1) & "|" & arrCD(i, 2) & "|" & arrCD(i, 4)
        sKey = arrCD(i, 1) '//Tim kiem theo 1 tieu chi : so oder
        If dic.Exists(sKey) Then    '// Kiem tra xem sKey co ton tai trong DIC khong
        '/Cung giong voi viec kiem tra so oder trong "DATA CD" co ton tai trong sheet "DATA" khong
            r = dic.Item(sKey)                          '// Neu ton tai tra ve so dong so Oder tim kiem
            '// So sanh thoi gian hoan thanh trong "DATA CD" voi gia tri arrCD(i, 6): cot thu 6(CotH, tu C den H), dong r tim duoc o tren
            '// so voi thoi gian hoan thanh trong sheet "DATA" voi gia tri arrData(r, 5): cot thu 5(CotF, tu B den F), dong r tim duoc o tren
            If arrCD(i, 6) > arrData(r, 5) Then         '// Neu lon hon
                arrData(r, 5) = arrCD(i, 6)             '// Cap nhat thoi gian cua sheet "DATA CD"
                arrData(r, 4) = arrCD(i, 4)             '// Cap nhat tien do cua sheet "DATA CD"
            End If                                      '// Ket thuc If cua neu lon hon
        End If                                          '// Ket thuc If cua neu tim duoc so oder
    Next i                                              '// Ket thuc vong lap (dong cuoi cung)
    r = UBound(arrData, 1)                              '// So dong du lieu sheet DATA khong bao gom dong tieu de
    i = UBound(arrData, 2)                              '// So cot du lieu sheet DATA khong tu B den F
    rData.Resize(r, 2).NumberFormat = "@"               '// Dinh dang cot B,C dang Text tranh sai so oder & ma hang
    rData.Resize(r, i).Value = arrData                  '// Ghi ket qua xuong bang tinh
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Xài thử code này xem được không bạn
Mã:
Sub GPE_hehehe()
On Error Resume Next
Dim i&, DataCD(), SoOrder(), KQ(), Dic As Object, STT()
DataCD = Range(Sheets("DATA CD").[C2], Sheets("DATA CD").[I10000].End(3))
SoOrder = Range(Sheets("DATA").[B3], Sheets("DATA").[B10000].End(3))
ReDim KQ(1 To UBound(SoOrder), 1 To 4)
ReDim STT(1 To UBound(SoOrder), 1 To 1)
Set Dic = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(DataCD)
    Dic(CStr(DataCD(i, 1))) = i
Next
For i = 1 To UBound(SoOrder)
    STT(i, 1) = i
    KQ(i, 1) = DataCD(Dic.Item(CStr(SoOrder(i, 1))), 2)
    KQ(i, 2) = DataCD(Dic.Item(CStr(SoOrder(i, 1))), 3)
    KQ(i, 3) = DataCD(Dic.Item(CStr(SoOrder(i, 1))), 4)
    KQ(i, 4) = DataCD(Dic.Item(CStr(SoOrder(i, 1))), 6)
Next
Sheets("DATA").[A3].Resize(i - 1, 1) = STT
Sheets("DATA").[C3].Resize(i - 1, 4) = KQ
End Sub

Chỉ có điều, ví dụ mã Order "S37" tương ứng cột Tiến độ có 3 kết quả, vậy bạn muốn lấy cái đầu tiên hay lấy cái cuối cùng?
 

File đính kèm

  • DT.xls
    1 MB · Đọc: 1
Lần chỉnh sửa cuối:
Upvote 0
Em mới phát hiện ra 1 điểm khác nhau giữa code của anh và của em.
Code của anh phân biệt chính xác chữ cái viết thường và viết hoa, code của em thì không
Tuy không ảnh hưởng đến chức năng nhưng nếu em muốn sửa code của anh để không phân biệt ký tự viết thường và hoa thì thế nào anh nhỉ?
 
Upvote 1
Em mới phát hiện ra 1 điểm khác nhau giữa code của anh và của em.
Code của anh phân biệt chính xác chữ cái viết thường và viết hoa, code của em thì không
Tuy không ảnh hưởng đến chức năng nhưng nếu em muốn sửa code của anh để không phân biệt ký tự viết thường và hoa thì thế nào anh nhỉ?
Nếu không muốn phân biệt chữ hoa, chữ thường, bạn thêm dòng này sau dòng:

Mã:
Set dic = CreateObject("Scripting.Dictionary")
Dic.comparemode = vbTextCompare

P/s: cái này mới học lỏm được của bác @Ba Tê
 
Upvote 0
Web KT
Back
Top Bottom