Nhờ hỗ trợ lọc trùng về thời gian (1 người xem)

Liên hệ QC

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

tangoctuan

Thành viên hoạt động
Tham gia
22/4/08
Bài viết
153
Được thích
19
Chào các bạn,
Mình đang có vấn đề về lọc trùng thời gian (thời gian nhiều khoảng bị trùng chờm lên nhau) không biết xử lý cách nào, nhờ mọi người hỗ trợ.
Trong file đính kèm mình có ghi cụ thể vấn đề và kết quả trả về mong muốn (nhưng đang phải làm bằng mắt và tay, chưa có cách tự động).
Dữ liệu thực tế rất nhiều, nên nhờ các bác hỗ trợ xử lý bằng vba được thì tốt quá.
Cám ơn mọi người.
 

File đính kèm

Chào các bạn,
Mình đang có vấn đề về lọc trùng thời gian (thời gian nhiều khoảng bị trùng chờm lên nhau) không biết xử lý cách nào, nhờ mọi người hỗ trợ.
Trong file đính kèm mình có ghi cụ thể vấn đề và kết quả trả về mong muốn (nhưng đang phải làm bằng mắt và tay, chưa có cách tự động).
Dữ liệu thực tế rất nhiều, nên nhờ các bác hỗ trợ xử lý bằng vba được thì tốt quá.
Cám ơn mọi người.
Nếu C3 ="Máy 3" thì sao?
 
Nếu C3 ="Máy 3" thì sao?
Bác ơi, C3 đang = "Máy 1", nếu đổi C3 ="Máy 3" thì kết quả vẫn không có gì thay đổi.
Mục đích cuối cùng của mình là muốn lọc trùng theo khoảng thời gian.
Cứ hễ trong cùng 1 khoảng thời gian có trường hợp:
- Một máy chạy cho nhiều trạm.
- Hoặc nhiều máy chạy cho một trạm.
- Hoặc vẫn 1 máy đó chạy cho 1 trạm đó nhưng lặp lại nhiều lần (dòng).
=> Thì sẽ phát hiện ra và trả kết quả về như mong muốn: Loại trùng, trùng với dòng stt nào, lượng thời gian trùng.
Nhờ các bác hỗ trợ giúp, món này phức tạp quá. Vì trùng 1s cũng phải phát hiện ra.
1568916397333.png
 
Bác ơi, C3 đang = "Máy 1", nếu đổi C3 ="Máy 3" thì kết quả vẫn không có gì thay đổi.
Mục đích cuối cùng của mình là muốn lọc trùng theo khoảng thời gian.
Cứ hễ trong cùng 1 khoảng thời gian có trường hợp:
- Một máy chạy cho nhiều trạm.
- Hoặc nhiều máy chạy cho một trạm.
- Hoặc vẫn 1 máy đó chạy cho 1 trạm đó nhưng lặp lại nhiều lần (dòng).
=> Thì sẽ phát hiện ra và trả kết quả về như mong muốn: Loại trùng, trùng với dòng stt nào, lượng thời gian trùng.
Nhờ các bác hỗ trợ giúp, món này phức tạp quá. Vì trùng 1s cũng phải phát hiện ra.
View attachment 225281
Hy vọng không bị lỗi font
Mã:
Sub XetTrung()
  Dim sArr(), Res()
  Dim eRow&, sRow&, i&, tmp$, d As Double
  Dim Tram$, May$, fTime, eTime
  With Sheets("Sheet4")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    sArr = .Range("B3:E" & eRow).Value
  End With
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 3)
  For i = 1 To sRow - 1
    Tram = sArr(i, 1):    May = sArr(i, 2)
    fTime = sArr(i, 3):   eTime = sArr(i, 4)
    For r = i + 1 To sRow
      If Not (sArr(r, 3) >= eTime Or sArr(r, 4) <= fTime) Then
        If sArr(r, 1) = Tram Then tmp = "Trùng tr" & ChrW(7841) & "m, " Else tmp = "Khác tr" & ChrW(7841) & "m, "
        If sArr(r, 2) = May Then tmp = tmp & "trùng máy" Else tmp = tmp & "Khác máy"
        If InStr(1, Res(i, 1), tmp) = 0 Then Res(i, 1) = tmp
        If InStr(1, Res(r, 1), tmp) = 0 Then Res(r, 1) = tmp
        If Len(Res(i, 2)) Then Res(i, 2) = Res(i, 2) & ", " & r Else Res(i, 2) = r
        If Len(Res(r, 2)) Then Res(r, 2) = Res(r, 2) & ", " & i Else Res(r, 2) = i
        d = (Application.Median(fTime, eTime, sArr(r, 4)) - Application.Median(fTime, eTime, sArr(r, 3))) * 1440
        Res(i, 3) = Res(i, 3) + d
        Res(r, 3) = Res(r, 3) + d
      End If
    Next r
  Next i
  Sheets("Sheet4").Range("F3").Resize(sRow, 3) = Res
End Sub
Cách khác xét điều kiện Trùng thời gian
Mã:
    For r = i + 1 To sRow
      d = (Application.Median(fTime, eTime, sArr(r, 4)) - Application.Median(fTime, eTime, sArr(r, 3))) * 1440
      If d > 0 Then
        If sArr(r, 1) = Tram Then tmp = "Trùng tr" & ChrW(7841) & "m, " Else tmp = "Khác tr" & ChrW(7841) & "m, "
        If sArr(r, 2) = May Then tmp = tmp & "trùng máy" Else tmp = tmp & "Khác máy"
        If InStr(1, Res(i, 1), tmp) = 0 Then Res(i, 1) = tmp
        If InStr(1, Res(r, 1), tmp) = 0 Then Res(r, 1) = tmp
        If Len(Res(i, 2)) Then Res(i, 2) = Res(i, 2) & ", " & r Else Res(i, 2) = r
        If Len(Res(r, 2)) Then Res(r, 2) = Res(r, 2) & ", " & i Else Res(r, 2) = i
        Res(i, 3) = Res(i, 3) + d
        Res(r, 3) = Res(r, 3) + d
      End If
    Next r
  Next i
 

File đính kèm

Lần chỉnh sửa cuối:
Hy vọng không bị lỗi font
Mã:
Sub XetTrung()
  Dim sArr(), Res()
  Dim eRow&, sRow&, i&, tmp$, d As Double
  Dim Tram$, May$, fTime, eTime
  With Sheets("Sheet4")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    sArr = .Range("B3:E" & eRow).Value
  End With
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 3)
  For i = 1 To sRow - 1
    Tram = sArr(i, 1):    May = sArr(i, 2)
    fTime = sArr(i, 3):   eTime = sArr(i, 4)
    For r = i + 1 To sRow
      If Not (sArr(r, 3) >= eTime Or sArr(r, 4) <= fTime) Then
        If sArr(r, 1) = Tram Then tmp = "Trùng tr" & ChrW(7841) & "m, " Else tmp = "Khác tr" & ChrW(7841) & "m, "
        If sArr(r, 2) = May Then tmp = tmp & "trùng máy" Else tmp = tmp & "Khác máy"
        If InStr(1, Res(i, 1), tmp) = 0 Then Res(i, 1) = tmp
        If InStr(1, Res(r, 1), tmp) = 0 Then Res(r, 1) = tmp
        If Len(Res(i, 2)) Then Res(i, 2) = Res(i, 2) & ", " & r Else Res(i, 2) = r
        If Len(Res(r, 2)) Then Res(r, 2) = Res(r, 2) & ", " & i Else Res(r, 2) = i
        d = (Application.Median(fTime, eTime, sArr(r, 4)) - Application.Median(fTime, eTime, sArr(r, 3))) * 1440
        Res(i, 3) = Res(i, 3) + d
        Res(r, 3) = Res(r, 3) + d
      End If
    Next r
  Next i
  Sheets("Sheet4").Range("F3").Resize(sRow, 3) = Res
End Sub
Cách khác xét điều kiện Trùng thời gian
Mã:
    For r = i + 1 To sRow
      d = (Application.Median(fTime, eTime, sArr(r, 4)) - Application.Median(fTime, eTime, sArr(r, 3))) * 1440
      If d > 0 Then
        If sArr(r, 1) = Tram Then tmp = "Trùng tr" & ChrW(7841) & "m, " Else tmp = "Khác tr" & ChrW(7841) & "m, "
        If sArr(r, 2) = May Then tmp = tmp & "trùng máy" Else tmp = tmp & "Khác máy"
        If InStr(1, Res(i, 1), tmp) = 0 Then Res(i, 1) = tmp
        If InStr(1, Res(r, 1), tmp) = 0 Then Res(r, 1) = tmp
        If Len(Res(i, 2)) Then Res(i, 2) = Res(i, 2) & ", " & r Else Res(i, 2) = r
        If Len(Res(r, 2)) Then Res(r, 2) = Res(r, 2) & ", " & i Else Res(r, 2) = i
        Res(i, 3) = Res(i, 3) + d
        Res(r, 3) = Res(r, 3) + d
      End If
    Next r
  Next i
Nhờ bác xem hộ giúp mình đưa dữ liệu vào file nhưng khi chạy lại không ra được kết quả. Cám ơn bác nhiều.
 

File đính kèm

File mình gởi là file của bạn
Bạn phải lưu file theo đuôi .xlsb hoặc .xlsm và vào option của excel cho phép macro chạy
Thôi chết sr bạn, mình attach bị nhầm file. Mình xin attach lại, nhờ bạn xem lại giúp mình. Mình đã chạy được file của bạn ban đầu rồi (nghĩa là đã bật macro rồi), nhưng khi đưa data nhiều vào thì không chạy được nữa, báo lỗi debug. Có trường hợp data sẽ có thể lên tới khoảng 3-400k dòng.
 

File đính kèm

Thôi chết sr bạn, mình attach bị nhầm file. Mình xin attach lại, nhờ bạn xem lại giúp mình. Mình đã chạy được file của bạn ban đầu rồi (nghĩa là đã bật macro rồi), nhưng khi đưa data nhiều vào thì không chạy được nữa, báo lỗi debug. Có trường hợp data sẽ có thể lên tới khoảng 3-400k dòng.
Dữ liệu khác, code sẽ khác
Do hạn chế của VBA, mình chỉ lấy kết quả 1 ô dưới 250 ký tự
Cột STT phải xếp thứ tự từ nhỏ tới lớn
Mã:
Sub XetTrung()
  Dim sArr(), Res()
  Dim eRow&, sRow&, i&, r&, tmp$,  d As Double
  Dim stt&, kVuc$, Tram$, May$, fTime, eTime
  Dim tTram$, kTram$, tMay$, kMay$, kTram_kMay$
 
  tTram = "Trùng tr" & ChrW(7841) & "m, "
  kTram = "Khác tr" & ChrW(7841) & "m, "
  tMay = "trùng máy"
  kMay = "khác máy"
  kTram_kMay = "Khác tr" & ChrW(7841) & "m, khác máy"
  Application.ScreenUpdating = False
  With Sheets("Sheet4")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    .Range("A2:F" & eRow).Sort .[E2], 1, Header:=xlYes
    sArr = .Range("A3:F" & eRow).Value
  End With
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 3)
  For i = 1 To sRow - 1
    stt = sArr(i, 1):    kVuc = sArr(i, 2):    Tram = sArr(i, 3)
    May = sArr(i, 4):   fTime = sArr(i, 5):     eTime = sArr(i, 6)
    For r = i + 1 To sRow
      If sArr(r, 5) < eTime Then
        If sArr(r, 3) = Tram Then tmp = tTram Else tmp = kTram
        If sArr(r, 4) = May Then tmp = tmp & tMay Else tmp = tmp & kMay
        If sArr(r, 2) = kVuc Or tmp <> kTram_kMay Then
          If Len(Res(i, 1)) = 0 Then Res(i, 1) = tmp
          If Len(Res(r, 1)) = 0 Then Res(r, 1) = tmp
          If Len(Res(i, 2)) Then
            If Len(Res(i, 2)) < 250 Then Res(i, 2) = Res(i, 2) & ", " & sArr(r, 1) 'Gioi han so ky tu ket qua
          Else
            Res(i, 2) = sArr(r, 1)
          End If
          If Len(Res(r, 2)) Then
            If Len(Res(r, 2)) < 250 Then Res(r, 2) = Res(r, 2) & ", " & sArr(i, 1)
          Else
            Res(r, 2) = sArr(i, 1)
          End If
          If sArr(r, 6) < eTime Then d = sArr(r, 6) - sArr(r, 5) Else d = eTime - sArr(r, 5)
          Res(i, 3) = Res(i, 3) + d
          Res(r, 3) = Res(r, 3) + d
        End If
      Else
        Exit For
      End If
    Next r
  Next i
  With Sheets("Sheet4")
    .Range("G3").Resize(sRow, 3).Value = Res
    .Range("A2:I" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Erase sArr: Erase Res
  Application.ScreenUpdating = True
End Sub
 
Dữ liệu khác, code sẽ khác
Do hạn chế của VBA, mình chỉ lấy kết quả 1 ô dưới 250 ký tự
Cột STT phải xếp thứ tự từ nhỏ tới lớn
Mã:
Sub XetTrung()
  Dim sArr(), Res()
  Dim eRow&, sRow&, i&, r&, tmp$,  d As Double
  Dim stt&, kVuc$, Tram$, May$, fTime, eTime
  Dim tTram$, kTram$, tMay$, kMay$, kTram_kMay$

  tTram = "Trùng tr" & ChrW(7841) & "m, "
  kTram = "Khác tr" & ChrW(7841) & "m, "
  tMay = "trùng máy"
  kMay = "khác máy"
  kTram_kMay = "Khác tr" & ChrW(7841) & "m, khác máy"
  Application.ScreenUpdating = False
  With Sheets("Sheet4")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    .Range("A2:F" & eRow).Sort .[E2], 1, Header:=xlYes
    sArr = .Range("A3:F" & eRow).Value
  End With
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 3)
  For i = 1 To sRow - 1
    stt = sArr(i, 1):    kVuc = sArr(i, 2):    Tram = sArr(i, 3)
    May = sArr(i, 4):   fTime = sArr(i, 5):     eTime = sArr(i, 6)
    For r = i + 1 To sRow
      If sArr(r, 5) < eTime Then
        If sArr(r, 3) = Tram Then tmp = tTram Else tmp = kTram
        If sArr(r, 4) = May Then tmp = tmp & tMay Else tmp = tmp & kMay
        If sArr(r, 2) = kVuc Or tmp <> kTram_kMay Then
          If Len(Res(i, 1)) = 0 Then Res(i, 1) = tmp
          If Len(Res(r, 1)) = 0 Then Res(r, 1) = tmp
          If Len(Res(i, 2)) Then
            If Len(Res(i, 2)) < 250 Then Res(i, 2) = Res(i, 2) & ", " & sArr(r, 1) 'Gioi han so ky tu ket qua
          Else
            Res(i, 2) = sArr(r, 1)
          End If
          If Len(Res(r, 2)) Then
            If Len(Res(r, 2)) < 250 Then Res(r, 2) = Res(r, 2) & ", " & sArr(i, 1)
          Else
            Res(r, 2) = sArr(i, 1)
          End If
          If sArr(r, 6) < eTime Then d = sArr(r, 6) - sArr(r, 5) Else d = eTime - sArr(r, 5)
          Res(i, 3) = Res(i, 3) + d
          Res(r, 3) = Res(r, 3) + d
        End If
      Else
        Exit For
      End If
    Next r
  Next i
  With Sheets("Sheet4")
    .Range("G3").Resize(sRow, 3).Value = Res
    .Range("A2:I" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Erase sArr: Erase Res
  Application.ScreenUpdating = True
End Sub
Mình sử dụng được rồi. Cảm ơn bạn nhiều lắm.
Qua vba của bạn chạy mình mới nhận ra còn có các trường hợp vừa bị đồng thời cả "Trùng trạm, khác máy", vừa "Khác trạm, trùng máy", vừa "Trùng trạm, trùng máy", nhưng hiện trong file chỉ chỉ ra 01/4 t/hợp này. Nhưng không phải lỗi của file, mà do mình cũng không lường hết được có tình huống này. Vậy bạn có thể chia giúp mình ra các t/hợp như vậy theo file đính kèm được không? Các luật thì vẫn như cũ.
Một lần nữa cám ơn bạn rất nhiều.Untitled.png
 

File đính kèm

Mình sử dụng được rồi. Cảm ơn bạn nhiều lắm.
Qua vba của bạn chạy mình mới nhận ra còn có các trường hợp vừa bị đồng thời cả "Trùng trạm, khác máy", vừa "Khác trạm, trùng máy", vừa "Trùng trạm, trùng máy", nhưng hiện trong file chỉ chỉ ra 01/4 t/hợp này. Nhưng không phải lỗi của file, mà do mình cũng không lường hết được có tình huống này. Vậy bạn có thể chia giúp mình ra các t/hợp như vậy theo file đính kèm được không? Các luật thì vẫn như cũ.
Một lần nữa cám ơn bạn rất nhiều.View attachment 225490
Có những dòng thời gian bắt đầu > kết thúc, xử lý như thế nào
 
Mình sử dụng được rồi. Cảm ơn bạn nhiều lắm.
Qua vba của bạn chạy mình mới nhận ra còn có các trường hợp vừa bị đồng thời cả "Trùng trạm, khác máy", vừa "Khác trạm, trùng máy", vừa "Trùng trạm, trùng máy", nhưng hiện trong file chỉ chỉ ra 01/4 t/hợp này. Nhưng không phải lỗi của file, mà do mình cũng không lường hết được có tình huống này. Vậy bạn có thể chia giúp mình ra các t/hợp như vậy theo file đính kèm được không? Các luật thì vẫn như cũ.
Một lần nữa cám ơn bạn rất nhiều.View attachment 225490

Mình đóng góp ý kiến thế này

1, Bạn đang phân tích 1 chỉ tiêu có sự tương quan cao giữa các dòng (thuật ngữ gọi là bản ghi) - tức là kết quả cần tìm phụ thuộc vào các dòng khác

2, Bình thường nếu bạn chỉ xử lý dữ liệu nội bộ bản ghi: tức là lấy value các cột trong 1 bản ghi cộng trừ nhân chia tán loạn cho nhau rồi đẩy kết quả vào 1 cột mới, thì dùng máy tính casio cũng ra.

3, Nhưng khi có nhiều bản ghi cũng cần tính toán như vậy, thì bạn phải dùng excel, bằng cách tạo hàm và kéo full các dòng (bản ghi)

4, Nhưng khi thông tin cần tìm lại phụ thuộc vào nhiều bản ghi, thì nên dùng công cụ so sánh khác như Pivot table. Đừng đẩy kết quả ra 1 cột rồi Filter để xem cũng như để phân tích.
Mình ko chuyên về dữ liệu nên ko gọi ra chính xác tên vấn đề được mà chỉ mô tả cách làm ở trên như kiểu dùng màn hình 10px xem jav vậy, ko thể dựng nổi.

Như hình ở đây, chỉ liếc sơ cũng biết ngày 25 máy 4 chạy trên 2 trạm, nếu kéo giờ ra là biết có trùng, có hơn cái filter rối mắt tốn code kia không
1569257609834.png

5, [Về cái gọi là ánh xạ 1 phần hay gì gì không nhớ, túm lại là kiểu 1 đầu vào, đẩy vào 1 hàm cho ra nhiều kết quả].

Ngày 07/07 trạm A có 3 máy là [1,2,5] cùng chạy, nếu muốn tính số giờ trùng thì bạn sẽ phải tính:
Trùng giữa máy [2,1] là bao lâu, [2,5] ; [1,5] là bao lâu và nếu số máy nhiều hơn thì chắc là tổ hợp chịch X của Y các thể loại.
Vậy thời gian trùng phải ghi nhận của trường hợp nào [2,1] hay [2,5] hay [1,5], thực tế mà nhiều hơn nữa thì thế nào, so sánh làm sao ?

Nếu chị A hôm nay đang ngủ với anh B, thì chồng chị là C về, ngủ 1 tí thì C đi, D đến chơi phát, rồi rủ E sang some, thì tính thời gian trùng của bạn là thời gian anh B cùng anh C có mặt ở nhà, hay anh B cùng anh D, E có mặt ở nhà với chị A.

Vì vậy cột thời gian trùng này mình để xuất xem lại mục đích khai thác thông tin, hoặc là phải đổi kiểu ghi chép dữ liệu, sang thành cứ mỗi 1 giây thì có bao nhiêu máy tính đang hoạt động để đỡ tốn công ngồi phân tích nhé (gọi là gì nhỉ, right data collecting ?)
 
Lần chỉnh sửa cuối:
Có những dòng thời gian bắt đầu > kết thúc, xử lý như thế nào
Trường hợp bản ghi nào bị thời gian bắt đầu sau thời gian kết thúc là 1 bản ghi lỗi, và bỏ qua không xét tới bản ghi này nữa. Vậy nhờ bạn hỗ trợ giúp.
Mình đóng góp ý kiến thế này

1, Bạn đang phân tích 1 chỉ tiêu có sự tương quan cao giữa các dòng (thuật ngữ gọi là bản ghi) - tức là kết quả cần tìm phụ thuộc vào các dòng khác

2, Bình thường nếu bạn chỉ xử lý dữ liệu nội bộ bản ghi: tức là lấy value các cột trong 1 bản ghi cộng trừ nhân chia tán loạn cho nhau rồi đẩy kết quả vào 1 cột mới, thì dùng máy tính casio cũng ra.

3, Nhưng khi có nhiều bản ghi cũng cần tính toán như vậy, thì bạn phải dùng excel, bằng cách tạo hàm và kéo full các dòng (bản ghi)

4, Nhưng khi thông tin cần tìm lại phụ thuộc vào nhiều bản ghi, thì nên dùng công cụ so sánh khác như Pivot table. Đừng đẩy kết quả ra 1 cột rồi Filter để xem cũng như để phân tích.
Mình ko chuyên về dữ liệu nên ko gọi ra chính xác tên vấn đề được mà chỉ mô tả cách làm ở trên như kiểu dùng màn hình 10px xem jav vậy, ko thể dựng nổi.

Như hình ở đây, chỉ liếc sơ cũng biết ngày 25 máy 4 chạy trên 2 trạm, nếu kéo giờ ra là biết có trùng, có hơn cái filter rối mắt tốn code kia không
View attachment 225502

5, [Về cái gọi là ánh xạ 1 phần hay gì gì không nhớ, túm lại là kiểu 1 đầu vào, đẩy vào 1 hàm cho ra nhiều kết quả].

Ngày 07/07 trạm A có 3 máy là [1,2,5] cùng chạy, nếu muốn tính số giờ trùng thì bạn sẽ phải tính:
Trùng giữa máy [2,1] là bao lâu, [2,5] ; [1,5] là bao lâu và nếu số máy nhiều hơn thì chắc là tổ hợp chịch X của Y các thể loại.
Vậy thời gian trùng phải ghi nhận của trường hợp nào [2,1] hay [2,5] hay [1,5], thực tế mà nhiều hơn nữa thì thế nào, so sánh làm sao ?

Nếu chị A hôm nay đang ngủ với anh B, thì chồng chị là C về, ngủ 1 tí thì C đi, D đến chơi phát, rồi rủ E sang some, thì tính thời gian trùng của bạn là thời gian anh B cùng anh C có mặt ở nhà, hay anh B cùng anh D, E có mặt ở nhà với chị A.

Vì vậy cột thời gian trùng này mình để xuất xem lại mục đích khai thác thông tin, hoặc là phải đổi kiểu ghi chép dữ liệu, sang thành cứ mỗi 1 giây thì có bao nhiêu máy tính đang hoạt động để đỡ tốn công ngồi phân tích nhé (gọi là gì nhỉ, right data collecting ?)
Đúng như bạn đã nói đó, cái này phải xét tương quan nhiều bản ghi để phân tích, nên mình đã từng dùng pivot nhưng cuối cùng nhận ra là không sử dụng được, vài bản ghi thì còn làm vậy được, chứ đến vài trăm bản ghi thì không thể luôn.
 
Mình sử dụng được rồi. Cảm ơn bạn nhiều lắm.
Qua vba của bạn chạy mình mới nhận ra còn có các trường hợp vừa bị đồng thời cả "Trùng trạm, khác máy", vừa "Khác trạm, trùng máy", vừa "Trùng trạm, trùng máy", nhưng hiện trong file chỉ chỉ ra 01/4 t/hợp này. Nhưng không phải lỗi của file, mà do mình cũng không lường hết được có tình huống này. Vậy bạn có thể chia giúp mình ra các t/hợp như vậy theo file đính kèm được không? Các luật thì vẫn như cũ.
Một lần nữa cám ơn bạn rất nhiều.View attachment 225490
Mã:
Sub XetTrung()
  Dim sArr(), Res()
  Dim eRow&, sRow&, j&, i&, r&, tmp$, d As Double
  Dim stt&, kVuc$, Tram$, May$, fTime, eTime

  Application.ScreenUpdating = False
  With Sheets("Check")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    .Range("A2:R" & eRow).Sort .[E2], 1, Header:=xlYes
    sArr = .Range("A3:F" & eRow).Value
  End With
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 12)
  For i = 1 To sRow - 1
    stt = sArr(i, 1):    kVuc = sArr(i, 2):    Tram = sArr(i, 3)
    May = sArr(i, 4):   fTime = sArr(i, 5):     eTime = sArr(i, 6)
    If fTime < eTime Then
      For r = i + 1 To sRow
        If sArr(r, 5) < eTime Then
          If sArr(r, 5) < sArr(r, 6) Then
            If sArr(r, 3) = Tram Then j = 1 Else j = 7
            If sArr(r, 4) <> May Then j = j + 3
            If sArr(r, 2) = kVuc Or j <> 10 Then
              Res(i, j) = Res(i, j) + 1
              Res(r, j) = Res(r, j) + 1
              If Len(Res(i, j + 1)) Then
                If Len(Res(i, j + 1)) < 250 Then Res(i, j + 1) = Res(i, j + 1) & ", " & sArr(r, 1) 'Gioi han so ky tu ket qua
              Else
                Res(i, j + 1) = sArr(r, 1)
              End If
              If Len(Res(r, j + 1)) Then
                If Len(Res(r, j + 1)) < 250 Then Res(r, j + 1) = Res(r, j + 1) & ", " & sArr(i, 1)
              Else
                Res(r, j + 1) = sArr(i, 1)
              End If
              If sArr(r, 6) < eTime Then d = sArr(r, 6) - sArr(r, 5) Else d = eTime - sArr(r, 5)
              Res(i, j + 2) = Res(i, j + 2) + d
              Res(r, j + 2) = Res(r, j + 2) + d
            End If
          Else
            Exit For
          End If
        End If
      Next r
    End If
  Next i
  With Sheets("Check")
    .Range("G3").Resize(sRow, 12).Value = Res
    .Range("A2:R" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Erase sArr: Erase Res
  Application.ScreenUpdating = True
End Sub
 
Bạn cho hỏi 1 chút là "thời gian trùng (phút)" của STT 1 (trong bảng của bạn) là so với máy 5 hay máy 2
Trạm ở đây là gì, mỗi chạm có 1 máy tên là Máy 1, Máy 2, Máy 5 hay mỗi máy 1, máy 2, máy 5 có thể chạy trên nhiều trạm khác nhau

STTTrạmMáyThời gian bắt đầu chạy máyThời gian kết thúc chạy máyLoại trùngTrùng với STTThời gian trùng (phút)
1AMáy 107/07/2019 12:32:0007/07/2019 16:23:00 Trùng trạm, khác máy 2, 7400.5
2AMáy 207/07/2019 12:32:4507/07/2019 16:23:25 Trùng trạm, khác máy 1, 7400.9166667
7AMáy 507/07/2019 13:32:4507/07/2019 19:23:25 Trùng trạm, khác máy 1, 2
 
Mã:
Sub XetTrung()
  Dim sArr(), Res()
  Dim eRow&, sRow&, j&, i&, r&, tmp$, d As Double
  Dim stt&, kVuc$, Tram$, May$, fTime, eTime

  Application.ScreenUpdating = False
  With Sheets("Check")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    .Range("A2:R" & eRow).Sort .[E2], 1, Header:=xlYes
    sArr = .Range("A3:F" & eRow).Value
  End With
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 12)
  For i = 1 To sRow - 1
    stt = sArr(i, 1):    kVuc = sArr(i, 2):    Tram = sArr(i, 3)
    May = sArr(i, 4):   fTime = sArr(i, 5):     eTime = sArr(i, 6)
    If fTime < eTime Then
      For r = i + 1 To sRow
        If sArr(r, 5) < eTime Then
          If sArr(r, 5) < sArr(r, 6) Then
            If sArr(r, 3) = Tram Then j = 1 Else j = 7
            If sArr(r, 4) <> May Then j = j + 3
            If sArr(r, 2) = kVuc Or j <> 10 Then
              Res(i, j) = Res(i, j) + 1
              Res(r, j) = Res(r, j) + 1
              If Len(Res(i, j + 1)) Then
                If Len(Res(i, j + 1)) < 250 Then Res(i, j + 1) = Res(i, j + 1) & ", " & sArr(r, 1) 'Gioi han so ky tu ket qua
              Else
                Res(i, j + 1) = sArr(r, 1)
              End If
              If Len(Res(r, j + 1)) Then
                If Len(Res(r, j + 1)) < 250 Then Res(r, j + 1) = Res(r, j + 1) & ", " & sArr(i, 1)
              Else
                Res(r, j + 1) = sArr(i, 1)
              End If
              If sArr(r, 6) < eTime Then d = sArr(r, 6) - sArr(r, 5) Else d = eTime - sArr(r, 5)
              Res(i, j + 2) = Res(i, j + 2) + d
              Res(r, j + 2) = Res(r, j + 2) + d
            End If
          Else
            Exit For
          End If
        End If
      Next r
    End If
  Next i
  With Sheets("Check")
    .Range("G3").Resize(sRow, 12).Value = Res
    .Range("A2:R" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Erase sArr: Erase Res
  Application.ScreenUpdating = True
End Sub
Đúng ý mình luôn. VBA kỳ diệu thật, có lẽ phải đi học món này nghiêm túc thôi. Một lần nữa cám ơn bạn rất nhiều.
À quên, muốn hỏi bạn chút ngoài lề, mình thấy bạn toàn để file dạng xlsm, không biết có ý đồ gì cụ thể không? Bởi khi mình save as lại dưới xlsb thì dung lượng giảm đi rất nhiều luôn?
 
Đúng ý mình luôn. VBA kỳ diệu thật, có lẽ phải đi học món này nghiêm túc thôi. Một lần nữa cám ơn bạn rất nhiều.
À quên, muốn hỏi bạn chút ngoài lề, mình thấy bạn toàn để file dạng xlsm, không biết có ý đồ gì cụ thể không? Bởi khi mình save as lại dưới xlsb thì dung lượng giảm đi rất nhiều luôn?
Do thói quen thôi, mình nghĩ có sự khác biệt ở 2 dạng, nếu .xlsb lợi hơn .xlsm mọi mặt thì mirosoft khai tử .xlsm lâu rồi
 
Do thói quen thôi, mình nghĩ có sự khác biệt ở 2 dạng, nếu .xlsb lợi hơn .xlsm mọi mặt thì mirosoft khai tử .xlsm lâu rồi
Mình chỉ thấy save dưới xlsb thì dung lượng giảm đi đáng kể, đó là cái lợi rất rõ ràng thấy được trước mắt luôn, và tạm sơ qua thì chưa thấy có điểm gì bất lợi, còn ẩn sâu hơn nữa không biết thế nào (không bít có hạn chế về số dòng, ký tự, thời gian chạy hàm... gì không).
 
Do thói quen thôi, mình nghĩ có sự khác biệt ở 2 dạng, nếu .xlsb lợi hơn .xlsm mọi mặt thì mirosoft khai tử .xlsm lâu rồi
Bạn ơi, lại làm phiền bạn thêm nữa với, bạn giúp mình làm sao để tính được thứ tự lần xuất hiện theo thời gian, ví dụ như trong file attach mình đang làm bằng tay (ở 2 cột vàng). Cám ơn bạn nhiều!
 

File đính kèm

Bạn ơi, lại làm phiền bạn thêm nữa với, bạn giúp mình làm sao để tính được thứ tự lần xuất hiện theo thời gian, ví dụ như trong file attach mình đang làm bằng tay (ở 2 cột vàng). Cám ơn bạn nhiều!
Chạy code
Mã:
Sub ThuTu()
  Dim sArr(), Res(), Arr(), Arr2(), Dic As Object, iKey$
  Dim eRow&, sRow&, i&, stt&, tmp$, d As Double
  Dim May$, fTime, eTime, fDate&, eDate&
 
  With Sheets("Sheet4")
    eRow = .Range("A" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    Application.ScreenUpdating = False
    .Range("A2:D" & eRow).Sort .[B2], 1, .[C2], , 1, Header:=xlYes
    sArr = .Range("B2:D" & eRow).Value
  End With
  sRow = UBound(sArr)
  Set Dic = CreateObject("scripting.dictionary")
  ReDim Res(2 To sRow, 1 To 2)
  For i = 2 To sRow
    May = sArr(i, 1)
    fDate = DateValue(sArr(i, 2)):    eDate = DateValue(sArr(i, 3))
    If eDate >= fDate Then
      ReDim Arr(fDate To eDate)
      ReDim Arr2(fDate To eDate)
      For r = fDate To eDate
        iKey = sArr(i, 1) & "#" & r
        Dic.Item(iKey) = Dic.Item(iKey) + 1
        If r > fDate Then fTime = r Else fTime = sArr(i, 2)
        If r < eDate Then eTime = r + 1 Else eTime = sArr(i, 3)
        If fDate = eDate Then
          Arr(r) = Dic.Item(iKey)
          Arr2(r) = Round((eTime - fTime) * 1440, 2)
        Else
          Arr(r) = Dic.Item(iKey) & " (" & Format(r, "dd/mm") & ")"
          Arr2(r) = Round((eTime - fTime) * 1440, 2) & " (" & Format(r, "dd/mm") & ")"
        End If
      Next r
      Res(i, 1) = Join(Arr, "; ")
      Res(i, 2) = Join(Arr2, "; ")
    End If
  Next i
  With Sheets("Sheet4")
    .Range("E3").Resize(sRow - 1, 2) = Res
    .Range("A2:F" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Application.ScreenUpdating = True
End Sub
 
Chạy code
Mã:
Sub ThuTu()
  Dim sArr(), Res(), Arr(), Arr2(), Dic As Object, iKey$
  Dim eRow&, sRow&, i&, stt&, tmp$, d As Double
  Dim May$, fTime, eTime, fDate&, eDate&

  With Sheets("Sheet4")
    eRow = .Range("A" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    Application.ScreenUpdating = False
    .Range("A2:D" & eRow).Sort .[B2], 1, .[C2], , 1, Header:=xlYes
    sArr = .Range("B2:D" & eRow).Value
  End With
  sRow = UBound(sArr)
  Set Dic = CreateObject("scripting.dictionary")
  ReDim Res(2 To sRow, 1 To 2)
  For i = 2 To sRow
    May = sArr(i, 1)
    fDate = DateValue(sArr(i, 2)):    eDate = DateValue(sArr(i, 3))
    If eDate >= fDate Then
      ReDim Arr(fDate To eDate)
      ReDim Arr2(fDate To eDate)
      For r = fDate To eDate
        iKey = sArr(i, 1) & "#" & r
        Dic.Item(iKey) = Dic.Item(iKey) + 1
        If r > fDate Then fTime = r Else fTime = sArr(i, 2)
        If r < eDate Then eTime = r + 1 Else eTime = sArr(i, 3)
        If fDate = eDate Then
          Arr(r) = Dic.Item(iKey)
          Arr2(r) = Round((eTime - fTime) * 1440, 2)
        Else
          Arr(r) = Dic.Item(iKey) & " (" & Format(r, "dd/mm") & ")"
          Arr2(r) = Round((eTime - fTime) * 1440, 2) & " (" & Format(r, "dd/mm") & ")"
        End If
      Next r
      Res(i, 1) = Join(Arr, "; ")
      Res(i, 2) = Join(Arr2, "; ")
    End If
  Next i
  With Sheets("Sheet4")
    .Range("E3").Resize(sRow - 1, 2) = Res
    .Range("A2:F" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Application.ScreenUpdating = True
End Sub
Cảm ơn bạn. Mình đưa dữ liệu vào file thì chỉ chạy được với mấy dòng đầu. Nhờ bạn xem hộ với, dữ liệu thực có thể có t/hợp phải chạy đến 500k dòng. :(
 

File đính kèm

Oh sr bạn, đã hiểu vì sao rồi, không được để trống cột stt. Hi. Cám ơn bạn nhiều, mình đã dùng được rồi. :)
 
Bạn ơi chỉnh lại giúp mình chỗ cột "Tổng thời gian chạy máy trong ngày" với, nó là giá trị tổng thời gian của tất cả các dòng trong ngày đó, chứ không phải giá trị thời gian của riêng dòng đó à. Mình làm tay như trong file để bạn hiểu ý mình hơn. Bạn xem lại giúp mình nhé.
 

File đính kèm

Bạn ơi chỉnh lại giúp mình chỗ cột "Tổng thời gian chạy máy trong ngày" với, nó là giá trị tổng thời gian của tất cả các dòng trong ngày đó, chứ không phải giá trị thời gian của riêng dòng đó à. Mình làm tay như trong file để bạn hiểu ý mình hơn. Bạn xem lại giúp mình nhé.
Trong ngày chạy máy bị trùng thời gian, công hết hay loại trùng?
 
Với ngày chạy máy bị trùng thời gian thì vẫn cộng lại hết bạn à.
Chỉnh code
Mã:
Sub ThuTu()
  Dim sArr(), Res(), Arr(), Arr2(), S, Dic As Object, iKey$
  Dim eRow&, sRow&, i&, r&, d As Double
  Dim May$, fTime, eTime, fDate&, eDate&
 
  With Sheets("Sheet4")
    eRow = .Range("A" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    Application.ScreenUpdating = False
    .Range("A2:D" & eRow).Sort .[B2], 1, .[C2], , 1, Header:=xlYes
    sArr = .Range("B2:D" & eRow).Value
  End With
  sRow = UBound(sArr)
  Set Dic = CreateObject("scripting.dictionary")
  ReDim Res(2 To sRow, 1 To 2)
 
  For i = 2 To sRow
    May = sArr(i, 1)
    fDate = DateValue(sArr(i, 2)):    eDate = DateValue(sArr(i, 3))
    If eDate >= fDate Then
      ReDim Arr(fDate To eDate)
      ReDim Arr2(fDate To eDate)
      For r = fDate To eDate
        If r > fDate Then fTime = r Else fTime = sArr(i, 2)
        If r < eDate Then eTime = r + 1 Else eTime = sArr(i, 3)
        d = Round((eTime - fTime) * 1440, 2)
        iKey = sArr(i, 1) & "#" & r
        If Dic.exists(iKey) = False Then
          Dic.Add iKey, Array(1, d)
        Else
          S = Dic.Item(iKey)
          S(0) = S(0) + 1
          S(1) = S(1) + d
          Dic.Item(iKey) = S
        End If
        If fDate = eDate Then
          Arr(r) = Dic.Item(iKey)(0)
          Arr2(r) = iKey
        Else
          Arr(r) = Dic.Item(iKey)(0) & " (" & Format(r, "dd/mm") & ")"
          Arr2(r) = iKey & " (" & Format(r, "dd/mm") & ")"
        End If
      Next r
      Res(i, 1) = Join(Arr, "; ")
      Res(i, 2) = Join(Arr2, "; ")
    End If
  Next i
 
  For i = 2 To sRow
    fDate = DateValue(sArr(i, 2)):    eDate = DateValue(sArr(i, 3))
    If eDate >= fDate Then
      For r = fDate To eDate
        iKey = sArr(i, 1) & "#" & r
        Res(i, 2) = Replace(Res(i, 2), iKey, Dic.Item(iKey)(1))
      Next r
    End If
  Next i
 
  With Sheets("Sheet4")
    .Range("E3").Resize(sRow - 1, 2) = Res
    .Range("A2:F" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Application.ScreenUpdating = True
End Sub
 
Bạn ơi cho mình hỏi chút, mình chạy vba ra kết quả như file đính kèm. Kết quả ô P10701 lớn hơn rất nhiều so với kết quả ở ô Q10701 (mà đúng ra phải tương đương, kết quả cột P với các giá trị thấp đều rất chuẩn so với cột Q tương ứng). Nhờ bạn xem hộ vì sao với? Mình đang suy đoán có phải do 1 cell bị giới hạn ký tự nên không list được hết không nhỉ?
 

File đính kèm

Bạn ơi cho mình hỏi chút, mình chạy vba ra kết quả như file đính kèm. Kết quả ô P10701 lớn hơn rất nhiều so với kết quả ở ô Q10701 (mà đúng ra phải tương đương, kết quả cột P với các giá trị thấp đều rất chuẩn so với cột Q tương ứng). Nhờ bạn xem hộ vì sao với? Mình đang suy đoán có phải do 1 cell bị giới hạn ký tự nên không list được hết không nhỉ?
Trong code có lệnh
If Len(Res(i, j + 1)) < 250 Then Res(i, j + 1) = Res(i, j + 1) & ", " & sArr(r, 1) 'Gioi han so ky tu ket qua
Nếu số ký tự quá lớn khi gán mảng kết quả lên sheet sẽ bị lổi, nếu muốn lấy hết ký tự phải gán từng range, code sẽ chạy chậm
 
Nhờ bạn xem hộ thêm 1 vấn đề này nữa với, cùng vba đó, mình chạy cho 2 tập data: 1 tập 49k dòng, 1 tập 11k dòng (nằm trong (thuộc) tập 49k dòng) => Thì kết quả trả về ở cột P ở mỗi file lại khác nhau? Trong khi đúng ra nó phải như nhau vì thuật toán check ở cột P chỉ phụ thuộc vào cột B (khi cùng giá trị ở cột B thì mới xét "khác trạm, khác máy"). File 11k là tập con của file 49k nên cột P đối với cùng 1 STT phải như nhau.
Trong file đính kèm mình filter sẵn ví dụ 1 STT bị như thế. Vậy rất mong bạn xem giúp mình là bị sao với?
 

File đính kèm

Nhờ bạn xem hộ thêm 1 vấn đề này nữa với, cùng vba đó, mình chạy cho 2 tập data: 1 tập 49k dòng, 1 tập 11k dòng (nằm trong (thuộc) tập 49k dòng) => Thì kết quả trả về ở cột P ở mỗi file lại khác nhau? Trong khi đúng ra nó phải như nhau vì thuật toán check ở cột P chỉ phụ thuộc vào cột B (khi cùng giá trị ở cột B thì mới xét "khác trạm, khác máy"). File 11k là tập con của file 49k nên cột P đối với cùng 1 STT phải như nhau.
Trong file đính kèm mình filter sẵn ví dụ 1 STT bị như thế. Vậy rất mong bạn xem giúp mình là bị sao với?
Code nhầm vị trí lệnh Exit for
Mã:
Sub XetTrung()
  Dim sArr(), Res()
  Dim eRow&, sRow&, j&, i&, r&, tmp$, d As Double
  Dim stt&, kVuc$, Tram$, May$, fTime, eTime

  Application.ScreenUpdating = False
  With Sheets("Check")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    .Range("A2:R" & eRow).Sort .[E2], 1, Header:=xlYes
    sArr = .Range("A3:F" & eRow).Value
  End With
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 12)
  For i = 1 To sRow - 1
    stt = sArr(i, 1):    kVuc = sArr(i, 2):    Tram = sArr(i, 3)
    May = sArr(i, 4):   fTime = sArr(i, 5):     eTime = sArr(i, 6)
    If fTime < eTime Then
      For r = i + 1 To sRow
        If sArr(r, 5) < eTime Then
          If sArr(r, 5) < sArr(r, 6) Then
            If sArr(r, 3) = Tram Then j = 1 Else j = 7
            If sArr(r, 4) <> May Then j = j + 3
            If sArr(r, 2) = kVuc Or j <> 10 Then
              Res(i, j) = Res(i, j) + 1
              Res(r, j) = Res(r, j) + 1
              If Len(Res(i, j + 1)) Then
                If Len(Res(i, j + 1)) < 250 Then Res(i, j + 1) = Res(i, j + 1) & ", " & sArr(r, 1) 'Gioi han so ky tu ket qua
              Else
                Res(i, j + 1) = sArr(r, 1)
              End If
              If Len(Res(r, j + 1)) Then
                If Len(Res(r, j + 1)) < 250 Then Res(r, j + 1) = Res(r, j + 1) & ", " & sArr(i, 1)
              Else
                Res(r, j + 1) = sArr(i, 1)
              End If
              If sArr(r, 6) < eTime Then d = sArr(r, 6) - sArr(r, 5) Else d = eTime - sArr(r, 5)
              Res(i, j + 2) = Res(i, j + 2) + d
              Res(r, j + 2) = Res(r, j + 2) + d
              If d < 0 Then
                a = 1
              End If
            End If
          End If
        Else
          Exit For
        End If
      Next r
    End If
  Next i
  With Sheets("Check")
    .Range("G3").Resize(sRow, 12).Value = Res
    .Range("A2:R" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Erase sArr: Erase Res
  Application.ScreenUpdating = True
End Sub
End If
Else
Exit For
End If
Next r
End If
Next i
 
Code nhầm vị trí lệnh Exit for
Mã:
Sub XetTrung()
  Dim sArr(), Res()
  Dim eRow&, sRow&, j&, i&, r&, tmp$, d As Double
  Dim stt&, kVuc$, Tram$, May$, fTime, eTime

  Application.ScreenUpdating = False
  With Sheets("Check")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    .Range("A2:R" & eRow).Sort .[E2], 1, Header:=xlYes
    sArr = .Range("A3:F" & eRow).Value
  End With
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 12)
  For i = 1 To sRow - 1
    stt = sArr(i, 1):    kVuc = sArr(i, 2):    Tram = sArr(i, 3)
    May = sArr(i, 4):   fTime = sArr(i, 5):     eTime = sArr(i, 6)
    If fTime < eTime Then
      For r = i + 1 To sRow
        If sArr(r, 5) < eTime Then
          If sArr(r, 5) < sArr(r, 6) Then
            If sArr(r, 3) = Tram Then j = 1 Else j = 7
            If sArr(r, 4) <> May Then j = j + 3
            If sArr(r, 2) = kVuc Or j <> 10 Then
              Res(i, j) = Res(i, j) + 1
              Res(r, j) = Res(r, j) + 1
              If Len(Res(i, j + 1)) Then
                If Len(Res(i, j + 1)) < 250 Then Res(i, j + 1) = Res(i, j + 1) & ", " & sArr(r, 1) 'Gioi han so ky tu ket qua
              Else
                Res(i, j + 1) = sArr(r, 1)
              End If
              If Len(Res(r, j + 1)) Then
                If Len(Res(r, j + 1)) < 250 Then Res(r, j + 1) = Res(r, j + 1) & ", " & sArr(i, 1)
              Else
                Res(r, j + 1) = sArr(i, 1)
              End If
              If sArr(r, 6) < eTime Then d = sArr(r, 6) - sArr(r, 5) Else d = eTime - sArr(r, 5)
              Res(i, j + 2) = Res(i, j + 2) + d
              Res(r, j + 2) = Res(r, j + 2) + d
              If d < 0 Then
                a = 1
              End If
            End If
          End If
        Else
          Exit For
        End If
      Next r
    End If
  Next i
  With Sheets("Check")
    .Range("G3").Resize(sRow, 12).Value = Res
    .Range("A2:R" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Erase sArr: Erase Res
  Application.ScreenUpdating = True
End Sub
End If
Else
Exit For
End If
Next r
End If
Next i
Bạn ơi mình chạy code cho 1 trường hợp (như file) thì thấy có 1 vấn đề như này.
Tổng số máy ở cột D chỉ là 37, nhưng kết quả trùng trạm khác máy ở J3 lại là 488. Đúng ra thì KQ luôn phải nhỏ hơn 37 (số giá trị khác nhau duy nhất ở cột D).
1.png
Mình gửi file chạy dữ liệu. Nhờ bạn xem giúp với.
 

File đính kèm

Bạn ơi mình chạy code cho 1 trường hợp (như file) thì thấy có 1 vấn đề như này.
Tổng số máy ở cột D chỉ là 37, nhưng kết quả trùng trạm khác máy ở J3 lại là 488. Đúng ra thì KQ luôn phải nhỏ hơn 37 (số giá trị khác nhau duy nhất ở cột D).
View attachment 227797
Mình gửi file chạy dữ liệu. Nhờ bạn xem giúp với.
Số 488 là số lần trùng với dòng khác không phân biệt cùng máy hay khác máy
 
Số 488 là số lần trùng với dòng khác không phân biệt cùng máy hay khác máy
Vậy riêng chỗ này nhờ bạn code lại giúp để phân biệt chỉ tính khác máy thôi với. Trùng trạm và khác máy (có giao trong khoảng thời gian đó).
Tương tự như thế, cột M cũng chỉ tính khác trạm.
 
Vậy riêng chỗ này nhờ bạn code lại giúp để phân biệt chỉ tính khác máy thôi với. Trùng trạm và khác máy (có giao trong khoảng thời gian đó).
Tương tự như thế, cột M cũng chỉ tính khác trạm.
Kiểm tra lại
Mã:
Sub XetTrung()
  Dim sArr(), Res(), Dic As Object
  Dim eRow&, sRow&, j&, i&, r&, tmp$, d As Double
  Dim stt$, stt2$, kVuc$, Tram$, May$, fTime, eTime

  Application.ScreenUpdating = False
  With Sheets("Check")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    .Range("A2:R" & eRow).Sort .[E2], 1, Header:=xlYes
    sArr = .Range("A3:F" & eRow).Value
  End With
  Set Dic = CreateObject("scripting.dictionary")
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 12)
  For i = 1 To sRow - 1
    stt = sArr(i, 1):    kVuc = sArr(i, 2):    Tram = sArr(i, 3)
    May = sArr(i, 4):   fTime = sArr(i, 5):     eTime = sArr(i, 6)
    If fTime < eTime Then
      For r = i + 1 To sRow
        If sArr(r, 5) < eTime Then
          If sArr(r, 5) < sArr(r, 6) Then
            If sArr(r, 3) = Tram Then j = 1 Else j = 7
            If sArr(r, 4) <> May Then j = j + 3
            stt2 = sArr(r, 1)
            If sArr(r, 2) = kVuc Or j <> 10 Then
              If j = 4 Then
                tmp = Dic.Item(stt) & ","
                If InStr(1, tmp, "," & sArr(r, 4) & ",") = 0 Then
                  Res(i, j) = Res(i, j) + 1
                  Dic.Item(stt) = Dic.Item(stt) & "," & sArr(r, 4)
                End If
                tmp = Dic.Item(stt2) & ","
                If InStr(1, tmp, "," & sArr(i, 4) & ",") = 0 Then
                  Res(r, j) = Res(r, j) + 1
                  Dic.Item(stt2) = Dic.Item(stt2) & "," & sArr(i, 4)
                End If
              ElseIf j = 7 Then
                tmp = Dic.Item(stt) & ","
                If InStr(1, tmp, "," & sArr(r, 3) & ",") = 0 Then
                  Res(i, j) = Res(i, j) + 1
                  Dic.Item(stt) = Dic.Item(stt) & "," & sArr(r, 3)
                End If
                tmp = Dic.Item(stt2) & ","
                If InStr(1, tmp, "," & sArr(i, 3) & ",") = 0 Then
                  Res(r, j) = Res(r, j) + 1
                  Dic.Item(stt2) = Dic.Item(stt2) & "," & sArr(i, 3)
                End If
              Else
                Res(i, j) = Res(i, j) + 1
                Res(r, j) = Res(r, j) + 1
              End If
              If Len(Res(i, j + 1)) Then
                If Len(Res(i, j + 1)) < 250 Then Res(i, j + 1) = Res(i, j + 1) & ", " & sArr(r, 1) 'Gioi han so ky tu ket qua
              Else
                Res(i, j + 1) = sArr(r, 1)
              End If
              If Len(Res(r, j + 1)) Then
                If Len(Res(r, j + 1)) < 250 Then Res(r, j + 1) = Res(r, j + 1) & ", " & sArr(i, 1)
              Else
                Res(r, j + 1) = sArr(i, 1)
              End If
              If sArr(r, 6) < eTime Then d = sArr(r, 6) - sArr(r, 5) Else d = eTime - sArr(r, 5)
              Res(i, j + 2) = Res(i, j + 2) + d
              Res(r, j + 2) = Res(r, j + 2) + d
            End If
          End If
        Else
          Exit For
        End If
      Next r
    End If
  Next i
  With Sheets("Check")
    .Range("G3").Resize(sRow, 12).Value = Res
    .Range("A2:R" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Erase sArr: Erase Res
  Application.ScreenUpdating = True
End Sub
 
Kiểm tra lại
Mã:
Sub XetTrung()
  Dim sArr(), Res(), Dic As Object
  Dim eRow&, sRow&, j&, i&, r&, tmp$, d As Double
  Dim stt$, stt2$, kVuc$, Tram$, May$, fTime, eTime

  Application.ScreenUpdating = False
  With Sheets("Check")
    eRow = .Range("B" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    .Range("A2:R" & eRow).Sort .[E2], 1, Header:=xlYes
    sArr = .Range("A3:F" & eRow).Value
  End With
  Set Dic = CreateObject("scripting.dictionary")
  sRow = UBound(sArr)
  ReDim Res(1 To sRow, 1 To 12)
  For i = 1 To sRow - 1
    stt = sArr(i, 1):    kVuc = sArr(i, 2):    Tram = sArr(i, 3)
    May = sArr(i, 4):   fTime = sArr(i, 5):     eTime = sArr(i, 6)
    If fTime < eTime Then
      For r = i + 1 To sRow
        If sArr(r, 5) < eTime Then
          If sArr(r, 5) < sArr(r, 6) Then
            If sArr(r, 3) = Tram Then j = 1 Else j = 7
            If sArr(r, 4) <> May Then j = j + 3
            stt2 = sArr(r, 1)
            If sArr(r, 2) = kVuc Or j <> 10 Then
              If j = 4 Then
                tmp = Dic.Item(stt) & ","
                If InStr(1, tmp, "," & sArr(r, 4) & ",") = 0 Then
                  Res(i, j) = Res(i, j) + 1
                  Dic.Item(stt) = Dic.Item(stt) & "," & sArr(r, 4)
                End If
                tmp = Dic.Item(stt2) & ","
                If InStr(1, tmp, "," & sArr(i, 4) & ",") = 0 Then
                  Res(r, j) = Res(r, j) + 1
                  Dic.Item(stt2) = Dic.Item(stt2) & "," & sArr(i, 4)
                End If
              ElseIf j = 7 Then
                tmp = Dic.Item(stt) & ","
                If InStr(1, tmp, "," & sArr(r, 3) & ",") = 0 Then
                  Res(i, j) = Res(i, j) + 1
                  Dic.Item(stt) = Dic.Item(stt) & "," & sArr(r, 3)
                End If
                tmp = Dic.Item(stt2) & ","
                If InStr(1, tmp, "," & sArr(i, 3) & ",") = 0 Then
                  Res(r, j) = Res(r, j) + 1
                  Dic.Item(stt2) = Dic.Item(stt2) & "," & sArr(i, 3)
                End If
              Else
                Res(i, j) = Res(i, j) + 1
                Res(r, j) = Res(r, j) + 1
              End If
              If Len(Res(i, j + 1)) Then
                If Len(Res(i, j + 1)) < 250 Then Res(i, j + 1) = Res(i, j + 1) & ", " & sArr(r, 1) 'Gioi han so ky tu ket qua
              Else
                Res(i, j + 1) = sArr(r, 1)
              End If
              If Len(Res(r, j + 1)) Then
                If Len(Res(r, j + 1)) < 250 Then Res(r, j + 1) = Res(r, j + 1) & ", " & sArr(i, 1)
              Else
                Res(r, j + 1) = sArr(i, 1)
              End If
              If sArr(r, 6) < eTime Then d = sArr(r, 6) - sArr(r, 5) Else d = eTime - sArr(r, 5)
              Res(i, j + 2) = Res(i, j + 2) + d
              Res(r, j + 2) = Res(r, j + 2) + d
            End If
          End If
        Else
          Exit For
        End If
      Next r
    End If
  Next i
  With Sheets("Check")
    .Range("G3").Resize(sRow, 12).Value = Res
    .Range("A2:R" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Erase sArr: Erase Res
  Application.ScreenUpdating = True
End Sub
Tuyệt vời, một lần nữa cảm ơn bạn rất nhiều và chúc bạn sức khỏe!
 
Chỉnh code
Mã:
Sub ThuTu()
  Dim sArr(), Res(), Arr(), Arr2(), S, Dic As Object, iKey$
  Dim eRow&, sRow&, i&, r&, d As Double
  Dim May$, fTime, eTime, fDate&, eDate&

  With Sheets("Sheet4")
    eRow = .Range("A" & Rows.Count).End(xlUp).Row
    If eRow < 3 Then MsgBox ("Khong co du lieu"): Exit Sub
    Application.ScreenUpdating = False
    .Range("A2:D" & eRow).Sort .[B2], 1, .[C2], , 1, Header:=xlYes
    sArr = .Range("B2:D" & eRow).Value
  End With
  sRow = UBound(sArr)
  Set Dic = CreateObject("scripting.dictionary")
  ReDim Res(2 To sRow, 1 To 2)

  For i = 2 To sRow
    May = sArr(i, 1)
    fDate = DateValue(sArr(i, 2)):    eDate = DateValue(sArr(i, 3))
    If eDate >= fDate Then
      ReDim Arr(fDate To eDate)
      ReDim Arr2(fDate To eDate)
      For r = fDate To eDate
        If r > fDate Then fTime = r Else fTime = sArr(i, 2)
        If r < eDate Then eTime = r + 1 Else eTime = sArr(i, 3)
        d = Round((eTime - fTime) * 1440, 2)
        iKey = sArr(i, 1) & "#" & r
        If Dic.exists(iKey) = False Then
          Dic.Add iKey, Array(1, d)
        Else
          S = Dic.Item(iKey)
          S(0) = S(0) + 1
          S(1) = S(1) + d
          Dic.Item(iKey) = S
        End If
        If fDate = eDate Then
          Arr(r) = Dic.Item(iKey)(0)
          Arr2(r) = iKey
        Else
          Arr(r) = Dic.Item(iKey)(0) & " (" & Format(r, "dd/mm") & ")"
          Arr2(r) = iKey & " (" & Format(r, "dd/mm") & ")"
        End If
      Next r
      Res(i, 1) = Join(Arr, "; ")
      Res(i, 2) = Join(Arr2, "; ")
    End If
  Next i

  For i = 2 To sRow
    fDate = DateValue(sArr(i, 2)):    eDate = DateValue(sArr(i, 3))
    If eDate >= fDate Then
      For r = fDate To eDate
        iKey = sArr(i, 1) & "#" & r
        Res(i, 2) = Replace(Res(i, 2), iKey, Dic.Item(iKey)(1))
      Next r
    End If
  Next i

  With Sheets("Sheet4")
    .Range("E3").Resize(sRow - 1, 2) = Res
    .Range("A2:F" & eRow).Sort .[A2], 1, Header:=xlYes
  End With
  Application.ScreenUpdating = True
End Sub
Bạn ơi xem giúp hộ mình file dữ liệu này chạy với code này thì báo lỗi không biết là lỗi gì nhỉ?
 

File đính kèm

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

Back
Top Bottom