2012-05-15 45 views
10

Tôi đã tìm thấy nhiều tài nguyên trên internet thực hiện gần như những gì tôi muốn thực hiện, nhưng không hoàn toàn.Tôi có một phạm vi được đặt tên là "danh sách ban ngày". Đối với mỗi ngày trong danh sách ban ngày, tôi muốn tạo một nút trên biểu mẫu người dùng sẽ chạy macro cho ngày đó. Tôi có thể add the buttons dynamically nhưng không biết cách vượt qua daycell.text từ phạm vi được đặt tên, tới nút, tới trình xử lý sự kiện, tới macro: S Heres mã tôi phải tạo biểu mẫu người dùng:Chỉ định các trình xử lý sự kiện để điều khiển trên biểu mẫu người dùng được tạo động trong VBA

Sub addLabel() 
ReadingsLauncher.Show vbModeless 
Dim theLabel As Object 
Dim labelCounter As Long 
Dim daycell As Range 
Dim btn As CommandButton 
Dim btnCaption As String 


For Each daycell In Range("daylist") 
    btnCaption = daycell.Text 
    Set theLabel = ReadingsLauncher.Controls.Add("Forms.Label.1", btnCaption, True) 
    With theLabel 
     .Caption = btnCaption 
     .Left = 10 
     .Width = 50 
     .Top = 20 * labelCounter 
    End With 

    Set btn = ReadingsLauncher.Controls.Add("Forms.CommandButton.1", "runButton", True) 
    With btn 
     .Caption = "Run Macro for " & btnCaption 
     .Left = 80 
     .Width = 80 
     .Top = 20 * labelCounter 
    ' .OnAction = "btnPressed" 
    End With 

    labelCounter = labelCounter + 1 
Next daycell 

End Sub 

để khắc phục vấn đề trên tôi đang nhắc nhở người dùng gõ ngày họ muốn chạy (ví dụ Day1) và chuyển thông tin này đến vĩ mô và hoạt động:

Sub B45runJoinTransactionAndFMMS() 


loadDayNumber = InputBox("Please type the day you would like to load:", Title:="Enter Day", Default:="Day1") 

Call JoinTransactionAndFMMS(loadDayNumber) 

End Sub 

Sub JoinTransactionAndFMMS(loadDayNumber As String) 
xDayNumber = loadDayNumber 

Sheets(xDayNumber).Activate 
-Do stuff 

End Sub 

vì vậy, đối với mỗi runButtons của tôi, nó cần hiển thị daycell.text và chạy macro sử dụng cùng văn bản đó làm tham số để chọn trang tính để thực hiện công việc của nó.

Mọi trợ giúp đều tuyệt vời. Ive thấy phản ứng tự động viết mã vba, để xử lý các macro, nhưng tôi tin rằng phải có someway nó có thể được thực hiện một chút thanh lịch hơn thông qua các thông số đi qua, chỉ cần không chắc chắn như thế nào. Rất cám ơn trước!

+0

[này] (http://www.access-programmers.co.uk/forums/archive/index.php/t-88887.html) trông gần với những gì bạn muốn. OTOH tại sao không tạo ra một combobox mà populates từ 'daylist' và một nút lệnh duy nhất có thể đọc các giá trị được lựa chọn? –

+0

Im nghĩ tôi có thể phải đi cho tùy chọn đó. Vì macro được sử dụng để sàng lọc và tải lên dữ liệu, tôi đã hy vọng rằng tôi có thể tạo màn hình khởi chạy nhỏ có thể có dòng cho mỗi ngày và hiển thị # bản ghi, số lỗi, v.v. các nút cho mỗi một trong số đó sẽ làm cho người dùng thân thiện hơn một chút. Tuy nhiên, trừ khi tôi có thể tìm thấy một giải pháp đơn giản hơn, tôi nghĩ rằng đề xuất của bạn sẽ là người chiến thắng. – BiGXERO

+0

Một suy nghĩ khác ... Có lẽ bạn có thể xây dựng một bảng thông tin có liên quan (số ngày, # bản ghi, # lỗi, v.v.) trong một trang tính đặc biệt và nắm bắt các sự kiện nhấp tại đó. –

Trả lời

16

Tôi biết bạn đã chấp nhận một giải pháp bây giờ mà sẽ làm việc cho bạn và là đơn giản hơn nhiều so với bên dưới, nhưng nếu bạn quan tâm, đây sẽ là câu trả lời trực tiếp hơn đến câu hỏi của bạn.

Bạn cần tạo lớp để xử lý các lần nhấp nút, mỗi khi nút được nhấp, nó sử dụng sự kiện trong lớp, bạn chỉ cần thực hiện thao tác này một lần sau đó tạo phiên bản mới cho mỗi nút. Để ngăn chặn các lớp này đi ra khỏi phạm vi và bị mất, họ cần lưu trữ trong một tuyên bố cấp lớp. Ở bên dưới tôi đã di chuyển mã của bạn xung quanh một chút.

Trong mô-đun lớp (tôi đã gọi nó là cButtonHandler)

Public WithEvents btn As MSForms.CommandButton 

Private Sub btn_Click() 
    MsgBox btn.Caption 
End Sub 

Với sự kiện được sử dụng vì nó cho phép bạn sử dụng hầu hết các sự kiện cho sự kiểm soát. Tôi đã chuyển mã thế hệ nút vào userform như sau:

Dim collBtns As Collection 

Private Sub UserForm_Initialize() 

Dim theLabel As Object 
Dim labelCounter As Long 
Dim daycell As Range 
Dim btn As CommandButton 
Dim btnCaption As String 
'Create a variable of our events class 
Dim btnH As cButtonHandler 
'Create a new collection to hold the classes 
Set collBtns = New Collection 

For Each daycell In Range("daylist") 
    btnCaption = daycell.Text 
    Set theLabel = ReadingsLauncher.Controls.Add("Forms.Label.1", btnCaption, True) 
    With theLabel 
     .Caption = btnCaption 
     .Left = 10 
     .Width = 50 
     .Top = 20 * labelCounter 
    End With 

    Set btn = ReadingsLauncher.Controls.Add("Forms.CommandButton.1", "runButton", True) 
    With btn 
     .Caption = "Run Macro for " & btnCaption 
     .Left = 80 
     .Width = 80 
     .Top = 20 * labelCounter 
     'Create a new instance of our events class 
     Set btnH = New cButtonHandler 
     'Set the button we have created as the button in the class 
     Set btnH.btn = btn 
     'Add the class to the collection so it is not lost 
     'when this procedure finishes 
     collBtns.Add btnH 
    End With 

    labelCounter = labelCounter + 1 
Next daycell 


End Sub 

Sau đó chúng ta có thể gọi useform từ một thói quen riêng biệt:

Sub addLabel() 
ReadingsLauncher.Show vbModeless 

End Sub 

Lớp học trong VBA không đặc biệt tốt được đề cập trong nhiều VBA sách (nói chung bạn cần phải đọc sách VB6 để có được một sự hiểu biết), tuy nhiên một khi bạn hiểu họ và làm thế nào họ làm việc, họ trở nên vô cùng hữu ích :)

Hy vọng điều này sẽ giúp

EDIT - để giải quyết các truy vấn bổ sung

Để tham chiếu đến các đối tượng trong bộ sưu tập, việc này được thực hiện thông qua khóa hoặc chỉ mục.Để sử dụng chìa khóa, bạn cần phải thêm nó khi bạn thêm các mục vào bộ sưu tập, vì vậy:

collBtns.Add btnH 

sẽ trở thành

collBtns.Add btnH, btnCaption 

Vì lý do này, phím phải là duy nhất. Sau đó bạn có thể tham khảo như sau:

'We refer to objects in a collection via the collection's key 
'Or by it's place in the collection 
'So either: 
MsgBox collBtns("Monday").btn.Caption 
'or: 
MsgBox collBtns(1).btn.Caption 
'We can then access it's properties and methods 
'N.B you won't get any intellisense 
collBtns("Monday").btn.Enabled = False 

Bạn cũng có thể bổ sung thêm các thuộc tính/phương pháp để lớp học của bạn nếu cần thiết, vì vậy ví dụ:

Public WithEvents btn As MSForms.CommandButton 

Private Sub btn_Click() 
    MsgBox btn.Caption 
End Sub 

Public Property Let Enabled(value As Boolean) 
    btn.Enabled = value 
End Property 

sau đó có thể được truy cập:

collBtns("Monday").Enabled = False 

Điều này có hữu ích không? Để đọc thêm tôi sẽ chỉ cho bạn hướng tới trang web của Chip Pearson, anh ấy có nhiều nội dung tuyệt vời về hầu hết các chủ đề http://www.cpearson.com/excel/Events.aspx

Chỉ cần nhớ rằng VBA dựa trên VB6 vì vậy không phải là một ngôn ngữ OO hoàn toàn chính thức, không hỗ trợ kế thừa theo nghĩa thông thường, chỉ có giao diện thừa kế

Hope this helps :)

+0

Cảm ơn đống cho câu trả lời chuyên sâu. Vẫn còn muốn sử dụng biểu mẫu người dùng hay các trang tính, nhưng đây là một phản ứng tuyệt vời, đặc biệt khi bạn đề cập đến, các lớp dường như bị tránh (hoặc được giải thích về mặt kỹ thuật siêu).Tôi đã thay đổi câu trả lời của bạn thành câu trả lời thực tế vì câu trả lời thực sự là câu trả lời cho câu hỏi – BiGXERO

+1

Câu trả lời của bạn đã cho tôi sự tự tin (khi tôi đã hoàn thành giải pháp dựa trên trang tính hiện tại) để thử các biểu mẫu người dùng. 2 câu hỏi mà tôi nghĩ sẽ giúp bản thân và các noobs khác, 1) Nếu tôi muốn tham khảo một btn cụ thể trong bộ sưu tập (ví dụ: để thay đổi chú thích hoặc để làm cho nó vô hình) sau này, tôi có thể tham khảo nó bằng cách sử dụng một bộ sưu tập tham khảo (ví dụ: collBtns.btn [2]) 2) Bạn có biết bất kỳ tài nguyên trực tuyến nào giải thích các bộ sưu tập, xử lý sự kiện, v.v. Có một nền java noob tôi thích ý tưởng hướng đối tượng và ít sự kiện hơn – BiGXERO

+0

Tôi đã thay đổi ở trên để trả lời câu hỏi của bạn – SWa

2

Ví dụ về đánh bắt nhấp chuột vào trang tính. Đặt này trong module bảng:

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    ' e.g., range(A1:E1) is clicked 
    If Not Application.Intersect(Target, Range("A1:E1")) Is Nothing Then 
    MsgBox "You clicked " & Target.Address 
    End If 
End Sub 
+0

Tôi nghĩ rằng bạn lên một cái gì đó. Nếu tôi sử dụng phương thức giao nhau, sau đó sử dụng một cái gì đó dọc theo dòng của 'tế bào (dayCell, 6' để lặp qua phạm vi được đặt tên của tôi, điều này có khả năng có thể là một giải pháp đơn giản đáng giá cho vấn đề của tôi. – BiGXERO

+0

nó hoạt động để kiểm tra mã tôi sử dụng: 'Sub intersectCallingMacro() Phạm vi (" D8 "). Chọn 'được sử dụng để thử nghiệm chỉ Đặt target = ActiveCell Nếu Not Application.Intersect (target, Range (" A1: M100")) Is Nothing Sau đó Gọi testIntersect (ActiveCell.Value) End Nếu End Sub Sub testIntersect (dayString As string) Dim xDayString As string xDayString = dayString 0.123.Trang tính (xDayString) .Kích hoạt Kết thúc Sub' (xin lỗi để định dạng mã) Chuyển vale ô thành macro làm tham số. KINH NGẠC! – BiGXERO

Các vấn đề liên quan