For ...Next sai ở đâu?

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

bluecat

Thành viên mới
Tham gia
7/10/06
Bài viết
37
Được thích
1
Tôi dùng đọan mã sau nhập dữ liệu cho excel từ form (có 19 textbox) gồm 19 hàng trong cùng 1 cột và dùng cell A1 (đặt tên là DemCot) để nhảy số cho vòng lặp. Giá trị đầu tiên của DemCot = 1.

Private Sub GhiSo_Click()
S01.Select
Range("DemCot").Select
TongSoCot = Range("DemCot").Value
For N = 1 To TongSoCot
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.Dai.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo1.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo2.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo3.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo4.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo5.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo6.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo7.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo8.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo9.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo10.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo11.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo12.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo13.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo14.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo15.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo16.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo17.Value
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo18.Value
Range("DemCot").Select
Range("DemCot").Value = Range("DemCot").Value + 1
ActiveCell.Offset(0, N).Select
Next
End Sub

Xin cho hỏi tôi bị sai ở đâu :
- Sau mỗi lần nhập dữ liệu thì DemCot lại tăng thành gấp đôi chứ không phải là một đơn vị?
- Vòng lặp sai ở chổ nào mà Excel luôn ghi dữ liệu bắt đầu từ cột A
Xin giúp tôi :
- Có cách nào không cần dùng cel tham chiếu A1 (DemCot)?
- Để Excel tự động nhảy cột tiếp theo để ghi dữ liệu không?
- Làm sao để khi đến cột 256 thì Excel tự động xuống dòng và tiếp tục ghi?
Cảm ơn các bạn nhiều. (Xin chỉ cụ thể vì tôi mới tiếp xúc vơi VBA)
 
Mình hiểu bài toán của bạn thế này ko biết có đúng không?
Bạn lập một UserForm gồm có 19 Textbox (có tên là Dai, XLo1 ~ XLo18) và 01 Command (có tên là GhiSo).
Sau khi bạn đã nhập dữ liệu vào 19 Textbox và nhấn nút GhiSo để cập nhật dữ liệu vào sheet S01.
Các số liệu này sẽ được ghi thành n cột giống nhau (tạo thành một vùng gồm 19 dòng và n cột).
Nếu đúng như vậy thì bạn
Mã:
Private Sub GhiSo_Click()
    S01.Select
    Range("DemCot").Select
    TongSoCot = Range("DemCot").Value
    For n = 1 To TongSoCot
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.Dai.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo1.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo2.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo3.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo4.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo5.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo6.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo7.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo8.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo9.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo10.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo11.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo12.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo13.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo14.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo15.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo16.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo17.Value
        ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.XLo18.Value
        'Range("DemCot").Select
        'Range("DemCot").Value = Range("DemCot").Value + 1
        ActiveCell.Offset(-19, [COLOR=red][B]1[/B][/COLOR]).Select
    Next n
End Sub
Vấn đề là bạn sử dụng dòng lệnh ActiveCell.Offset(0, N).Select
Dòng lệnh đúng là ActiveCell.Offset(-19, 1).Select

Bạn thử chạy xem
 
Upvote 0
Theo mình bạn không nên dùng nhiều nhiều phương thức select như vậy, điều này sẽ làm cho màn hình không đẹp (nháy nháy) và tốc độ chậm. Bạn có thể sử dụng offset để điền giá trị cho các ô là được rồi.

Thân!
 
Upvote 0
Gởi nvson!
Bạn hiểu như vậy là đúng rồi, nhưng mình không ghi dữ liệu vào 19 cột mà chỉ ghi vào 1 cột - 19 dòng, sau đó nhập dữ liệu mới ghi vào cột tiếp theo.
Mình đã thử đọan mã của bạn rồi nhưng nó vẫn ghi đè lên cột A và giá trị của DemCot không thay đổi nên nó không nhảy sang cột tiếp theo.

Gởi ruadangyeu!
Mình mới tiếp xúc VBA nên không biết cách dùng OFSSET như thế nào? Bạn có thể hướng dẫn cụ thể hoặc cho ví dụ cũng được. Trong phần help có hướng dẫn dùng For...Next để ghi dữ liệu trên 1 dòng và nhiều cột còn ngược lại thì +-+-+-+ . Mong được hướng dẫn của bạn.

Thân chào!
 
Upvote 0
Bạn hiểu như vậy là đúng rồi, nhưng mình không ghi dữ liệu vào 19 cột mà chỉ ghi vào 1 cột - 19 dòng, sau đó nhập dữ liệu mới ghi vào cột tiếp theo.
Bạn nên thế này:
Khai báo 1 biến mảng gồm 19 hay 20 thành viên để chứa dữ liệu của các controls sau mỗi lần nhấn chuột vô nút lệnh;
Sau nữa là tìm tự động đến cột cuối cùng có dữ liệu
( Tham khảo dòng lệnh tìm đến dòng cuối sau đây : Range("A65536").End(xlUp).Select )
Phần còn lại của công việc sẽ là tăng kí tự biểu thị cột cần chép lên 1 & chép thôi; (Và lúc này chép = vòng lặp sẽ tiên hơn! - VBA thích hợp trong ~ trường hợp sự việc lặp đi lặp lại 1 cách nhàm chán)

2./
Hình như 2 câu lệnh
Mã:
ActiveCell.Offset(1, 0).Select: ActiveCell.Value = Me.Dai.Value
có thể nhập thành một mà
 
Upvote 0
Gởi nvson!
Đây là file của bài tóan For...Next.
 

File đính kèm

Upvote 0
Dear bluecat,
-------------
Bạn tham khảo thêm chủ đề Có nên tạo màn hình nhập liệu bằng User Form trên Excel? để quyết định có nên tiếp tục xây dựng User form nhập liệu hay không.

Về thủ tục của bạn:
1. Bạn nên khai báo biến một cách tường minh trước khi sử dụng chúng. Đây là kinh nghiệm của những người lập trình chuyên nghiệp.
2. "Sau mỗi lần nhập dữ liệu thì DemCot lại tăng thành gấp đôi chứ không phải là một đơn vị" là do sau mỗi bước lặp, Range("DemCot").Value tăng thêm 1 đơn vị. Như vậy sau TongSoCot lần lặp thì Range("DemCot").Value tăng TongSoCot đơn vị.
3. "Vòng lặp sai ở chổ nào mà Excel luôn ghi dữ liệu bắt đầu từ cột A":
- Không nhất thiết sử dụng phương thức Select để ActiveCell trước khi điền dữ liệu. Khi muốn cập nhật giá trị của Cell nào bạn chỉ việc tham chiếu tới thuộc tính Value hoặc Formula của Cell đó.
- Yêu cầu là điền dữ liệu từ 19 Textbox trên User form vào mỗi cột sau mỗi lần cập nhật. Thủ tục của bạn có liệt kê từng Textbox để điền dữ liệu xuống các Cell, đến Textbox cuối cùng là kết thúc thủ tục. Vậy bạn lặp lại nhóm thao tác đó bằng cấu trúc For… Next làm gì nữa?
- Một đặc điểm của cấu trúc For … Next là thi hành các lệnh tuần tự qua từng bước (step) với số vòng lặp (end) xác định. Đoạn code của bạn không thể hiện được điều này.
4.Theo ý tưởng của bạn, cấu trúc For… Next có thể được xây dựng như thế này:
For i = 1 to 19
Cells(i, <Chỉ số cột cuối cùng>).Value = TextBoxs(i).Value
Next
Trong đó:
<Chỉ số cột cuối cùng> được xác định bởi “Cao ta” (COUNTA) n cột hiện hành + chỉ số cột đầu tiên của bảng
TextBoxs(i) là một mảng điều khiển các TextBox. Nhưng rất tiếc mảng này chỉ có trong Visual Basic 6 chứ không được hỗ trợ trong Visual Basic for Applications.
Nhưng không sao, nếu bạn ngại phải… viết nhiều dòng lệnh liệt kê những TextBox như trên, bạn vẫn có thể dùng For… Next để điều hướng chương trình, bằng cách:
- Đặt tên các Text box theo chỉ số: TextBox1, TextBox2, TextBox3,.., TextBox19
- Áp dụng cấu trúc lặp For… Next:
For i = 1 to 19
Cells(i, <Chỉ số cột cuối cùng>).Value = Controls(“TextBox” & i).Value
Next
5. Nếu chưa biết nhiều về VBA, cách hay nhất là hãy dừng lại, đừng viết code vội. Có lẽ Góc học tập là nơi thích hợp nhất cho bạn luyện tập.
 
Lần chỉnh sửa cuối:
Upvote 0
Trước tiên xin cảm ơn ý kiến của bạn Đào Việt Cường về For...Next. Mình sẽ cố gắng thực hiện theo cách bạn chỉ.
Còn bạn cho rằng mình đừng viết code vội mà vào góc học tập trước thì mình vào rồi nên mới đem ra ứng dụng đó. Ở góc học tập có rất nhiều lý thuyết để học, mình cũng đã học rồi nhưng vẫn chưa áp dụng được vì lý thuyết vẫn còn chung quá và có rất ít ví dụ để hiểu.
Vì vậy mình thấy tốt nhất là nên thực hành rồi từ từ hiểu ra. Nếu có gì sai hoặc hiểu chưa đúng mong các bạn giúp đỡ. Như vậy chác sẽ nhanh hơn.
Thân.
 
Upvote 0
Trong VBA hàm COUNTA sử dụng như thế nào vạya anh VIệt Cường? Sao trong phần help VBA không thấy?
 
Upvote 0
Application.WorksheetFunction.Các hàm Excel.
 
Upvote 0
Chỉ cho mình cụ thể đi các bạn ơi.
CountA(rng1,rng2...rng30). Vậy làm sao đưa vào For... Next

To nvson : Sao không thấy bạn nữa vậy?
 
Upvote 0
Lần chỉnh sửa cuối:
Upvote 0
Dear nvson,
------------
Trong file đính kèm, em không thấy For...Next đâu cả. Thủ tục ứng dụng For...Next có thể được viết như thế này được không:
Mã:
Private Sub GhiSo_Click()
[COLOR=darkgreen]'Nếu chưa chọn tỉnh thì chưa làm gì cả:[/COLOR]
If Dai.Value = "" Then
    Dai.SetFocus
    SendKeys "%{down}"
    Exit Sub
End If
Sheets("KetQua").Select
soCot = GetSetting("Microsoft Excel - GPE", "Setting", "End_Column", "1")
soDong = GetSetting("Microsoft Excel - GPE", "Setting", "End_Row", "2")
If soCot >= 256 Then
    soCot = 1
    soDong = soDong + 20
End If
Cells(soDong, soCot).Select
Cells(soDong, soCot).Offset(1, 0).Value = Me.Dai.Value
Dim i As Long
For i = 1 To 18
    [COLOR=darkgreen]'Trước khi gán giá trị cho Cells(soDong, soCot).Offset(i + 1, 0) cần kiểm tra hợp lệ [/COLOR]
[COLOR=darkgreen]    của Controls("XLo" & i).Value, hạn chế biến cố Worksheet_Change, ví dụ:[/COLOR]
     If IsNumeric(Controls("XLo" & i).Value) And Controls("XLo" & i).Value <> "" Then
         Cells(soDong, soCot).Offset(i + 1, 0).Value = Controls("XLo" & i).Value
     End If
Next
 
SaveSetting "Microsoft Excel - GPE", "Setting", "End_Row", ActiveCell.Row
SaveSetting "Microsoft Excel - GPE", "Setting", "End_Column", ActiveCell.Column + 1
End Sub

bluecat đã viết:
Chỉ cho mình cụ thể đi các bạn ơi.
CountA(rng1,rng2...rng30). Vậy làm sao đưa vào For... Next
Dear bluecat,
-------------
Bạn có thể thiết lập hàm tham số <Chỉ số cột cuối cùng> bằng hàm COUNTA() tại một Worksheet độc lập. Trong thủ tục bạn tham chiếu đến Cell có chứa giá trị này rồi gán vào một biến. Nếu không muốn tạo thêm Worksheet trung gian thì bạn có thể sử dụng WorksheetFunction.CountA để gán vào biến:

Sheets("KetQua").Select
soDong = 1
soCot = WorksheetFunction.CountA(Range("1:1").Value) + 1

Bạn lưu ý Worksheet cập nhật (Sheets("KetQua")) phải thuần dữ liệu thì kết quả CountA mới chính xác. Và bạn cũng nên để dòng đầu tiên của sheet là dòng tiêu đề bảng (dòng 'Tỉnh thành') cột đầu tiên là cột 'Giải thưởng' để tiện cho việc kiểm tra. Bạn cũng cần phải kiểm tra nếu dữ liệu không hợp lệ thì không cho phép cập nhật để hạn chế các sai sót bằng cách trước khi cập nhật thì duyệt qua các Text box. Nếu có một Text box không hợp lệ thì SetFocus để người dùng sửa lại cho đến khi tất cả đều thảo mãn thì mới cho thực hiện cập nhật. Thủ tục này nếu bạn làm việc trực tiếp trên Sheet thì chỉ cần chức năng Data/Validation là đủ!

Nhưng chừng đó vẫn chưa đủ. Vấn đề phức tạp hơn mà mình nghĩ rằng bạn chưa lường hết là tác dụng của việc xây dựng màn hình nhập liệu bằng User Form còn quá ít so với công sức mà bạn tạo ra nó. Tất cả những gì đang đề cập trong chủ để này mới chỉ dừng lại ở việc nhập dữ liệu một chiều từ User Form xuống Sheet, thậm trí mới chỉ là thêm mới dữ liệu. Vấn đề sẽ phức tạp hơn nhiều (và mất nhiều công sức không đáng có) nếu bạn muốn cập nhật và chỉnh sửa dữ liệu đã cập nhật trên Sheet bằng User Form. Và đó mới là công dụng thực sự của một màn hình nhập liệu. Theo mình, chẳng thà bạn ngồi nhập trực tiếp vào sheet KetQua chẳng "sướng" hơn hay sao, chỉnh sửa cũng đơn giản, dễ dàng!
Tất nhiên, phải tập lập trình thì mới biết song mong bạn đừng quên rằng VBA giúp cho người sử dụng tự động hoá các xử lý phức tạp chứ không phải gây ra những phiền toái hay những cố gắng không đáng có!

Bạn tham khảo thêm cách sử dụng Data Form trong file đính kèm, phần nào thoả mãn yêu cầu của bạn!
 

File đính kèm

Upvote 0
Web KT

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

Back
Top Bottom