Nhờ giúp sửa code bị chậm

Liên hệ QC

Dang Le Khanh Ninh

Thành viên mới
Tham gia
5/6/21
Bài viết
13
Được thích
-2
Xin chào cả nhà. Em là thành viên mới. Em mới tập tọe lập trình. Nay em có viết đoạn code để cập nhật dữ liệu. Em sử dụng 2 vòng lặp for lồng nhau. Khi em chạy chương trình mất tận 20 phút lận. Các cao thủ chỉ giáo giúp em với ạ. Chi tiết các bác xem attach file ạ.
Đoạn code của em như sau:
PHP:
Sub Check_Fabric_Contract()
Dim Row_Order As Variant
Dim Row_Fabric As Variant
Dim i, j As Integer
Dim Fabric_filter As String
Dim PO_filter As String
Dim Row_Copy As Variant
Dim Find_PO As Double
Dim Find_Fabric As Double
Dim Compare_SheetsFabric1 As Variant
Dim Compare_SheetsFabric2 As Variant
Dim Compare_SheetOrder1 As Variant
Dim Compare_SheetOrder2 As Variant

Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
Application.Calculation = xlCalculationManual

'Compare_format'
Sheets("Fabric contract").Select
Compare_SheetFabric1 = WorksheetFunction.Concat(Sheets("Fabric contract").Range("A1:W1"))
Compare_SheetFabric2 = WorksheetFunction.Concat(Sheets("Fabric contract").Range("A2:W2"))
Sheets("Order list").Select
Compare_SheetOrder1 = WorksheetFunction.Concat(Sheets("Order list").Range("A1:W1"))
Compare_SheetOrder2 = WorksheetFunction.Concat(Sheets("Order list").Range("A2:W2"))

If Compare_SheetFabric1 = Compare_SheetFabric2 And Compare_SheetOrder1 = Compare_SheetOrder2 Then

    'Define quantity of Row in Fabric contract'
    Sheets("Fabric contract").Select
    If AutoFilterMode = True Then AutoFilterMode = False
    Sheets("Fabric contract").Range("A3").Select
    Sheets("Fabric contract").Range(Selection, Selection.End(xlDown)).Select
    Row_Fabric = Selection.Count + 2
 
    'Define quantity of Row in Order list'
    Sheets("Order list").Select
    If AutoFilterMode = True Then AutoFilterMode = False
    Sheets("Order list").Range("C2").Select
    Sheets("Order list").Range(Selection, Selection.End(xlDown)).Select
    Row_Order = Selection.Count + 1
 
    'Run program'
    For i = 1 To Row_Fabric - 3
    For j = 1 To Row_Order - 2
    Sheets("Fabric contract").Select
    Fabric_filter = Sheets("Fabric contract").Range("H" & i + 2).Text
    PO_filter = Sheets("Fabric contract").Range("D" & i + 2).Text
    Sheets("Order list").Select
    If AutoFilterMode = True Then AutoFilterMode = False
    Sheets("Order list").Select
    Find_Fabric = Application.IfError(Application.Search(Fabric_filter, Sheets("Order list").Range("K" & j + 2).Text, 1), 0)
    Find_PO = Application.IfError(Application.Search(PO_filter, Sheets("Order list").Range("R" & j + 2).Text, 1), 0)
    If Find_Fabric > 0 And Find_PO > 0 Then
    Sheets("Order list").Range("X" & j + 2).Value = Sheets("Fabric contract").Range("O" & i + 2).Value
    Sheets("Order list").Range("Y" & j + 2).Value = Sheets("Fabric contract").Range("W" & i + 2).Value
    End If
    Next j
    Next i
Else: MsgBox "Incorrect Format"
End If
 
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.AskToUpdateLinks = True
Application.Calculation = xlCalculationAutomatic

End Sub
 

File đính kèm

  • Check.xlsm
    197.3 KB · Đọc: 12
Chỉnh sửa lần cuối bởi điều hành viên:
Tôi cũng vắt óc ra mà cũng không biết Sub Check_Fabric... hoạt động thế nào.
Hàm Concat là hàm gì của EX mà máy tôi chạy cứ báo lỗi?

Thực tình mà nói: do mình dốt ngoại ngữ nên thấy đặt tến biến, tên sub toàn là tiếng Anh thì dị ứng.
Tại sao là Dim PO_filter As String mà không là Dim POloc as String cho dẽ đọc, dễ viết
Hay Dim Compare_SheetsFabric1 As Variant sao không là Dim Rng1 as Variant vừa dễ đọc, dễ viết, viết ngắn hơn....
Vấn đề này tôi cũng đã có một bài để hỏi rồi.
Xét cho cùng đối với người dùng thì tính hiệu quả (chính xác, nhanh) là cần thiết nhất, chứ không nhất thiết là phải đặt tến biến, tên sub, tên hàm có tý ngoại ngữ cho nó có tính quốc tế mới là đẳng cấp hay gì gì đó.
 
Upvote 0
Bạn có thể trình bày rõ hơn về công việc của Sub Check_Fabric_Contract .

.
Cụ thể là em muốn cập nhật tình trạng hàng về từ sheets fabric contract sang sheets order list. ở sheets fabric contract em lấy giá trị của cột PO và của cột Item trên cùng một dòng sau đó tìm ở bên sheet order list dòng nào có Fabric PO và Fabric item code giống thì em sẽ gán ngày Est ETA ở sheets fabric contract sang cột Est ETA của sheets Order list và gán Actual ETA từ sheets fabric contract sang Actual ETA của sheets order list.
 
Upvote 0
Tôi cũng vắt óc ra mà cũng không biết Sub Check_Fabric... hoạt động thế nào.
Hàm Concat là hàm gì của EX mà máy tôi chạy cứ báo lỗi?

Thực tình mà nói: do mình dốt ngoại ngữ nên thấy đặt tến biến, tên sub toàn là tiếng Anh thì dị ứng.
Tại sao là Dim PO_filter As String mà không là Dim POloc as String cho dẽ đọc, dễ viết
Hay Dim Compare_SheetsFabric1 As Variant sao không là Dim Rng1 as Variant vừa dễ đọc, dễ viết, viết ngắn hơn....
Vấn đề này tôi cũng đã có một bài để hỏi rồi.
Xét cho cùng đối với người dùng thì tính hiệu quả (chính xác, nhanh) là cần thiết nhất, chứ không nhất thiết là phải đặt tến biến, tên sub, tên hàm có tý ngoại ngữ cho nó có tính quốc tế mới là đẳng cấp hay gì gì đó.
Em đang học tiếng anh nên em tập dần thế bác ạ. hic. bác thông cảm cho em nhé. chứ không phải em đặt cho đẳng cấp đâu ạ. EM cũng đang mù tịt tiếng anh. huhu
 
Upvote 0
Thực tình mà nói: do mình dốt ngoại ngữ nên thấy đặt tến biến, tên sub toàn là tiếng Anh thì dị ứng.
tên sub, tên hàm có tý ngoại ngữ cho nó có tính quốc tế mới là đẳng cấp hay gì gì đó.
Ngược lại, tôi không thích tên biến tên sub là tiếng Việt. VBA không cho gõ tiếng Việt có dấu nên tên tiếng Việt đọc rất kỳ khôi. Còn nữa: Sub, Variant, Long, Range, Cell, For Next, chẳng tiếng Anh thì là gì? Học tin học bắt buộc phải biết ngoại ngữ tiếng Anh, tất cả thông báo và thông báo lỗi đều là tiếng Anh, chẳng có gì gọi là đẳng cấp hay quốc tế ở đây.

Code tôi chạy hết hơn 2 phút, không sửa gì chỉ xoá các dòng select chỉ còn 7 giây.
 

File đính kèm

  • Check.xlsm
    195.4 KB · Đọc: 14
Upvote 0
Ngược lại, tôi không thích tên biến tên sub là tiếng Việt. VBA không cho gõ tiếng Việt có dấu nên tên tiếng Việt đọc rất kỳ khôi. Còn nữa: Sub, Variant, Long, Range, Cell, For Next, chẳng tiếng Anh thì là gì? Học tin học bắt buộc phải biết ngoại ngữ tiếng Anh, tất cả thông báo và thông báo lỗi đều là tiếng Anh, chẳng có gì gọi là đẳng cấp hay quốc tế ở đây.

Code tôi chạy hết hơn 2 phút, không sửa gì chỉ xoá các dòng select chỉ còn 7 giây.
Cảm ơn bạn rất nhiều! giờ mình mới biết các lệnh select ấy cũng khiến chạy chậm chương trình.
 
Upvote 0
Cảm ơn bạn rất nhiều! giờ mình mới biết các lệnh select ấy cũng khiến chạy chậm chương trình.
Trong 2 vòng lặp lồng nhau, select 100 lần sheet này x select 100 lần sheet kia thành 10 ngàn lần chạy qua chạy lại các sheet, không chóng mặt mới là lạ
 
Upvote 0
Xin chào cả nhà. Em là thành viên mới. Em mới tập tọe lập trình. Nay em có viết đoạn code để cập nhật dữ liệu. Em sử dụng 2 vòng lặp for lồng nhau. Khi em chạy chương trình mất tận 20 phút lận. Các cao thủ chỉ giáo giúp em với ạ. Chi tiết các bác xem attach file ạ.
Tôi không hiểu đoạn này thớt muốn gì:
Rich (BB code):
Sheets("Fabric contract").Select
Compare_SheetFabric1 = WorksheetFunction.Concat(Sheets("Fabric contract").Range("A1:W1"))
Compare_SheetFabric2 = WorksheetFunction.Concat(Sheets("Fabric contract").Range("A2:W2"))
Sheets("Order list").Select
Compare_SheetOrder1 = WorksheetFunction.Concat(Sheets("Order list").Range("A1:W1"))
Compare_SheetOrder2 = WorksheetFunction.Concat(Sheets("Order list").Range("A2:W2"))

If Compare_SheetFabric1 = Compare_SheetFabric2 And Compare_SheetOrder1 = Compare_SheetOrder2 Then

Hai dòng mà thớt so sánh đó là 2 dòng tiêu đề được lặp lại nguyên xi, không liên quan gì đến code trong If ... Enf If cả
 
Upvote 0
Tôi không hiểu đoạn này thớt muốn gì:
Rich (BB code):
Sheets("Fabric contract").Select
Compare_SheetFabric1 = WorksheetFunction.Concat(Sheets("Fabric contract").Range("A1:W1"))
Compare_SheetFabric2 = WorksheetFunction.Concat(Sheets("Fabric contract").Range("A2:W2"))
Sheets("Order list").Select
Compare_SheetOrder1 = WorksheetFunction.Concat(Sheets("Order list").Range("A1:W1"))
Compare_SheetOrder2 = WorksheetFunction.Concat(Sheets("Order list").Range("A2:W2"))

If Compare_SheetFabric1 = Compare_SheetFabric2 And Compare_SheetOrder1 = Compare_SheetOrder2 Then

Hai dòng mà thớt so sánh đó là 2 dòng tiêu đề được lặp lại nguyên xi, không liên quan gì đến code trong If ... Enf If cả
Vì file e sẽ lấy từ người khác nên em cố định dòng đầu tiên để khi em paste file khác vào nó sẽ báo là định dạng có khớp không ấy ạ.
 
Upvote 0
Theo nội dung câu trả lời thì bạn ấy "tập dần" tiếng Anh chứ không phải tập dần code.
Em trích dẫn một phần để có cái 'kết nối'.

--------------
Em tự làm thôi ạ. vì trước có được học lập trình VBA ở trên trường nhưng là học không chuyên sâu nên em cà dốt lắm.

PHP:
Dim i, j As Integer
Khai báo như thế thì chỉ có biến j được khai báo kiểu Integer, còn biến i không khai báo gì và nó được nhận mặc định kiểu Variant.
Kiểu tra bằng cách đơn giản:
PHP:
Sub Vidu()
Dim i, j As Integer
Msgbox typename(i)
End Sub

File Excel 2007 trở lên có 1048576 dòng, vậy nên khai báo j kiểu Integer 1629516552499.png
sẽ dính lỗi vượt tầm vực (overflow)


1629516526575.png
 
Upvote 0
Em trích dẫn một phần để có cái 'kết nối'.
--------------
Khai báo như thế thì chỉ có biến j được khai báo kiểu Integer,
Do mới học và tự học nên còn nhiều lỗi:
- lỗi integer (như đã nói)
- khai báo variant nhiều quá
- lỗi select tràn lan
- lỗi lặp lệnh (select 1 sheet 2 lần trong cùng 1 vòng lặp, 1 sheet autofilterMode = False 2 lần, trong đó 1 lần trong vòng lặp thành 10 ngàn lần)
- ...

Tôi không hiểu đoạn này thớt muốn gì:

Theo tôi đoán thì ban đầu sheet trắng, dòng 1 là tiêu đề chuẩn. Khi copy dữ liệu của file khác về (có thể là của người khác), thì copy cả tiêu đề về vào dòng 2, và phải kiểm tra đúng thứ tự cột so với dòng 1 đang chuẩn.
 
Upvote 0
Xin chào cả nhà. Em là thành viên mới. Em mới tập tọe lập trình. Nay em có viết đoạn code để cập nhật dữ liệu. Em sử dụng 2 vòng lặp for lồng nhau. Khi em chạy chương trình mất tận 20 phút lận. Các cao thủ chỉ giáo giúp em với ạ. Chi tiết các bác xem attach file ạ.
Đoạn code của em như sau:
PHP:
Sub Check_Fabric_Contract()
Dim Row_Order As Variant
Dim Row_Fabric As Variant
Dim i, j As Integer
Dim Fabric_filter As String
Dim PO_filter As String
Dim Row_Copy As Variant
Dim Find_PO As Double
Dim Find_Fabric As Double
Dim Compare_SheetsFabric1 As Variant
Dim Compare_SheetsFabric2 As Variant
Dim Compare_SheetOrder1 As Variant
Dim Compare_SheetOrder2 As Variant

Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
Application.Calculation = xlCalculationManual

'Compare_format'
Sheets("Fabric contract").Select
Compare_SheetFabric1 = WorksheetFunction.Concat(Sheets("Fabric contract").Range("A1:W1"))
Compare_SheetFabric2 = WorksheetFunction.Concat(Sheets("Fabric contract").Range("A2:W2"))
Sheets("Order list").Select
Compare_SheetOrder1 = WorksheetFunction.Concat(Sheets("Order list").Range("A1:W1"))
Compare_SheetOrder2 = WorksheetFunction.Concat(Sheets("Order list").Range("A2:W2"))

If Compare_SheetFabric1 = Compare_SheetFabric2 And Compare_SheetOrder1 = Compare_SheetOrder2 Then

    'Define quantity of Row in Fabric contract'
    Sheets("Fabric contract").Select
    If AutoFilterMode = True Then AutoFilterMode = False
    Sheets("Fabric contract").Range("A3").Select
    Sheets("Fabric contract").Range(Selection, Selection.End(xlDown)).Select
    Row_Fabric = Selection.Count + 2
 
    'Define quantity of Row in Order list'
    Sheets("Order list").Select
    If AutoFilterMode = True Then AutoFilterMode = False
    Sheets("Order list").Range("C2").Select
    Sheets("Order list").Range(Selection, Selection.End(xlDown)).Select
    Row_Order = Selection.Count + 1
 
    'Run program'
    For i = 1 To Row_Fabric - 3
    For j = 1 To Row_Order - 2
    Sheets("Fabric contract").Select
    Fabric_filter = Sheets("Fabric contract").Range("H" & i + 2).Text
    PO_filter = Sheets("Fabric contract").Range("D" & i + 2).Text
    Sheets("Order list").Select
    If AutoFilterMode = True Then AutoFilterMode = False
    Sheets("Order list").Select
    Find_Fabric = Application.IfError(Application.Search(Fabric_filter, Sheets("Order list").Range("K" & j + 2).Text, 1), 0)
    Find_PO = Application.IfError(Application.Search(PO_filter, Sheets("Order list").Range("R" & j + 2).Text, 1), 0)
    If Find_Fabric > 0 And Find_PO > 0 Then
    Sheets("Order list").Range("X" & j + 2).Value = Sheets("Fabric contract").Range("O" & i + 2).Value
    Sheets("Order list").Range("Y" & j + 2).Value = Sheets("Fabric contract").Range("W" & i + 2).Value
    End If
    Next j
    Next i
Else: MsgBox "Incorrect Format"
End If
 
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.AskToUpdateLinks = True
Application.Calculation = xlCalculationAutomatic

End Sub
Dùng Dic để tăng tốc code
Mã:
Sub Check()
  Dim sArr(), oArr(), res(), S, S2, T, dic As Object
  Dim sRow&, i&, j&, j2&
 
  Set dic = CreateObject("scripting.dictionary")
  dic.CompareMode = vbTextCompare
  With Sheets("Fabric contract")
    For j = 1 To 23
      If .Cells(1, j) <> .Cells(2, j) Then MsgBox "Incorrect Format": Exit Sub
    Next j
    If .AutoFilterMode = True Then .AutoFilterMode = False
    sArr = .Range("D3", .Range("W" & .Range("D1000000").End(xlUp).Row)).Value
  End With
  With Sheets("Order list")
    For j = 1 To 23
      If .Cells(1, j) <> .Cells(2, j) Then MsgBox "Incorrect Format": Exit Sub
    Next j
    If .AutoFilterMode = True Then .AutoFilterMode = False
    oArr = .Range("K3", .Range("R1000000").End(xlUp)).Value
  End With
 
  sRow = UBound(sArr)
  For i = 1 To sRow
    dic.Item(sArr(i, 1) & "|" & sArr(i, 5)) = Array(sArr(i, 12), sArr(i, 20))
  Next i
  Call TangToc(False)
  sRow = UBound(oArr)
  ReDim res(1 To sRow, 1 To 2)
  For i = 1 To sRow
    S = Split("/" & oArr(i, 8), "/")
    S2 = Split("/" & oArr(i, 1), "/")
    For j = 1 To UBound(S)
      For j2 = 1 To UBound(S2)
        If dic.exists(S(j) & "|" & S2(j2)) Then
          T = dic.Item(S(j) & "|" & S2(j2))
          res(i, 1) = T(0)
          res(i, 2) = T(1)
        End If
      Next j2
    Next j
  Next i
  Sheets("Order list").Range("X3").Resize(sRow, 2) = res
  Call TangToc(True)
  MsgBox "Xong!"
End Sub

Sub TangToc(ByVal bT As Boolean)
  Application.ScreenUpdating = bT
  Application.DisplayAlerts = bT
  Application.AskToUpdateLinks = bT
End Sub
 
Upvote 0
Xin chào cả nhà. Em là thành viên mới. Em mới tập tọe lập trình. Nay em có viết đoạn code để cập nhật dữ liệu. Em sử dụng 2 vòng lặp for lồng nhau. Khi em chạy chương trình mất tận 20 phút lận. Các cao thủ chỉ giáo giúp em với ạ. Chi tiết các bác xem attach file ạ.
Dùng mảng xem thử bạn nhé. Chạy hết 0,125 giây.

Không bì được với tốc độ thực thi code bài #19 nhưng được cái là code ngắn và dễ đọc --=0
Rich (BB code):
Sub Find_n_Fill()
Dim arrC, arrL, arrR
Dim i&, j&, k&
Dim tmr#

tmr = Timer()
arrC = Sheet1.Range("A3:W" & Sheet1.Range("A" & Rows.Count).End(xlUp).Row)
arrL = Sheet2.Range("A3:W" & Sheet2.Range("A" & Rows.Count).End(xlUp).Row)
ReDim arrR(1 To UBound(arrL), 1 To 2)

For i = 1 To UBound(arrC)
    For j = 1 To UBound(arrL)
        If InStr(1, arrL(j, 11), arrC(i, 8)) And InStr(1, arrL(j, 18), arrC(i, 4)) Then
            arrR(j, 1) = arrC(i, 15)
            arrR(j, 2) = arrC(i, 23)
        End If
    Next
Next
Sheet2.Range("X3").Resize(UBound(arrL), 2).ClearContents
Sheet2.Range("X3").Resize(UBound(arrL), 2) = arrR
MsgBox Timer() - tmr
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

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

Back
Top Bottom