Em dùng đoạn code này để xóa dữ liệu cột D3 đến E, và cột J, và cột L của sheet Beginning.
Mà chạy code không thấy chạy ạ.
Mong các anh chỉ giúp em sai chổ nào ạ. Thông cảm em dùng điện thoại, nên chỉ chụp hình.
Code chạy đã đúng ý chưa?
Tôi kém về diễn đạt lắm, theo ý hiểu của tôi thì Union nó tương tự như khi bạn bấm phím ctrl để chọn các ô, các cột, các dòng lẻ tẻ không liền kề nhau.
...
For Each Sh In Worksheets(Array("Beginning"))
' Sheets(Sh).Select
lr = Sheets("Beginning").Cells(Rows.Count, 4).End(xlUp).Row
Sh.Range("D3:D" & lr + 1).Clear 'Contents
Sh.Range("E3:E" & lr + 1).Clear 'Contents
Sh.Range("J3:J" & lr + 1).Clear
Sh.Range("L3:L" & lr + 1).Clear
Next Sh
lr = Sheets("Beginning").Cells(Rows.Count, 4).End(xlUp).Row
Cột 4 tức là cột D. Code trên lầ dòng cuối của cột D. Ví dụ dòng ấy là 1234.
Sh.Range("D3: D" & lr + 1) = Sh.Range("D3: D1235")
Sh.Range("E3:E" & lr + 1) = Sh.Range("D3: D1235")
Hai range trên nằm sát nhau và có cùng số dòng cho nên bạn có thể gom lại thành 1
Sh.Range("D3:E" & lr + 1) = Sh.Range("D3:E1235")
Tuy nhiên, trường hợp bài này thì nên để chúng riêng 2 cột dễ debug hơn.
Trong code này, bạn hấp tấp nên gõ sót:
Nếu lr là 1234
Sh.Range("J3" & lr + 1) = Sh.Range("J31235") : một ô
Nếu gõ đúng
Sh.Range("J3:J" & lr + 1) = Sh.Range("J3:J1235") : một vùng gồm 1233 ô
Sub XoaDuLieu()
Dim sh As Worksheet, lr As Long, i As Long, arr
Set sh = ThisWorkbook.Sheets("Beginning")
arr = Array(4, 5, 10, 12)
lr = sh.Cells(Rows.Count, 4).End(xlUp).Row
If Range("D4").Value <> "" Then 'them vào
With sh
For i = 0 To UBound(arr)
.Range(.Cells(3, arr(i)), .Cells(lr, arr(i))).ClearContents
Next i
End With
End If ' them vào
End Sub
Thấy chạy đúng ý của em rồi, mà không biết về sau có sự cố gì không ạ.
Code này viết theo trường phái thịnh hành ở GPE, code không sai nhưng trường phái của tôi quan niệm khác:
1. ở đây chỉ có 4 cột, lập cái array chuyển tên cột thành số làm cho code khó đọc. Lúc dựng array lại không chú thích nó dùng làm gì - nếu có chú thích, người đọc có thể tự tính ra 4 là cột D, 10 là cột J,...
2. With chỉ định đối tượng tiền tố cho dấu chấm "." trong block
Người ta chỉ dùng With khi cái tên nó dài, gõ cực và dễ bị nhầm ký tự. Ở đây cái tên Sh chỉ có 2 ký tự, không nên dùng With.
Cái bất lợi của With là nếu thiếu dấu "." thì VBA sẽ hiểu là dùng đối tượng mặc định. Với Sheet thì VBA sẽ mặc định là ActiveSheet.
Vì vậy, nên tránh dùng With với WorkSheet. Trừ phi chỉ muốn nhắc đến sheet 1 lần
With WorkSheets("abcdef")
...
End With
Dùng như thế này tránh được phải khai báo biến và set cho sheet.
Union theo Toán Đại Số là phép hội, gộp nhiều nhóm lại với nhau.
Lý thuyết:
Có 2 nhóm A và B. A hội B là một nhóm gồm tất cả các phần tử của A và tất cả các phần tử của B; nếu A và B chia sẻ nhau một số phần tử thì nhóm hội này chỉ chứa các phần tử chung ấy 1 lần (không phải 2 lần)
Union trong VBA và Excel là phép hội nhiều ranges lại thành một nhóm range.
Bình thường người ta dùng Union khi cần sử lý một nhóm ranges bằng một lệnh chung.
Ví dụ tôi muốn gán 1 vào ô A1, B2:C3, và E5:E10
union(range("a1"), range("b2:c3"), range("e5:e10")) = 1 ' lười gõ 3 dòng
Kiểm tra xem lúc đang lỗi thì lr bằng bao nhiêu, hoặc tốt nhất là mỗi lần tính lại lr thì lr có giá trị bao nhiêu. Đối chiếu với điều kiện If lr = 4
Do lr luôn lớn hơn 4 nên Rng = nothing và không thể sử dụng method Clear
Lý thuyết bổ sung:
Khai báo biến, gán giá trị cho biến, còn phải kiểm soát biến:
- Kiểm soát kiểu biến. Biến kiểu Long mà gắn Text là tiêu. Biến kiểu String, hoặc biến kiểu Sheet, biến kiểu Range, phải gắn giá trị phù hợp.
- Kiểm soát giá trị biến. Tại từng thời điểm biến có giá trị bao nhiêu. Giá trị đó được sử dụng ở đâu, có tương thích hay không.
Như code của @Hoàng Tuấn 868 mà bạn than phiền là chạy lần 2, lần 3 nó xóa dần lên tiêu đề và lên cả dòng 1. Nếu kiểm soát giá trị biến thì biết rằng sau lần xóa thứ nhất, lr = 2, sau lần xóa thứ 2, lr = 1. Lẽ ra phải có điều kiện như vừa rồi.
À như code của anh @HUONGHCKT khi em chỉnh lr>=4, thì code chạy, nhưng khi xóa xong mà lỡ chạy tiếp lần 2 thì báo lỗi, vậy mình có thể bẫy lỗi được không Thầy Mỹ, như em tính thêm:
If lr <4 then Exit Sub
nhưng không biết để chổ nào cho phù hợp.
À như code của anh @HUONGHCKT khi em chỉnh lr>=4, thì code chạy, nhưng khi xóa xong mà lỡ chạy tiếp lần 2 thì báo lỗi, vậy mình có thể bẫy lỗi được không Thầy Mỹ, như em tính thêm:
If lr <4 then Exit Sub
nhưng không biết để chổ nào cho phù hợp.
Kiểm tra xem lúc đang lỗi thì lr bằng bao nhiêu, hoặc tốt nhất là mỗi lần tính lại lr thì lr có giá trị bao nhiêu. Đối chiếu với điều kiện If lr = 4
Do lr luôn lớn hơn 4 nên Rng = nothing và không thể sử dụng method Clear
Cảm ơn Anh đã nhắc nhở. Đúng là tôi có sửa lại code của bạn ấy và do không có file nên cũng không test lại
Do không test lại nên nhâm chỗ Lr= 4 mà đúng ra phải là Lr>= 4 thì mới đúng.
Chủ bài đăng mới học cấp 1 về VBA, mà hai bác viết cho những Code có chứa những dòng lệnh của cấp 2 hay cấp III thì tẩu hỏa nhập ma là cái chắc!
Để chọn 4 cột không theo 1 trật tự thì ta xài hàm CHOOSE() (Lý do là trong excel chủ bài đăng cũng đã tiếp cận với nó)
PHP:
Dim J as Integer, Col as Integer, Rws as long
For J = 1 to 4
Col = Choose( J , 4 , 5, 10, 12, 19)
Rws = Cells(9999,Col).End(xlup).row +9 'Dòng cuối có dữ liệu của cột đang xét'
'Thêm dòng lệnh kiểm tra Rws >=4 '
Dòng lệnh xóa dữ liệu của cột đang xét
Next J
tới anh @Hoàng Tuấn 868 , sao code của anh em chạy lần đầu thấy đúng rồi (đã xóa đúng các cột)
Nhưng em lỡ tay chạy lần 2, thì code lại xóa luôn dòng tiêu đề của em luôn. (D3: E3), J3, L3.
Em có thử chạy tiếp thì lại xóa tiếp D2:E2,J2,L2. Chạy tiếp thì xóa tới D1:E1, J1, L1. Hết mới thôi.
Có cách nào hạn chế việc này không ạ.
Như là D4:E4 có dữ liệu thì mới xóa.
Sub XoaDuLieu()
Dim sh As Worksheet, lr As Long, i As Long, arr
Set sh = ThisWorkbook.Sheets("Beginning")
arr = Array(4, 5, 10, 12)
lr = sh.Cells(Rows.Count, 4).End(xlUp).Row
if lr < 3 then lr = 3
With sh
For i = 0 To UBound(arr)
.Range(.Cells(3, arr(i)), .Cells(lr, arr(i))).ClearContents
Next i
End With
End Sub