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
2,32 MB
Nội dung
Private Sub MyAttachment_AttachmentCurrent() ‘ update the text boxes for form view where the ‘ default view is not a split form or datasheet view. If (Me.CurrentView = AcCurrentView.acCurViewFormBrowse _ And Me.DefaultView <> AcDefView.acDefViewSplitForm And Me.DefaultView <> AcDefView.acDefViewDataSheet) Then Me.txtFileName.Value = Me.MyAttachment.FileName Me.txtFileCount.Value = Me.MyAttachment.AttachmentCount Me.txtFileType.Value = Me.MyAttachment.FileType Else Me.txtFileName.Value = Null Me.txtFileCount.Value = Null Me.txtFileType.Value = Null End If End Sub With this code, you can now view the attachment filenames and file types (extension) as you browse through the attachments. It may seem redundant to explicitly retrieve the file type because it typically shows up in the filename, but the purpose here is to demonstrate how to retrieve the information. This example code starts by retrieving the values for the attachment only if the form is not displayed in Split Form or Datasheet view (we already learned that lesson). There may be issues or unexpected results when trying to obtain these values from other form views, so the value is set to null for other cases. In specifying the values, the left side of the equation identifies the text box that will display the value retrieved. The right side identifies the source of the data; in this case, it is looking at the control called MyAttachment. Because it’s an attachment control, it has some special properties, including FileName, FileType, and AttachmentCount. ❑ FileName: The actual name of the file (MyPicture.jpeg will display as MyPicture.jpeg). ❑ FileType: Refers to file extension or type (JPEG, TXT, BMP, PDF). ❑ AttachmentCount: The number of attachments stored for that record. The event AttachmentCurrent works similar to the form’s OnCurrent event in that it fires when mov- ing the focus from one attachment to another. Within this event you can both extract information and specify the way that attachments will be represented. As the preceding code demonstrated, you can use the AttachmentCount property to list the number of attachments. It is helpful to use this count in con- junction with the icon and image displays since they do not indicate the number of attachments. The attachment control uses an image and has the following three display options: ❑ acDisplayAsIcon: Displays the default icon for that file. ❑ acDisplayAsImageIcon: Displays icons for txt files; actual picture for jpeg’s and bmp’s. ❑ acDisplayAsPaperclip: The default setting. Although this does not indicate the file type, it is the only option that, by default, displays the AttachmentCount. 303 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:25 AM Page 303 In the next example, an option group demonstrates the three different views to display the image. The option group is added to the form, and Figure 10-7 uses the DisplayAsImageIcon option in showing the same record and attachment shown in Figure 10-6. Figure 10-7 The following code allows the user to choose whether the attachment control will display as an icon, icon/image, or paper clip. Private Sub grpAttachView_Click() Dim OptSelect as Integer OptSelect = Me.grpAttachView.Value Select Case OptSelect Case 1 With Me.MyAttachment .ControlTipText = “This option displays file Icons only.” .DisplayAs = acDisplayAsIcon .Height = “450” End With Case 2 With Me.MyAttachment .ControlTipText = “This option displays file Images and Icons.” .DisplayAs = acDisplayAsImageIcon .Height = “1440” End With Case 3 With Me.MyAttachment .ControlTipText = “This option displays files as a Paperclip.” .DisplayAs = acDisplayAsPaperclip End With End Select End Sub For options acDisplayAsIcon and acDisplayAsImageIcon, you add the Height property and set it to “450” twips and “1440” twips (1 inch), respectively. Why specify the height? Because the default height for an attachment control that is set to acDisplayAsPaperclip is only 0.1667 inches. By specify- ing the height in code, the control can grow or shrink as appropriate for the display type. 304 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 304 When using code to specify the height and width in twips, do not use commas as regional settings may cause the comma to be interpreted as a decimal point. Notice that the code uses 1440 not 1,440 and that the numbers are enclosed in double quotes. While you are at it, you may also want to use the Property Sheet Format tab and change the Picture Size Mode to Zoom, which will preserve the image proportions. If you are concerned about space or present- ing a compact look, you may also want to adjust the cell padding around images and icons. Figure 10-8 illustrates the effects of several of these settings. Figure 10-8 The attachment control has its own pop-up menu for adding, removing, opening, saving, and moving through attachments. This is a powerful little control because it works like the OpenFile dialog box but saves the collections of files within the record rather than in a separate table, streamlining the process of saving or attaching files to a record. However, with the built-in control, you must select working with none, one, or all attachments. Unlike a fully functional multi-select group, it does not allow users to select several (but not all) attachments. Combo Boxes The combo box is a potent control that can combine the processes to search, select, and populate data into fields (or other objects), as well as limit the values that a user may enter. Many nuances affect how I don’t know about you, but I certainly am not accustomed to calculating in twips. So, if you are trying to specify image heights, you may appreciate knowing that a twip is 1 ⁄1,440 of an inch, which is the equivalent of 1 ⁄567 of a centimeter or 1 ⁄20th of a point. 305 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 305 combo boxes work; this section addresses some of the more common ones. It also covers some new fea- tures, including two new properties: Allow Value List Edits and List Items Edit Form. The combo box and list box have a lot of the same properties and functionality. The primary difference is that the contents of the list box are always displayed on the form, so the list box takes more space. List box values are also limited to the list, which can be updated programmatically by adding values to the row source, but not directly by the user. Combo boxes, on the other hand, generally use the space of a normal text box and employ a drop-down list to display the number of rows specified in the properties. The row source can be set to be updateable or to allow only existing values. Before continuing, let’s clarify the difference between control source and row source. The control source is specified if the value selected in the combo box will automatically (rather than programmatically) be stored in a field. The last question in the Combo Box Wizard, for instance, is about remembering or stor- ing the selected value. If you choose to store the selected value in a field, that field becomes the control source. The row source provides the values that are displayed and used by the combo box. It can be a table, a query, a value list, or a field list. The row source value can even be an empty string when the form opens and then be set programmatically. For the most part, the row source consists of multiple columns with only one column visible to the user. The other columns can be used to populate other fields or as the link to other record sources. For example, one column could be the field that links the current form to a subform. Again, referring to the wizard provides a quick demonstration of some of the properties related to the row source. When you tell the Combo Box Wizard, for instance, that the combo box will look up values in a table or query, you are specifying the row source. The wizard then goes through the process of selecting the fields for the columns and allowing you to specify the column widths. The wizard automatically adds the primary key if one is available. The other main element that you’ll work with is controlling the values that the user can use or add. But first, you’ll tackle an easy example of using a combo box to display existing data. Combo Box as a Look-Up An excellent use for the combo box control is to display descriptive information for the user even though the data that’s actually stored in the database is the value of some sort of key (primary or foreign). For example, you may have a form in which users allocate sales and you want the users to identify a depart- ment. If that form (or even just the combo box) is bound to a table that stores the Department ID rather than the name of the department, you don’t want to force the user to remember or figure out which Department ID to enter. Instead, you can use a combo box to display a list of departments (field name Department) and let the form manage how the Department ID is stored. The following table lists the combo box settings for this scenario. You will also find this in frmContactsComboLookUp in this chap- ter’s database file named ComboBox.accdb. Property Value Control Source Department (this is from the table Contacts) Row Source Select DepartmentID and Department from tblDepartment Row Source Type Table/Query Bound Column 1 Limit To List Yes 306 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 306 Property Value Allow Value List Edits No List Items Edit Form No value (leave blank) Column Count 2 Column Width 0”;2” Two of the properties that are crucial to selecting the value that will be stored in the database are Bound Column and Column Width. Setting Bound Column to 1 means the data for the field that will be stored in the database is in the first column of the Row Source. Setting the Column Width of the bound col- umn to 0 means that the bound column will not be displayed in the combo box. If you are familiar with coding combo boxes, you probably noticed the new Access 2007 Combo Box properties Allow Value List Edits and List Items Edit Form. These new properties enable you to let users maintain their own set of valid values for the field without requiring you to write code. The next two sections examine those properties. As in prior versions of Access, if the Limit To List property is set to No, the user is allowed to type whatever he wants as many times as he wants. The combo box only helps the user select previously defined values without restricting him to only those values, and it allows users to enter the same value multiple times and with myriad variations. When Limit To List is set to Yes, the user can select only the values in the list. However, if the user enters a value that isn’t in the list, it can trigger a response depending on whether you’ve captured bad data entry using the On Not In List event and/or based on the settings for the new Allow Value List Edits property along with the List Items Edit Form property. All this is by way of saying you should be aware that the On Not In List event occurs before the settings of the new properties are even considered. It may seem as though we are hammering on just a few properties, but slight variations in how they are combined can have a big impact on results. Allow Value List Edits The Allow Value List Edits property provides a simple way for you to allow the user to change the contents of the list without requiring the user to go into Design view to change the row source or you (the developer) to write code to change the row source. Keep in mind that this property is intended for combo boxes where the Row Source Type property is set to Value List — meaning that it is not designed to work with other row source types, so don’t be tempted to misapply this feature. If Allow Value List Edits is set to No and the user enters a value that isn’t in the list, the user will see the standard Access message (see Figure 10-9) advising him to select an item from the list. Figure 10-9 307 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 307 If Allow Value List Edits is set to Yes and the user enters a value that isn’t in the list, the user will see a message box that asks if he wants to edit the items in the list, as shown in Figure 10-10a. You’ll also notice the extra question at the bottom of the message box, “Was this information helpful?” That mes- sage will appear if the user has enabled “Help Improve Access.” Responding to this query will clear that message without closing the message box, as shown in Figure 10-10b. Figure 10-10 If the user chooses Yes, to edit the list, the default Access Edit Items List form displays (see Figure 10-11). This default form is clearly designed to capture only a simple list of values, and it is intended to be used only when the combo box Row Source Type is set to Value List, Inherit Value List is set to Yes, and both the the Bound Column and Column Count are set to 1. Keep in mind that this form provides no means for you to control the values that the user might enter, so terms may be entered multiple times with different spellings. In Figure 10-11, you can see that Dance has been added to the list from the combo box labeled “ Value List With Edit:” even though “Dancing” was already in the list. If you want more control over what the user enters for the list or if you want to pro- vide a multicolumn list, you should set the Row Source Type to be Table/Query and use the List Items Edit Form property to specify a custom form. We will discuss that approach shortly. Figure 10-11 One thing to note about using this approach to allow value list edits is that the Row Source property of the combo box is actually updated, which in turn causes Access to respond as though the design of the form has changed. Because of this, when the user closes the form that contains the (updated) combo box, Access will display a message box to ask if the user wants to “…save changes to the design of the form [form name]”. This is not a good message for users to see, so you may want to use the DoCmd.Save 308 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 308 acForm, Me.Name statement to save the form in the Form_AfterUpdate event. (This is obviously not a desired scenario, and you can hope for a resolution in an early Access update.) List Items Edit Form As mentioned earlier, the big advantages of the new Allow Value List Edits property is that you don’t have to write code in the On NotIn List event to capture the new value, and it provides a method that allows the user to include the values he wants in the list. But please remember (and this is worth repeating) that the new Allow Value List Edits property is intended only for combo boxes and list boxes with a Row Source Type of Value List. If you are using the Row Source Type of Table/Query , you can use the new List Items Edit Form property to display an alternate form that allows the user to edit the list. First you must first create a form that will maintain the data that is displayed from the row source of the combo box. Then you set the List Items Edit Form property to name of that form. You could get a little fancy with your form by programmatically taking the invalid value that the user entered in the combo box and loading it into the appropriate field on your edit form. That kind of defeats the concept of using this new feature to avoid writing code, but then this book is about code and creating solutions that save time and prevent errors. Coming up is one example of using code to optimize use of a couple of the new “no code required” features. Because users can use the Navigation pane, it might be beneficial to programmatically restrict the capa- bility to open your edit forms, such as by using the Is Loaded event (see discussion later in this chap- ter). After all, you don’t want users to get an error message if they open a form from the Navigation pane. (In the database for this section, EditValueList.accdb, the form frmMayorUpdate includes a method to prevent the form from being opened from the Navigation pane.) This example uses a form called frmContactMayor with combo box cboCity, which uses a look-up table to capture the city for the contact, storing the data in the field named City in tblContacts. For this exercise, assume that the application needs to capture the mayor of every city. Basically, this means that if a user enters a new city, you want the application, through a form, to require him to enter the name of that city’s mayor. To accomplish this, the example uses a table of mayors called tblMayors and a frmMayorUpdate form to update that table. You also want to think about creating an index on city/state and requiring that to have a unique value. This example is provided in the chapter download file, EditValueList.accdb. To get the process started, you’ll create (or modify) the combo box, cboCity, to have the key property values shown in the follow- ing table. When allowing value list edits by using the default Access Edit Items List form, it is critical that the Row Source Type is Value List and Inherit Value List is set to Yes. This allows Access to properly handle the update. With other property configurations, users may get a warning and be asked if they want to save changes to the design of the form. After all, a change to a value list behind a control is a change to the form’s design. 309 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 309 Property Value Control Source City Row Source tblMayors Row Source Type Table/Query Bound Column 2 Limit To List Yes Allow Value List Edits Yes List Items Edit Form frmMayorUpdate Column Count 2 Column Widths 0”;2” To ensure that the mayor’s name is provided, the form should use one of the other techniques you’ve learned in this book. For instance, you could use the Form_BeforeUpdate event to see if the mayor’s name field has a value. The example uses Form_Open to check for the value. Additionally, set the frmMayorUpdate form Pop Up property to Yes, and set the Modal property to Yes, and set Cycle to Current Record (found on the Other tab of the property sheet). You do this so that the Form_Open code in the form frmMayorUpdate always executes. One reason for making this a modal form is to force the user to close the form before he can enter additional data in the form frmContactMayor (or before he can work with other objects, for that matter). If the user is allowed to leave frmMayorUpdate open while continuing to enter data on frmContactMayor, the next invalid entry in cboCity won’t fire the Form_Open event in frmMayorUpdate. At this point, you’re about ready to put the following code in the Open event for frmMayorUpdate. First you establish a constant to be used for the “calling form.” That makes this snippet more portable. Instead of replacing the name of the calling form throughout the code, you merely change the value for the constant, cFormUsage. Const cFormUsage = “frmContactMayor” Private Sub Form_Open(Cancel As Integer) Dim strText As String Dim rs As Recordset ‘ Don’t let this form be opened from the Navigator If Not CurrentProject.AllForms(cFormUsage).IsLoaded Then MsgBox “This form cannot be opened from the Navigation Pane.”, _ vbInformation + vbOKOnly, “Invalid form usage” Cancel = True Exit Sub End If strText = Forms(cFormUsage)!cboCity.Text If strText = “” Then ‘ If the City is empty, the user may have opened the form from the navigator 310 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 310 ‘ while the other form is opened (thus it passed the above test) MsgBox “This form is intended to add Cities for the ‘“ & i Forms(cFormUsage).Caption & “‘ form.”, _ vbInformation + vbOKOnly, “Invalid form usage” Cancel = True Exit Sub End If ‘ If you use the following syntax to insert the new value, ‘ make sure that the user hasn’t entered an apostrophy (‘) in his text. ‘ Of course there are many ways to add the record DoCmd.SetWarnings False DoCmd.RunSQL “INSERT INTO tblMayors (City) VALUES (‘“ & strText & “‘)“ Me.Requery DoCmd.SetWarnings True ‘ Now point to the row just added and set the filter so the user can’t scroll Set rs = Me.RecordsetClone rs.FindFirst “City = ‘“ & strText & “‘“ If Not rs.EOF Then Me.Bookmark = rs.Bookmark Me.Filter = “[ID] = “ & Me.ID Me.FilterOn = True End If Me.Mayor.SetFocus End Sub After the user indicates that she wants to edit the items in the list, the process will open frmMayorUpdate because it is the form specified as the value for the List Items Edit Form. The Form_Open event looks at the cboCity field in frmContactMayor and stores the text of that field in strText. The code then inserts the City that doesn’t have a value associated with the Mayor’s name into tblMayors. With the record inserted, the code makes a copy of the recordset of the form, uses the FindFirst method to locate that record, and moves to it using the Bookmark property. Finally it sets the focus on the Mayor name field, so that it is easy for the user to enter the required data. Of course, you could accomplish that with a lot less code, as shown in the following snippet: Private Sub Form_Open(Cancel As Integer) DoCmd.RunCommand acCmdRecordsGoToNew ‘ insert a new record Me.City = Forms(“frmContactMayor”)!cboCity.Text Me.txtMayor.SetFocus End Sub This code simply goes to a new record on the form and copies the text from cboCity to the City field. An advantage of this method is that you can then define the Mayor name field in tblMayors as required and let Access determine if the data entered by the user is valid. Then you don’t need the Form_BeforeUpdate check to make sure the user entered something in the Mayor name field. Now that you’ve worked through this example, take a moment to think about related business rules. This scenario has some obvious issues that would have to be addressed, such as the potential to have 311 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 311 multiple cities with the same name, the opportunity for people to use different spellings of the same city, and the need to be able to rename a city or mayor. But it does provide a fairly elegant process to allow users to add values. If you prefer to write code (and most developers do), there is another way to allow the users to update the list of valid values available in a combo box. It provides the means for you to validate the value and saves you from having to create another form. It’s the Not In List event, which you look at next. Not In List() The Not In List event is triggered when the Limit To List property is set to Yes and the user enters data that is not in the list. It occurs independently of the settings for Allow Value List Edits and List Items Edit Form properties, so you can use it to control how your application responds when invalid data is entered in a combo box. Because combo boxes are usually based on a look-up table, the following example offers the user a chance to add a value that is not in the list. To provide a friendlier dialogue with the user, it also demon- strates how to create a custom message box such as the one shown in Figure 10-12. As you can see, the user tried to use “Entertainment” as the main category. Because it isn’t in the list, he’s asked if he’d like to add it. Figure 10-12 As a refresher, you can use the Limit To List property to control what happens when a user enters data into a control. If the value is set to No, it places no restrictions on what is entered. If the value is set to Yes, several things can be triggered, including the following: ❑ The user is limited to what is in the list. ❑ If other data is entered, users are asked to choose from the list. ❑ Entering other data can trigger the NotInList event. Because combo boxes are typically based on a look-up table, the following example provides code to offer the user a chance to add a value that is not in the list. It also creates a custom message box. Private Sub cboMainCategory_NotInList(NewData As String, Response As Integer) On Error GoTo Error_Handler Dim intAnswer as Integer intAnswer = MsgBox(“”“” & NewData & “”“ is not an approved category. “ & vbcrlf _ 312 Chapter 10: Using VBA to Enhance Forms 47033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 312 [...]... Me!lstContacts.ItemsSelected.Count = 0 Then Exit Sub For Each varItem In Me!lstContacts.ItemsSelected ‘char( 34) adds quotes to Me!lstContacts ‘Then add a comma to separate the selected items 320 47 033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 321 Chapter 10: Using VBA to Enhance Forms emName = emName & Chr( 34) & Me!lstContacts.Column (4, varItem) & Chr( 34) & “,” Next varItem ‘remove the extra comma at the end emName = Left$( emName,... DoCmd.Close will close the splash screen This scenario has worked well in the past, but it can cause problems if the database is 325 47 033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 326 Chapter 10: Using VBA to Enhance Forms opened in disabled mode by Access 2007 If the VBA is disabled, the timer event code never runs and the splash screen is not closed To avoid risking that situation, you can close a... are stored in a field with a Text data type rather than as a hyperlink On your form, you can add a list box named lstContacts, as shown in Figure 10- 14 319 47 033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 320 Chapter 10: Using VBA to Enhance Forms Figure 10- 14 The list box RowSource would equal tblContacts, so the column count and column width need to be set to display the first name, last name, and e-mail... without adding the item to the list Either of those constants (responses) will suppress the default Access message The point here is that by creating custom messages boxes you proivde a more informative and professional user interface 313 47 033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 3 14 Chapter 10: Using VBA to Enhance Forms Field List One of the values for Row Source Type that hasn’t been mentioned... to PDF A common challenge for Access developers has been to have a way to send data or output to a PDF file format Sure, you could do it, but it wasn’t easy Previous versions required the developer to obtain some third-party software (CutePDF, for example) and then to build creative workarounds Now Access 2007 has streamlined the process by providing the bridge between Access and PDF utilities, particularly... concatenating the empty string Because Access trims spaces off of data entered on the form, you’re not required to test for a single space entered in a field The code used in the field_ BeforeUpdate example is just a technique used to simplify validations as well as ensure that Access behaves the way you expect it to Saving E-mail Addresses Using Textbox AfterUpdate Event Access 2007 is smarter about the way... type Contacts For the condition, type: Not IsNull([Screen].[ActiveControl]) 337 47 033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 338 Chapter 10: Using VBA to Enhance Forms 2 3 The Action column has a drop-down list; select RunCode 4 The Code Builder assists with syntax, but the key is to include the where clause as you did in VBA Alternatively, you can type the arguments directly into the Arguments field... for your user In Access 2007, Allow Value List Edits and List Items Edit Form enable you to eliminate some of the code that we used to capture data-entry errors Of course, you can still use the Not In List event to trap user input and provide special handling The combo box is definitely worth spending some time learning about so that you can leverage its versatility and benefits 316 47 033c10.qxd:WroxProgRef... need to download and install the file SaveAsPDFandXPS.exe A link to the web is provided in the Access Help files You can find it by typing XPS or PDF in the Search text box or by going to Microsoft.com and searching for SaveAsPDFandXPS.exe 322 47 033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 323 Chapter 10: Using VBA to Enhance Forms People will still need a PDF viewer to open PDF files But viewers are commonly... form that should be opened only by certain users Because users can open the form from the Navigation pane, it’s possible for any user to open a form — unless you 323 47 033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 3 24 Chapter 10: Using VBA to Enhance Forms have implemented programmatic restriction One approach is to use the following code in the form’s OnOpen event to prevent it from being opened from . grow or shrink as appropriate for the display type. 3 04 Chapter 10: Using VBA to Enhance Forms 47 033c10.qxd:WroxProgRef 3/30/07 12:26 AM Page 3 04 When using code to specify the height and width in. settings may cause the comma to be interpreted as a decimal point. Notice that the code uses 144 0 not 1 ,44 0 and that the numbers are enclosed in double quotes. While you are at it, you may also want. knowing that a twip is 1 ⁄1 ,44 0 of an inch, which is the equivalent of 1 ⁄567 of a centimeter or 1 ⁄20th of a point. 305 Chapter 10: Using VBA to Enhance Forms 47 033c10.qxd:WroxProgRef 3/30/07