Xin giải thích Code có Private đứng trước Sub (1 người xem)

Liên hệ QC

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

a.nguoidensau

Thành viên hoạt động
Tham gia
12/4/12
Bài viết
138
Được thích
28
Chào mọi ngươi!
Tôi vướng mắc như sau và nhờ mọi người giải thích giùm, nó như sau:
Tại Sheet1 tôi có 1 vùng dữ liệu cần xử lý và có 1 Code để xử lý nó, chẳng hạn
Mã:
Sub abc()
--------
End Sub
Và tôi ấn F5 chạy Code là OK, nhưng với những Code có thêm "tiền tố" Private
Mã:
Private Sub.......
--------
End Sub

thì tôi không biết phải chạy Code thế nào, hay nguyên tắc hoạt động của Code đó ra sao.
Xin mọi người chỉ giúp để tôi có thể hiểu được vấn đề.
Xin cảm ơn.
 
Chạy thử như sau:

Application.Run "TenSheet.TenSub"
 
Upvote 0
Em chạy thử:
Mã:
Option Explicit

Sub Macro1()
    Range("A4:A25").Select
End Sub

Sub abc()
Application.Run "Sheet1.Macro1"
End Sub

Nó báo Macro1 trong Sheet1 không tìm thấy bác ah.

Vậy cái Macro1 đó bạn để ở đâu? Nằm trong tên sheet (Sheet1) được thấy trong cửa sổ code?
 
Upvote 0
Vậy cái Macro1 đó bạn để ở đâu? Nằm trong tên sheet (Sheet1) được thấy trong cửa sổ code?
Cái Code:
Mã:
Sub Macro1()

    Range("A4:A25").Select
End Sub
Sub abc()
Application.Run "Sheet1.Macro1"
End
Lúc trước em để trong Module, không phải trong Sheet1, vì vậy có câu "không tìm thấy....".
Còn nếu em đặt nó trong cửa sổ Code của Sheet1 thì nó chọn vùng A4:A25.
 
Upvote 0
Cái Code:
Mã:
Sub Macro1()

    Range("A4:A25").Select
End Sub
Sub abc()
Application.Run "Sheet1.Macro1"
End
Lúc trước em để trong Module, không phải trong Sheet1, vì vậy có câu "không tìm thấy....".
Còn nếu em đặt nó trong cửa sổ Code của Sheet1 thì nó chọn vùng A4:A25.

Muốn gọi Private Sub trong module thì dùng code sau:

Application.Run "TênModuleChuaMacro.TenSub"
 
Upvote 0
Cái Code:
Mã:
Sub Macro1()

    Range("A4:A25").Select
End Sub
Sub abc()
Application.Run "Sheet1.Macro1"
End Sub
Lúc trước em để trong Module, không phải trong Sheet1, vì vậy có câu "không tìm thấy....".
Còn nếu em đặt nó trong cửa sổ Code của Sheet1 thì nó chọn vùng A4:A25.

Nếu đặt Macro1 trong sheet nào đó thì ít nhất thì phải sửa Macro1 thành vầy:
Mã:
Sub Macro1()
  [COLOR=#ff0000]Me.Select[/COLOR]
  Range("A4:A25").Select
End Sub
Mọi code liên quan đến chọn vùng, bắt buộc phải chọn Sheet chứa vùng ấy trước
 
Upvote 0
các sub/function nếu có tiền tố Private thì chỉ các câu lệnh trong cùng modul với nó mới thấy để gọi. còn nếu là Public (hoặc không có tiền tố) thì các câu lệnh trong tất cả các modul đều gọi được.

lưu ý: với các sub/function khai báo Public (hoặc không có tiền tố) trong các sheet, form thì khi gọi nó phải thêm tên sheet/form + dấu "." + sub/function.

Việc khai báo biến cũng tương tự. Nếu khai báo trong modul với tiền tố Public thì có thể dùng trong mọi modul, sheet, form, class, nếu khai báo Dim trong một sub/function thì chỉ dùng được trong sub/function đó, còn nếu khai báo Dim phía trên cùng (ngoài các sub/function) thì dùng được trong cả modul đó.
cái này người ta gọi là tầm vực (scope)

lưu ý: trong các sheet/form/class chỉ có thể khai báo Dim.
 
Upvote 0
Tôi chờ đã 10 ngày, không thấy bạn hỏi tiếp: tại sao lại phải đặt "Private". Tại sao không "Public" hết cho khoẻ thân?
 
Upvote 0
Tôi chờ đã 10 ngày, không thấy bạn hỏi tiếp: tại sao lại phải đặt "Private". Tại sao không "Public" hết cho khoẻ thân?
Thực ra em đang tìm hiểu về VBA, nên mắc chỗ nào thì hỏi chỗ đó thôi chứ cũng chưa nghĩ ra câu hỏi như bác đã đưa ra ở trên.Em đã từng đọc các bài viết của bác, thấy bác phân tích tỉ mỉ, rõ ràng, mạch lạc và rất khâm phục kiến thức của bác. Em thấy câu hỏi của bác rất hay, bác vui lòng chỉ giúp em cũng như những ai chưa từng biết về điều này không?
Xin chân thành cảm ơn bác.
 
Upvote 0
Thử tìm hiểu đi. Hãy tạm bỏ qua việc VBA mặc định cho code của Sheet. Xét khía canh chủ quan, khi nào thì bạn nên đặt từ khoá này vào Sub/Func/... của mình?

Gợi ý: nó quan trọng đối với cách viết code của tôi, nhưng không quan trọng lắm đối với cách viết của nhiều người khác ở đây.
 
Upvote 0
Thử tìm hiểu đi. Hãy tạm bỏ qua việc VBA mặc định cho code của Sheet. Xét khía canh chủ quan, khi nào thì bạn nên đặt từ khoá này vào Sub/Func/... của mình?
xin chen ngang một chút:
tui thường viết addin nên hay dùng Private để không cho người khác thấy các hàm.
 
Upvote 0
xin chen ngang một chút:
tui thường viết addin nên hay dùng Private để không cho người khác thấy các hàm.

Nếu muốn giấu không cho thấy khi sử dụng sub hay public thì vẫn có cách khác mà không nhất thiết phải dùng private.
 
Upvote 0
Em cũng đang lơ mơ khi nào thì dùng Public, khi nào thì Private.
Đã không hiểu thì tội gì đụng đầu vào tường cho đau. Cứ quăng hết vào Module, muốn chạy thì gọi, không cho chạy thì đừng gọi.
Trừ những sự kiện thì tự nhiên nó nằm trong sheet và tự động thêm cái Private quỷ gì đó.
Khi nào khấm khá chút rồi tính. Mình cũng chả hiểu lúc nào xài cái nào, nhưng code chạy ầm ầm đó thôi.
 
Upvote 0
"tại sao lại có chuyện Private mà chẳng Public hết cho khoẻ":

Tôi đã nói trước là vấn đề này chỉ quan trọng đối với tôi. Đúng không?

Trên quan điểm đối tượng, một module có thể tạm coi như một cơ sở làm việc. Mỗi cơ sở có một đội ngũ làm việc tiếp xúc với người ngoài và một đội ngũ chỉ chuyên làm việc bên trong, không tiếp xúc với ai cả. Ví dụ như trong một nhà náy, phòng tiếp thị và kho xuất nhập tiếp xúc với bên ngoài, trong khi phân xuởng hoàn toàn biệt lập không tiếp xúc. Người mua hàng chỉ cần biết nơi lấy hàng và trả tiền thôi chứ phân xưởng làm việc thế nào là chuyện của nhà máy. Nơi bán hàng như thế gọi là cái giao diện của nhà máy với bên ngoài, và nó là public. Phân xưởng như thế gọi là vấn đề nội bộ của nhà máy, và nó là private.

Một module cũng đưa ra giao diện của nó là những hàm, thủ tục, và những biến, khai báo public. Những cái nó không muốn đưa ra giaio diện thì nó dùng tiền tố private; ngụ ý: những gì trong code này là chuyện riêng của tôi; tôi chỉ bảo đảm những gì qua giao diện tôi đưa ra, còn những cái tôi không dưa ra, bạn lạm dụng bị sai ráng chịu.

Ví dụ trong moduleX tôi có hàm TongTri(sheet, range). Khi đặt trong giao diện public, moduleX bảo đảm rằng nếu code của moduleY nào đó gọi hàm này thì sẽ được tổng của các trị trong range-sheet. Bên trong moduleX, tôi thấy rằng hàm TongTri cần một cách thức để lấy trị trong range. Tôi viết hàm DocTriCuaRange để đọc từng trị của range. Sau đó tôi đặt DocTriCuaRange là private vì tôi không muốn đưa nó vào cái giao kèo giao diện. Tại sao vậy?

Một ngày đẹp trời nào đó, tôi khám phá ra rằng DocTriCuaRange là thừa, tôi có thể dùng hàm WorksheetFunction.SUM để thực hiện. Thế là tôi xoá DocTriCuaRange. Vì DocTriCuaRange không nằm trong giao diện cho nên tôi tự tiện làm mà không phải báo cáo, điều chỉnh ở đâu cả. Nếu DocTriCuaRange là public, tôi phải dò xem nó được gọi ở những nơi nào và chỉnh sửa chỗ đó.

Ví dụ trên là ví dụ đơn giản; các bạn thấy việc chỉnh sửa code giao diện thực ra không khó lắm. Trên thực tế, có những trường hợp rất phức tạp mà sửa giao diện rất ư là rườm rà, và dẫn tới một đống test để chắc ăn là không bị tình trạng "kéo chăn kín đầu thì hở chân". Nếu bạn có biết qua về biến toàn cục và biến nội bộ thì đã có kinh nghiệm sơ về vấn đề này.

Đối với VBA, thường thì tôi viết các code giao diện trước cho nên chúng là public. Sau đó tôi viết các hàm, thủ tục hổ trợ, hơạc cắt code trong các hàm giao diện ra cho gọn. Đám sau này là pricvate hết.
Cũng có người viết theo kiểu cho public hết. Sau khi code chạy rồi thì chuyển tất cả những cái không phải là giao diện sang private.

Lưu ý: những code worksheetChange, vv được code là private bởi vì chúng không phải là giao diện của worksheet, các hiện tượng gọi chúng mới là giao diện của worksheet.

@jack nt: trong C, có 2 cách để tạo private
1. dùng #define để đặt lại tên cho function. Cách này rất ít người đồng ý
2. C module 'publics' các thành phần giao diện của mình qua headers (.h). Muốn private thì đặt khai báo prototype bên ngoài headers. Không có prototype, code của module khác sẽ không 'thấy' được các function này.
 
Upvote 0
Web KT

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

Back
Top Bottom