Xin chỉ cách bỏ qua dòng Code ở dưới và đi thẳng đến dòng Code được chỉ định

Liên hệ QC

hung2412

Thành viên tích cực
Tham gia
5/8/08
Bài viết
917
Được thích
240
Giới tính
Nam
Xin chào các bạn GPE!
Có cách nào bỏ qua dòng Code ở dưới và đi thẳng đến dòng Code được chỉ định hay không?
Untitled01.png
Xin các bạn chỉ giúp
Xin cảm ơn!
 
Hình như lệnh Goto chỉ trong phạm vi trong một Sub thôi. Mình muốn nó chạy thẳng sang Sub khác cơ
Mỗi sub có một cái tên đúng không? Vậy nên nó sẽ có kiểu này:
Sub ABC()
If ... then
Call XYZ
End If
End Sub
Với XYZ là tên Sub muốn gọi.
 
Upvote 0
Dùng 1 biến public Yes/No hoặc True/ False
Mã:
Public IsGoto As Boolean
_________
Sub abc()
...
...
IsGoto = True
Call xyz
...
End Sub
_________
Sub xyz()
If IsGoto Then Goto BarClub
...
...
BarClub:
' Do Something
...
End Sub
 
Upvote 0
Hoặc là dùng tham số truyền, không cần biến Public
Mã:
Sub abc()
...
...
 
Call xyz True
...
End Sub
_________
Sub xyz( IsGoto As Boolean)
If IsGoto Then Goto BarClub
...
...
BarClub:
' Do Something
...
End Sub
 
Upvote 0
Dùng 1 biến public Yes/No hoặc True/ False
...
Sau khi call xyz rồi thì biến kia có cần chỉnh lại?

Hoặc là dùng tham số truyền, không cần biến Public
...
Không nên dùng tham số. Tự dưng đem đổi chữ ký của hàm sẽ làm động đến nhiều hàm khác cần gọi nó.

Cách tốt hơn hết là viết một hàm trung gian, lấy tham số và gọi hàm cần thiết

Sub GoiXYZ(Optional tkn As Long = 0)
Dim SvNhayTumLum As Long
SvNhayTumLum = NhayTumLum ' NhayTumLum là biến toàn cục
NhayTumLum = tkn
xyz
NhayTumLum = SvNhayTumLum
' sau khi chạy xong, trả nó về vị trí cũ
End Sub

Bên trong sub xyz
Sub xyz(...)
On NhayTumLum Goto ViTri1 [, Vitri 2, Vitri3,...]
...
Vitri1:
...
End Sub

Vói code này, bất cứ hàm nào cũng có thể gọi xyz qua GoiXYZ, và muốn trao cái token để nhảy đi đâu tùy ý. Nếu token là 0 thì là nhảy dến dòng kế tiếp.

Lưu ý:
Cái mà thớt đòi hỏi là loại lập trình đi ngược lại nguyên tắc của lập trình cấu trúc (structured).
Vả lại, lệnh Goto là căn bản của code mỳ Ý (spaghetti code)

Tất cả những gì đặt thêm đều phải đi kèm với cách gỡ.
Vì đi ngược nguyên tắc cho nên nó có rất nhiều ổ voi. Chạy xe Merc S 350 sẽ gãy càng.
Dùng kỹ thuật re-structure code là cách lắp ổ voi.
 
Upvote 0
Sau khi call xyz rồi thì biến kia có cần chỉnh lại?


Không nên dùng tham số. Tự dưng đem đổi chữ ký của hàm sẽ làm động đến nhiều hàm khác cần gọi nó.

Cách tốt hơn hết là viết một hàm trung gian, lấy tham số và gọi hàm cần thiết

Sub GoiXYZ(Optional tkn As Long = 0)
Dim SvNhayTumLum As Long
SvNhayTumLum = NhayTumLum ' NhayTumLum là biến toàn cục
NhayTumLum = tkn
xyz
NhayTumLum = SvNhayTumLum
' sau khi chạy xong, trả nó về vị trí cũ
End Sub

Bên trong sub xyz
Sub xyz(...)
On NhayTumLum Goto ViTri1 [, Vitri 2, Vitri3,...]
...
Vitri1:
...
End Sub

Vói code này, bất cứ hàm nào cũng có thể gọi xyz qua GoiXYZ, và muốn trao cái token để nhảy đi đâu tùy ý. Nếu token là 0 thì là nhảy dến dòng kế tiếp.

Lưu ý:
Cái mà thớt đòi hỏi là loại lập trình đi ngược lại nguyên tắc của lập trình cấu trúc (structured).
Vả lại, lệnh Goto là căn bản của code mỳ Ý (spaghetti code)

Tất cả những gì đặt thêm đều phải đi kèm với cách gỡ.
Vì đi ngược nguyên tắc cho nên nó có rất nhiều ổ voi. Chạy xe Merc S 350 sẽ gãy càng.
Dùng kỹ thuật re-structure code là cách lắp ổ voi.
Dễ mà dưới cái Call XYZ thì thêm dòng Exit Sub
 
Upvote 0
Xin chào các bạn GPE!
Có cách nào bỏ qua dòng Code ở dưới và đi thẳng đến dòng Code được chỉ định hay không?
View attachment 301698
Xin các bạn chỉ giúp
Xin cảm ơn!
Mục đích làm gì mới quan trọng
Còn chế thì kiểu gì cũng làm được, nhưng hậu quả thì khó lường, và chính ta có khi lại bằng bẫy tự giăng ra
 
Upvote 0
Mục đích làm gì mới quan trọng
Còn chế thì kiểu gì cũng làm được, nhưng hậu quả thì khó lường, và chính ta có khi lại bằng bẫy tự giăng ra
Mục đích thì ngoài tầm hiểu biết của chúng ta rồi. Theo tôi hiểu thì có người từng tuyên bố rằng đây là project viết sẵn cho 10 năm tới.
 
Upvote 0
Sau khi call xyz rồi thì biến kia có cần chỉnh lại?
Trường hợp dùng biến Public thì mỗi khi có bất kỳ sub nào cần gọi tới Sub xyz đều phải gán giá trị cho biến IsGoto trước khi gọi.
Nếu sub xyz có trường hợp tự thân chạy thì phải trả IsGoto về False ngay sau cái nhãn BarClub

Không nên dùng tham số. Tự dưng đem đổi chữ ký của hàm sẽ làm động đến nhiều hàm khác cần gọi nó.
Nhiều hàm gọi thì mỗi hàm khi gọi đều phải truyền giá trị True/ False
--------------
Mặc dù vậy, theo tôi thì không xài Label rất khó kiểm soát đối với người mới học. Tôi sẽ tạo 1 Sub con mang nội dung của các câu lệnh Do Something.
Mã:
Subcon()
Do Something
End Sub
_____________
Sub abc()
...
...
 
Call SubCon
...
End Sub
_________
Sub xyz( )
...
...
Call SubCon
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Trường hợp dùng biến Public thì mỗi khi có bất kỳ sub nào cần gọi tới Sub xyz đều phải gán giá trị cho biến IsGoto trước khi gọi.
Điểm tôi nói trên là bao cả trường hợp có nhiều Sub's gọi xyz.
Tại sao abc phải nhảy ngang vào xyz? Vì nó cần chạy một số code mà không muốn ảnh hưởng đến những chuyện khác xyz làm trước đoạn code kia. Đồng thời, nhảy ngang như vậy sẽ được các biến nội ở tình trạng mặc định.

Nếu sub xyz có trường hợp tự thân chạy thì phải trả IsGoto về False ngay sau cái nhãn BarClub
...
Ai biết trước đó IsGoTo là cái gì?
Tốt hơn hết là save nó lại. Dùng xong thì trả nó về trị trước (đã saved)

...
Nhiều hàm gọi thì mỗi hàm khi gọi đều phải truyền giá trị True/ False
--------------
Mặc dù vậy, theo tôi thì không xài Label rất khó kiểm soát đối với người mới học. Tôi sẽ tạo 1 Sub con mang nội dung của các câu lệnh Do Something.
...
Gọi sub con là đúng với truyền thống structured programming.
Nhưng làm vậy đâu phải là từ sub này nhảy ngang vào giữa sub kia. Ở đây ta gặp người có đầu óc tính trước người thường được 10 năm, chắc 10 năm sau người ta chuyên xài code nhảy tùm lum không màng tới heap hay stack gì cả.
 
Upvote 0
Ai biết trước đó IsGoTo là cái gì?
Nhiều cái chưa biết lắm, nên tôi còn không chắc kiểm soát label có đưa câu lệnh Exit Sub vào hay không
- Sub gọi (abc) không biết sau khi gọi xyz có còn chạy tiếp những lệnh bên dưới của chính nó hay không
- Khi gọi xyz để chạy nhóm lệnh DoSomething, bên dưới DoSomething còn câu lệnh nào khác không? Có chạy luôn đến hết xyz hay không?
- Sub được gọi (xyz) không biết ngoài abc còn ai gọi nữa không? Gọi kiểu gì? Có Goto không? nếu có thì có Goto cùng chỗ không?
- Sub xyz ngoài việc được gọi ra có tự thân chạy 1 mình không? Nếu có thì có chạy từ đầu đến hết các câu của DoSomething không? Sau các câu lệnh DoSomething có các câu lệnh khác không? Có chạy hết luôn không?

Thế nên Exit sub sẽ có các tình trạng:
- Có đặt không? Đặt Sub nào?
- Nếu đặt ở abc thì đặt ngay sau Call hay đặt ở đâu?
- Nếu đặt ở xyz thì đặt trước Label hay sau DoSomething? Điều kiện Exit là gì (chỉ exit khi abc gọi, exit khi bị gọi bởi bất kỳ ai, exit khi tự chạy, ...)

Kết luận là tạo sub con khỏi đau đầu.
 
Upvote 0
...
Kết luận là tạo sub con khỏi đau đầu.
Tạo sub con tức là lập trình cấu trúc.
Trong phần "lưu ý" ở bài #7, tôi đã có nói qua vụ này. Và đặt tiền đề rằng cái thớt muốn là "lập trình phi cấu trúc". Có lẽ cái này chỉ giành cho hackers.

Nói rõ ra theo hình ở bài #1. thớt muốn rằng sub abc đang chạy tới dòng lệnh n thì gặp 1 lệnh rẽ nhánh. Một nhánh đi tiếp xuống dòng lệnh n+1. Nhánh còn lại rẽ qua dòng k của sub xyz, chạy cho đến exit/end sub của xyz.
Vì đây là lệnh nhảy ngoài tầm vực của sub cho nên không thể kể nó là spaghetti code. Luật của lệnh nhảy là mỗi địa chỉ nhánh rẽ đều phải nằm trong tầm vực của sub.

Tầm vực:
Tầm vực của abc là từ dòng khai báo sub cho đến dòng end sub. Tầm vực này chỉ có 1 lối vào duy nhất là lúc khai báo. Lối ra thì có thể nhiều nhưng chỉ qua hai loại lệnh: exit sub và end sub. Vì sub chỉ có một lối vào duy nhất là từ lệnh khai báo sub, tất cả cách nhảy ngang vào đều là cách nhảy thẳng vào địa chỉ dòng lệnh.

Bộ Nhớ:
Khi sub xyz được gọi, VBA sẽ dồn một mớ trị của sub gọi vào stack, mở một mớ biến nội trong stack, và ghi đường về sub gọi vào stack.

Chuyện gì sẽ xảy ra cho tầm vực và bộ nhớ? giả sử ta có viết được code nhảy ngang như thớt muốn ở bài #1?
- vì không có biến nội, code chỉ chạy được với biến toàn cục.
- khi đang chạy code trong xyz, một số dòng lệnh vì không định rõ địa chỉ trong bộ nhớ, sẽ bị vỡ và --> BSOD
- vì không có ghi đường về, khi chạy tới Exit/End Sub trong xyz, VBA sẽ té ngửa, không biết làm gì tiếp. --> BSOD.

Vì vậy theo lô gic, ta chỉ có 2 đường:
1. viết code spaghetti, "nhại" cách nhảy ngang như đòi hỏi. Cách nhại gần nhất có thể là dùng lệnh GoSub.
2. vì yêu cầu được phân tích là phản cấu trúc cho nên lập trình phi cấu trúc như HĐT có thể trông đẹp mắt hơn ==> chuyển xyz thành một class, code cần chạy nằm trong một method.
 
Upvote 0
Cái thớt muốn là "lập trình phi cấu trúc".
Tôi mặc kệ việc thớt muốn. Tôi (và có lẽ cả anh) đang mở rộng vấn đề và cách xử lý vấn đề theo chuẩn lập trình chính thống, không làm theo cách mà bản thân không hiểu rõ cách làm và tác hại. Những ai muốn học hỏi mà đọc qua bài của anh có lẽ sẽ hiểu hơn về lý thuyết, đọc bài của tôi sẽ thấy cách xử lý đơn giản.
 
Upvote 0
Web KT
Back
Top Bottom