VBA lồng 2 phương thức Find (1 người xem)

Liên hệ QC

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

chipiu3001

Thành viên hoạt động
Tham gia
22/8/15
Bài viết
105
Được thích
15
Chào anh chị em

Mình có tạo VBA tính toán số điểm cho NCC.
Giao chậm thì bị trừ điểm.

Mình có lồng 2 phương thức Find
- Tìm ngày KH về sau đó tìm ngày giao hàng.
Tuy nhiên bị báo lỗi này
1705283188451.png
Không biết có phải không thể lồng 2 phương thức find vào nhau không. Các bạn xem file đính kèm lý giải giúp mình với nhé.

Mình cảm ơn nhiều
1705283171394.png
 

File đính kèm

Cách trừ điểm của bạn được tính như nào. Mô tả rõ hơn 1 chút được không?
 
Upvote 0
Giải pháp
Cảm ơn bạn. Cái trừ điểm đó là 1 phần tính toán ( Mình nghĩ nó ko ảnh hưởng đến code chạy) . Cho dù mình xóa cái trừ đó đi thì vẫn bị lỗi.
Xóa cái phương thức Find thứ 2 đi thì chạy bình thường ko báo lỗi nữa. Nên mình nghi 2 cái find không lồng vào nhau được

If NgayGH - NgayKH < 1 Then 'giao hang truoc
D = D
ElseIf NgayGH - NgayKH < 3 Then ' Giao hang muon 1~2 ngay
D = D - 2
ElseIf NgayGH - NgayKH < 5 Then ' giao hang muon 3~4 ngay
D = D - 5
Else ' Giao hang muon tren 5 ngay
D = D - 7
End If

X ~ NgayKH: tương ứng ngày KH về
O ~ NgayGH : tương ứng ngày giao hàng

Cách tính thì như trên nhé.

Cảm ơn bạn
 
Upvote 0
Hình như thế gian này không có Loop While, chỉ có Do While ... Loop và vài thứ nữa
 
Upvote 0
Vâng . Xin lỗi anh e không hiểu rõ ý của anh.

Do While .... Loop => Kiểm tra điều khiện ở đầu vòng lặp.
Do ....Loop While => Kiểm tra điều khiện ở cuối vòng lặp.

Anh có thể chỉ lại giúp em được không ạ

Em cảm ơn
 
Upvote 0
Chào anh chị em

Mình có tạo VBA tính toán số điểm cho NCC.
Giao chậm thì bị trừ điểm.

Mình có lồng 2 phương thức Find
- Tìm ngày KH về sau đó tìm ngày giao hàng.
Tuy nhiên bị báo lỗi này
View attachment 298458
Không biết có phải không thể lồng 2 phương thức find vào nhau không. Các bạn xem file đính kèm lý giải giúp mình với nhé.

Mình cảm ơn nhiều

Một kỹ thuật tìm lỗi là bạn rê con chuột vào từng đối tượng ở dòng màu vàng để xem nó có trả giá trị gì về không. Cụ thể ở cái "KH.Address" là không có giá trị gì ==> lỗi chỗ "Set KH..."
 
Upvote 0
Lỗi ở dòng Loop While ở trên là KH lúc đó nó không phải là một Range Object, nên không để truy xuất Address

Bạn cần thêm lệnh bẫy lỗi đầu thủ tục: On Error Resume Next
Kiểm tra:
JavaScript:
    Err.Clear: Set KH = ...
    If Err <> 0 Or KH Is Nothing Then Exit Do
 
Upvote 0
Một kỹ thuật tìm lỗi là bạn rê con chuột vào từng đối tượng ở dòng màu vàng để xem nó có trả giá trị gì về không. Cụ thể ở cái "KH.Address" là không có giá trị gì ==> lỗi chỗ "Set KH..."
Cảm ơn bạn. Mình cũng đã biết việc này nhưng không hiểu tại sao lại lỗi.
Nếu xóa đoạn giữa này đi ( Xóa 1 phương thức Find) thì code chạy ko lỗi. Thêm Msgbox (KH.address) => chạy sẽ tìm ra được nhiều địa chỉ có chưa X.
Cảm ơn bạn

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

Lỗi ở dòng Loop While ở trên là KH lúc đó nó không phải là một Range Object, nên không để truy xuất Address

Bạn cần thêm lệnh bẫy lỗi đầu thủ tục: On Error Resume Next
Kiểm tra:
JavaScript:
    Err.Clear: Set KH = ...
    If Err <> 0 Or KH Is Nothing Then Exit Do
Chào bạn. Thêm đoạn bẫy lỗi thì sẽ chỉ tìm được 1 lần Kế hoạch "X" duy nhất thôi, Không tìm được các lần kế hoạch về tiếp theo để so sánh.
Mình chưa hiểu tại sao set KH vậy lại bằng nothing.

Cảm ơn bạn nhiều
Bài đã được tự động gộp:

Lỗi ở dòng Loop While ở trên là KH lúc đó nó không phải là một Range Object, nên không để truy xuất Address

Bạn cần thêm lệnh bẫy lỗi đầu thủ tục: On Error Resume Next
Kiểm tra:
JavaScript:
    Err.Clear: Set KH = ...
    If Err <> 0 Or KH Is Nothing Then Exit Do
Chào bạn. Thêm đoạn bẫy lỗi thì sẽ chỉ tìm được 1 lần Kế hoạch "X" duy nhất thôi, Không tìm được các lần kế hoạch về tiếp theo để so sánh.
Mình chưa hiểu tại sao set KH vậy lại bằng nothing.

Cảm ơn bạn nhiều
 

File đính kèm

  • 1705294156570.png
    1705294156570.png
    134.4 KB · Đọc: 3
Upvote 0
Gán Vùng ô nguồn vào một biến rồi mới dùng Find bạn nhé
JavaScript:
Dim rg, KH
Set rg = Sheet1.Range(Sheet1.Cells(...),Sheet1.Cells(...))
Set KH= rg.Find(...)
Set KH= rg.FindNext(KH)
 
Upvote 0
@Chủ bài đăng: Phương thức FIND() không thể lồng vô nhau được;
& mình cũng chưa rõ khái niệm 'tìm ngày khách hàng (KH) về' là như thế nào?
Thứ nữa: Các ô chứa dữ liệu không nên trộn như bạn; Tuy có đẹp như lắm phiền phức khi xài VBA
 
Upvote 0
Lỗi ở dòng Loop While ở trên là KH lúc đó nó không phải là một Range Object, nên không để truy xuất Address

Bạn cần thêm lệnh bẫy lỗi đầu thủ tục: On Error Resume Next
Kiểm tra:
JavaScript:
    Err.Clear: Set KH = ...
    If Err <> 0 Or KH Is Nothing Then Exit Do
Chào bạn. Thêm đoạn bẫy lỗi thì sẽ chỉ tìm được 1 lần Kế hoạch "X" duy nhất thôi, Không tìm được các lần kế hoạch về tiếp theo để so sánh.
Mình chưa hiểu tại sao set KH vậy lại bằng nothing.

Cảm ơn bạn nhiều
Gán Vùng ô nguồn vào một biến rồi mới dùng Find bạn nhé
JavaScript:
Dim rg, KH
Set rg = Sheet1.Range(Sheet1.Cells(...),Sheet1.Cells(...))
Set KH= rg.Find(...)
Set KH= rg.FindNext(KH)
Cảm ơn bạn.
Gán biến bên trên theo mình thấy chỉ thu gọn code lại thôi. Mình chạy vẫn bị lỗi. Mình gửi file đã sửa. Bạn xem giúp mình nhé.

Cảm ơn bạn.
Bài đã được tự động gộp:

Lỗi ở dòng Loop While ở trên là KH lúc đó nó không phải là một Range Object, nên không để truy xuất Address

Bạn cần thêm lệnh bẫy lỗi đầu thủ tục: On Error Resume Next
Kiểm tra:
JavaScript:
    Err.Clear: Set KH = ...
    If Err <> 0 Or KH Is Nothing Then Exit Do
Chào bạn. Thêm đoạn bẫy lỗi thì sẽ chỉ tìm được 1 lần Kế hoạch "X" duy nhất thôi, Không tìm được các lần kế hoạch về tiếp theo để so sánh.
Mình chưa hiểu tại sao set KH vậy lại bằng nothing.

Cảm ơn bạn nhiều
Gán Vùng ô nguồn vào một biến rồi mới dùng Find bạn nhé
JavaScript:
Dim rg, KH
Set rg = Sheet1.Range(Sheet1.Cells(...),Sheet1.Cells(...))
Set KH= rg.Find(...)
Set KH= rg.FindNext(KH)
Cảm ơn bạn.
Gán biến bên trên theo mình thấy chỉ thu gọn code lại thôi. Mình chạy vẫn bị lỗi. Mình gửi file đã sửa. Bạn xem giúp mình nhé.

Cảm ơn bạn.
Bài đã được tự động gộp:

Lỗi ở dòng Loop While ở trên là KH lúc đó nó không phải là một Range Object, nên không để truy xuất Address

Bạn cần thêm lệnh bẫy lỗi đầu thủ tục: On Error Resume Next
Kiểm tra:
JavaScript:
    Err.Clear: Set KH = ...
    If Err <> 0 Or KH Is Nothing Then Exit Do
Chào bạn. Thêm đoạn bẫy lỗi thì sẽ chỉ tìm được 1 lần Kế hoạch "X" duy nhất thôi, Không tìm được các lần kế hoạch về tiếp theo để so sánh.
Mình chưa hiểu tại sao set KH vậy lại bằng nothing.

Cảm ơn bạn nhiều
Gán Vùng ô nguồn vào một biến rồi mới dùng Find bạn nhé
JavaScript:
Dim rg, KH
Set rg = Sheet1.Range(Sheet1.Cells(...),Sheet1.Cells(...))
Set KH= rg.Find(...)
Set KH= rg.FindNext(KH)
Cảm ơn bạn.
Gán biến bên trên theo mình thấy chỉ thu gọn code lại thôi. Mình chạy vẫn bị lỗi. Mình gửi file đã sửa. Bạn xem giúp mình nhé.

Cảm ơn bạn.
@Chủ bài đăng: Phương thức FIND() không thể lồng vô nhau được;
& mình cũng chưa rõ khái niệm 'tìm ngày khách hàng (KH) về' là như thế nào?
Thứ nữa: Các ô chứa dữ liệu không nên trộn như bạn; Tuy có đẹp như lắm phiền phức khi xài VBA
Chào anh.
Đúng là VBA mà trộn ô thì sau phát triển tiếp rất khó.
File này em chỉ làm code trong phạm vi không trộn ô thôi.
Em giải thích lại .

1 NCC có 2 dòng.
- 1 dòng tương ứng ngày kế hoạch giao : Đánh "X"
- 1 dòng tương ứng ngày giao hàng thực tế : Đánh"O"
- Trong tháng ( file chỉ 1 tháng 1) có nhiều lần KH và GH ("X" và "O)
Code:

+ So sánh ngày kế hoạch và ngày giao hàng.
-Nếu giao trước thì dc 0 điểm ( ko bị trừ)
- Nếu giao muộn 1~2 ngày thì bị trừ 2 điểm
- Nếu giao muộn 3~4 ngày bị trừ 5 điểm
- Nếu giao muộn trên 5 ngày trừ 7 điểm.

Em cảm ơn a
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Tôi chỉ giúp bạn sửa mã, còn bài toán đáng lý ra là phải đăng ngay từ bài viết đầu để nhận trợ giúp về bài toán.

JavaScript:
Sub tinh_toan()

  Dim NgayGH%, NgayKH%, D%, n%, GH_BD%
  Dim cell As Range, rg0 As Range, rg As Range, KH As Range, KHFirstAddress As String
  Dim GH As Range, GHFirstAddress As String
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Const GH_KT = 35 ' cot Ngay GH ket thuc
  Set cell = [A5]
  For n = 1 To 32 Step 2 ' SL NCC
    D = 0: GH_BD = 5 ' cot Ngay GH bat dau
    Set rg = cell(n, KH_BD).Resize(, 31)
    Set KH = rg.Find("X", After:=rg(1, 31), LookIn:=xlValues, LookAt:=xlWhole)
    If Not KH Is Nothing Then
      KHFirstAddress = KH.Address
      Do
        NgayKH = KH.Column
        Set rg0 = cell(n + 1, GH_BD).Resize(, GH_KT - GH_BD + 1)
        Set GH = rg0.Find("O", After:=rg0(1, rg0.Columns.Count), LookIn:=xlValues, LookAt:=xlWhole)
        If Not GH Is Nothing Then
          GHFirstAddress = GH.Address
          NgayGH = GH.Column
          GH_BD = NgayGH + 1 ' Vùng tim kiem "O" se duoc thu hep lai trong lan Loop tìm "X" tiep theo
        Else
          D = D - 7: Exit Do' Khong co ngay giao hang ( chua giao hang)
        End If
        Select Case NgayGH - NgayKH
        Case Is < 1: D = D     'giao hang truoc
        Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
        Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
        Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
        End Select
        Set KH = rg.FindNext(KH)
        If KH Is Nothing Then Exit Do
        If KHFirstAddress = KH.Address Then Exit Do
      Loop
      cell(n, KH_KT + 1).Value = D ' Diem
    Else
    End If
  Next
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Giải bài toán của bạn:

JavaScript:
Sub tinh_toan()
  Dim NgayKH%, D%, n%, i%, cell As Range, rg As Range
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Set cell = [A5]: n = 1
  While cell(n, 1).Value <> Empty
    D = 0
    Set rg = cell(n, KH_BD).Resize(2, 31)
    For i = 1 To 31
      If CStr(rg(1, i).Value) = "X" Then
        If NgayKH > 0 Then D = D - 7
        NgayKH = i
      End If
      If CStr(rg(2, i).Value) = "O" Then GoSub v: NgayKH = 0
    Next
    rg(1, i).Value = D
    n = n + cell(n, 1).MergeArea.Rows.Count
  Wend
Exit Sub
v:
  Select Case i - NgayKH
  Case Is < 1: D = D     ' giao hang truoc
  Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
  Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
  Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
  End Select
Return
End Sub
 
Upvote 0
Chào anh chị em

Mình có tạo VBA tính toán số điểm cho NCC.
Giao chậm thì bị trừ điểm.

Mình có lồng 2 phương thức Find
- Tìm ngày KH về sau đó tìm ngày giao hàng.
Tuy nhiên bị báo lỗi này
View attachment 298458
Không biết có phải không thể lồng 2 phương thức find vào nhau không. Các bạn xem file đính kèm lý giải giúp mình với nhé.

Mình cảm ơn nhiều
View attachment 298457
Dùng mảng và vòng For
Mã:
Sub XYZ()
  Dim arr(), res(), sRow&, sCol&, i&, j&, c&, d&, fC&, cl&
 
  arr = Range("B5", Range("AI" & Range("B1000000").End(xlUp).Row + 1)).Value
  sRow = UBound(arr):             sCol = UBound(arr, 2)
  ReDim res(1 To sRow, 1 To 1)
  For i = 1 To sRow
    If arr(i, 1) <> Empty Then
      d = 0: fC = 4
      For j = 4 To sCol
        If UCase(arr(i, j)) = "X" Then
          For c = fC To sCol
            If UCase(arr(i + 1, c)) = "O" Then
              cl = c - j
              If cl > 4 Then 'Tru 7 diem
                d = d - 7
              ElseIf cl > 2 Then 'Tru 5 diem
                d = d - 5
              ElseIf cl > 0 Then 'Tru 2 diem
                d = d - 2
              End If
              fC = c + 1
              Exit For
            End If
          Next c
          If c = sCol + 1 Then d = d - 7 'Tru 7 diem
        End If
      Next j
      res(i, 1) = d
    End If
  Next i
  Range("AJ5").Resize(sRow) = res
End Sub
 
Upvote 0
Khổ. Bà con chỉ tuông code ra chứ chẳng ai chịu viết giải thuật.
Mình muốn xem có ai có ý tưởng hay mà đọc code thì mệt quá.
 
Upvote 0
Lỗi ở dòng Loop While ở trên là KH lúc đó nó không phải là một Range Object, nên không để truy xuất Address

Bạn cần thêm lệnh bẫy lỗi đầu thủ tục: On Error Resume Next
Kiểm tra:
JavaScript:
    Err.Clear: Set KH = ...
    If Err <> 0 Or KH Is Nothing Then Exit Do
Chào bạn. Thêm đoạn bẫy lỗi thì sẽ chỉ tìm được 1 lần Kế hoạch "X" duy nhất thôi, Không tìm được các lần kế hoạch về tiếp theo để so sánh.
Mình chưa hiểu tại sao set KH vậy lại bằng nothing.

Cảm ơn bạn nhiều
Gán Vùng ô nguồn vào một biến rồi mới dùng Find bạn nhé
JavaScript:
Dim rg, KH
Set rg = Sheet1.Range(Sheet1.Cells(...),Sheet1.Cells(...))
Set KH= rg.Find(...)
Set KH= rg.FindNext(KH)
Cảm ơn bạn.
Gán biến bên trên theo mình thấy chỉ thu gọn code lại thôi. Mình chạy vẫn bị lỗi. Mình gửi file đã sửa. Bạn xem giúp mình nhé.

Cảm ơn bạn.
@Chủ bài đăng: Phương thức FIND() không thể lồng vô nhau được;
& mình cũng chưa rõ khái niệm 'tìm ngày khách hàng (KH) về' là như thế nào?
Thứ nữa: Các ô chứa dữ liệu không nên trộn như bạn; Tuy có đẹp như lắm phiền phức khi xài VBA
Chào anh.
Đúng là VBA mà trộn ô thì sau phát triển tiếp rất khó.
File này em chỉ làm code trong phạm vi không trộn ô thôi.
Em giải thích lại .

1 NCC có 2 dòng.
- 1 dòng tương ứng ngày kế hoạch giao : Đánh "X"
- 1 dòng tương ứng ngày giao hàng thực tế : Đánh"O"
- Trong tháng ( file chỉ 1 tháng 1) có nhiều lần KH và GH ("X" và "O)
Code:

+ So sánh ngày kế hoạch và ngày giao hàng.
-Nếu giao trước thì dc 0 điểm ( ko bị trừ)
- Nếu giao muộn 1~2 ngày thì bị trừ 2 điểm
- Nếu giao muộn 3~4 ngày bị trừ 5 điểm
- Nếu giao muộn trên 5 ngày trừ 7 điểm.

Em cảm ơn a
Tôi chỉ giúp bạn sửa mã, còn bài toán đáng lý ra là phải đăng ngay từ bài viết đầu để nhận trợ giúp về bài toán.

JavaScript:
Sub tinh_toan()

  Dim NgayGH%, NgayKH%, D%, n%, GH_BD%
  Dim cell As Range, rg0 As Range, rg As Range, KH As Range, KHFirstAddress As String
  Dim GH As Range, GHFirstAddress As String
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Const GH_KT = 35 ' cot Ngay GH ket thuc
  Set cell = [A5]
  For n = 1 To 32 Step 2 ' SL NCC
    D = 0: GH_BD = 5 ' cot Ngay GH bat dau
    Set rg = cell(n, KH_BD).Resize(, 31)
    Set KH = rg.Find("X", After:=rg(1, 31), LookIn:=xlValues, LookAt:=xlWhole)
    If Not KH Is Nothing Then
      KHFirstAddress = KH.Address
      Do
        NgayKH = KH.Column
        Set rg0 = cell(n + 1, GH_BD).Resize(, GH_KT - GH_BD + 1)
        Set GH = rg0.Find("O", After:=rg0(1, rg0.Columns.Count), LookIn:=xlValues, LookAt:=xlWhole)
        If Not GH Is Nothing Then
          GHFirstAddress = GH.Address
          NgayGH = GH.Column
          GH_BD = NgayGH + 1 ' Vùng tim kiem "O" se duoc thu hep lai trong lan Loop tìm "X" tiep theo
        Else
          D = D - 7: Exit Do' Khong co ngay giao hang ( chua giao hang)
        End If
        Select Case NgayGH - NgayKH
        Case Is < 1: D = D     'giao hang truoc
        Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
        Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
        Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
        End Select
        Set KH = rg.FindNext(KH)
        If KH Is Nothing Then Exit Do
        If KHFirstAddress = KH.Address Then Exit Do
      Loop
      cell(n, KH_KT + 1).Value = D ' Diem
    Else
    End If
  Next
End Sub
Cảm ơn bạn đã sửa code giúp mình.
Set KH = rg.FindNext(KH)
If KH Is Nothing Then Exit Do
If KHFirstAddress = KH.Address Then Exit Do
Đoạn này làm cho chỉ tìm được 1 ngày KH~ X trong khi đó 1 tháng có nhiều ngày đánh X.
Mình vẫn chưa hiểu lồng 2 phương thức Find thì KH lại bằng nothing với lần FindNext thứ 2.

Cảm ơn bạn nhiều
Bài đã được tự động gộp:

Lỗi ở dòng Loop While ở trên là KH lúc đó nó không phải là một Range Object, nên không để truy xuất Address

Bạn cần thêm lệnh bẫy lỗi đầu thủ tục: On Error Resume Next
Kiểm tra:
JavaScript:
    Err.Clear: Set KH = ...
    If Err <> 0 Or KH Is Nothing Then Exit Do
Chào bạn. Thêm đoạn bẫy lỗi thì sẽ chỉ tìm được 1 lần Kế hoạch "X" duy nhất thôi, Không tìm được các lần kế hoạch về tiếp theo để so sánh.
Mình chưa hiểu tại sao set KH vậy lại bằng nothing.

Cảm ơn bạn nhiều
Gán Vùng ô nguồn vào một biến rồi mới dùng Find bạn nhé
JavaScript:
Dim rg, KH
Set rg = Sheet1.Range(Sheet1.Cells(...),Sheet1.Cells(...))
Set KH= rg.Find(...)
Set KH= rg.FindNext(KH)
Cảm ơn bạn.
Gán biến bên trên theo mình thấy chỉ thu gọn code lại thôi. Mình chạy vẫn bị lỗi. Mình gửi file đã sửa. Bạn xem giúp mình nhé.

Cảm ơn bạn.
@Chủ bài đăng: Phương thức FIND() không thể lồng vô nhau được;
& mình cũng chưa rõ khái niệm 'tìm ngày khách hàng (KH) về' là như thế nào?
Thứ nữa: Các ô chứa dữ liệu không nên trộn như bạn; Tuy có đẹp như lắm phiền phức khi xài VBA
Chào anh.
Đúng là VBA mà trộn ô thì sau phát triển tiếp rất khó.
File này em chỉ làm code trong phạm vi không trộn ô thôi.
Em giải thích lại .

1 NCC có 2 dòng.
- 1 dòng tương ứng ngày kế hoạch giao : Đánh "X"
- 1 dòng tương ứng ngày giao hàng thực tế : Đánh"O"
- Trong tháng ( file chỉ 1 tháng 1) có nhiều lần KH và GH ("X" và "O)
Code:

+ So sánh ngày kế hoạch và ngày giao hàng.
-Nếu giao trước thì dc 0 điểm ( ko bị trừ)
- Nếu giao muộn 1~2 ngày thì bị trừ 2 điểm
- Nếu giao muộn 3~4 ngày bị trừ 5 điểm
- Nếu giao muộn trên 5 ngày trừ 7 điểm.

Em cảm ơn a
Tôi chỉ giúp bạn sửa mã, còn bài toán đáng lý ra là phải đăng ngay từ bài viết đầu để nhận trợ giúp về bài toán.

JavaScript:
Sub tinh_toan()

  Dim NgayGH%, NgayKH%, D%, n%, GH_BD%
  Dim cell As Range, rg0 As Range, rg As Range, KH As Range, KHFirstAddress As String
  Dim GH As Range, GHFirstAddress As String
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Const GH_KT = 35 ' cot Ngay GH ket thuc
  Set cell = [A5]
  For n = 1 To 32 Step 2 ' SL NCC
    D = 0: GH_BD = 5 ' cot Ngay GH bat dau
    Set rg = cell(n, KH_BD).Resize(, 31)
    Set KH = rg.Find("X", After:=rg(1, 31), LookIn:=xlValues, LookAt:=xlWhole)
    If Not KH Is Nothing Then
      KHFirstAddress = KH.Address
      Do
        NgayKH = KH.Column
        Set rg0 = cell(n + 1, GH_BD).Resize(, GH_KT - GH_BD + 1)
        Set GH = rg0.Find("O", After:=rg0(1, rg0.Columns.Count), LookIn:=xlValues, LookAt:=xlWhole)
        If Not GH Is Nothing Then
          GHFirstAddress = GH.Address
          NgayGH = GH.Column
          GH_BD = NgayGH + 1 ' Vùng tim kiem "O" se duoc thu hep lai trong lan Loop tìm "X" tiep theo
        Else
          D = D - 7: Exit Do' Khong co ngay giao hang ( chua giao hang)
        End If
        Select Case NgayGH - NgayKH
        Case Is < 1: D = D     'giao hang truoc
        Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
        Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
        Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
        End Select
        Set KH = rg.FindNext(KH)
        If KH Is Nothing Then Exit Do
        If KHFirstAddress = KH.Address Then Exit Do
      Loop
      cell(n, KH_KT + 1).Value = D ' Diem
    Else
    End If
  Next
End Sub
Cảm ơn bạn đã sửa code giúp mình.
Set KH = rg.FindNext(KH)
If KH Is Nothing Then Exit Do
If KHFirstAddress = KH.Address Then Exit Do
Đoạn này làm cho chỉ tìm được 1 ngày KH~ X trong khi đó 1 tháng có nhiều ngày đánh X.
Mình vẫn chưa hiểu lồng 2 phương thức Find thì KH lại bằng nothing với lần FindNext thứ 2.

Cảm ơn bạn nhiều
Giải bài toán của bạn:

JavaScript:
Sub tinh_toan()
  Dim NgayKH%, D%, n%, i%, cell As Range, rg As Range
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Set cell = [A5]: n = 1
  While cell(n, 1).Value <> Empty
    D = 0
    Set rg = cell(n, KH_BD).Resize(2, 31)
    For i = 1 To 31
      If CStr(rg(1, i).Value) = "X" Then
        If NgayKH > 0 Then D = D - 7
        NgayKH = i
      End If
      If CStr(rg(2, i).Value) = "O" Then GoSub v: NgayKH = 0
    Next
    rg(1, i).Value = D
    n = n + cell(n, 1).MergeArea.Rows.Count
  Wend
Exit Sub
v:
  Select Case i - NgayKH
  Case Is < 1: D = D     ' giao hang truoc
  Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
  Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
  Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
  End Select
Return
End Sub
Xin lỗi. Code chạy không cho ra kết quả chính xác.
Bạn test lại giúp mình.
Mình cảm ơn
 
Lần chỉnh sửa cuối:
Upvote 0
Mình mong muốn kết quả ra như hình. Nhờ bạn chỉnh code giúp.
Mình cảm ơn
1705369610994.png
Bài đã được tự động gộp:

Dùng mảng và vòng For
Mã:
Sub XYZ()
  Dim arr(), res(), sRow&, sCol&, i&, j&, c&, d&, fC&, cl&
 
  arr = Range("B5", Range("AI" & Range("B1000000").End(xlUp).Row + 1)).Value
  sRow = UBound(arr):             sCol = UBound(arr, 2)
  ReDim res(1 To sRow, 1 To 1)
  For i = 1 To sRow
    If arr(i, 1) <> Empty Then
      d = 0: fC = 4
      For j = 4 To sCol
        If UCase(arr(i, j)) = "X" Then
          For c = fC To sCol
            If UCase(arr(i + 1, c)) = "O" Then
              cl = c - j
              If cl > 4 Then 'Tru 7 diem
                d = d - 7
              ElseIf cl > 2 Then 'Tru 5 diem
                d = d - 5
              ElseIf cl > 0 Then 'Tru 2 diem
                d = d - 2
              End If
              fC = c + 1
              Exit For
            End If
          Next c
          If c = sCol + 1 Then d = d - 7 'Tru 7 diem
        End If
      Next j
      res(i, 1) = d
    End If
  Next i
  Range("AJ5").Resize(sRow) = res
End Sub
Code của bạn chạy đúng yêu cầu rồi .
Tuy nhiên hơi khó nhìn chút. Mình sẽ xem lại chi tiết .
Cảm ơn bạn nhiều.
 
Upvote 0
Bạn xem lại mã này, Bạn đưa ra bài toán thiếu khá nhiều dữ kiện

Còn trường hợp này thì tính sao:


XX
OO



JavaScript:
Sub tinh_toan()
  Dim NgayKH%, NgayGH%, D%, n%, i%, cell As Range, rg As Range
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Set cell = [A5]: n = 1
  While cell(n, 1).Value <> Empty
    D = 0
    Set rg = cell(n, KH_BD).Resize(2, 31)
    For i = 1 To 31
      If CStr(rg(1, i).Value) = "X" Then
        If NgayGH > 0 Then
          NgayGH = 0: NgayKH = 0
        Else
          If NgayKH > 0 Then D = D - 7
          NgayKH = i
        End If
      End If
      If CStr(rg(2, i).Value) = "O" Then
        If NgayKH > 0 Then
          Select Case i - NgayKH
          Case Is < 1: D = D     ' giao hang truoc
          Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
          Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
          Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
          End Select
        Else
          NgayGH = i
        End If
        NgayKH = 0
      End If
    Next
    rg(1, i).Value = D
    n = n + cell(n, 1).MergeArea.Rows.Count
  Wend
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn xem lại mã này, Bạn đưa ra bài toán thiếu khá nhiều dữ kiện

Còn trường hợp này thì tính sao:


XX
OO



JavaScript:
Sub tinh_toan()
  Dim NgayKH%, NgayGH%, D%, n%, i%, cell As Range, rg As Range
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Set cell = [A5]: n = 1
  While cell(n, 1).Value <> Empty
    D = 0
    Set rg = cell(n, KH_BD).Resize(2, 31)
    For i = 1 To 31
      If CStr(rg(1, i).Value) = "X" Then
        If NgayGH > 0 Then
          NgayGH = 0: NgayKH = 0
        Else
          If NgayKH > 0 Then D = D - 7
          NgayKH = i
        End If
      End If
      If CStr(rg(2, i).Value) = "O" Then
        If NgayKH > 0 Then
          Select Case i - NgayKH
          Case Is < 1: D = D     ' giao hang truoc
          Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
          Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
          Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
          End Select
        Else
          NgayGH = i
        End If
        NgayKH = 0
      End If
    Next
    cell(n, i).Value = D
    n = n + cell(n, 1).MergeArea.Rows.Count
  Wend
End Sub
Trường hợp này sẽ đều giao chậm
Lần 1 giao chậm 5 ngày
Lần 2 giao chậm 3 ngày.
Cảm ơn bạn
Bài đã được tự động gộp:

Code so sánh, X được tìm thấy đầu tiên từ trái qua phải với O đầu tiên từ trái qua phải.
Và tiếp theo.
 
Upvote 0
Bó tay luôn bạn nhé, nếu vậy trường hợp này, làm sao xác định biết O của X nào

XX
O
Trường hợp này.
Lần 1 giao chậm 5 ngày
Lần 2 chưa giao thì có nghĩa tính theo giao chậm 7 ngày
--------
Code của bạn HieuCD đáp ứng hoàn toàn yêu cầu của mình.
Tuy nhiên code của bạn dễ đọc.
Với mình cũng hay quen dùng Find. Nếu bạn cũng quen dùng Find thì chỉ giúp mình code bên trên lồng 2 Find sao set KH = rg.FindNext(KH) lại là Nothing. Như vậy mình rất mừng vì giải đáp được thắc mắc.

Cảm ơn bạn nhiều.
 
Upvote 0
Có khi nào nó còn trường hợp lần 1 giao chậm lần 2 chưa giao không nhỉ?
 
Upvote 0
Có khi nào nó còn trường hợp lần 1 giao chậm lần 2 chưa giao không nhỉ?
1705372156210.png
Là cái này bạn ạ.
Lần 1 tìm X so sánh với O tìm thấy lần đầu.
Lần 2 tìm X so sánh với O tìm thấy lần 2 ( nếu có)
Tiếp tục như vậy.

Code find của mình ban đầu cũng làm theo nguyên lý này

Find X
Nếu có => Find O ( Ko next O, chỉ lấy vị trí tìm thấy đầu tiên)
Next X ( Cái này đang bị nothing mà ko rõ lý do)
Nếu có => Find O ( Vùng tìm O thu hẹp lại, loại trừ vị trí O tìm thấy bên trên)

Cảm ơn bạn
 
Upvote 0
Ý của bạn là không có trường hợp X1 chưa giao đã giao X2, nếu vậy thì nghịch lý thực tế?
Bài đã được tự động gộp:

Bạn nên đánh số mới hợp lý
Vì có trường hợp này nữa, trong thực tế thì xác xuất luôn luôn xảy ra

KH12
GH21

Trong Excel bạn chỉ cần Format số thành X và O là được
 
Upvote 0
Ý của bạn là không có trường hợp X1 chưa giao đã giao X2, nếu vậy thì nghịch lý thực tế?
Bài đã được tự động gộp:

Bạn nên đánh số mới hợp lý
Vì có trường hợp này nữa, trong thực tế thì xác xuất luôn luôn xảy ra

KH12
GH21

Trong Excel bạn chỉ cần Format số thành X và O là được
Vâng. Không phân biệt đâu bạn ạ. PO nào đặt trước phải giao hàng trước.
Cảm ơn bạn.
 
Upvote 0
Vui là chính. há há há.
BS: Thêm điều kiện lợi dụng tháng có 31 ngày nên cứ không tìm được thì cho 31x2 để chắc ăn.

For i = LBound(AKQ, 1) To UBound(AKQ, 1)
For j = LBound(AKQ, 2) To UBound(AKQ, 2)
If AKQ(i, j) = "" Then AKQ(i, j) = 31 * 2
Next
Next

Mã:
'Option Explicit
Option Base 1
Sub zzz()
Dim AVung, AKQ
Dim i&
AVung = [E5:AI16].Value
ReDim AKQ(1 To UBound(AVung, 1), 1)
For i = LBound(AVung, 1) To UBound(AVung, 1)
k = 0
For j = LBound(AVung, 2) To UBound(AVung, 2)
If AVung(i, j) = "X" Or AVung(i, j) = "O" Then
k = k + 1
On Error Resume Next
ReDim Preserve AKQ(UBound(AKQ, i), 1 To k)
AKQ(i, k) = j
End If
Next
Next

For i = LBound(AKQ, 1) To UBound(AKQ, 1) Step 2
D = 0
For j = LBound(AKQ, 2) To UBound(AKQ, 2)
Select Case AKQ(i + 1, j) - AKQ(i, j)
Case Is < 1: D = D     'giao hang truoc
Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
End Select
Range("AJ" & i + 4).Value = D
Next
Next
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Vâng. Không phân biệt đâu bạn ạ. PO nào đặt trước phải giao hàng trước.
Cảm ơn bạn.
Cứ mỗi bài viết mới của bạn, lại có thêm một điều kiện mới sao.
"PO nào đặt trước phải giao hàng trước" điều kiện này này
 
Upvote 0
"PO nào đặt trước phải giao hàng trước"
ý mình nói.
X đầu tiên tìm thấy thì so sánh với O đầu tiên tìm thấy.
X thử 2 tìm thấy thì so sánh với O tìm thấy tiếp theo.

Đâu có thay đổi điều kiện đâu bạn. Comment bên trên mình nói liên tục về việc này rồi mà bạn.
Bài đã được tự động gộp:

Vui là chính. há há há.
Mã:
'Option Explicit
Option Base 1
Sub zzz()
Dim AVung, AKQ
Dim i&
AVung = [E5:AI16].Value
ReDim AKQ(1 To UBound(AVung, 1), 1)
For i = LBound(AVung, 1) To UBound(AVung, 1)
k = 0
For j = LBound(AVung, 2) To UBound(AVung, 2)
If AVung(i, j) = "X" Or AVung(i, j) = "O" Then
k = k + 1
On Error Resume Next
ReDim Preserve AKQ(UBound(AKQ, i), 1 To k)
AKQ(i, k) = j
End If
Next
Next

For i = LBound(AKQ, 1) To UBound(AKQ, 1) Step 2
D = 0
For j = LBound(AKQ, 2) To UBound(AKQ, 2)
Select Case AKQ(i + 1, j) - AKQ(i, j)
Case Is < 1: D = D     'giao hang truoc
Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
End Select
Range("AJ" & i + 4).Value = D
Next
Next
End Sub
Kết quả ko đúng bạn ạ.
Cảm ơn bạn
 

File đính kèm

Upvote 0
Giải bài toán như những điều kiện bạn đã nói trên với mã dưới đây

JavaScript:
Sub tinh_toan()
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Dim D%, n%, i%, cell As Range, rg As Range, r As Range
  Set cell = [A5]: n = 1
  While cell(n, 1).Value <> Empty
    D = 0
    Set rg = cell(n + 1, KH_BD).Resize(1, 31)
    For i = KH_BD To KH_KT
      If CStr(cell(n, i).Value) = "X" Then
        Set r = rg.Find("O")
        If Not r Is Nothing Then
          Select Case r.Column - cell(n, i).Column
          Case Is < 1: D = D     ' giao hang truoc
          Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
          Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
          Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
          End Select
          Set rg = r(1, 2).Resize(1, KH_KT - r.Column)
        Else
           D = D - 7
        End If
      End If
    Next
    cell(n, KH_KT + 1).Value = D
    n = n + cell(n, 1).MergeArea.Rows.Count
  Wend
End Sub

Còn trường hợp X sau cùng chỉ biết trừ 7, chứ bạn chưa nói điều kiện này

XX
O
 
Lần chỉnh sửa cuối:
Upvote 0
Giải bài toán như những điều kiện bạn đã nói trên với mã dưới đây

JavaScript:
Sub tinh_toan()
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Dim D%, n%, i%, cell As Range, rg As Range, r As Range
  Set cell = [A5]: n = 1
  While cell(n, 1).Value <> Empty
    D = 0
    Set rg = cell(n + 1, KH_BD).Resize(1, 31)
    For i = KH_BD To KH_KT
      If CStr(cell(n, i).Value) = "X" Then
        Set r = rg.Find("O")
        If Not r Is Nothing Then
          Select Case r.Column - cell(n, i).Column
          Case Is < 1: D = D     ' giao hang truoc
          Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
          Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
          Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
          End Select
          Set rg = r(1, 2).Resize(1, KH_KT - r.Column)
        End If
      End If
    Next
    cell(n, KH_KT + 1).Value = D
    n = n + cell(n, 1).MergeArea.Rows.Count
  Wend
End Sub

Còn trường hợp dư X sau cùng thì chỉ biết -7, chứ trên điều kiện bạn chưa nói, bạn nói đi rồi lại viết mã

XX
O
Code đã chạy đúng ý. Tuy nhiên vẫn thiếu trường hợp Tìm dc X mà không tìm được O để so sánh. Mình có thêm
Else
D = D - 7
vào code bên dưới.
Cảm ơn bạn đã trao đổi giúp mình. Code rất dễ đọc.
If Not r Is Nothing Then
Select Case r.Column - cell(n, i).Column
Case Is < 1: D = D ' giao hang truoc
Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
Case Else: D = D - 7 ' Giao hang muon tren 5 ngay
End Select
Set rg = r(1, 2).Resize(1, KH_KT - r.Column)
Else
D = D - 7
End If
 
Upvote 0
Code cuối cùng đây bạn nhé, sẽ không gặp lỗi khi gặp trường hợp

28293031
XX
O

JavaScript:
Sub tinh_toan()
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Dim D%, n%, i%, cell As Range, rg As Range, r As Range, a%
  Set cell = [A5]: n = 1
  While cell(n, 1).Value <> Empty
    D = 0
    Set rg = cell(n + 1, KH_BD).Resize(1, 31)
    For i = KH_BD To KH_KT
      If CStr(cell(n, i).Value) = "X" Then
        Set r = rg.Find("O", rg(1, rg.Count))
        If Not r Is Nothing Then
          a = 0: If r.Column > i Then a = WorksheetFunction.CountIf(Cells(2, i + 1).Resize(1, r.Column - i - 1), "N")
          Select Case r.Column - cell(n, i).Column - a
          Case Is < 1: D = D     ' giao hang truoc
          Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
          Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
          Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
          End Select
          Set rg = r(1, 2).Resize(1, IIf(KH_KT - r.Column <= 0, 1, KH_KT - r.Column))
        Else
          D = D - 7
        End If
      End If
    Next
    cell(n, KH_KT + 1).Value = D
    n = n + cell(n, 1).MergeArea.Rows.Count
  Wend
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Code cuối cùng đây bạn nhé, sẽ không gặp lỗi khi gặp trường hợp

28293031
XX
O

JavaScript:
Sub tinh_toan()
  Const KH_BD = 5 ' cot Ngay KH bat dau
  Const KH_KT = 35 ' cot Ngay KH ket thuc
  Dim D%, n%, i%, cell As Range, rg As Range, r As Range
  Set cell = [A5]: n = 1
  While cell(n, 1).Value <> Empty
    D = 0
    Set rg = cell(n + 1, KH_BD).Resize(1, 31)
    For i = KH_BD To KH_KT
      If CStr(cell(n, i).Value) = "X" Then
        Set r = rg.Find("O")
        If Not r Is Nothing Then
          Select Case r.Column - cell(n, i).Column
          Case Is < 1: D = D     ' giao hang truoc
          Case Is < 3: D = D - 2 ' Giao hang muon 1~2 ngay
          Case Is < 5: D = D - 5 ' giao hang muon 3~4 ngay
          Case Else: D = D - 7   ' Giao hang muon tren 5 ngay
          End Select
          Set rg = r(1, 2).Resize(1, IIf(KH_KT - r.Column <= 0, 1, KH_KT - r.Column))
        Else
          D = D - 7
        End If
      End If
    Next
    cell(n, KH_KT + 1).Value = D
    n = n + cell(n, 1).MergeArea.Rows.Count
  Wend
End Sub
Đúng rồi. Cảm ơn bạn 1 lần nữa vì code ngắn gọn rễ hiểu.
 
Upvote 0
Còn 1 số tình huống sẽ thế này, ít gặp nhưng xét thì sẽ hoàn hảo hơn.

1705377820339.png
1705377833563.png
1705377862380.png
 
Upvote 0
Còn 1 số tình huống sẽ thế này, ít gặp nhưng xét thì sẽ hoàn hảo hơn.

View attachment 298496
View attachment 298497
View attachment 298498
Tính ra có lẽ chỉ có 4 trường hợp: O trước X, O trùng X, O sau X, không có O. Trường hợp không có X thì là không biết ý chủ thớt thế nào
Các trường hợp lại chia nhỏ ra để tính điểm.

May là X, O chứ không mà là X, Y lại tưởng đang nói về tinh trùng
 
Upvote 0
Lại thêm một điều kiện nữa này, lúc đầu tôi nhìn thấy hàng [N] là nghi nghi lắm
 
Upvote 0
#42 Bạn xem lại mã ở #32
Bài đã được tự động gộp:

Bạn muốn biết tại sao hàm Find của bạn bị lỗi?

Đơn giản là bạn đã gọi Find "X", sau đó gọi Find "O", bây giờ bạn lại muốn gọi FindNext cho Find "X"
Lúc này phương thức Find của Range không còn lưu lệnh tìm "X" nên trả về Nothing cho KH
 
Lần chỉnh sửa cuối:
Upvote 0
Lại thêm một điều kiện nữa này, lúc đầu tôi nhìn thấy hàng [N] là nghi nghi lắm
Tại vì phần khó mới hỏi thôi. Ban đầu thắc mắc tại sao Find set KH lại nothing.
Còn phần này mình tự làm rồi.
Cảm ơn bạn nhé
#42 Bạn xem lại mã ở #32
Bài đã được tự động gộp:

Bạn muốn biết tại sao hàm Find của bạn bị lỗi?

Đơn giản là bạn đã gọi Find "X", sau đó gọi Find "O", bây giờ bạn lại muốn gọi FindNext cho Find "X"
Lúc này phương thức Find của Range không còn lưu lệnh tìm "X" nên trả về Nothing cho KH
Đây chính là cái mình muốn biết.
Vì vậy không thể lồng 2 phương thức Find vào nhau.
Cảm ơn bạn.
 
Upvote 0

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

Back
Top Bottom