Special Edition Using Microsoft Office FrontPage 2003

Now that you know about the Visual Basic Editor and the FrontPage object models, it's time to put that knowledge to work and write a macro.

NOTE

The files for the macro you will write are on the CD-ROM in the CH30 folder. Instead of entering the code and creating the UserForm, you can install the files from the CD and then drag and drop the files for the macro to the Project Explorer window.

One of the many exciting new features to FrontPage 2003 is the ability to specify HTML code optimizations that are applied when you publish a FrontPage Web site. Everything from FrontPage webbot comment tags to FrontPage's GENERATOR and ProgID meta tags can be automatically cleaned up from your pages when you publish a FrontPage Web site. Naturally, the FrontPage object model provides us with programmatic access to this functionality, so we'll use that functionality to write a useful macro.

You will want your macro to allow for the entry of a server name. It will then access that Web server and will provide a list of all the FrontPage Web sites on that server. When one of those Web sites is selected, it will show what HTML optimizations are applied for that Web site, and it will allow you to easily change those settings with the click of the mouse.

Let's have a look at the requirements for your macro. You'll need

  • A UserForm that will be used to interact with your macro

  • A method to retrieve the list of FrontPage Web sites from a given server

  • A method to determine the current HTML optimization settings for a given Web site

  • A method to set the HTML optimizations for a given Web site as specified by your macro.

Creating the Userform

The first thing to do is create a UserForm. You'll need to provide a way for users to enter the name of a Web server, a button for the user to click to get a list of FrontPage Web sites on that server, a method of displaying the list of Web sites to the user, and some check boxes that will display the current HTML optimization settings. The UserForm will also allow the user of your macro to change the HTML optimization settings and to specify new settings.

Start the Visual Basic Editor if it's not already running and insert a new UserForm by right-clicking inside the Project Explorer and selecting Insert, UserForm. A new UserForm is inserted into your project, and the Toolbox window appears. The Toolbox contains all the tools you will need to create the user interface for your macro.

NOTE

You're not limited to the tools that are in the Toolbox by default. By right-clicking on the Toolbox and selecting Additional Controls from the menu, you can add other controls that are installed on your system.

After adding the UserForm, the Properties window will contain a listing of the properties for the UserForm. All objects in a macro have certain properties that control their behavior, and each of these properties has a value associated with it that describes that property. In the case of our UserForm, one of the properties is the Name property; the value for that property is currently set to UserForm1. We can change the Name property, but other properties are read-only and can only be read.

A discussion of all the UserForm properties is outside the scope of this book, but by selecting a property and pressing F1, you can review the context-sensitive help on that property.

At the top of the list of properties is the Name property. This property defines the name used to refer to the selected object in your macro code. Select the Name property and change it from UserForm1 to frmMain. After changing the name of the UserForm, change the Caption property to HTML Optimizer, the Height property to 277, and the Width property to 375.

Next you'll need to add some controls to the UserForm. Add a Label control from the Toolbox to the UserForm by clicking the Label control button (the button marked with the letter A) and then drawing the Label on the UserForm. After drawing the Label on the UserForm, change the Left property to 12, the Top property to 18, the Height property to 12, the Width property to 210, and the Caption property to Enter the server name:.

Add the controls in Table 30.1 and set their properties as indicated. If you aren't sure which Toolbox button represents which control, hover over the button with your mouse and the name of the control will display in a ToolTip. If you'd prefer, you can install the files from the CD accompanying this book and import the frmMain.frm file from the CH36 folder.

Table 30.1. Controls for the UserForm

Control

Control/Property

Value

TextBox

TextBox

 
 

Name

txtServerName

 

Height

18

 

Left

12

 

Top

30

 

Width

216

CommandButton

CommandButton

 
 

Name

cmdGetSites

 

Caption

Get Site List

 

Default

True

 

Enabled

False

 

Height

18

 

Left

235

 

TakeFocusOnClick

False

 

Top

30

 

Width

100

Label

Label

 
 

Name

lblSelectSite

 

Caption

Select site:

 

Enabled

False

 

Height

12

 

Left

12

 

Top

66

 

Width

210

ComboBox

ComboBox

 
 

Name

cboSites

 

Enabled

False

 

Height

18

 

Left

12

 

Style

2- fmStyleDropDownList

 

Top

80

 

Width

215

CheckBox

CheckBox

 
 

Name

chkAuthorComponents

 

Caption

Author-time component comments

 

Enabled

False

 

Height

15

 

Left

12

 

Top

125

 

Width

180

CheckBox

CheckBox

 
 

Name

chkBrowseComponents

 

Caption

Browse-time component comments

 

Enabled

False

 

Height

15

 

Left

12

 

Top

141.75

 

Width

180

CheckBox

CheckBox

 
 

Name

chkDynamicTemplates

 

Caption

Dynamic Web Template comments

 

Enabled

False

 

Height

15

 

Left

12

 

Top

158.45

 

Width

180

CheckBox

CheckBox

 
 

Name

chkGenerator

 

Caption

GENERATOR and ProgIdProgID Meta tags

 

Enabled

False

 

Height

15

 

Left

12

 

Top

175.2

 

Width

180

CheckBox

CheckBox

 
 

Name

chkWhitespace

 

Caption

HTML whitespaces

 

Enabled

False

 

Height

15

 

Left

12

 

Top

192

 

Width

180

CheckBox

CheckBox

 
 

Name

chkHTMLComments

 

Caption

HTML comments

 

Enabled

False

 

Height

15

 

Left

186

 

Top

125

 

Width

180

CheckBox

CheckBox

 
 

Name

chkLeadingWhitespace

 

Caption

Leading whitespaces

 

Enabled

False

 

Height

15

 

Left

186

 

Top

141.75

 

Width

180

CheckBox

CheckBox

 
 

Name

chkScriptComments

 

Caption

Script comments

 

Enabled

False

 

Height

15

 

Left

186

 

Top

158.45

 

Width

180

CheckBox

CheckBox

 
 

Name

chkThemeComments

 

Caption

Theme comments

 

Enabled

False

 

Height

15

 

Left

186

 

Top

175.2

 

Width

180

CommandButton

CommandButton

 
 

Name

cmdClose

 

Caption

Close

 

Height

20

 

Left

228

 

Top

222

 

Width

60

CommandButton

CommandButton

 
 

Name

cmdOK

 

Caption

OK

 

Height

20

 

Left

294

 

Top

222

 

Width

60

Figure 30.4 shows the completed version of the UserForm.

Figure 30.4. The completed UserForm provides all the controls necessary for users to control the operation of your macro.

Implementing the Functionality

Now that the UserForm is complete, it is time to write the main sub procedure for the macro. This sub procedure is what you will run to start executing the macro. If Module1 is not visible in the Project Explorer, click the plus sign next to Microsoft_Office_FrontPage, click the plus sign next to the Modules folder, and then double-click Module1 to open the code window. You'll enter the main sub procedure in the Module1 code window because it must be available in the Macro dialog in FrontPage. Only public sub procedures are available in the Macro dialog, and you can only enter a public sub procedure in a module.

Code for a macro can be written inside a sub procedure or a function. A sub procedure and function are defined as follows:

  • Sub procedure A block of code that performs a certain task but returns no value

  • Function A block of code that performs a certain task and returns a value

Click inside the Module1 code window and enter the code seen in Listing 30.3.

Listing 30.3 Procedure to Execute Macro

1 Public Sub StartHTMLOptimizer() 2 frmMain.Show 3 End Sub

The code in Listing 30.3 declares a public procedure that shows the macro's UserForm. If you now switch from the Visual Basic Editor to FrontPage and select Tools, Macro, Macros, you will see the StartHTMLOptimizer macro listed as seen in Figure 30.5. If you run that macro, it will display your UserForm.

Figure 30.5. Your macro will now allow you to display the UserForm, but until the code that provides the functionality is added, none of the controls do anything.

Everything looks great so far, but if you click around on the UserForm, you will find that it doesn't do much. In fact, it doesn't do anything at all! You need to write some code to add functionality to the UserForm, and the Visual Basic Editor makes this very easy to do.

If you run the UserForm but you cannot seem to click anything on it, see "UserForm Seems Hung" in the "Troubleshooting" section at the end of this chapter.

Switch back to the Visual Basic Editor and double-click the Get Site List button. When you do this, the code window for the UserForm opens, and the cursor is placed inside the cmdGetSites_Click procedure. When you are running the macro and you click the Get Site List button, a Click event is fired for that button. This event automatically runs the code in the cmdGetSites_Click procedure. Therefore, any code written in this procedure will run whenever the button is clicked.

Place the cursor inside the Click event for cmdGetSites and enter the code in Listing 30.4.

Listing 30.4 Code for Click Event

1 ' Variable to hold return value of GetWebSites. 2 Dim bGotWebSites As Boolean 3 4 ' In case we're searching on a new site, reset the form. 5 ResetForm 6 7 ' Call the GetSubwebs procedure and pass the server name to it. 8 bGotWebSites = GetWebSites(txtServerName.Text) 9 10 If bGotWebSites Then 11 12 ' A variable to hold a control. 13 Dim c As Control 14 15 ' Iterate through all of the controls on the form and enable each one. 16 For Each c In Me.Controls 17 c.Enabled = True 18 Next 19 20 ' Select the first item in cboSites. 21 cboSites.ListIndex = 0 22 23 End If 24 25 End Sub

When the Get Site List button is clicked, FrontPage takes the server name that was entered and gets a list of all the FrontPage Web sites on that server. Let's have a look at the code we just entered to implement this.

TIP

You'll notice that many of the lines of code in our macro start with a single quote. These lines are comments that serve as inline documentation on what the code is doing. It is good practice to always comment your code, and as you write more complex macros, it becomes a necessity. Without comments, you almost certainly won't remember what you were thinking when you revisit code later.

Line 2 in Listing 30.4 declares a Boolean variable that will hold the return value of a call to a function that gets the FrontPage Web sites on the server we enter. A Boolean variable is a variable that has a value of either True or False. Our function will return True if successful and False if something goes wrong. (You will write that function later.)

Line 5 makes a call to a sub procedure called ResetForm. This sub procedure (which you will also write later) will be responsible for resetting the UserForm. It will return the UserForm to its initial state and prepare it for displaying information for a new server.

Line 8 sets the value of the Boolean variable to the value returned by the GetSubWebs function. It also passes the text entered into the txtServerName control to that function. When you call a function or sub procedure, you can pass values to it by appending them to the function's or sub procedure's name. The function or sub procedure has to be written to expect these values to be passed to it, and we'll have a look at how that's done in Listing 30.6. In this case, the server name is passed to the GetSubwebs function.

TIP

The code in Listing 30.4 illustrates an important point in programming. By separating the implementation of the button into separate sub procedures and functions, it is very easy to keep track of code and to change implementation later. If all the code existed within the Click event itself, the code would quickly become unmanageable, and any change in implementation would increase the risk of introducing bugs.

Line 10 checks the value returned by the call to GetWebSites. If this value is True (meaning that we successfully contacted the Web server and got a list of the FrontPage Web sites on it), the code between the If statement on line 10 and the End If statement on line 23 is executed. If the value of bGotWebSites is False (meaning that something prevented you from successfully getting the list of FrontPage Web sites from the Web server), the code between lines 10 and 23 is not executed.

Line 13 declares a variable of type Control. You will use this variable to cycle through all the controls on your UserForm in lines 16 18. This is a common technique that will become familiar to you after working with code for a while. The Controls collection of a UserForm represents all the controls on that UserForm. Any time you want to cycle through all the items in a collection programmatically, declare a variable of the same type as the objects in the collection (a variable of type Control in this case), and then use a For...Each statement to cycle through the collection. This is referred to as "iterating through the collection."

Remember that when the UserForm was created, the Enabled property of many of the controls was set to False. We did that because those particular controls are not applicable unless a list of FrontPage Web sites has already been obtained from the server. Since we now have a list of Web sites from the server, we are ready to enable all the controls so that the user of the macro can interact with those controls. Lines 16 18 accomplish this by iterating through each control on the UserForm and setting the Enabled property to True.

After the Get Site List button is clicked, we want the ComboBox to display the settings for the root Web site of the server, which will be the first item in the ComboBox. To do that, we set the ListIndex to 0 in line 21.

Now enter the code for the ResetForm procedure. Place the cursor at the end of the code window for frmMain and enter the code in Listing 30.5.

Listing 30.5 Code for the Resetform Procedure

1 Private Sub ResetForm() 2 3 ' Clear entries in cboSites. 4 cboSites.Clear 5 6 ' Variable to hold a reference to a control. 7 Dim c As Control 8 9 ' Iterate through all controls and disable all CheckBoxes. 10 For Each c In Me.Controls 11 If TypeName(c) = "CheckBox" Then c.Enabled = False 12 Next 13 14 ' Disable labels and the ComboBox. 15 lblSelectSite.Enabled = False 16 lblOptimizations.Enabled = False 17 cboSites.Enabled = False 18 19 End Sub

The code in Listing 30.5 resets the UserForm to its original state. Line 4 begins the process by clearing all items in the ComboBox. After that is done, lines 7 12 iterate through the controls on the form in the same manner used in Listing 30.4. The difference here is that instead of setting the Enabled property to True, we are setting the Enabled property to False just as it was when the UserForm was first displayed.

Take a look at line 11. We're using the TypeName function and passing the current control to it. The TypeName function returns a string that indicates the type of the control passed to it. In this particular case, we only want to set the Enabled property to False if the control is a CheckBox, so we use the TypeName function to check the control's type before we set the Enabled property. If the control is a CheckBox, the TypeName function will return "CheckBox" and we'll disable the control.

After we've disabled all the CheckBox controls, the procedure is ended by disabling the two label controls and the ComboBox control.

To complete the functionality of the Get Site List button, you need to enter the code for the GetWebSites function. Position the cursor at the end of the code window for frmMain again and enter the code in Listing 30.6.

Listing 30.6 Code for the Getwebsites Function

1 Private Function GetWebSites(serverName As String) As Boolean 2 3 ' Variables for this sub procedure 4 Dim oWeb As WebEx 5 Dim oFolder As WebFolder 6 7 ' Display an hourglass on our UserForm while we work. 8 Me.MousePointer = fmMousePointerHourGlass 9 10 ' Set up error handling so that we can inform the user of any problems. 11 On Error GoTo ErrorHandler 12 13 ' Get a reference to the root Web site of the server. 14 Set oWeb = Webs.Open("http://" & serverName, , , fpOpenNoWindow) 15 16 ' Recalculate hyperlinks on the root Web site. 17 oWeb.RecalcHyperlinks 18 19 ' Loop through all folders in oWeb. 20 For Each oFolder In oWeb.AllFolders 21 ' If the current oFolder is a Web, add it to cboSites on our UserForm. 22 If oFolder.IsWeb Then 23 cboSites.AddItem oFolder.URL 24 End If 25 Next 26 27 ' Destroy our WebEx object. 28 Set oWeb = Nothing 29 30 ' Return the mouse pointer to the default. 31 Me.MousePointer = fmMousePointerDefault 32 33 ' Return True. 34 GetWebSites = True 35 36 ' Exit the sub procedure to avoid running ErrorHandler code when no error occurs. 37 Exit Function 38 39 ' Error Handling code. 40 ErrorHandler: 41 42 ' If we've reached this point, an error occurred. Display the error to the user. 43 MsgBox Err.Number & ": " & Err.Description, vbExclamation + vbOKOnly, "HTML OPTIMIZER" 44 45 ' Restore the mouse pointer. 46 Me.MousePointer = fmMousePointerDefault 47 48 ' Return False. 49 GetWebSites = False 50 51 End Function

In line 9 of Listing 30.4, we called the GetWebSites function and passed the server name to it. As I said then, the function must be written to expect this value to be passed to it. By examining what's inside the parenthesis in line 1 of Listing 30.6, we can see that the GetWebSites function expects a string value (which means a text value) to be passed to it, and it assigns that value to a variable called serverName.

Line 4 declares a variable that will hold a reference to the root Web on the server, and line 5 introduces a new object in the FrontPage Web object model, the WebFolder object. A WebFolder represents a folder in a FrontPage Web site, and one of its properties is IsWeb, which returns True if the folder is a FrontPage Web site and False if it is not. This property is the perfect way for us to get a list of all the FrontPage Web sites on the Web server.

Line 8 sets the mouse pointer to an hourglass so that the user will know that we're processing some information while we parse the Web site. Using the Me keyword here simply refers to the UserForm itself. The Me keyword is not required here, but it makes the code more readable.

Line 11 sets up error handling just in case something goes wrong. When you are accessing an external resource (such as opening a Web site), there's always a chance that something can go wrong. If you don't account for that possibility, your macro might crash with an ugly error message. For that reason, it's always a good idea to implement some error handling if you anticipate that unwanted results are possible.

In VBA, you implement error handling by using the On Error GoTo <line_label> statement, where <line_label> is a label defined inside the same method. The ErrorHandler line label in this case appears on line 37; line 11 specifies that if an error occurs, code execution will skip to line 39 and a message containing the error will be displayed to the user. We will then return a value of False indicating that something went wrong.

Line 14 sets the oWeb variable to a valid WebEx object by opening the root Web on the server that was passed to the function. To do that, we call the Open method of the Webs collection.

Line 17 recalculates hyperlinks on the Web site. We do this so that any new Web sites added to the server since the current session of FrontPage was started will be recognized. Without doing this, we cannot guarantee that new Web sites have been added to FrontPage's configuration files. Recalculating hyperlinks forces FrontPage to update its configuration files for the Web server and guarantees that we will have fresh information to work with.

Beginning at line 19 we iterate through all the folders in the Web. If the folder is a Web site (which we determine via the IsWeb property as discussed earlier), we add its URL to the cboSites ComboBox on line 23.

After we've run through all the folders, we destroy our WebEx object on line 28, reset the mouse pointer to the default pointer, and return a value of True. Finally, on line 37 we explicitly exit the function so that our error handling code won't run when no errors are encountered.

NOTE

Whenever you explicitly create an object (such as the WebEx object oWeb we created previously), you should destroy that object by setting it equal to Nothing when you have finished using it. When you do this, all resources and memory used by that object are freed.

Now that you've gotten a list of Web sites on the server, you need to write some code to read the current HTML optimization values. You want to do that whenever a new site is chosen from the cboSites ComboBox. Therefore, you'll write that code in the Change event of the ComboBox.

Double-click the cboSites ComboBox and enter the code in Listing 30.7 into the Change event.

Listing 30.7 The cboSites_Change Event

[View full width]

1 ' Check to see if there are any entries in the ComboBox. 2 If cboSites.ListCount > 0 Then 3 4 ' A variable to hold a reference to a WebEx object. 5 Dim oWeb As WebEx 6 7 ' Set up error handling. 8 On Error GoTo ErrorHandler 9 10 ' Open the Web. 11 Set oWeb = Webs.Open(cboSites.SelText, , , fpOpenNoWindow) 12 13 ' Reset error handling. 14 On Error GoTo 0 15 16 ' Run through each CheckBox and check the flag to see if we should check it. 17 With Me 18 .chkAuthorComponents.Value = (oWeb.OptimizeHTMLPublishFlags And fpHtmlOptAuthorComponents) 19 .chkBrowseComponents.Value = (oWeb.OptimizeHTMLPublishFlags And fpHtmlOptBrowseComponents) 20 .chkDynamicTemplates.Value = (oWeb.OptimizeHTMLPublishFlags And fpHtmlOptDwtCmnts) 21 .chkGenerator.Value = (oWeb.OptimizeHTMLPublishFlags And fpHtmlOptGenerator) 22 .chkWhitespace.Value = (oWeb.OptimizeHTMLPublishFlags And fpHtmlOptHTMLAllWhitespace) 23 .chkHTMLComments.Value = (oWeb.OptimizeHTMLPublishFlags And fpHtmlOptHTMLCmnts) 24 .chkLeadingWhitespace.Value = (oWeb.OptimizeHTMLPublishFlags And fpHtmlOptHTMLLeadWhitespace) 25 .chkScriptComments.Value = (oWeb.OptimizeHTMLPublishFlags And fpHtmlOptScriptCmnts) 26 .chkThemeComments.Value = (oWeb.OptimizeHTMLPublishFlags And fpHtmlOptThemes) 27 End With 28 29 ' Destroy the Web object. 30 Set oWeb = Nothing 31 32 End If 33 34 Exit Sub 35 36 ErrorHandler: 37 38 MsgBox "An error occured while trying to open the Web site " & cboSites.SelText & "." & _ 39 vbCrLf & vbCrLf & Err.Description, vbCritical + vbOKOnly, "HTML OPTIMIZER"

In line 2, we check to see if there are any items in the ComboBox. This might seem like a strange thing to do because you would think that if the selection in the ComboBox has changed (which is, after all, what causes this code to run because it is in the Change event), there would obviously be an item in the ComboBox. In fact, the Change event does run once when there are no items in the ComboBox. When you run the ResetForm sub procedure in Listing 30.5, the Change event is fired when the ComboBox is cleared in line 4. We don't want the code that opens the Web site and applies optimization settings to run in this case, so we enclose the code within an If...End If block and only run it if the ListCount property is greater than 0.

The code up to line 14 should be familiar to you by now, but line 14 probably isn't. You will notice that line 8 sets up error handling just as we've done in some of our other code. However, in this case, we are resetting that error handling in line 14. Our error handling code is designed to handle an error occurring when we open the Web site in line 11. After we've successfully accomplished that, we reset the error handling in line 14.

Lines 17 28 also introduce a new concept. In these lines, we are determining the current HTML optimization settings for the Web site by checking the OptimizeHTMLPublishFlags property of the Web site. This property contains a value that is of type fpOptimizeHTMLFlags, which is a special type of value called a flag. Flags are commonly used when writing programs because they are binary values and the computer can efficiently manipulate them. Fortunately, VBA provides an efficient means of manipulating them as well.

In lines 18 26, we use the And operator to check the current HTML optimization settings. The return value of OptmizeHTMLPublishFlags And <flag> will return True if the flag denoted by <flag> is set and False if it is not.

The rest of the code in Listing 30.7 uses concepts we have already covered and should already be familiar to you.

The functionality of the macro is almost complete. You've written the code necessary to get a list of FrontPage Web sites on the server specified by our user, as well as the code necessary to determine what the current HTML optimizations are for the selected Web site. When the current HTML optimizations are displayed to the user, your macro allows them to change those settings and then apply them to the Web site. That's the code that you will write next.

Double-click the OK button on the UserForm and enter the code in Listing 30.8 into the Click event.

Listing 30.8 Click Event Code

[View full width]

1 ' Variable to hold return value of OptimizeSite 2 Dim bOptimized As Boolean 3 4 ' Call OptimizeSite and pass the selected URL. 5 bOptimized = OptimizeSite(cboSites.SelText) 6 7 ' If optimization was successful, display appropriate message. 8 If bOptimized Then _ 9 MsgBox "Optimizations applied successfully.", vbInformation + vbOKOnly, "HTML OPTIMIZER"

This code is very similar to the code in Listing 30.4. We are setting the Boolean value bOptimized to the value returned by the OptimizeSite function in line 5. Enter the code for the OptimizeSite function now.

Place your cursor at the end of the code window for the UserForm and enter the code in Listing 30.9.

Listing 30.9 The Optimizesite Function

[View full width]

1 Private Function OptimizeSite(sURL As String) As Boolean 2 3 ' Set up error handling. 4 On Error GoTo ErrorHandler 5 6 ' A variable for a WebEx object. 7 Dim oWeb As WebEx 8 9 ' Get a reference to the Web site URL we passed in. 10 Set oWeb = Webs.Open(sURL, , , fpOpenNoWindow) 11 12 ' Determine the OptimizeHTMLPublishFlags for the site. 13 With oWeb 14 15 ' Reset flags. 16 .OptimizeHTMLPublishFlags = fpHtmlOptEmpty 17 18 If Me.chkAuthorComponents.Value = True Then _ 19 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptAuthorComponents 20 21 If Me.chkBrowseComponents.Value = True Then _ 22 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptBrowseComponents 23 24 If Me.chkDynamicTemplates.Value = True Then _ 25 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptDwtCmnts 26 27 If Me.chkGenerator.Value = True Then _ 28 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptGenerator 29 30 If Me.chkWhitespace.Value = True Then _ 31 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptHTMLAllWhitespace 32 33 If Me.chkHTMLComments.Value = True Then _ 34 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptHTMLCmnts 35 36 If Me.chkLeadingWhitespace.Value = True Then _ 37 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptHTMLLeadWhitespace 38 39 If Me.chkScriptComments.Value = True Then _ 40 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptScriptCmnts 41 42 If Me.chkThemeComments.Value = True Then _ 43 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptThemes 44 45 If Not (.OptimizeHTMLPublishFlags And fpHtmlOptEmpty) Then _ 46 .OptimizeHTMLPublishFlags = .OptimizeHTMLPublishFlags + fpHtmlOptOn 47 48 End With 49 50 ' Destroy the oWeb object. 51 Set oWeb = Nothing 52 53 ' Return True 54 OptimizeSite = True 55 56 ' Exit the function 57 Exit Function 58 59 ErrorHandler: 60 61 ' Display the error. 62 MsgBox "An error occured while processing optimization." & vbCrLf & vbCrLf & Err .Description, _ 63 vbCritical + vbOKOnly, "HTML OPTIMIZER" 64 65 ' Return False 66 OptimizeSite = False 67 68 End Function

The OptimizeSite function is our longest code listing yet, but there's not as much here as you might think at first glance. The code up to line 16 follows the same concepts we covered in Listing 30.7.

Line 16 sets the OptimizeHTMLPublishFlags property of the Web site to fpHtmlOptEmpty. This clears all the existing HTML optimization settings in preparation for applying the new settings our user has specified. Lines 18 43 check each CheckBox's Value property, and if it is checked, the corresponding OptimizeHTMLPublishFlags bit is set.

Line 45 performs a check to see if the OptimizeHTMLPublishFlags property is still set to fpHtmlOptEmpty. If it is, the user of your macro hasn't checked any of the CheckBoxes and we need not apply any HTML optimizations. However, if the user has checked one or more of the CheckBoxes, we add the fpHtmlOptOn flag to the current OptimizeHTMLPublishFlags. This has the effect of turning on HTML optimization so that your user's settings will be applied the next time the Web site is published.

The rest of Listing 30.9 consists of concepts covered in Listing 30.6.

Finishing the Code

The main functionality of your macro is complete now. However, there are some finishing touches that you need to add.

First you'll add the code for the Close button. Double-click the Close button and add the following code to the Click event.

' Unload the form without making any changes... Unload Me

This is pretty simple code that does exactly what it appears to do. It unloads the UserForm from memory, which causes it to close and our macro to end. That's all we need for the Close button.

Finally, we don't want the users of your macro to be able to click the Get Site List button if they haven't entered a server name. In order to add that functionality, we'll add some code to the Change event of the txtServerName TextBox control.

Double-click the txtServerName TextBox control and enter the following code in the Change event.

' If no server name is entered, disable the Get Site List button. If txtServerName.Text = "" Then cmdGetSites.Enabled = False Else cmdGetSites.Enabled = True End If

The code in the Change event of txtServerName will run whenever the text in the TextBox changes. Each time the user of our macro presses a keyboard key while the cursor is in the txtServerName TextBox, we check to see if any text is in it. If there is, we enable the Get Site List button. If there isn't text in the TextBox, we disable the Get Site List button.

TIP

For the most part, we rely on FrontPage itself to handle any incorrect entries in the txtServerName TextBox. However, the macro can be made more robust by adding your own logic to check for invalid entries. Challenge yourself by adding some code to check for invalid entries.

Running the Macro

That's it! We are now ready to run the macro. Close the Visual Basic Editor (and make sure to save your changes when prompted) and then select Tools, Macro, Macros in FrontPage. Select the StartHTMLOptimizer macro and click Run.

Once the UserForm displays, enter the name of a Web server and click the Get Site List button. Your macro gets a list of the FrontPage Web sites on the server and populates the ComboBox with them.

Once the site list has populated, select a Web site from the ComboBox and examine the current HTML optimization settings. Change some of the settings and click the OK button to apply them. Figure 30.6 shows the macro with optimization settings applied. Figure 30.7 shows the Remote Web Site Properties dialog in FrontPage. Note that the changes applied with your macro are reflected in the Remote Web Site Properties dialog.

Figure 30.6. The completed macro. Note that we have configured the current site to remove the Author-time comments, the GENERATOR and ProgID meta tags, and HTML comments.

Figure 30.7. The Remote Web Site Properties dialog shows that the changes we made to the Web site with our macro did take effect.

If you've specified that browse-time comments be removed, yet they still remain in your pages after publishing, see "Browse-time Comments Still Exist" in the "Troubleshooting" section at the end of this chapter.

For more information on the Remote Web Site Properties dialog, see "Security and Administration of a Web Site," p. 323.

The next time this Web site is published, it will be published using the HTML optimizations set with your macro.

If the Remote Web Site Properties dialog does not reflect the settings you specified when you ran your macro, see "New Settings Don't Take" in the "Troubleshooting" section at the end of this chapter.

When Something Goes Wrong Debugging

One of the tried and true rules of programming is that something will always go wrong. When it does, knowing how to debug a macro is the key to finding the problem and getting it fixed.

Breakpoints are a vital aid in the debugging process. The Visual Basic Editor will automatically stop execution when a breakpoint in code is hit. You can then use the Debug toolbar (accessible from View, Toolbars, Debug) to step through your code. When hovering your mouse pointer over objects and variables in your code, a ScreenTip will display with the current value of that object or variable.

To set a breakpoint at a line of code, right-click the line of code and select Toggle, Breakpoint from the menu. You can also click in the left border of the code editor at a specific line to set a breakpoint on that line, or click anywhere on the line of code and press F9. You can create as many breakpoints as you would like. You can remove all of your breakpoints in one step by selecting Debug, Clear All Breakpoints.

The Locals Window is available by selecting View, Locals Window. It displays all objects available to you and their properties and values in a tree view structure. As you step through your code when debugging, the Locals Window allows you to see what properties of an object are changing and what their values are. When I am debugging code, I use the Locals Window more than any other debugging tool because it shows me everything in one convenient location.

The Immediate Window is available by selecting View, Immediate Window. It allows you to enter commands and view or change the value of variables and properties while your code is paused at a breakpoint.

The Watch Window is available by selecting View, Watch Window. It allows you to watch a particular variable while code executes or to set a conditional breakpoint so that the Visual Basic Editor breaks when a particular condition is met or when the value of an expression you specify changes. To add a new Watch in the Watch Window, right-click anywhere within the Watch Window and select Add Watch.

For detailed information on debugging and the Locals, Immediate, and Watch windows, see the Visual Basic Help available by selecting Help, Microsoft Visual Basic Help within the Visual Basic Editor.

Категории