[hỏi] Copy dữ liệu có điều kiện

Liên hệ QC

NguyenVietThinh08

Thành viên chính thức
Tham gia
12/5/20
Bài viết
86
Được thích
4
Xin chào các bác anh chị trong diễn đàn, chả là em có đang học VBA nhưng mà khó quá vẫn chưa nghĩ ra cách giải bài toán này ạ, bảng tính của em gồm 2 sheet, chả là em muốn copy theo điều kiện, Sheet 1 có cột A chứa dữ liệu ngày theo tuần tự, em muốn dựa vào số ngày trên ô D4 của sheet 2, sau đó dùng VBA để copy những ngày có trong cột A của sheet 1 trình bày vào ô C6 đến M6 trong sheet 2 với điều kiện bỏ qua những ngày không có trong sheet1, mỗi ngày xuất hiện 1 lần, em đã tập tành nhưng hoàn toàn không thành công. Như em đang làm thì em đã xóa ngày 29/08/2020 nhưng khi dùng mã vẫn hiện vào sheet2, hoặc tối đa trong sheet1 là ngày 02/09/2020 nếu để ngày 03/09/2020 thì lại không chạy được code, có bác nào hảo tâm chỉ giúp cách code không ạ, cảm ơn các bác, chúc các bác buổi tối vui vẻ
 

File đính kèm

  • Book1.xlsm
    19.1 KB · Đọc: 41
Xin chào các bác anh chị trong diễn đàn, chả là em có đang học VBA nhưng mà khó quá vẫn chưa nghĩ ra cách giải bài toán này ạ, bảng tính của em gồm 2 sheet, chả là em muốn copy theo điều kiện, Sheet 1 có cột A chứa dữ liệu ngày theo tuần tự, em muốn dựa vào số ngày trên ô D4 của sheet 2, sau đó dùng VBA để copy những ngày có trong cột A của sheet 1 trình bày vào ô C6 đến M6 trong sheet 2 với điều kiện bỏ qua những ngày không có trong sheet1, mỗi ngày xuất hiện 1 lần, em đã tập tành nhưng hoàn toàn không thành công. Như em đang làm thì em đã xóa ngày 29/08/2020 nhưng khi dùng mã vẫn hiện vào sheet2, hoặc tối đa trong sheet1 là ngày 02/09/2020 nếu để ngày 03/09/2020 thì lại không chạy được code, có bác nào hảo tâm chỉ giúp cách code không ạ, cảm ơn các bác, chúc các bác buổi tối vui vẻ
Xem thử code dưới đây
Mã:
Sub A_timdulieu()
Dim Ngay, slD
Dim DK
Dim DD
Dim kqLoc
Dim i, j, k
DK = Sheet2.Range("D4")
Ngay = Sheet1.Range("A2", Sheet1.Range("A" & Rows.Count).End(xlUp))
slD = UBound(Ngay)
ReDim DD(100000)
ReDim kqLoc(1 To 1, 1 To slD)
For i = slD To 1 Step -1
    If Ngay(i, 1) <> "" Then
        If Ngay(i, 1) <= DK Then
            k = CLng(Ngay(i, 1))
            If DD(k) = "" Then
                DD(k) = 1
                j = j + 1
                kqLoc(1, j) = Ngay(i, 1)
            End If
        End If
    End If
Next i
With Sheet2
    .Range("C6", .Range("XFD6").End(xlToLeft)).ClearContents
    .Range("C6").Resize(1, j) = kqLoc
End With
End Sub
 
Upvote 0
Xin chào các bác anh chị trong diễn đàn, chả là em có đang học VBA nhưng mà khó quá vẫn chưa nghĩ ra cách giải bài toán này ạ, bảng tính của em gồm 2 sheet, chả là em muốn copy theo điều kiện, Sheet 1 có cột A chứa dữ liệu ngày theo tuần tự, em muốn dựa vào số ngày trên ô D4 của sheet 2, sau đó dùng VBA để copy những ngày có trong cột A của sheet 1 trình bày vào ô C6 đến M6 trong sheet 2 với điều kiện bỏ qua những ngày không có trong sheet1, mỗi ngày xuất hiện 1 lần, em đã tập tành nhưng hoàn toàn không thành công. Như em đang làm thì em đã xóa ngày 29/08/2020 nhưng khi dùng mã vẫn hiện vào sheet2, hoặc tối đa trong sheet1 là ngày 02/09/2020 nếu để ngày 03/09/2020 thì lại không chạy được code, có bác nào hảo tâm chỉ giúp cách code không ạ, cảm ơn các bác, chúc các bác buổi tối vui vẻ
Thử code
Mã:
Sub ABC()
  Dim aNgay(), Res()
  Dim fDay As Date, sRow&, i&, j&, k&
 
  fDay = Sheet2.Range("D4")
  aNgay = Sheet1.Range("A2", Sheet1.Range("A" & Rows.Count).End(xlUp))
  sRow = UBound(aNgay)
  ReDim Res(1 To 1, 1 To sRow)
 
  For i = sRow To 1 Step -1
    If aNgay(i, 1) = fDay Then
      k = k + 1
      Res(1, k) = fDay
      fDay = fDay - 1
    ElseIf aNgay(i, 1) <> Empty Then
      If aNgay(i, 1) < fDay Then
        k = k + 1
        Res(1, k) = aNgay(i, 1)
        fDay = aNgay(i, 1) - 1
      End If
    End If
  Next i
  With Sheet2
    j = .Range("XFD6").End(xlToLeft).Column
    If j > 2 Then .Range("C6", .Cells(6, j)).ClearContents
    If k Then .Range("C6").Resize(1, k) = Res
  End With
End Sub
 
Upvote 0
Xem thử code dưới đây
Mã:
Sub A_timdulieu()
Dim Ngay, slD
Dim DK
Dim DD
Dim kqLoc
Dim i, j, k
DK = Sheet2.Range("D4")
Ngay = Sheet1.Range("A2", Sheet1.Range("A" & Rows.Count).End(xlUp))
slD = UBound(Ngay)
ReDim DD(100000)
ReDim kqLoc(1 To 1, 1 To slD)
For i = slD To 1 Step -1
    If Ngay(i, 1) <> "" Then
        If Ngay(i, 1) <= DK Then
            k = CLng(Ngay(i, 1))
            If DD(k) = "" Then
                DD(k) = 1
                j = j + 1
                kqLoc(1, j) = Ngay(i, 1)
            End If
        End If
    End If
Next i
With Sheet2
    .Range("C6", .Range("XFD6").End(xlToLeft)).ClearContents
    .Range("C6").Resize(1, j) = kqLoc
End With
End Sub
cảm ơn bác nhiều, hàm chạy OK ạ
Bài đã được tự động gộp:

Thử code
Mã:
Sub ABC()
  Dim aNgay(), Res()
  Dim fDay As Date, sRow&, i&, j&, k&

  fDay = Sheet2.Range("D4")
  aNgay = Sheet1.Range("A2", Sheet1.Range("A" & Rows.Count).End(xlUp))
  sRow = UBound(aNgay)
  ReDim Res(1 To 1, 1 To sRow)

  For i = sRow To 1 Step -1
    If aNgay(i, 1) = fDay Then
      k = k + 1
      Res(1, k) = fDay
      fDay = fDay - 1
    ElseIf aNgay(i, 1) <> Empty Then
      If aNgay(i, 1) < fDay Then
        k = k + 1
        Res(1, k) = aNgay(i, 1)
        fDay = aNgay(i, 1) - 1
      End If
    End If
  Next i
  With Sheet2
    j = .Range("XFD6").End(xlToLeft).Column
    If j > 2 Then .Range("C6", .Cells(6, j)).ClearContents
    If k Then .Range("C6").Resize(1, k) = Res
  End With
End Sub
Tuyệt vời, hơn cả mong đợi, cảm ơn bác nhiều nhé, em sẽ tìm hiểu thật kỹ mã code của bác
 
Upvote 0
Thử code
Mã:
Sub ABC()
  Dim aNgay(), Res()
  Dim fDay As Date, sRow&, i&, j&, k&

  fDay = Sheet2.Range("D4")
  aNgay = Sheet1.Range("A2", Sheet1.Range("A" & Rows.Count).End(xlUp))
  sRow = UBound(aNgay)
  ReDim Res(1 To 1, 1 To sRow)

  For i = sRow To 1 Step -1
    If aNgay(i, 1) = fDay Then
      k = k + 1
      Res(1, k) = fDay
      fDay = fDay - 1
    ElseIf aNgay(i, 1) <> Empty Then
      If aNgay(i, 1) < fDay Then
        k = k + 1
        Res(1, k) = aNgay(i, 1)
        fDay = aNgay(i, 1) - 1
      End If
    End If
  Next i
  With Sheet2
    j = .Range("XFD6").End(xlToLeft).Column
    If j > 2 Then .Range("C6", .Cells(6, j)).ClearContents
    If k Then .Range("C6").Resize(1, k) = Res
  End With
End Sub
Phiền bác giúp em chỉnh sửa em chỉ muốn lâuy 10 ngày gần nhất từ ngày tham chiếu ạ. Em đã thử nhưng k chạy đc. Tức là lọc ra ở cột đó 10 ngày điền vào hàng ạ
 
Upvote 0
Xem thử code dưới đây
Mã:
Sub A_timdulieu()
Dim Ngay, slD
Dim DK
Dim DD
Dim kqLoc
Dim i, j, k
DK = Sheet2.Range("D4")
Ngay = Sheet1.Range("A2", Sheet1.Range("A" & Rows.Count).End(xlUp))
slD = UBound(Ngay)
ReDim DD(100000)
ReDim kqLoc(1 To 1, 1 To slD)
For i = slD To 1 Step -1
    If Ngay(i, 1) <> "" Then
        If Ngay(i, 1) <= DK Then
            k = CLng(Ngay(i, 1))
            If DD(k) = "" Then
                DD(k) = 1
                j = j + 1
                kqLoc(1, j) = Ngay(i, 1)
            End If
        End If
    End If
Next i
With Sheet2
    .Range("C6", .Range("XFD6").End(xlToLeft)).ClearContents
    .Range("C6").Resize(1, j) = kqLoc
End With
End Sub
hàm của bác chạy chuẩn ạ, không lỗi gì
 
Upvote 0
Phiền bác giúp em chỉnh sửa em chỉ muốn lâuy 10 ngày gần nhất từ ngày tham chiếu ạ. Em đã thử nhưng k chạy đc. Tức là lọc ra ở cột đó 10 ngày điền vào hàng ạ
Thêm điều kiện k=10
Mã:
Sub ABC()
  Dim aNgay(), Res()
  Dim fDay As Date, sRow&, i&, j&, k&
 
  fDay = Sheet2.Range("D4")
  aNgay = Sheet1.Range("A2", Sheet1.Range("A" & Rows.Count).End(xlUp))
  sRow = UBound(aNgay)
  ReDim Res(1 To 1, 1 To sRow)
 
  For i = sRow To 1 Step -1
    If aNgay(i, 1) = fDay Then
      k = k + 1
      Res(1, k) = fDay
      fDay = fDay - 1
    ElseIf aNgay(i, 1) <> Empty Then
      If aNgay(i, 1) < fDay Then
        k = k + 1
        Res(1, k) = aNgay(i, 1)
        fDay = aNgay(i, 1) - 1
      End If
    End If
    if k=10 then exit for
  Next i
  With Sheet2
    j = .Range("XFD6").End(xlToLeft).Column
    If j > 2 Then .Range("C6", .Cells(6, j)).ClearContents
    If k Then .Range("C6").Resize(1, k) = Res
  End With
End Sub
 
Upvote 0
Thêm điều kiện k=10
Mã:
Sub ABC()
  Dim aNgay(), Res()
  Dim fDay As Date, sRow&, i&, j&, k&

  fDay = Sheet2.Range("D4")
  aNgay = Sheet1.Range("A2", Sheet1.Range("A" & Rows.Count).End(xlUp))
  sRow = UBound(aNgay)
  ReDim Res(1 To 1, 1 To sRow)

  For i = sRow To 1 Step -1
    If aNgay(i, 1) = fDay Then
      k = k + 1
      Res(1, k) = fDay
      fDay = fDay - 1
    ElseIf aNgay(i, 1) <> Empty Then
      If aNgay(i, 1) < fDay Then
        k = k + 1
        Res(1, k) = aNgay(i, 1)
        fDay = aNgay(i, 1) - 1
      End If
    End If
    if k=10 then exit for
  Next i
  With Sheet2
    j = .Range("XFD6").End(xlToLeft).Column
    If j > 2 Then .Range("C6", .Cells(6, j)).ClearContents
    If k Then .Range("C6").Resize(1, k) = Res
  End With
End Sub
vâng, thank bác nhiều ạ, chắc em phải đọc nhiều mới hiểu hết được vì nhiều câu lệnh giờ mới thấy, nhưng chắc ứng dụng là được ạ
 
Upvote 0
hôm trước có nhờ bác viết cho cái hàm excel, em đã phân tích và vẫn còn đôi chút chưa thật sự hiểu, mong bác giải thích giúp ạ, em đã bôi vàng trong ảnh, rất mong nhận được sự phản hồi từ bác
View attachment 246396
Mảng "DD" dùng để đánh dấu, cac vị trí đã đánh dấu rồi thì không nạp dữ liệu thêm.
Đại khái 3 câu lệnh trên là:
1./ k=CLng() ->chuyển ngày tháng về kiểu Long, dùng để làm chỉ số cho mảng "DD"
2./ Nếu phần tử thứ k tại mảng "DD" là chưa có gì thì: nạp vào kết quả ( kqLoc) & đánh dấu =1 vào mảng "DD" để lần sau không nạp thêm.

Đại ý là: với ngày (i,1), nếu phần tử trong mảng "DD" tương ứng với ngày đó ="" thì nạp vào & đánh dấu luôn, ngược lại thì không
 
Upvote 0
Mảng "DD" dùng để đánh dấu, cac vị trí đã đánh dấu rồi thì không nạp dữ liệu thêm.
Đại khái 3 câu lệnh trên là:
1./ k=CLng() ->chuyển ngày tháng về kiểu Long, dùng để làm chỉ số cho mảng "DD"
2./ Nếu phần tử thứ k tại mảng "DD" là chưa có gì thì: nạp vào kết quả ( kqLoc) & đánh dấu =1 vào mảng "DD" để lần sau không nạp thêm.

Đại ý là: với ngày (i,1), nếu phần tử trong mảng "DD" tương ứng với ngày đó ="" thì nạp vào & đánh dấu luôn, ngược lại thì không
em sẽ tìm hiểu thêm, nhưng mà ý em là làm sao lọc được ngày trùng nhau, tại em đang thắc mắc đoạn đó, tức là có 4 hoặc 5 ngày trùng nhau thì chỉ lấy 1 ngày điền vào mảng kqloc
 
Upvote 0
em sẽ tìm hiểu thêm, nhưng mà ý em là làm sao lọc được ngày trùng nhau, tại em đang thắc mắc đoạn đó, tức là có 4 hoặc 5 ngày trùng nhau thì chỉ lấy 1 ngày điền vào mảng kqloc
Giống như là bạn có 1 đống các quả bóng có số từ 0-9, mỗi loại có 4 hoặc 5 quả.

Giả sử đầu tiên bạn nhặt được quả số 2 đặt vào sọt, cùng lúc ấy bạn ghi số 2 vào cái bảng.
Lần tiếp theo, nếu nhặt được quả số 2, bạn nhìn vào bảng, thấy đã có số 2 thì không đặt quả bóng vào sọt nữa.
Kết quả trong sọt là các quả bóng duy nhất, chỉ có vậy thôi.
 
Upvote 0
Giống như là bạn có 1 đống các quả bóng có số từ 0-9, mỗi loại có 4 hoặc 5 quả.

Giả sử đầu tiên bạn nhặt được quả số 2 đặt vào sọt, cùng lúc ấy bạn ghi số 2 vào cái bảng.
Lần tiếp theo, nếu nhặt được quả số 2, bạn nhìn vào bảng, thấy đã có số 2 thì không đặt quả bóng vào sọt nữa.
Kết quả trong sọt là các quả bóng duy nhất, chỉ có vậy thôi.
Vâng. Em hiểu ạ. Nhưng em chưa hiểu câu lệnh ở chỗ nào trong số dãy hàm kia ạ
 
Upvote 0
Vâng. Em hiểu ạ. Nhưng em chưa hiểu câu lệnh ở chỗ nào trong số dãy hàm kia ạ
3 Dòng bôi vàng:
Dòng đầu tiên bạn cứ hiểu là nhặt cái Ngay(i,1) ra, ép cho nó = k. ( Như bạn nhặt bóng ra vậy )
Dòng thứ 2, kiểm tra xem trong mảng DD, tại phần tử có chỉ số = k, nếu là rỗng ( tức là chưa lấy lần nào ) --> thì nhặt Ngay(i,1).
Dòng thứ 3: Lấy xong thì đánh dấu phần tử đó = 1 ( Như là điền số 2 vào bảng vậy ). Lần sau, nhặt phải cái tương tự, thì mảng DD đánh dấu = 1 rồi thi không nhặt nữa. Vậy kết quả là duy nhất
 
Upvote 0
Giống như là bạn có 1 đống các quả bóng có số từ 0-9, mỗi loại có 4 hoặc 5 quả.

Giả sử đầu tiên bạn nhặt được quả số 2 đặt vào sọt, cùng lúc ấy bạn ghi số 2 vào cái bảng.
Lần tiếp theo, nếu nhặt được quả số 2, bạn nhìn vào bảng, thấy đã có số 2 thì không đặt quả bóng vào sọt nữa.
Kết quả trong sọt là các quả bóng duy nhất, chỉ có vậy thôi.
em đã chú thích trong ảnh ạ, mong anh giải thích giúp cho em
1601472123288.png
Bài đã được tự động gộp:

3 Dòng bôi vàng:
Dòng đầu tiên bạn cứ hiểu là nhặt cái Ngay(i,1) ra, ép cho nó = k. ( Như bạn nhặt bóng ra vậy )
Dòng thứ 2, kiểm tra xem trong mảng DD, tại phần tử có chỉ số = k, nếu là rỗng ( tức là chưa lấy lần nào ) --> thì nhặt Ngay(i,1).
Dòng thứ 3: Lấy xong thì đánh dấu phần tử đó = 1 ( Như là điền số 2 vào bảng vậy ). Lần sau, nhặt phải cái tương tự, thì mảng DD đánh dấu = 1 rồi thi không nhặt nữa. Vậy kết quả là duy nhất
nhưng khi nhặt giá trị mới tại sao nó lại bằng "", đó là cái em ko hiểu ạ, cơ chế của nó là gì ạ
 
Upvote 0
em đã chú thích trong ảnh ạ, mong anh giải thích giúp cho em
View attachment 246469
Bạn gõ 1 ngày bất kỳ vào 1 ô, sau đó định dạng nó về general sẽ thấy nó là 1 số.
k=CLng(...) có ý nghĩa tương tự.

Tức là ép ngày tháng về số, để dùng làm chỉ số của mảng DD
Bài đã được tự động gộp:

em đã chú thích trong ảnh ạ, mong anh giải thích giúp cho em
View attachment 246469
Bài đã được tự động gộp:


nhưng khi nhặt giá trị mới tại sao nó lại bằng "", đó là cái em ko hiểu ạ, cơ chế của nó là gì ạ
Phần chữ xanh: k là chỉ số, không phải giá trị. DD(k)="" là chưa nhặt k ra, DD(k)=1 là đã nhặt ra rồi.
Nếu lần sau nhặt phải k 1 lần nữa, xét thấy DD(k) đã = 1, tức là đã nhặt 1 lần rồi thì loại.
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn gõ 1 ngày bất kỳ vào 1 ô, sau đó định dạng nó về general sẽ thấy nó là 1 số.
k=CLng(...) có ý nghĩa tương tự.

Tức là ép ngày tháng về số, để dùng làm chỉ số của mảng DD
Bài đã được tự động gộp:


Phần chữ xanh: k là chỉ số, không phải giá trị. DD(k)="" là chưa nhặt k ra, DD(k)=1 là đã nhặt ra rồi.
Nếu lần sau nhặt phải k 1 lần nữa, xét thấy DD(k) đã = 1, tức là đã nhặt 1 lần rồi thì loại.
Em đã hiểu. Thank bác
 
Upvote 0
Bạn gõ 1 ngày bất kỳ vào 1 ô, sau đó định dạng nó về general sẽ thấy nó là 1 số.
k=CLng(...) có ý nghĩa tương tự.

Tức là ép ngày tháng về số, để dùng làm chỉ số của mảng DD
Bài đã được tự động gộp:


Phần chữ xanh: k là chỉ số, không phải giá trị. DD(k)="" là chưa nhặt k ra, DD(k)=1 là đã nhặt ra rồi.
Nếu lần sau nhặt phải k 1 lần nữa, xét thấy DD(k) đã = 1, tức là đã nhặt 1 lần rồi thì loại.
cách làm của bác thật là chuẩn chỉ, nhờ bác mà em tìm hiểu thêm về mảng và cũng dần hiểu rõ hơn, hôm nay em xin phép hỏi bác 1 câu nữa mong bác chỉ giáo: giả sử em tìm được 1 ô với các biến như này sheet1.cells(i;j) vậy thì có hàm nào để xóa hàng i, cột j không ạ, hay là lệnh copy hàng i, cột j mà chỉ dựa vào các chỉ số của Cells.
em xin cảm ơn bác
 
Upvote 0
giả sử em tìm được 1 ô với các biến như này sheet1.cells(i;j) vậy thì có hàm nào để xóa hàng i, cột j không ạ, hay là lệnh copy hàng i, cột j mà chỉ dựa vào các chỉ số của Cells.
Mình chưa đọc hết mấy bài trên đâu nha, nhưng mình chỉ trả lời câu này (không rõ có liên quan đến bài trên không):
Bạn thử chạy code:
PHP:
Sub bac()
Sheet1.Cells(5, 3).EntireRow.Select
End Sub
Bạn thấy chọn dòng 5, thì chắc là bạn sẽ hiểu để delete sửa thế nào (cột thì entirecolumn)
 
Upvote 0
cách làm của bác thật là chuẩn chỉ, nhờ bác mà em tìm hiểu thêm về mảng và cũng dần hiểu rõ hơn, hôm nay em xin phép hỏi bác 1 câu nữa mong bác chỉ giáo: giả sử em tìm được 1 ô với các biến như này sheet1.cells(i;j) vậy thì có hàm nào để xóa hàng i, cột j không ạ, hay là lệnh copy hàng i, cột j mà chỉ dựa vào các chỉ số của Cells.
em xin cảm ơn bác
Đại khái thế này, xóa dòng tương tự.
Mã:
Sheet1.Columns(j).Delete
Copy cả dòng hoặc cả cột thì sửa .Delete thành .Copy
Trong câu lệnh trên, nếu bạn để chỉ số trong ngoặc là rỗng ->(), khi gõ dấu "." sau ngoặc, bạn sẽ thấy hiển thị danh sách các lệnh tùy biến lựa chọn
 
Upvote 0
Web KT
Back
Top Bottom