Nhờ chỉ giúp em chố sai của Code

Liên hệ QC

Dauthivan

Thành viên tiêu biểu
Tham gia
15/8/08
Bài viết
565
Được thích
327
Bài toán em đặt ra là tại Sheet 1 (đầu vào) những hàng mà tại đó cột A là số dương (>0) thì giá trị cột B tương ứng của Sheet1 sẽ được lọc sang cột A của Sheet 2.

PHP:
Sub Trichloc()
Dim n As Long, m As Long
n = S01.Range("A65000").End(xlUp).Row
m = S02.Range("A65000").End(xlUp).Row
For i = 3 To n
If S01.Cells(i, 1) > 0 Then
S02.Cells(m, 1) = S01.Cells(i, 2)
End If
Next
End Sub

Kết quả đúng phải là được cả 3 số (121,12,454) thì nó chỉ ra sai (được mỗi số 454) thôi. Em đang tập từng đoạn Code con một, rất mong được mọi người, các thày trên diễn đàn giúp đỡ.
 

File đính kèm

Bài toán em đặt ra là tại Sheet 1 (đầu vào) những hàng mà tại đó cột A là số dương (>0) thì giá trị cột B tương ứng của Sheet1 sẽ được lọc sang cột A của Sheet 2.

PHP:
Sub Trichloc()
Dim n As Long, m As Long
n = S01.Range("A65000").End(xlUp).Row
m = S02.Range("A65000").End(xlUp).Row
For i = 3 To n
If S01.Cells(i, 1) > 0 Then
S02.Cells(m, 1) = S01.Cells(i, 2)
End If
Next
End Sub

Kết quả đúng phải là được cả 3 số (121,12,454) thì nó chỉ ra sai (được mỗi số 454) thôi. Em đang tập từng đoạn Code con một, rất mong được mọi người, các thày trên diễn đàn giúp đỡ.
Vấn đề là ở chỗ giá trị của m chỉ được xác định duy nhất một lần ở đầu Sub, do đó tất cả các giá trị thỏa mãn sẽ đều gán vào mỗi một ô, và tất nhiên là chỉ kết quả cuối cùng được giữ lại.
Bạn bỏ câu lệnh gán m đi và thay câu lệnh:
PHP:
S02.Cells(m, 1) = S01.Cells(i, 2)
bởi câu lệnh:
PHP:
S02.[A65536].End(xlUp).Offset(1) = S01.Cells(i, 2)
Tuy nhiên, nếu là mình thì mình sẽ thêm hàng tiêu đề cho Sheet1, sau đó sử dụng AdvancedFilter để lọc kết quả sang Sheet2, sẽ nhanh hơn rất nhiều.
 
Upvote 0
Bài toán em đặt ra là tại Sheet 1 (đầu vào) những hàng mà tại đó cột A là số dương (>0) thì giá trị cột B tương ứng của Sheet1 sẽ được lọc sang cột A của Sheet 2.

PHP:
Sub Trichloc()
Dim n As Long, m As Long
n = S01.Range("A65000").End(xlUp).Row
m = S02.Range("A65000").End(xlUp).Row
For i = 3 To n
If S01.Cells(i, 1) > 0 Then
S02.Cells(m, 1) = S01.Cells(i, 2)
End If
Next
End Sub
Kết quả đúng phải là được cả 3 số (121,12,454) thì nó chỉ ra sai (được mỗi số 454) thôi. Em đang tập từng đoạn Code con một, rất mong được mọi người, các thày trên diễn đàn giúp đỡ.
m luôn luôn bằng 1 ==> dù có 100 thằng thoả điều kiện nó cũng chỉ tuần tự chui vào S02.Cells(m,1) ==> em nào nằm cuối cùng ở s01 thì được ưu ái ở lại S02.Cells(m,2)
Híc
 
Upvote 0
Tuy nhiên, nếu là mình thì mình sẽ thêm hàng tiêu đề cho Sheet1, sau đó sử dụng AdvancedFilter để lọc kết quả sang Sheet2, sẽ nhanh hơn rất nhiều.

Cách này thì em làm được ah, chủ yếu là em muốn biết cách thực hiện bằng VBA thôi.

Em có được thày Ptm0412, thày Concogia chỉ bảo nhưng em vẫn chưa thực hiện được: Làm cách nào biết được Kết quả dòng m = S02.Range("A65000").End(xlUp).Row nó bằng mấy (1?). Em bắt chước câu này hơi máy móc mà chưa biết quan sát, thực hiện (bấm F8) xem trước nó là bao nhiêu?

(tự như F9 trong công thức mảng Excel đơn thuần)
------------------------------
PHP:
S02.[A65536].End(xlUp).Offset(1) = S01.Cells(i, 2)

Trong câu này lệnh này thì ý nghĩa của Offset(1) nghĩa là sao ah?
 
Lần chỉnh sửa cuối:
Upvote 0
Cách này thì em làm được ah, chủ yếu là em muốn biết cách thực hiện bằng VBA thôi.

Em có được thày Ptm0412, thày Concogia chỉ bảo nhưng em vẫn chưa thực hiện được: Làm cách nào biết được Kết quả dòng m = S02.Range("A65000").End(xlUp).Row nó bằng mấy (1?). Em bắt chước câu này hơi máy móc mà chưa biết quan sát, thực hiện (bấm F8) xem trước nó là bao nhiêu?

(tự như F9 trong công thức mảng Excel đơn thuần)
Tất nhiên mình vẫn đang nói đến VBA đấy chứ. Sử dụng phương thức AdvancedFilter trong VBA chứ không phải lệnh Data\Filter\Advanced Filter trong Excel.
Muốn biết m bằng mấy thì cứ thử câu lệnh Msgbox m sau câu lệnh gán ở trên là được thôi, hoặc khỏi cần gán, gõ như vầy:
PHP:
Msgbox S02.Range("A65000").End(xlUp).Row
 
Upvote 0
Cách này thì em làm được ah, chủ yếu là em muốn biết cách thực hiện bằng VBA thôi.

......Làm cách nào biết được Kết quả dòng m = S02.Range("A65000").End(xlUp).Row nó bằng mấy (1?). Em bắt chước câu này hơi máy móc mà chưa biết quan sát, thực hiện (bấm F8) xem trước nó là bao nhiêu?
------------------------------
PHP:
S02.[A65536].End(xlUp).Offset(1) = S01.Cells(i, 2)

Trong câu này lệnh này thì ý nghĩa của Offset(1) nghĩa là sao ah?
Làm cách nào biết được Kết quả dòng m = S02.Range("A65000").End(xlUp).Row nó bằng mấy (1?).
Thì cứ F8 ==> khi code bị bôi vàng ở đoạn For i = 3 To n nhìn xuống dưới sẽ thấy biến m có gía trị là 1
S02.[A65536].End(xlUp).Offset(1) = S01.Cells(i, 2)
S02.[A65536]. ==> từ Cell A65536 ở sheet S02
End(xlUp). ==> chạy ngược lên trên, gặp cell có dữ liệu thì "xì tốp hia", nếu hổng có thì chạy hoải khi nào hết chạy được thì ngừng ( lên tới.......nóc màn hình trang tính )
Offset(1) ==> từ chỗ "xì tốp hia" quay xuống dưới 1 dòng
Híc
 
Upvote 0
Thì cứ F8 ==> khi code bị bôi vàng ở đoạn For i = 3 To n nhìn xuống dưới sẽ thấy biến m có gía trị là 1

S02.[A65536]. ==> từ Cell A65536 ở sheet S02
End(xlUp). ==> chạy ngược lên trên, gặp cell có dữ liệu thì "xì tốp hia", nếu hổng có thì chạy hoải khi nào hết chạy được thì ngừng ( lên tới.......nóc màn hình trang tính )
Offset(1) ==> từ chỗ "xì tốp hia" quay xuống dưới 1 dòng
Híc

Tức là ban đầu không có dữ liệu (S02.[A65536].End(xlUp)=1?); kết quả gán được điền xuống dòng 2 {lùi xuống cách 1 dòng thể hiện ở Offset(1)}, sau đó điền dữ liệu rồi thì cái thành phần S02.[A65536].End(xlUp) được nâng lên là 2 và kết quả S02.[A65536].End(xlUp).Offset(1) điền xuống hàng thứ 3...cứ như vậy.

Tức là S02.[A65536].End(xlUp) có 2 trường hợp:

i)
TH1: Đặt ngay ban đầu khi khai báo trước khi thực hiện For..như ban đầu của em thì nó là hằng số.

ii)
TH2: đặt nó vào trong cụm For..như của anh nghĩa phúc thì nó là biến (thay đổi)?

Rất mong các thày, các anh chị chỉ bảo giúp em nắm được vấn đề này.
 
Lần chỉnh sửa cuối:
Upvote 0
Tức là ban đầu không có dữ liệu (S02.[A65536].End(xlUp)=1?); kết quả gán được điền xuống dòng 2 {lùi xuống cách 1 dòng thể hiện ở Offset(1)}, sau đó điền dữ liệu rồi thì cái thành phần S02.[A65536].End(xlUp) được nâng lên là 2 và kết quả S02.[A65536].End(xlUp).Offset(1) điền xuống hàng thứ 3...cứ như vậy.

Tóm lại em muốn hỏi cái thằng S02.[A65536].End(xlUp) thực chất nó cũng là biến ?.
S02.[A65536].End(xlUp) là ô cuối cùng có dữ liệu trên cột A. Và nếu muốn gán cho 1 biến nào đó thì biến đó có kiểu Range.
 
Upvote 0
Tức là ban đầu không có dữ liệu (S02.[A65536].End(xlUp)=1?); kết quả gán được điền xuống dòng 2 {lùi xuống cách 1 dòng thể hiện ở Offset(1)}, sau đó điền dữ liệu rồi thì cái thành phần S02.[A65536].End(xlUp) được nâng lên là 2 và kết quả S02.[A65536].End(xlUp).Offset(1) điền xuống hàng thứ 3...cứ như vậy.

Tức là S02.[A65536].End(xlUp) có 2 trường hợp:

i)
TH1: Đặt ngay ban đầu khi khai báo trước khi thực hiện For..như ban đầu của em thì nó là hằng số.

ii)
TH2: đặt nó vào trong cụm For..như của anh nghĩa phúc thì nó là biến (thay đổi)?

Rất mong các thày, các anh chị chỉ bảo giúp em nắm được vấn đề này.
S02.[A65536].End(xlUp) chẳng phải là biến gì cả ---> Đó chẳng qua là 1 kết quả suy ra từ thuộc tính của Range mà có
Ví dụ:
Range("A6").Row sẽ cho kết quả = 6
Range("A6:A10").Rows.Count sẽ cho kết quả = 5
Lưu ý
- S02.[A65536].End(xlUp) là Range
- S02.[A65536].End(xlUp).Row là 1 số nào đó thuộc Long
Mà code ở bài 1 cũng gần đúng rồi còn gì, chỉ sửa thế này là được

Mã:
Sub hehe()
  Dim n As Long, m As Long
  n = S01.Range("A65000").End(xlUp).Row
  For i = 3 To n
    If S01.Cells(i, 1) > 0 Then
      [COLOR=#ff0000][B]m = m + 1[/B][/COLOR]
      S02.Cells(m, 1) = S01.Cells(i, 2)
    End If
  Next
End Sub
 
Upvote 0
Cho em hỏi thêm chút nữa ah

Nếu em để như thế này:
PHP:
Sub hehe()
  Dim n As Long, m As Long
  n = S01.Range("A65000").End(xlUp).Row
  m = S02.Range("A65000").End(xlUp).Row
  For i = 3 To n
    If S01.Cells(i, 1) > 0 Then
      m = m + 1
      S02.Cells(m, 1) = S01.Cells(i, 2)
    End If
  Next
End Sub
thì cũng không vấn đề gì (tương đương với việc cho m đầu tiên bằng 1), trong khi Code của thày sửa giúp em:

PHP:
Sub hehe()
  Dim n As Long, m As Long
  n = S01.Range("A65000").End(xlUp).Row
    For i = 3 To n
    If S01.Cells(i, 1) > 0 Then
      m = m + 1
      S02.Cells(m, 1) = S01.Cells(i, 2)
    End If
  Next
End Sub

Không nói gì về giá trị của m (không nó gì nghĩa là hiểu giá trị ban đầu =0)?
 
Upvote 0
Tuy nhiên, nếu là mình thì mình sẽ thêm hàng tiêu đề cho Sheet1, sau đó sử dụng AdvancedFilter để lọc kết quả sang Sheet2, sẽ nhanh hơn rất nhiều.
Cách này thì em làm được ah, chủ yếu là em muốn biết cách thực hiện bằng VBA thôi.
Xin góp một tham khảo về phương thức AdvancedFilter cho bài toán này. Với số lượng dữ liệu lớn (cỡ vài chục ngàn dòng), bạn sẽ thấy sử dụng AdvancedFilter nhanh hơn nhiều.
PHP:
Sub HaHa()
    Application.ScreenUpdating = False
    S02.Activate
    [A1] = S01.[B2]
    [C2] = "=Sheet1!A3>0"
    S01.[A2].CurrentRegion.AdvancedFilter xlFilterCopy, [C1:C2], [A1]
    [C2].ClearContents
    Application.ScreenUpdating = True
End Sub
 

File đính kèm

Upvote 0
Không nói gì về giá trị của m (không nó gì nghĩa là hiểu giá trị ban đầu =0)?
Chính xác là vậy! Mỗi loại biến có 1 giá trị mặc định riêng (Default)
Ví dụ:
- Biến String, nếu chưa bị thay đổi thì ban đầu nó = rổng
- Biến Boolean, nếu chưa bị thay đổi thì ban đầu nó = FALSE
- Biến Long, nếu chưa bị thay đổi thì ban đầu nó = 0
- Biến Range (hoặc Object), nếu chưa được thiết lập bằng động tác Set thì ban đầu nó = Nothing
vân vân
--------------------------
Xin góp một tham khảo về phương thức AdvancedFilter cho bài toán này. Với số lượng dữ liệu lớn (cỡ vài chục ngàn dòng), bạn sẽ thấy sử dụng AdvancedFilter nhanh hơn nhiều.
Có lẽ người ta đang muốn học vòng lập đấy nghiaphuc à
 
Upvote 0
S02.[A65536].End(xlUp) chẳng phải là biến gì cả ---> Đó chẳng qua là 1 kết quả suy ra từ thuộc tính của Range mà có
Ví dụ:
Range("A6").Row sẽ cho kết quả = 6
Range("A6:A10").Rows.Count sẽ cho kết quả = 5
Lưu ý
- S02.[A65536].End(xlUp) là Range
- S02.[A65536].End(xlUp).Row là 1 số nào đó thuộc Long
Mà code ở bài 1 cũng gần đúng rồi còn gì, chỉ sửa thế này là được

Mã:
Sub hehe()
  Dim n As Long, m As Long
  n = S01.Range("A65000").End(xlUp).Row
  For i = 3 To n
    If S01.Cells(i, 1) > 0 Then
      [COLOR=#ff0000][B]m = m + 1[/B][/COLOR]
      S02.Cells(m, 1) = S01.Cells(i, 2)
    End If
  Next
End Sub

Nhờ thày và thày Ptm0412, các anh chị trên diễn đàn chỉ bảo em vấn đề này từ sáng, em vỡ lẽ ra được cả 2 bài em hỏi rồi, bài này như thế này cũng được ah:
PHP:
Sub hehe()
  Dim n As Long, m As Long
  n = S01.Range("A65000").End(xlUp).Row
      For i = 3 To n
          m = S02.Range("A65000").End(xlUp).Row
          If S01.Cells(i, 1) > 0 Then
                     S02.Cells(m + 1, 1) = S01.Cells(i, 2)
    End If
  Next
End Sub
 
Upvote 0
Nhờ thày và thày Ptm0412, các anh chị trên diễn đàn chỉ bảo em vấn đề này từ sáng, em vỡ lẽ ra được cả 2 bài em hỏi rồi, bài này như thế này cũng được ah:
PHP:
Sub hehe()
  Dim n As Long, m As Long
  n = S01.Range("A65000").End(xlUp).Row
      For i = 3 To n
          m = S02.Range("A65000").End(xlUp).Row
          If S01.Cells(i, 1) > 0 Then
                     S02.Cells(m + 1, 1) = S01.Cells(i, 2)
    End If
  Next
End Sub
Được thì có được nhưng tốc độ sẽ chậm hơn
Bạn nghĩ xem:
- Cứ mỗi 1 lần lập lại phải xét End(xlUp).Row (để biết dòng cuối = bi nhiêu)
- Vậy sao không xét End(xlUp).Row từ đầu rồi cứ thế mỗi lần lập ta cộng thêm 1
Tuy về mặt giải thuật là như nhau nhưng chắc chắn dùng End property như kiểu của bạn sẽ chậm hơn
 
Upvote 0
Bài toán chỉ lọc khi cột A dương (không lọc hàng có cột A<=0, cột A là chữ).

Đúng là có voi lại đòi tiên, mấy hôm nay học được những cái này em rất thích.

Em lại xin mạo muội nhờ các mọi người lần nữa, nếu bài toán của em thay đổi đầu bài thế này ah:

- Đầu bài cũ: Lọc cột B tương ứng với cột A dương (>0)
- Nay xin thay đổi một chút: Lọc cột B sang tương ứng với cột A dương (đến đây như bài cũ), nhưng khó hơn 1 chút thêm điều kiện nếu cột A là chữ thì không lọc.
 

File đính kèm

Upvote 0
Đúng là có voi lại đòi tiên, mấy hôm nay học được những cái này em rất thích.

Em lại xin mạo muội nhờ các mọi người lần nữa, nếu bài toán của em thay đổi đầu bài thế này ah:

- Đầu bài cũ: Lọc cột B tương ứng với cột A dương (>0)
- Nay xin thay đổi một chút: Lọc cột B sang tương ứng với cột A dương (đến đây như bài cũ), nhưng khó hơn 1 chút thêm điều kiện nếu cột A là chữ thì không lọc.
Chỉ cần thay điều kiện S01.Cells(i, 1) > 0 thành S01.Cells(i, 1) > 0 And Not WorksheetFunction.IsText(S01.Cells(i, 2)) là được chứ có gì đâu. (không dám dùng IsNumeric vì lỡ còn thứ khác ngoài Text và Number)
 
Upvote 0
Chỉ cần thay điều kiện S01.Cells(i, 1) > 0 thành S01.Cells(i, 1) > 0 And Not WorksheetFunction.IsText(S01.Cells(i, 2)) là được chứ có gì đâu. (không dám dùng IsNumeric vì lỡ còn thứ khác ngoài Text và Number)
Tốt nhất đừng bao giờ dùng WorksheetFunction trong code (trừ trường hợp bất khả kháng)
Thiếu gì cách kiểm tra kiểu dữ liệu, chẳng hạn:
- IsNumeric
- TypeName
- CDble
vân vân...
 
Upvote 0
Web KT

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

Back
Top Bottom