- Tham gia
- 5/6/23
- Bài viết
- 106
- Được thích
- 19
Có lẽ code ngắn quá nên không cần đưa vào thẻ.Mà bác ít code nên không biết thẻ rồi.
Lệnh Delete Range, bác sử dụng quá tùy tiện. Các lỗi của cách viết mã như trên:Code không khó lắm, quan trọng là đề bài phải dễ.
Mã:Option Explicit Sub zzz() Dim i& Dim OHienTai As Range For i = 1 To 1000 Step 1 Set OHienTai = Range("A" & i) If [OHienTai] = 7 Or [OHienTai] = 8 Or [OHienTai] = 9 Or [OHienTai] = 10 Then [OHienTai].EntireRow.Delete i = i - 1 End If Next End Sub
Có lẽ code ngắn quá nên không cần đưa vào thẻ.Mà bác ít code nên không biết thẻ rồi.
Lệnh Delete Range, bác sử dụng quá tùy tiện. Các lỗi của cách viết mã như trên:
1. Mỗi lần Delete là toàn bộ công thức trong trang tính sẽ tính toán lại, chứ không riêng gì các công thức liên quan đến vùng đã xóa. Vòng lặp sẽ gọi rất nhiều lần Delete.
2. Nếu dưới 1000 dòng có một vùng dữ liệu khác, vùng ô đó sẽ dịch chuyển lên.
3. Giải thuật không có.
..., tiết kiệm rất nhiều khoảng trống.
Mà bác ít code nên không biết thẻ rồi.
Máy tôi bị lỗi cứ gõ hai dấu cách liên tiếp là nó nổi khùng. Vì vậy tôi viết code không thụt ra thụt vào cho nó khỏe.Có lẽ code ngắn quá nên không cần đưa vào thẻ.
Cách để khắc phục nhược điểm (2) này cũng có & mình nghỉ là vầy:. . . ;.
1. . . . .
2. Nếu dưới 1000 dòng có một vùng dữ liệu khác, vùng ô đó sẽ dịch chuyển lên.
3. . . . .
cho các vùng bên dưới, ví dụ có 5 vùng cách nhau, em chưa nghĩ được cách để tìm dòng giới hạn của từng vùng.Cách để khắc phục nhược điểm (2)
Option Explicit
Sub Xoa4DongCua1chuc()
Dim x&, i&
x = Chuc(Cells(Rows.Count, "A").End(xlUp).Row)
For i = (x + 7) To 1 Step -10
Cells(i, 1).Resize(4).EntireRow.Delete
Next
End Sub
Function Chuc(NumR As Integer)
Chuc = Int(NumR / 10) * 10
End Function
Sub zzz()
Dim i&, DongDau&, DongCuoi&
Dim OHienTai As Range, OVung As Range, VVung As Range
Set OVung = Application.InputBox("Chon vung:", , , , , , , 8)
Set VVung = OVung.CurrentRegion
DongCuoi = VVung.End(xlDown).Row
DongDau = Cells(DongCuoi, "A").End(xlUp).Row
For i = DongCuoi To DongDau Step -1
Set OHienTai = Range("A" & i)
If (OHienTai.Row - (DongDau - 1) - 1) Mod 10 + 1 > 6 Then
OHienTai.EntireRow.Delete
Cells(DongCuoi + 1, "A").EntireRow.Insert
End If
Next
End Sub
Đây là cách thô nhất có thể để tìm ra dòng cuối của vùng 1 (trên nhất) có chứa dữ liệu:cho các vùng bên dưới, ví dụ có 5 vùng cách nhau, em chưa nghĩ được cách để tìm dòng giới hạn của từng vùng.
Sub TimDongCuoiCuaVung1()
Dim fRw As Integer, lRw As Long
If [A1].Value <> Space(0) Then
fRw = 1
Else
fRw = [A1].End(xlDown).Row
End If
lRw = Cells(fRw, "A").End(xlDown).Row
MsgBox lRw
End Sub
Bạn dùng AI chưa, tôi hỏi nó trả lời code chính xác = ))))Chào các anh chị GPE. Em có 1 vùng A1:A1000 em muốn cứ cách 6 dòng, xóa đi 4 dòng thì phải dùng code VBA như thế nào. Xin cảm Ơn
View attachment 298757
Private Sub ClearStepRows_test()
ClearStepRows [A1:C60], 6, 4
End Sub
Sub ClearStepRows(ByVal table As Range, Optional ByVal stepRows& = 1, Optional ByVal ClearRows& = 1)
Dim d$: d = table.Address(0, 0, , 1)
Static t!, a, s$:
If table Is Nothing Then a = Empty: t = 0: s = Empty: Exit Sub
If t > 0 And (Timer - t < 0) Then
If d = s Then table = a: t = 0: Exit Sub
End If
Dim k&, r&, lr&, fr&, lc&, c&, z
a = table.Value
lr = UBound(a): lc = UBound(a, 2)
stepRows = IIf(stepRows < 1, 1, stepRows)
ClearRows = IIf(ClearRows < 1, 1, ClearRows)
ReDim z(1 To lr, 1 To lc)
While r < lr
r = r + 1
For c = 1 To lc
z(r - k, c) = a(r, c)
Next c
fr = ((r - 1) Mod cr) + 1
If fr >= stepRows Then r = r + ClearRows: k = k + ClearRows
Wend
table = z
t = Timer + 7: s = d
Application.OnTime Now + TimeSerial(0, 0, 7), "'" & ThisWorkbook.Name & "'!ClearStepRows_FreeMemory"
End Sub
Sub ClearStepRows_FreeMemory()
ClearStepRows Nothing
End Sub
Private Sub DeleteStepRows_test()
DeleteStepRows [A1:C60], 6, 4
End Sub
Sub DeleteStepRows(ByVal table As Range, Optional ByVal stepRows& = 1, Optional ByVal ClearRows& = 1)
Dim k&, r&, lr&, lc&, cr&, rg As Range
stepRows = IIf(stepRows < 1, 1, stepRows)
ClearRows = IIf(ClearRows < 1, 1, ClearRows)
cr = stepRows + ClearRows
If MsgBox("Xóa vùng ô " & table.Address(0, 0) & ":" & vbLf & _
" Cách " & stepRows & " xóa " & ClearRows & " dong" & vbLf & _
" (Hanh dong nay không the hoan tac)" & vbLf & _
" Tiêp tuc?", _
vbYesNo, Title:="Rows Delete") <> vbYes Then Exit Sub
lr = table.rows.CountLarge:
lc = table.columns.CountLarge:
While r < lr
r = r + stepRows
If Not rg Is Nothing Then
Set rg = Union(rg, table(r + 1, 1).Resize(ClearRows, lc))
Else
Set rg = table(r + 1, 1).Resize(ClearRows, lc)
End If
r = r + ClearRows
Wend
If Not rg Is Nothing Then rg.Delete xlShiftUp
End Sub
Do với cách làm đó thì không thể làm cho phần dữ liệu bên dưới đẩy lên theo được. Nhưng thay vì nói rõ nhược điểm đó tác giả lại cố tình nói việc đẩy dữ liệu lên như bình thường là nhược điểm để bạn ngầm hiểu không đẩy dữ liệu lên là ưu điểm.Code bạn bi hay chỗ Undo được. Còn xóa mà không đẩy lên thì em cũng thấy hơi lạ, cần phải có ứng dụng điển hình mới được.
Mình xin đăng lại (gần đúng) bài hỏi của mình, để ai đó khỏi lăn tăn:@SA_DQ Theo em thì cách giải bài của bác
1. Sử dụng XML API
2. Giải thuật bước nhảy
3. Dùng vòng lặp
Em đang hoàn thành mã, giải thuật khó quá, nên hơi lâu
----------------------------------------------------
. . . . .
Nếu muốn như vậy thì xóa bao nhiêu dòng thì chèn lại bấy nhiêu dòng sau dòng cuối cùng là được mà.Mình xin đăng lại (gần đúng) bài hỏi của mình, để ai đó khỏi lăn tăn:
Giả sử phía dưới vùng DL (dữ liệu) thứ nhất có vài ba dòng trắng & sau đó là vùng DL thứ 2 ở bên dưới;
Vậy làm sao ta có thể xóa các dòng thứ 7 đến dòng 10 trong từng chục dòng của vùng DL thứ nhất, sao cho yên vị (không đôn) vùng DL thứ 2 lên trên.
Cách của bác giống bạn HeSanbi. Code bạn ấy có Ctrl+V.Mình mới nghỉ ra cách này & tự cho là đơn giản đối với mình:
a./ Xác định dòng cuối (lRws) có DL (dữ liệu) của vùng trên cùng (là vùng cần xóa 4 cho mỗi 1 chục dòng);
b./ Khai báo 1 mảng có chỉ số dòng bằng với trị đã xác đinh trên.
c./ Tạo vòng lặp duyệt từ 1 đến lRws;
Dòng nào không thỏa điều kiện xóa thì ghi vô mảng
d./ Chuyển DL trong mảng lên trang tính
PC: Nếu DL vùng I này không bình thường thì sẽ bổ sung chuyện xử lý sau, . . . .
Sub Xoa_Dong()
Dim sArr(), dArr(), k As Long, i As Long, ii As Long
sArr = Range("A1", Range("A" & Rows.Count).End(3)).Resize(, 2).Value
ReDim dArr(1 To UBound(sArr), 1 To UBound(sArr, 2))
For i = 1 To UBound(sArr) - 4 Step 10
For ii = 0 To 5
k = k + 1
dArr(k, 1) = sArr(i + ii, 1)
dArr(k, 2) = sArr(i + ii, 2)
Next
Next
Range("E1").Resize(k, UBound(dArr, 2)) = dArr
End Sub
À, theo cách hiểu không bài bản của em thì cứ gắn mảng xuống bảng tính thì nó cũng giống giống control v.Cách của bác Sa làm gì có copy paste mà có Ctrl V?