Biến dùng chung cho nhiều sub trong vba (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Nhattanktnn

Thành viên gắn bó
Tham gia
11/11/16
Bài viết
3,160
Được thích
4,147
Donate (Momo)
Donate
Giới tính
Nam
Chào anh chị và các bạn!
Mình mới tập tành VBA có vấn đề như này, search trên google cũng không biết dùng từ như nào cho phù hợp nên tìm không ra giải pháp.
Giả sử mình khai báo LastRow để tìm dòng cuối cùng của một sheet sử dụng trong một module.
Trong module này có nhiều sub,mà sub nào cũng cần dùng đến LastRow. Mình không muốn sub nào cũng phải khai báo LastRow xong LastRow=... mà mình muốn khai báo một lần. các sub tiếp theo đều dùng chung được,
Có cách nào làm như vậy không ạ?
Nếu cách dưới đây thì mình cũng đã nghĩ ra (nhưng không biết còn cách nào khác không):
Sub lastRow()
...
End sub

Sub abc()
Call lastRow
...
End sub
Diễn giải nếu hơi khó hiểu thì anh chị và các bạn thông cảm vì chưa rành nên khó diễn đạt
Cảm ơn!
 
Bạn khai báo bên ngoài sub, trên sub đầu tiên
Mã:
Dim LastRow As Long
Sub Macro1()
...
End Sub
 
Bạn khai báo bên ngoài sub, trên sub đầu tiên
Mã:
Dim LastRow As Long
Sub Macro1()
...
End Sub
Để em thử xem sao, cảm ơn anh hữu thắng (không biết gọi anh hay gọi bác nữa), Thấy anh rep trên diễn đàn từ năm 200x cơ. Ngưỡng mộ lắm hihi
Bài đã được tự động gộp:

Nhưng anh ơi, nếu em muốn cái này nó dùng chung luôn thì có được không: LastRow = Sheet1.Range("E" & Rows.Count).End(xlUp).Row
Hay cứ phải sub nào cũng để nó vào?
 
Lần chỉnh sửa cuối:
Để em thử xem sao, cảm ơn anh hữu thắng (không biết gọi anh hay gọi bác nữa), Thấy anh rep trên diễn đàn từ năm 200x cơ. Ngưỡng mộ lắm hihi
Bài đã được tự động gộp:

Nhưng anh ơi, nếu em muốn cái này nó dùng chung luôn thì có được không: LastRow = Sheet1.Range("E" & Rows.Count).End(xlUp).Row
Hay cứ phải sub nào cũng để nó vào?
Bạn phải tính 1 lần. Giá trị sẽ được lưu lại. Tính khi sheet được chọn chẳng hạn.
 
là biến thì bạn phải gán trước 1 lần, là function thì gọi bao nhiêu lần cũng được, tùy trường hợp bạn sử dụng.
Public biến và hàm trong module thì có thể gọi bất kì đâu trong một Workbook
PHP:
'Phương án 1'
Public Glb_LastRow As Long
Sub GetLastRow()
 If Glb_LastRow = 0 Then Glb_LastRow = fGlb_LastRow
End Sub
'Phương án 2'
Function fGlb_LastRow() As Long
fGlb_LastRow = Sheet1.Range("E" & Rows.Count).End(xlUp).Row
End Function
 
Ví dụ gì chẳng chịu, lại nhè ngay cái trường hợp không nên toàn cục mang ra làm ví dụ.
Một Workbook thì có nhiều Sheets. Mang cái thuộc tính lastRow ra làm biến toàn cục thì biết nó là của sheet nào? Về sau này phát triển thêm vài modules nữa thì lại càng khó hiểu. Có phải là mời gọi sự nhầm lẫn tùm lum?

Điều tối thiểu phải làm là gán cho nó:
1. Một cái tiền tố/hậu tố (prefix/subfix) trong tên để nhận biết nó là sheet nào
ví dụ: lstRow_Sh1
2. Nếu không cần phải qua module khác thì lúc khai báo, cho nó là Private. Khi nào cần gọi nó từ module khác thì xoá cái Private đi.
 
Chào anh chị và các bạn!
Mình mới tập tành VBA có vấn đề như này, search trên google cũng không biết dùng từ như nào cho phù hợp nên tìm không ra giải pháp.
Giả sử mình khai báo LastRow để tìm dòng cuối cùng của một sheet sử dụng trong một module.
Trong module này có nhiều sub,mà sub nào cũng cần dùng đến LastRow. Mình không muốn sub nào cũng phải khai báo LastRow xong LastRow=... mà mình muốn khai báo một lần. các sub tiếp theo đều dùng chung được,
Có cách nào làm như vậy không ạ?
Nếu cách dưới đây thì mình cũng đã nghĩ ra (nhưng không biết còn cách nào khác không):
Sub lastRow()
...
End sub

Sub abc()
Call lastRow
...
End sub
Diễn giải nếu hơi khó hiểu thì anh chị và các bạn thông cảm vì chưa rành nên khó diễn đạt
Cảm ơn!
Bạn không nên dùng biến cho nhiều sub trong trường hợp này vì rất khó kiểm soát được biến này có đúng với dữ liệu không.
 
Ví dụ gì chẳng chịu, lại nhè ngay cái trường hợp không nên toàn cục mang ra làm ví dụ.
Một Workbook thì có nhiều Sheets. Mang cái thuộc tính lastRow ra làm biến toàn cục thì biết nó là của sheet nào? Về sau này phát triển thêm vài modules nữa thì lại càng khó hiểu. Có phải là mời gọi sự nhầm lẫn tùm lum?

Điều tối thiểu phải làm là gán cho nó:
1. Một cái tiền tố/hậu tố (prefix/subfix) trong tên để nhận biết nó là sheet nào
ví dụ: lstRow_Sh1
2. Nếu không cần phải qua module khác thì lúc khai báo, cho nó là Private. Khi nào cần gọi nó từ module khác thì xoá cái Private đi.
Không biết anh VetMini không hiểu ý em hay là em không hiểu ý anh muốn nói, em mới tập tành viết code nên nhiều điều không biết. Em đang thao tác với sheet1 và em khai báo lastRow_sh1 (như anh nói), trong cùng 1 module nhưng có nhiều sub thì có cách nào làm cho mỗi sub trong module đó đều hiểu giá trị lastRow_sh1 bằng bao nhiêu mà không cần sub nào cũng phải viết kiểu như vậy không: LastRow_Sh1 = Sheet1.Range("E" & Rows.Count).End(xlUp).Row
Em đang tập viết những code đơn giản nên em chỉ suy nghĩ được những cái khó trước mắt của em thôi. Có gì không đúng mong anh chỉ giáo.
Nếu có thể làm được điều đó thì anh cho em ví dụ luôn nhé, nói chung chung em không hiểu hết được đâu
 
Không biết anh VetMini không hiểu ý em hay là em không hiểu ý anh muốn nói, em mới tập tành viết code nên nhiều điều không biết. Em đang thao tác với sheet1 và em khai báo lastRow_sh1 (như anh nói), trong cùng 1 module nhưng có nhiều sub thì có cách nào làm cho mỗi sub trong module đó đều hiểu giá trị lastRow_sh1 bằng bao nhiêu mà không cần sub nào cũng phải viết kiểu như vậy không: LastRow_Sh1 = Sheet1.Range("E" & Rows.Count).End(xlUp).Row
Em đang tập viết những code đơn giản nên em chỉ suy nghĩ được những cái khó trước mắt của em thôi. Có gì không đúng mong anh chỉ giáo.
Nếu có thể làm được điều đó thì anh cho em ví dụ luôn nhé, nói chung chung em không hiểu hết được đâu
Cái mà bạn muốn đó, tôi đã nói ở phần đầu của bài #6 rồi là không nên làm, vì có những phức tạp của nó.
Và để giảm bớt sự phức tạp (chỉ giảm bớt thôi), tôi cũng đã chỉ cách thực hiện ở phần kế tiếp (cũng ở bài #6)

Rốt cuộc lại thì bạn phải tự hỏi lại mình là muốn gì?

1. Muốn học cách dùng 1 biến mà có thể được thấy qua nhiều Sub/Function khác nhau?
Nếu là trường hợp này thì bạn nên tìm ví dụ khác. Ví dụ lastRow nói thẳng là không xài được.

2. Muốn thực hiện cách truy cứu dòng cuối của 1 sheet một cách đơn giản, gọn gàng.
Trường hợp này thì bạn phải xác định lại rằng mình muốn "dòng cuối" trong cảnh huống nào?

2.1 Cảnh huống thao tác của nhóm code liên hệ. Tức là trị ấy có hiệu lực và cập nhật trong lúc chạy code, các Sub/Function trong nhóm cùng biết với nhau.
Dùng phương án đề nghị từ bài #2, #4, và phần 1 của bài #5. Nếu dùng phần 1 của bài #5 thì cho cái sự kiện Workbook_Open gọi sub ấy.
Lưu ý là muốn dùng phần 1 của bài #5 thì phải gồm luôn cả phần 2.

2.2 Cảnh huống bất kỳ. Tức là trị ấy luôn luôn được cập nhật; không phân biệt là do code hay do thao tác khác (thao tác bởi code khác không trng nhóm).
Dùng phương án 2 của bài #5. Tạo một Function trả về trị này. Nếu Function này là public thì bất cứ sub/function nào cũng gọi được nó để lấy trị dòng cuối của sheet.
Đây là phương pháp rất thích hợp. Chính tôi cũng dùng. Chỉ cần quăng cái code ấy vào thư viện - đặt tên là module ThuVienChung chẳng hạn. Mỗi lần có file (project) cần VBA thì import ThuVienChung vào. Từ đó, bất cứ ở đâu trong project tôi cũng có thể DongCuoi() là xong.
Tuy nhiên, theo như cảnh báo ở bài #6. Code của bài #5 là loại code cẩu thả. Nó cứ mặc định là Sheet1 chứ không phân biệt được cho bạn cái "dòng cuối" ấy là ở sheet nào.
Có 2 cách để cải tiến:
(a) đặt thêm hậu tố _sh1 vào tên của hàm. Nhìn code gọi hàm DongCuoi_Sh1() thì biết nó là dòng cuối của sheet1
(b) đặt thêm tham số cho hàm. Nhìn code gọi hàm DongCuoi(Sheet1) thì biết nó tính dòng cuối của sheet1

Public Function DongCuoi(Optional Sh = ActiveSheet, Optional Cot = "A") As Long
DongCuoi = Sh.Range(Cot & Rows.Count).End(xlUp).Row
End Function

Chú thích: tôi chuyên nghề quản lý. Một trong những cái tôi quản lý là đồ án phần mềm, và đương nhiên là tôi phải biết chú trọng quản lý code.
Những gì tôi chỉ dẫn không bảo đảm là hiệu quả nhất ở đây. Có nhiều ngừoi viết code tiết kiệm hơn, chạy nhanh hơn, hoành tráng (làm được khối việc) hơn tôi. Nhưng bảo đảm là ở đây không ai viết code thực tế (*) an toàn hơn tôi.
(*) nhiều ngừoi ở đây vẫn phê bình tôi nói chuyện lý thuyết nhiều quá. Những ngừoi ấy chưa trải qua các project lớn, chia chung nhiều người viết code cho nên chưa biết tầm quan trọng của "lý thuyết" quản lý code.
 
Lần chỉnh sửa cuối:
Cái mà bạn muốn đó, tôi đã nói ở phần đầu của bài #6 rồi là không nên làm, vì có những phức tạp của nó.
Và để giảm bớt sự phức tạp (chỉ giảm bớt thôi), tôi cũng đã chỉ cách thực hiện ở phần kế tiếp (cũng ở bài #6)

Rốt cuộc lại thì bạn phải tự hỏi lại mình là muốn gì?

1. Muốn học cách dùng 1 biến mà có thể được thấy qua nhiều Sub/Function khác nhau?
Nếu là trường hợp này thì bạn nên tìm ví dụ khác. Ví dụ lastRow nói thẳng là không xài được.

2. Muốn thực hiện cách truy cứu dòng cuối của 1 sheet một cách đơn giản, gọn gàng.
Trường hợp này thì bạn phải xác định lại rằng mình muốn "dòng cuối" trong cảnh huống nào?

2.1 Cảnh huống thao tác của nhóm code liên hệ. Tức là trị ấy có hiệu lực và cập nhật trong lúc chạy code, các Sub/Function trong nhóm cùng biết với nhau.
Dùng phương án đề nghị từ bài #2, #4, và phần 1 của bài #5. Nếu dùng phần 1 của bài #5 thì cho cái sự kiện Workbook_Open gọi sub ấy.
Lưu ý là muốn dùng phần 1 của bài #5 thì phải gồm luôn cả phần 2.

2.2 Cảnh huống bất kỳ. Tức là trị ấy luôn luôn được cập nhật; không phân biệt là do code hay do thao tác khác (thao tác bởi code khác không trng nhóm).
Dùng phương án 2 của bài #5. Tạo một Function trả về trị này. Nếu Function này là public thì bất cứ sub/function nào cũng gọi được nó để lấy trị dòng cuối của sheet.
Đây là phương pháp rất thích hợp. Chính tôi cũng dùng. Chỉ cần quăng cái code ấy vào thư viện - đặt tên là module ThuVienChung chẳng hạn. Mỗi lần có file (project) cần VBA thì import ThuVienChung vào. Từ đó, bất cứ ở đâu trong project tôi cũng có thể DongCuoi() là xong.
Tuy nhiên, theo như cảnh báo ở bài #6. Code của bài #5 là loại code cẩu thả. Nó cứ mặc định là Sheet1 chứ không phân biệt được cho bạn cái "dòng cuối" ấy là ở sheet nào.
Có 2 cách để cải tiến:
(a) đặt thêm hậu tố _sh1 vào tên của hàm. Nhìn code gọi hàm DongCuoi_Sh1() thì biết nó là dòng cuối của sheet1
(b) đặt thêm tham số cho hàm. Nhìn code gọi hàm DongCuoi(Sheet1) thì biết nó tính dòng cuối của sheet1

Public Function DongCuoi(Optional Sh = ActiveSheet, Optional Cot = "A") As Long
DongCuoi = Sh.Range(Cot & Rows.Count).End(xlUp).Row
End Function

Chú thích: tôi chuyên nghề quản lý. Một trong những cái tôi quản lý là đồ án phần mềm, và đương nhiên là tôi phải biết chú trọng quản lý code.
Những gì tôi chỉ dẫn không bảo đảm là hiệu quả nhất ở đây. Có nhiều ngừoi viết code tiết kiệm hơn, chạy nhanh hơn, hoành tráng (làm được khối việc) hơn tôi. Nhưng bảo đảm là ở đây không ai viết code thực tế (*) an toàn hơn tôi.
(*) nhiều ngừoi ở đây vẫn phê bình tôi nói chuyện lý thuyết nhiều quá. Những ngừoi ấy chưa trải qua các project lớn, chia chung nhiều người viết code cho nên chưa biết tầm quan trọng của "lý thuyết" quản lý code.
Cảm ơn anh, em sẽ nghiền ngẫm và tập thực hành những gì anh chỉ giảng.
 
Web KT

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

Back
Top Bottom