2013-04-11 30 views
9

Dưới đây là một câu hỏi mà tôi sẽ tự trả lời, tuy nhiên nó gây ra một sự thất vọng tuyệt vời cho tôi và tôi gặp rất nhiều khó khăn khi tìm kiếm trên web, vì vậy tôi gửi bài ở đây với hy vọng tiết kiệm một chút thời gian & nỗ lực cho những người khác, và có thể cho bản thân mình nếu tôi quên này trong tương lai:

đối với VBA (trong trường hợp của tôi, MS Excel), tờ khai Public là nghĩa vụ phải làm cho biến (hoặc chức năng) có thể truy cập toàn cục bởi các hàm hoặc chương trình con khác trong mô-đun đó, cũng như trong bất kỳ mô-đun nào khác.

Tắt điều này là không đúng, trong trường hợp Forms
và tôi cũng nghi ngờ trong số Sheets, nhưng tôi chưa xác minh điều sau.

Tóm lại, sau đây sẽ KHÔNG tạo ra một cộng đồng, biến truy cập khi được tạo ra trong một Form, và do đó sẽ sụp đổ, nói rằng các biến bYesNo và dRate là không xác định trong mModule1:
Các biến công khai không phải là REALLY công khai trong VBA trong Biểu mẫu

(inside fMyForm) 
Public bYesNo As Boolean` 
Public dRate As Double 

Private Sub SetVals() 
    bYesNo = Me.cbShouldIHaveADrink.value 
    dRate = CDec(Me.tbHowManyPerHour.value) 
End Sub 
(Presume the textbox & checkbox are defined in the form) 

(inside mModule1) 
Private Sub PrintVals() 
    Debug.Print CStr(bYesNo) 
    Debug.Print CStr(dRate) 
End Sub 


Tuy nhiên, nếu bạn thực hiện các thay đổi nhỏ dưới đây, tất cả sẽ làm việc tốt:

(inside fMyForm) 

Private Sub SetVals() 
    bYesNo = Me.cbShouldIHaveADrink.value 
    dRate = CDec(Me.tbHowManyPerHour.value) 
End Sub 
(Presume the textbox & checkbox are defined in the form) 

(inside mModule1) 
Public bYesNo As Boolean` 
Public dRate As Double 
Private Sub PrintVals() 
    Debug.Print CStr(bYesNo) 
    Debug.Print CStr(dRate) 
End Sub 


mModule1 sẽ làm việc hoàn toàn tốt đẹp, và giả định rằng fMyForm luôn gọi đầu tiên, sau đó vào thời điểm thói quen PrintVals đang chạy, các giá trị từ các textbox và hộp kiểm dưới hình thức sẽ đúng cách được chụp.

Tôi thành thật không thể hiểu được những gì MS đang nghĩ đến với sự thay đổi này, nhưng thiếu tính nhất quán là rất lớn về hiệu quả, học cách đồng bộ hóa như thế này. được khoảng một thập kỷ trở lên là rất khó khăn để tìm kiếm.

+3

Biểu mẫu người dùng và trang tính là mô-đun đối tượng: chúng không hoạt động giống như mô-đun thông thường. Tuy nhiên, bạn có thể tham khảo một biến trong một biểu mẫu người dùng theo cách tương tự như cách bạn muốn tham chiếu đến một thuộc tính lớp. Trong ví dụ của bạn đề cập đến 'fMyForm.bYesNo' sẽ hoạt động tốt. Nếu bạn không khai báo bYesNo là Public, nó sẽ không hiển thị cho mã bên ngoài biểu mẫu, vì vậy khi bạn đặt nó thành Công khai, nó thực sự khác với không công khai. –

+3

Thực tế là nếu bạn muốn các biến công khai thực sự, bạn cần khai báo chúng trong một mô-đun mã và không phải trong vùng mã Form/Sheet. Xem liên kết này http://msdn.microsoft.com/en-us/library/office/gg264241.aspx 'Các biến công cộng có thể được sử dụng trong bất kỳ quy trình nào trong dự án. Nếu một biến công khai được khai báo trong một mô-đun chuẩn hoặc một mô-đun lớp, nó cũng có thể được sử dụng trong bất kỳ dự án nào tham chiếu đến dự án mà biến công khai được khai báo.' –

+0

Về bạn nhận xét cuối cùng. vào năm 2013, điều gì đó có khả năng xảy ra trong một thập niên trở lên là rất khó khăn để tìm kiếm.' Có thể bạn đang tìm kiếm bằng từ khóa sai? Thử tìm kiếm trong Google? 'msdn VBA khai báo biến công khai ';) –

Trả lời

2

Nhận xét đầu tiên:

Mô-đun và mô-đun bảng là mô-đun đối tượng: chúng không hoạt động giống như mô-đun thông thường. Tuy nhiên, bạn có thể tham khảo một biến trong một biểu mẫu người dùng theo cách tương tự như cách bạn muốn tham chiếu đến một thuộc tính lớp. Trong ví dụ của bạn đề cập đến fMyForm.bYesNo sẽ hoạt động tốt. Nếu bạn không khai báo bYesNo là Public, nó sẽ không hiển thị cho mã bên ngoài biểu mẫu, vì vậy khi bạn đặt nó thành Công khai, nó thực sự khác với không công khai. - Tim Williams 11 tháng 4 '13 tại 21:39

thực sự là một câu trả lời đúng ...

+1

Vui lòng đánh dấu câu trả lời này là" câu trả lời của cộng đồng " –

0

Như một cách nhanh chóng add-on câu trả lời cho các câu trả lời của cộng đồng, chỉ dành riêng cho một heads-up:

Khi bạn khởi tạo các biểu mẫu của mình, bạn có thể sử dụng chính đối tượng biểu mẫu hoặc bạn có thể tạo một cá thể mới của đối tượng biểu mẫu bằng cách sử dụng Mới và đặt nó vào một biến. Phương pháp thứ hai là IMO sạch hơn, vì điều này làm cho việc sử dụng ít singleton-ish.

Tuy nhiên, khi trong biểu mẫu người dùng của bạn, bạn gọi Hủy tải (Tôi), tất cả thành viên công khai sẽ bị xóa sạch.Vì vậy, nếu mã của bạn đi như thế này:

Dim oForm as frmWhatever 
    Set oForm = New frmWhatever 
    Call oForm.Show(vbModal) 
    If Not oForm.bCancelled Then ' <- poof - bCancelled is wiped clean at this point 

Giải pháp tôi sử dụng để ngăn chặn điều này, và nó là một giải pháp thay thế tốt đẹp cho OP là tốt, là để nắm bắt tất cả IO với hình thức (tức là tất cả các thành viên cộng đồng) vào một lớp riêng biệt và sử dụng một thể hiện của lớp đó để giao tiếp với biểu mẫu. Vì vậy, ví dụ:

Dim oFormResult As CWhateverResult 
    Set oFormResult = New CWhateverResult 
    Dim oForm as frmWhatever 
    Set oForm = New frmWhatever 
    Call oForm.Initialize(oFormResult) 
    Call oForm.Show(vbModal) 
    If Not oFormResult.bCancelled Then ' <- safe 
Các vấn đề liên quan