Tìm số còn thiếu trong dãy số bằng VBA (1 người xem)

  • Thread starter Thread starter bactu
  • Ngày gửi Ngày gửi
Liên hệ QC

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

bactu

Thành viên thường trực
Tham gia
19/10/07
Bài viết
304
Được thích
277
Donate (Momo)
Donate
Em có một cột bao gồm các dãy số từ bé đến lớn (số nhỏ nhất được xác định bằng min(day_so), số lớn nhất được xác định max(day_so))
Yêu cầu là lọc ra các số còn thiếu trong dãy số trên bằng VBA.
Trân trọng cảm ơn nhiều!
 

File đính kèm

Lần chỉnh sửa cuối:
E có một cột bao gồm các dãy số từ bé đến lớn (số nhỏ nhất được xác định bằng min(day_so), số lớn nhất được xác định max(day_so))
Yêu cầu là lọc ra các số còn thiếu trong dãy số trên bằng VBA.
Trân trọng cảm ơn nhiều!
Bạn thử. [CODE]Sub ass() Dim arr, kq, i As Long, max As Long, min As Long, dic As Object, a As Long min = 1000000 Set dic = CreateObject("scripting.dictionary") With Sheets("sheet1") arr = .Range("a2:A14").Value For i = 1 To UBound(arr) If min > arr(i, 1) Then min = arr(i, 1) If max < arr(i, 1) Then max = arr(i, 1) If Not dic.exists(arr(i, 1)) Then dic.Add arr(i, 1), "" End If Next i ReDim kq(1 To max - min, 1 To 1) For i = min To max If Not dic.exists(i) Then a = a + 1 kq(a, 1) = i End If Next i .Range("d2:D10000").ClearContents If a Then .Range("d2").Resize(a).Value = kq End With End Sub[/CODE]
 
Upvote 0
E có một cột bao gồm các dãy số từ bé đến lớn (số nhỏ nhất được xác định bằng min(day_so), số lớn nhất được xác định max(day_so))
Yêu cầu là lọc ra các số còn thiếu trong dãy số trên bằng VBA.
Trân trọng cảm ơn nhiều!
Bạn thử
Mã:
Sub ass()
   Dim arr, kq, i As Long, max As Long, min As Long, dic As Object, a As Long
   min = 1000000
   Set dic = CreateObject("scripting.dictionary")
       With Sheets("sheet1")
            arr = .Range("a2:A14").Value
            For i = 1 To UBound(arr)
                If min > arr(i, 1) Then min = arr(i, 1)
                If max < arr(i, 1) Then max = arr(i, 1)
                If Not dic.exists(arr(i, 1)) Then
                   dic.Add arr(i, 1), ""
                End If
           Next i
           ReDim kq(1 To max - min, 1 To 1)
           For i = min To max
               If Not dic.exists(i) Then
                  a = a + 1
                  kq(a, 1) = i
               End If
          Next i
          .Range("d2:D10000").ClearContents
          If a Then .Range("d2").Resize(a).Value = kq
      End With
End Sub
 
Upvote 0
E có một cột bao gồm các dãy số từ bé đến lớn (số nhỏ nhất được xác định bằng min(day_so), số lớn nhất được xác định max(day_so))
Yêu cầu là lọc ra các số còn thiếu trong dãy số trên bằng VBA.
Trân trọng cảm ơn nhiều!
E và Em chỉ ít hơn 1 lần gõ. Bạn gõ lại cho đầy đủ đi.
 
Upvote 0
Bạn thử
Mã:
Sub ass()
   Dim arr, kq, i As Long, max As Long, min As Long, dic As Object, a As Long
   min = 1000000
   Set dic = CreateObject("scripting.dictionary")
       With Sheets("sheet1")
            arr = .Range("a2:A14").Value
            For i = 1 To UBound(arr)
                If min > arr(i, 1) Then min = arr(i, 1)
                If max < arr(i, 1) Then max = arr(i, 1)
                If Not dic.exists(arr(i, 1)) Then
                   dic.Add arr(i, 1), ""
                End If
           Next i
           ReDim kq(1 To max - min, 1 To 1)
           For i = min To max
               If Not dic.exists(i) Then
                  a = a + 1
                  kq(a, 1) = i
               End If
          Next i
          .Range("d2:D10000").ClearContents
          If a Then .Range("d2").Resize(a).Value = kq
      End With
End Sub
Thử không dùng Dic, dùng mảng sẽ nhanh hơn
 
Upvote 0
Chưa biết đúng sai nhưng tốc độ chóng mặt. Thế là đủ, ý tưởng đầu tiên, viết 1 lần không sửa, không cần biết có thể nhanh hơn không, không tham dự cuộc thi "nhanh nhất".

Yêu cầu: dữ liệu cột A sắp xếp tăng dần, y như bài #1.

Trong tập tin có 100 000 dữ liệu. Thiếu 99997 dữ liệu.
Mã:
Sub test()
Dim lastRow As Long, k As Long, r As Long, curr_number As Long, curr_pos As Long, data(), result(), t
    t = Timer
    With ThisWorkbook.Worksheets("Sheet1")
        .Range("E2:E" & Rows.Count).ClearContents
        lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
        If lastRow < 3 Then Exit Sub
        data = .Range("A2:A" & lastRow).Value
    End With
    curr_number = data(1, 1)
    curr_pos = 0
    ReDim result(1 To data(UBound(data, 1), 1) - data(1, 1) + 1, 1 To 1)
    For k = 2 To UBound(data, 1)
        If curr_number + 1 < data(k, 1) Then
            For r = curr_number + 1 To data(k, 1) - 1
                curr_pos = curr_pos + 1
                result(curr_pos, 1) = r
            Next r
        End If
        curr_number = data(k, 1)
    Next k
    If curr_pos Then Sheet1.Range("E2").Resize(curr_pos).Value = result
    MsgBox "batman1: " & Timer - t
End Sub
 

File đính kèm

Upvote 0
Thử code
Mã:
Sub ABC()
    Dim sArr(), Res()
    Dim fN&, eN&, k&, r&, i&
    With Sheets("Sheet1")
      .Range("F2:F" & Rows.Count).ClearContents
      i = .Cells(Rows.Count, "A").End(xlUp).Row
      If i < 3 Then Exit Sub
      sArr = .Range("A2:A" & i).Value
    End With
    fN = sArr(1, 1) + 1
    eN = sArr(UBound(sArr), 1) - 1
    r = 2
    ReDim Res(1 To eN - fN + 3, 1 To 1)
    For i = fN To eN
      If i < sArr(r, 1) Then
        k = k + 1
        Res(k, 1) = i
      Else
        r = r + 1
      End If
    Next i
    If k Then Sheet1.Range("F2").Resize(k).Value = Res
End Sub
 
Upvote 0
Thử code
Mã:
Sub ABC()
    Dim sArr(), Res()
    Dim fN&, eN&, k&, r&, i&
    With Sheets("Sheet1")
      .Range("F2:F" & Rows.Count).ClearContents
      i = .Cells(Rows.Count, "A").End(xlUp).Row
      If i < 3 Then Exit Sub
      sArr = .Range("A2:A" & i).Value
    End With
    fN = sArr(1, 1) + 1
    eN = sArr(UBound(sArr), 1) - 1
    r = 2
    ReDim Res(1 To eN - fN + 3, 1 To 1)
    For i = fN To eN
      If i < sArr(r, 1) Then
        k = k + 1
        Res(k, 1) = i
      Else
        r = r + 1
      End If
    Next i
    If k Then Sheet1.Range("F2").Resize(k).Value = Res
End Sub
Nếu min max không nằm ở đầu và cuối thì tính sao anh.
 
Upvote 0
Nếu min max không nằm ở đầu và cuối thì tính sao anh.
Xem code
Mã:
Sub ABC()
  Dim sArr(), Arr() As Boolean, Res()
  Dim fN&, eN&, sR&, k&, i&
  With Sheets("Sheet1")
    i = .Cells(Rows.Count, "A").End(xlUp).Row
    If i < 3 Then Exit Sub
    sArr = .Range("A2:A" & i).Value
    sR = UBound(sArr)
    fN = Application.Min(sArr)
    eN = Application.Max(sArr)
    ReDim Arr(fN To eN)
    ReDim Res(1 To eN - fN + 1, 1 To 1)
    For i = 1 To sR
      If sArr(i, 1) Then Arr(sArr(i, 1)) = True
    Next i
    For i = fN To eN
      If Arr(i) = False Then
        k = k + 1
        Res(k, 1) = i
      End If
    Next i
    .Range("F2:F" & Rows.Count).ClearContents
    If k Then .Range("F2").Resize(k).Value = Res
  End With
End Sub
 
Upvote 0
Nếu min max không nằm ở đầu và cuối thì tính sao anh.

Theo mình đường hướng giải bài này cần trãi qua các bước sau:

(1) Xác định trị MAX & trị MIN của vùng chứa số liệu.
(2.0) Dùng vòng lặp để so giữa 2 chuỗi xem trong vùng đó thiếu số trung gian nào
(2.1) Nếu thấy thiếu thì ghi lại
(3) Biểu diễn kết qua ghi được.

Xác định công cụ của các bước:
(1) Vì là bài toán đang trong Excel nên ta xài hàm Excel để tìm 2 cực trị này
(2.0) . . . . . . (như các bài trên)
(2.1) & (3) Ghi vô mảng Arr(n,1) là tối ưu; Ở đây n là hiệu số giữa 2 cực trị trong vùng chứa số liệu

Chúc các bạn có mùa xuân tươi vui & tràn trề hạnh phúc!
 
Lần chỉnh sửa cuối:
Upvote 0
...(1) Vì là bài toán đang trong Excel nên ta xài hàm Excel để tìm 2 cực trị này
...
Không hẳn như vậy. Ở đây trước sau gì cũng duyệt hết các con số. Cho nên tìm max/min trong lúc duyệt cũng được. Chỉ cần đặt cái mảng mapping lớn đủ để chứa.

Thuật toán kiểu lười biếng code, bắt máy làm việc:
Set vung = Range(vùng chứa số)
For i = Application.Min(vung) +1 To Application.Max(vung) - 1
If IsError(Application.Match(i, vung)) Then
Ghi kết quả
End If
Next i
 
Upvote 0
Cảm ơn tất cả các Thầy, các Anh đã giúp đỡ và cho ý kiến.
Kết quả ngoài mong đợi luôn.
Chân thành cảm ơn rất nhiều!
 
Upvote 0
Web KT

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

Back
Top Bottom