Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 115 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
115
Dung lượng
1,46 MB
Nội dung
Next, implement the onLoad callback routine to store a copy of the Ribbon. ‘ This should appear in the module declarations section Public gobjRibbon As IRibbonUI Public Sub onRibbonLoad(ribbon As IRibbonUI) ‘ save a copy of the ribbon for future invalidation Set gobjRibbon = ribbon End Sub To determine whether the tab should be made visible, implement the getVisible callback as shown. This code uses the Column property to check the third column in the combo box to determine whether the user is a Manager. Public Sub OnGetVisible(ctl As IRibbonControl, ByRef Visible) If ctl.id = “tabAdmin” Then ‘ check the login form to determine visibility. ‘ if the form is closed, just return false. If Not CurrentProject.AllForms(“frmLogin”).IsLoaded Then Visible = False Exit Sub End If ‘ The combo box on the login form contains the role: ‘ this can be either Manager or Employee. Show the tab ‘ if it is Manager, otherwise hide it. If Forms!frmLogin!cboUsers.Column(2) = “Manager” Then Visible = True Else Visible = False End If Else Visible = True End If End Sub Finally, add code to the Login button on the form to invalidate the Administration tab. Private Sub cmdLogin_Click() ‘ invalidate the admin tab to determine visibility gobjRibbon.InvalidateControl “tabAdmin” End Sub To test the callbacks, select different users from the combo box to show and hide the tab. Customizing the Office Menu As mentioned earlier, the Office menu is updated when you create a new Ribbon from scratch. In addi- tion to the changes made by the Ribbon, you can also customize the Office menu to suit your needs. In Office 2007, the Office menu is intended for options that affect an entire document or application. 418 Chapter 12: Customizing the Ribbon 47033c12.qxd:WroxProgRef 3/30/07 12:26 AM Page 418 To customize the Office Menu, use the officeMenu node, which is a child of the Ribbon node as shown below. <customUI xmlns=”http://schemas.microsoft.com/office/2006/01/customui”> <ribbon startFromScratch=”true”> <officeMenu> <button idMso=”FileNewDatabase” visible=”false”/> <button idMso=”FileOpenDatabase” visible=”false”/> <button idMso=”FileCloseDatabase” visible=”false”/> <splitButton idMso=”FileSaveAsMenuAccess” visible=”false”/> </officeMenu> </ribbon> </customUI> This XML hides the built-in buttons for New, Open, Close, and the Save As group in the Office menu in Access. You should provide another means of closing your application gracefully if you choose to hide the Close button. Let’s look at another scenario for which you might customize the Office menu. Say you have a list of links you want to provide in your application. In the case of the travel agency application, you might maintain a list of links to travel sites, airline websites, or mapping sites. You can display this list in the Office menu so that it is available from anywhere in the application. The following XML includes a menu node in the Office menu. <customUI xmlns=”http://schemas.microsoft.com/office/2006/01/customui”> <ribbon> <officeMenu> <button idMso=”FileNewDatabase” visible=”false”/> <button idMso=”FileOpenDatabase” visible=”false”/> <button idMso=”FileCloseDatabase” visible=”false”/> <splitButton idMso=”FileSaveAsMenuAccess” visible=”false”/> <button idMso=”ApplicationOptionsDialog” visible=”false”/> <! Links menu > <menu id=”mnuLinks” label=”Links” imageMso=”HyperlinkInsert”> <menuSeparator id=”mnuLinksSep1” title=”Travel Sites”/> <button id=”btnLink1” label=”http://www.travelocity.com” tag=”http://www.travelocity.com” onAction=”OnSelectLink”/> <button id=”btnLink2” label=”http://www.expedia.com” tag=”http://www.expedia.com” onAction=”OnSelectLink”/> <button id=”btnLink3” label=”http://www.orbitz.com” tag=”http://www.orbitz.com” onAction=”OnSelectLink”/> <menuSeparator id=”mnuLinksSep2” title=”Mapping Sites”/> <button id=”btnLink4” label=”http://local.live.com” tag=”http://local.live.com” onAction=”OnSelectLink”/> <button id=”btnLink5” label=”http://maps.google.com” tag=”http://maps.google.com” onAction=”OnSelectLink”/> <menuSeparator id=”mnuLinksSep3” title=”Airline Sites”/> <button id=”btnLink6” label=”http://www.alaskaair.com” tag=”http://www.alaskaair.com” onAction=”OnSelectLink”/> <button id=”btnLink7” label=”http://www.delta.com” tag=”http://www.delta.com” onAction=”OnSelectLink”/> <button id=”btnLink8” label=”http://www.usair.com” 419 Chapter 12: Customizing the Ribbon 47033c12.qxd:WroxProgRef 3/30/07 12:26 AM Page 419 tag=”http://www.usair.com” onAction=”OnSelectLink”/> <button id=”btnLink9” label=”http://www.aa.com” tag=”http://www.aa.com” onAction=”OnSelectLink”/> <button id=”btnLink10” label=”http://www.jetblue.com” tag=”http://www.jetblue.com” onAction=”OnSelectLink”/> </menu> </officeMenu> </ribbon> </customUI> Because the URL for the website is stored in the tag attribute, you can use the FollowHyperlink method to open the link as shown in the following callback routine: Public Sub OnSelectLink(ctl As IRibbonControl) FollowHyperlink ctl.Tag End Sub This XML creates the Ribbon shown in Figure 12-35. Figure 12-35 Customizing the Quick Access Toolbar The Quick Access Toolbar, or QAT, is the small group of controls that appears next to the Office button. You can also use this space to add buttons to your application. The QAT provides fast access to those controls that are used most frequently. Add controls to the QAT for your application by adding the qat node as a child of the Ribbon node. The following XML adds a button to the QAT. The documentControls node adds controls only for the current database. <qat> <documentControls> <button id=”btnHello” onAction=”=MsgBox(‘Hello!’)“/> </documentControls> </qat> 420 Chapter 12: Customizing the Ribbon 47033c12.qxd:WroxProgRef 3/30/07 12:26 AM Page 420 More Ribbon Tips Here are a few tips to keep for writing ribbon customizations. They can help you in creating your appli- cations, as well as in providing additional polish to your solutions. ❑ Prevent the Ribbon from loading: You want to prevent the Ribbon from loading when testing or developing. For instance, when you are developing a Ribbon from scratch but you are also developing forms and reports. With a custom ribbon, the form design tools are not available. You can hold down the Shift key as you would to prevent the startup form from loading to pre- vent your custom ribbon from loading. ❑ Find existing controls: Office provides a lot of controls that you can use in your applications. So many in fact it begs the question, how do you find them all? You can download the List of Control IDs from the Microsoft website, but it turns out that Office provides this information for you in the Customize group of the Options dialog boxes. To get the control ID for the Toggle Filter button, simply hover over an item in the list as shown in the Access Options dialog box in Figure 12-36. The ID for the control appears in parentheses. Figure 12-36 ❑ Use screenTip, superTip, and description: Use these additional attributes for controls to customize the tooltip or descriptive information for a given control. The description attribute is only valid for controls in a menu node with the itemSize attribute set to large. ❑ Set keyTips: A keyTip is the accelerator key or keys for a given control. If not set, the Ribbon assigns keyTips for you such as Y01 or Y02. For keyTips that are more user friendly, set the keyTip attribute. You can also implement the getKeyTip callback for many controls, which would enable you to create a mapping table for control IDs, and keyTips. Additional Resources There has been a lot of excitement generated about customizing the Ribbon, and Microsoft has provided an incredible amount of documentation, including an entire MSDN developer center dedicated to the 421 Chapter 12: Customizing the Ribbon 47033c12.qxd:WroxProgRef 3/30/07 12:26 AM Page 421 Ribbon! There are examples, documentation, tools, and videos all related to building custom ribbons. Here are some of the resources that the authors have found to be indispensable when writing customiza- tions (all of these are available from the Ribbon Developer Center): ❑ Office Ribbon Developer Center: http://msdn.microsoft.com/office/tool/ribbon/ default.aspx ❑ List of Control IDs: Provides the list of Office controls that you can use in the imageMso attribute ❑ 2007 Office System: Schema Reference: Contains the XML Schema used by the Ribbon ❑ UI Style Guide for Solutions and Add-Ins Summary You can completely customize the Ribbon to suit the needs of your solutions. The tools described in this chapter take full advantage of the new Ribbon user interface in Office 2007. This chapter provided an in-depth look at customizing ribbons. You explored the controls that are avail- able, as well as put them to use in building a couple solutions of your own. By customizing the Ribbon, you can create new, innovative interfaces for your applications that are in line with today’s standards. The extensibility story for the Ribbon is quite large, and there are several pieces to it. For Access, it starts with the USysRibbons table, and the XML that you store in there. From there, you can implement call- back routines that give you the power of VBA that you’ve had in the past with controls and command bars. You also learned how to display images in your customizations to give your interface a fresh look, and how to dynamically use data from tables in a database to provide content to the Ribbon. Now you can take some of these techniques and create reusable objects to encapsulate Ribbon controls by using class modules. The next chapter provides an insight to working with objects, as well as new techniques that you can apply to your programming style to help create reusable, extensible applications of your own. 422 Chapter 12: Customizing the Ribbon 47033c12.qxd:WroxProgRef 3/30/07 12:26 AM Page 422 Creating Classes in VBA The capability to create self-contained software objects was first conceived in about 1970 with the development of SIMULA 67 (SIMUlation LAnguage), an extension of the scientific ALGOL 60 computer language. It took quite a while before the programming community realized the implications of the break- through that SIMULA represented. When they did, object-oriented programming (OOP) quickly became the new buzzword, relegating structured programming to the realm of the lesser-informed code cutters. With the release of languages such as SmallTalk, C++ and, later, Java, OOP earned its place in the software hall of fame as the new panacea to all your programming ills. When Visual Basic 4 was released in 1993, Basic developers were tantalized by a new toy: the class module. Long snubbed by C++ developers who had been using class modules for years, Basic developers were finally able to hold their heads high with the new found capability to create fully self- contained and reusable objects. In OOP parlance, an object is a unique instance of a data structure, called a class, that has both prop- erties (which define its characteristics), and executable procedures called methods (which define its behavior in modifying those properties). The properties of a class are completely isolated from the outside world and can be modified inter- nally only by its own methods. This doesn’t mean that the programmer can’t do anything to them, but that he can’t do anything to them directly; he must use those methods that are exposed for that purpose. The properties and methods you create are termed its implementation, whereas the meth- ods it exposes to the programming environment constitute its interface. Thus, an object is a com- pletely self-contained programmatic entity, in that it contains both its own data and the program code necessary to implement its own behavior. This chapter examines VBA classes and class objects. You learn what a class actually is and the dif- ference between it and a class object. Then you create your first class and figure out how it works. After that, you learn to identify classes and then how to get them to communicate with the rest of your application, before diving into the more advanced topics, such as building collection classes. Some object-oriented theory concludes the chapter. 47033c13v6.5.qxd 3/30/07 12:39 AM Page 423 Classes are not as daunting as you might first think, and it’s my hope that after reading this chapter, you will cast off any fears you may have had and happily find many uses for your new found skills. There are many ways to do a single task in Access, and the examples in this book are intended to pro- vide new perspective on programming with classes. Class modules in Access can be useful when applied to complex problems, and the code examples reinforce that theory. A Touch of Class Classes have been likened to rubber stamps, cookie-cutters, and a raft of other everyday items in an attempt to make the concept more easily understandable. Because you are reading a book on software development, it seems fairly safe to assume that you understand the concept of a template, such as a Microsoft Word template. That analogy succinctly describes the role of class modules and the distinction between them and class objects. Just as a class module is equivalent to a Word template, a class object is equivalent to a Word document that is based on that template. Of course, with VBA class modules, you don’t define styles or boilerplate text, but you do define a set of properties that includes their data types and read-write attributes. You also define the methods of a class, the data types they return (if any), and the events the class exposes to the calling procedure. It is these properties and methods that constitute the object’s interface to the pro- gramming environment. Each unique class object will be exactly the same as the class module it was based on, except of course, for the data it contains. In fact, the class module never gets instantiated and never contains any data because you don’t actually work on it. You can, however, create as many instances of it as you like, in the form of class objects, each identified by a different name. To make a change to all the class objects, you need change only the class module. Probably the easiest way to describe a class is to compare it to a stan- dard VBA module. VBA modules can contain many procedures, such as subs and functions, all of which were explained in Chapter 2. For instance, you may have a VBA module called modClassroom that contains procedures to implement a single property of a classroom — the number of students in the class: Option Compare Database Option Explicit Private mintStudents As Integer Public Sub AddStudent() mintStudents = mintStudents + 1 End Sub Public Function GetStudents() As Integer GetStudents = mintStudents End Function Your property, the number of students, is stored in a module-level variable called mintStudents. To add a student to the classroom, you call the AddStudent() procedure, and to retrieve the current count you call the GetStudents() function. The potential problem with this approach is illustrated by Figure 13-1. 424 Chapter 13: Creating Classes in VBA 47033c13v6.5.qxd 3/30/07 12:39 AM Page 424 Figure 13-1 What if you have another module somewhere that also uses the AddStudent() procedure? It would change the value of mintStudents. To ensure you can change the number of students for different class- rooms, you would have to either create multiple AddStudent procedures, or implement some other way of doing it, such as arrays. This is where class modules come in. Take a look at the following class module called clsClassroom. Don’t worry if you don’t quite understand it; all will be explained as you go along. Option Compare Database Option Explicit Private mintStudents As Integer Public Sub AddStudent() mintStudents = mintStudents + 1 End Sub Public Property Get Students() As Integer Students = mintStudents End Property This class is virtually the same as modClassroom. The nifty part about it is the fact that the code used to define the class is essentially a template that you can use to create as many classroom objects as you wish. Further, if you had two different procedures that each called AddStudent(), they would each operate on a different copy, or instance, of the clsClassroom class illustrated by Figure 13-2. Figure 13-2 mintStudents Class 1 Class 2 AddStudents() Students() AddStudents() Students() mintStudents Module1 Module2 mintStudents 425 Chapter 13: Creating Classes in VBA 47033c13v6.5.qxd 3/30/07 12:39 AM Page 425 For example, the following VBA module contains two procedures, each of which creates a classroom object called myClassroom. The first one, TestClassroom1, adds one student to the classroom then calls TestClassroom2, which creates a second classroom instance and adds two students. Option Compare Database Option Explicit Public Sub TestClassroom1() Dim MyClassroom As clsClassroom Set MyClassroom = New clsClassroom MyClassroom.AddStudent MsgBox “I have “ & MyClassroom.Students & “ student in my class.” TestClassroom2 MsgBox “I still have only “ & MyClassroom.Students & “ student in my class.” End Sub Public Sub TestClassroom2() Dim MyClassroom As clsClassroom Set MyClassroom = New clsClassroom MyClassroom. AddStudent MyClassroom. AddStudent MsgBox “I have “ & MyClassroom.Students & “ students in my class.” End Sub Both instances of the clsClassroom class are exactly the same in form and function, but are completely different entities. Thus, the properties of each are completely distinct from each other. Why Use Classes? From a coding perspective, the only real difference between using the built-in Access or VBA objects and the ones you write yourself, is that you have to instantiate your custom objects. Other than that, there’s no difference at all. There is a learning curve associated with creating your own class objects, but once learned, the major ben- efit is much simpler and more manageable code. Let’s say you are using API functions in your applica- tion. You can create your own interface that hides the complexity of the API functions with a class. By this same token, classes are also very useful if you are writing code that will be used by other developers. Also, while you can instantiate the built-in objects, using the Dim construct, you don’t always have to. For example, to expose the Name property of a Table object, either of the following examples will work. MsgBox DBEngine(0)(0).TableDefs(1).Name Set tdf = DBEngine(0)(0).TableDefs(1) Admittedly, if you’ve never written classes before, using them requires a different way of thinking at first. Once you become familiar with the concepts, you’ll find great benefit in their usage. Once written, classes provide increased reusability and a layer of abstraction that enables you to focus more on 426 Chapter 13: Creating Classes in VBA 47033c13v6.5.qxd 3/30/07 12:39 AM Page 426 business logic or rules. The end result is code that is easier to use. The Recordset class in DAO is an example of a class that is used quite frequently. So why not write your own? Now having just expounded the virtues of adopting modern OOP techniques, I most certainly wouldn’t recommend writing a collection class where a simple array would suffice. You should still apply the right tool to the right job! If a standard module is all you need, use one! In other words, don’t over- engineer a project, just so you can use the latest technology. Creating a Class Module Everyone learns best by doing, so to learn the basics of creating a class module, you’ll create one. The class module will model a classroom at a school. You’ll see this example throughout the chapter, show- ing the different parts of a class module and how to model its relationships with other classes. Adding a Class Module to the Project The easiest way to add a new class module to your project is to press Alt+F11 to open the Visual Basic Editor. Then, in the Visual Basic designer window, select Insert ➪ Class Module. You can also right-click anywhere in the Project Explorer and select Insert ➪ Class Module from the context menu. In addition, you can also create a class module from within Access by selecting Class Module under the Macro split button in the Other group in the Ribbon’s Create tab. VBA opens a new class module and adds a reference to it in the Project Explorer. Copy the clsClassroom code into the module as shown in Figure 13-3. That’s it! You’ve created your first class module! Figure 13-3 427 Chapter 13: Creating Classes in VBA 47033c13v6.5.qxd 3/30/07 12:39 AM Page 427 [...]... ‘using the object passed to the procedure Set mobjTeacher = objTeacher End Property 434 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 4 35 Chapter 13: Creating Classes in VBA To use this construct, external VBA code must pass the clsTeacher object to the Property Set procedure in a Set statement, after which it can access its properties and methods through myClassroom’s Teacher property Set myClassroom.Teacher... and so on), whereas Property Set is used for objects 432 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 433 Chapter 13: Creating Classes in VBA In the clsClassroom class example, mintStudents is the actual property, and the two Students methods are its property procedures The property itself is declared as Private, to ensure that VBA code must access the property through one of the defined property procedures... in the chapter you’ll explore it and look at a trick using the Instancing property to allow for additional reusability Figure 13 -5 shows the clsClassroom class in the Object Browser 428 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 429 Chapter 13: Creating Classes in VBA Figure 13 -5 Notice that details of the selected property or method are displayed under the Classes pane You can filter the Classes pane by... may want to assign the teachers Public Enum GradeLevel glFreshman glSophomore glJunior 4 35 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 436 Chapter 13: Creating Classes in VBA glSenior End Enum Notice that in the previous example, no values were specified for any of the constants This is perfectly acceptable because VBA automatically assigns a Long Integer value to each of them starting at zero and incrementing... ([arglist,] Set name ([arglist,] type] [As type] value) reference) 439 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 440 Chapter 13: Creating Classes in VBA The Static keyword ensures that all the procedure-level variables retain their values between calls Variables declared outside the procedure are unaffected For more information on Static, refer to Chapter 5 You’re already familiar with Public and Private attributes,... Get TestScore() As Byte ‘ get a random score between 0 and 100 Const MIN_SCORE = 0 Const MAX_SCORE = 100 444 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 4 45 Chapter 13: Creating Classes in VBA TestScore = CInt(Int((MAX_SCORE - MIN_SCORE + 1) * Rnd() + MIN_SCORE)) End Property Just like VBA procedures, you can declare event arguments using the ByVal and ByRef keywords By default, event arguments are passed... for the problem (or its resolution) Raising your own errors provides the flexibility of displaying more user-friendly or user-specific error messages 449 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 450 Chapter 13: Creating Classes in VBA The VBA Err object provides a Raise method, which enables you to construct and to fire your own custom errors You must supply everything the Err object needs to return anything... Err.Raise vbObjectError + 51 3, TypeName(Me), _ strErrDesc, _ “c:\MyProj\MyHelp.Hlp”, MyContextID Case Else ‘ Something else went wrong Err.Raise Err.Number, Err.Source, Err.Description End Select End Sub You might have noticed the TypeName function TypeName returns information about a variable, for example: ❑ 450 TypeName(strMyString) returns String 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 451 Chapter 13: Creating... TestFormClass() Dim frm As Form_Form1 Set frm = New Form_Form1 frm.Visible = True Set frm = Nothing End Sub Then try the same thing with a report Public Sub TestReportClass() 452 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 453 Chapter 13: Creating Classes in VBA Dim rpt As Report_Report1 Set rpt = New Report_Report1 rpt.Visible = True Set rpt = Nothing End Sub Often, you may want to display a data selection dialog box... programmer has to determine the purpose and function of objects in the applications you create 442 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 443 Chapter 13: Creating Classes in VBA Using Class Events Unlike standard modules, class modules can raise their own events This is a very powerful feature of VBA, because it not only gives your code the ability to know what’s going on inside the class instance, it . 2 AddStudents() Students() AddStudents() Students() mintStudents Module1 Module2 mintStudents 4 25 Chapter 13: Creating Classes in VBA 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 4 25 For example, the following VBA module contains two procedures, each of. ctl.Tag End Sub This XML creates the Ribbon shown in Figure 12- 35. Figure 12- 35 Customizing the Quick Access Toolbar The Quick Access Toolbar, or QAT, is the small group of controls that appears. reusability. Figure 13 -5 shows the clsClassroom class in the Object Browser. 428 Chapter 13: Creating Classes in VBA 47033c13v6 .5. qxd 3/30/07 12:39 AM Page 428 Figure 13 -5 Notice that details