Saving a chart as a GIF file The following code demonstrates how to create a GIF file named temp.gif from achart in this case, the first chart object on the sheet named Data: Set Current
Trang 1Figure 15-8: This modeless dialog box remains visible while the user
continues working
Refer to Chapter 18 for additional information about events
The event-handler procedures follow:
Private Sub Workbook_SheetSelectionChange _(ByVal Sh As Object, ByVal Target As Range)Call UpdateBox
End SubPrivate Sub Workbook_SheetActivate(ByVal Sh As Object)Call UpdateBox
End SubThese procedures call the UpdateBoxprocedure, which follows:
Sub UpdateBox()With UserForm1
‘ Make sure a worksheet is active
If TypeName(ActiveSheet) <> “Worksheet” Then.lblFormula.Caption = “N/A”
.lblNumFormat.Caption = “N/A”
.lblLocked.Caption = “N/A”
Exit SubEnd If
Cross-Reference
Trang 3Figure 15-9 shows a much more sophisticated version of this example (it’s also
on the CD-ROM) This version displays quite a bit of additional information aboutthe selected cell Long-time Excel users may notice the similarity with the Info window — a feature that was removed from Excel several years ago The code is too lengthy to display here, but you can view the well-commented code in theexample workbook
Figure 15-9: This UserForm displays information
about the active cell
Multiple Buttons, One Event-Handler
Every CommandButton on a UserForm must have its own procedure to handle itsClickevent For example, if you have two CommandButtons, you’ll need at leasttwo event-handler procedures:
Private Sub CommandButton1_Click()
‘ Code goes hereEnd Sub
Private Sub CommandButton2_Click()
‘ Code goes hereEnd Sub
In other words, you cannot assign a macro to execute when any CommandButton is
clicked Each Clickevent-handler is “hard-wired” to its CommandButton You can,however, have each event-handler call another all-inclusive macro in the event-handler procedures, but you’ll need to pass an argument to indicate whichbutton was clicked In the following examples, clicking either CommandButton1
orCommandButton2both execute the ButtonClickprocedure, and the single argument tells the ButtonClickprocedure which button was clicked
Trang 4Private Sub CommandButton1_Click()Call ButtonClick(1)
End SubPrivate Sub CommandButton2_Click()Call ButtonClick(2)
End Sub
If your UserForm has many CommandButtons, setting up all of these event-handlerscan get tedious You might prefer to have a single procedure that could determinewhich button was clicked, and take the appropriate action
This section describes a way around this limitation by using a Class Module todefine a new class
This example is available on the companion CD-ROM
Procedure
The following steps describe how to re-create the example workbook:
1 Create your UserForm as usual, and add several CommandButtons (the
exam-ple on the CD contains 16 CommandButttons).This examexam-ple assumes the form
is named UserForm1
2 Insert a class module into your project (use Insert ➪ Class Module), give it the
name BtnClass, and enter the following code You will need to customize theButtonGroup_Clickprocedure
Public WithEvents ButtonGroup As MsForms.CommandButtonPrivate Sub ButtonGroup_Click()
Msg = “You clicked “ & ButtonGroup.Name & vbCrLf _
& vbCrLfMsg = Msg & “Caption: “ & ButtonGroup.Caption _
& vbCrLfMsg = Msg & “Left Position: “ & ButtonGroup.Left _
& vbCrLfMsg = Msg & “Top Position: “ & ButtonGroup.TopMsgBox Msg, vbInformation, ButtonGroup.NameEnd Sub
3 Insert a normal VBA module and enter the following code This routine simply
displays the UserForm:
Sub ShowDialog()UserForm1.ShowEnd Sub
On the CD-ROM
Trang 54 In the code module for the UserForm, enter the code in Listing 15-4 This
pro-cedure is kicked off by the UserForm’s Initializeevent Notice that thecode excludes a button named OKButtonfrom the “button group.” Therefore,clicking the OKButton does not execute the ButtonGroup_Clickprocedure
Listing 15-4: Establishing the Buttons() object array
Dim Buttons() As New BtnClassPrivate Sub UserForm_Initialize()Dim ButtonCount As IntegerDim ctl As Control
‘ Create the Button objectsButtonCount = 0
For Each ctl In UserForm1.Controls
If TypeName(ctl) = “CommandButton” Then
If ctl.Name <> “OKButton” Then ‘Skip the OKButtonButtonCount = ButtonCount + 1
ReDim Preserve Buttons(1 To ButtonCount)Set Buttons(ButtonCount).ButtonGroup = ctlEnd If
End IfNext ctlEnd Sub
After performing these steps, you can execute the ShowDialogprocedure to play the UserForm Clicking any of the CommandButtons (except the OKButton)executes the ButtonGroup_Clickprocedure Figure 15-10 shows an example of the message displayed when a button is clicked
dis-Figure 15-10: The ButtonGroup_Click procedure describes
the button that was clicked
Trang 6Adapting this technique
You can adapt this technique to work with other types of controls You’ll need tochange the type name in the Public WithEventsdeclaration For example, if youhave OptionButtons instead of CommandButtons, use a declaration statement likethis:
Public WithEvents ButtonGroup As MsForms.OptionButton
A Color Picker Dialog
This example is similar to the example in the previous section, but a bit more plex The example workbook demonstrates a technique to display a UserForm thatallows the user to select a color from the Workbook’s color palette (which consists
com-of 56 colors)
The example is actually a function (named GetAColor) that displays a UserFormand returns a color value
This example is available on the companion CD-ROM
The GetAColorfunction follows:
Public ColorValue As VariantDim Buttons(1 To 56) As New ColorButtonClassFunction GetAColor() As Variant
‘ Displays a UserForm and returns a
‘ color value - or False if no color is selectedDim ctl As Control
Dim ButtonCount As IntegerButtonCount = 0
For Each ctl In UserForm1.Controls
‘ The 56 color buttons have their ‘
‘ Tag property set to “ColorButton”
If ctl.Tag = “ColorButton” ThenButtonCount = ButtonCount + 1Set Buttons(ButtonCount).ColorButton = ctl
‘ Get colors from the active workbook’s palette
Buttons(ButtonCount).ColorButton.BackColor = _ActiveWorkbook.Colors(ButtonCount)
End IfNext ctlUserForm1.ShowGetAColor = ColorValueEnd Function
On the CD-ROM
Trang 7The UserForm contains 56 CommandButton controls, which are colored using thecolors in the active workbook’s palette.
You can access the GetAColorfunction with a statement such as the following:
UserColor = GetAColor()Executing this statement displays the UserForm and assigns a color value to theUserColorvariable The color corresponds to the color selected by the user
Figure 15-11 shows the UserForm (it looks better in color), which contains 56CommandButton controls The BackColorproperty of each button corresponds
to one of the colors in the workbook’s color palette Clicking a button unloads theUserForm and provides a value for the function to return
Figure 15-11: This dialog box lets the user select a color
by clicking a button
The example file on the accompanying CD-ROM contains the following:
✦ A UserForm (UserForm1) that contains a dialog box with 56 CommandButtons(plus a few other accoutrements)
✦ A class module (ColorButtonClass) that defines a ColorButtonclass
✦ A VBA module (Module1) that contains a Function procedure (GetAColor)
✦ Two examples that demonstrate the GetAColorFunction procedure
The GetAColorprocedure sets up the UserForm and displays it It later returns thecolor value of the selected button If the user clicks Cancel, GetAColorreturnsFalse As the user moves the mouse pointer over the color buttons, the ColorSample image displays the color
The code behind this UserForm is rather lengthy, so it’s not listed here You can,however, open the workbook from the CD-ROM and examine the code
Trang 8Displaying a Chart in a UserForm
With Excel 5 or Excel 95, it was very easy to display a “live” chart in a custom dialogbox (using a dialog sheet): Just copy a chart and paste it into your dialog sheet
Oddly, there is no direct way to display a chart in a UserForm You can, of course,copy the chart and paste it to the Pictureproperty of an Image control, but thiscreates a static image of the chart and will not display any changes to the chart
Although UserForms are vastly superior to the old dialog sheets, this is one areathat Microsoft seems to have overlooked
You can still use dialog sheets in Excel 97 or later Therefore, you are certainly free
to use a dialog sheet to display a live chart in a dialog box
This section describes two methods to display a chart in a UserForm
Method 1: Save the chart as a file
Just because Microsoft doesn’t allow a live chart to be displayed in a UserForm,doesn’t mean it can’t be done! Figure 15-12 shows a UserForm with a chart dis-played in an Image object The chart actually resides on a worksheet, and theUserForm always displays the current chart This technique works by copying thechart to a temporary graphics file, then setting the Image control’s Pictureprop-erty to the temporary file
Figure 15-12: With a bit of trickery, a UserForm
can display “live” charts
General steps
To display a chart in a UserForm, follow these general steps:
1 Create your chart or charts as usual.
2 Insert a UserForm and then add an Image control.
Note
Trang 93 Write VBA code to save the chart as a GIF file, and then set the Image control’s
Pictureproperty to the GIF file You need to use VBA’s LoadPicturefunction
to do this
4 Add other bells and whistles as desired For example, the UserForm in the
demo file contains controls that let you change the chart type Alternatively,you could write code to display multiple charts
Saving a chart as a GIF file
The following code demonstrates how to create a GIF file (named temp.gif) from achart (in this case, the first chart object on the sheet named Data):
Set CurrentChart = Sheets(“Data”).ChartObjects(1).ChartFname = ThisWorkbook.Path & “\temp.gif”
CurrentChart.Export FileName:=Fname, FilterName:=”GIF”
When this code is executed, you’ll see a pop-up window that displays the progress
In response to a common question, I’m not aware of any way to suppress thisprogress display
Changing the Image control’s Picture property
If the Image control on the UserForm is named Image1, the following statementloads the image (represented by the Fnamevariable) into the Image control:
Image1.Picture = LoadPicture(Fname)This technique works fine, but you may notice a slight delay as the chart is savedand then retrieved On a fast system, however, this delay is barely noticeable
Method 2: Use the OWC ChartSpace control
As I mentioned in Chapter 13, a UserForm may contain other controls that aren’tnormally included in the Toolbox Microsoft includes the “Office Web Components”(OWC) with Office 2002, and you can use the Web Component controls in yourUserForms Figure 15-13 shows an example of a UserForm that contains aChartSpace control
This technique does not allow you to display an existing Excel chart on aUserForm Rather, you must write code that creates the chart in the ChartSpacecontrol
Making the ChartSpace control available
The first step is to add the ChartSpace control to your Toolbox Right-click the box to display the Additional Controls dialog box Scroll down the list and place acheck mark next to Microsoft Office Chart 10.0 (if you’re using Excel 2000, the itemwill be named Microsoft Office Chart 9.0) Click OK, and your Toolbox will have anew icon
tool-Note Note
Trang 10Figure 15-13: This UserForm contains a Spreadsheet control.
Adding the ChartSpace control to a UserForm
Adding a ChartSpace control to your UserForm works just like any of the standardcontrols When the control is added, you won’t see a chart displayed It is, after all,just a chart space control You’ll need to write code that creates the actual chart
Creating the chart
The following code, which is located in the UserForm code module, creates a chartusing data stored on a worksheet The category labels are in A2:A13, and the chartdata is in B2:B13 It assumes that the ChartSpaceobject is named ChartSpace1
Sub CreateChart()Dim Chart1 As ChChart ‘WCChartDim Series1 As ChSeries ‘WCSeriesDim r As Integer
Dim XValues(1 To 12)Dim DataValues(1 To 12)
‘ Add a chart to the ChartSpaceSet Chart1 = ChartSpace1.Charts.Add
‘ Give it a titleWith Chart1.HasTitle = True.Title.Caption = Range(“B1”)End With
Trang 11For r = 2 To 13XValues(r - 1) = Cells(r, 1)DataValues(r - 1) = Cells(r, 2)Next r
‘ Create a chart seriesSet Series1 = Chart1.SeriesCollection.Add
‘ Specify chart type and dataWith Series1
.Type = chChartTypeColumnClustered.SetData chDimCategories, chDataLiteral, XValues.SetData chDimValues, chDataLiteral, DataValuesEnd With
End SubThe code starts with variable declaration If you’re using Excel 2000, note that theobjects have a different type name For example, the chart object is of typeWCChart (not chChart) Similarly, the chart series object is of type WCSeries (notchSeries) Two arrays are declared: one to hold the category labels (XValues), andone to hold the data (DataValues)
The Setstatement creates a Chartobject within the ChartSpace This Chartobject
is named Chart1 The next block of statements sets the chart’s title, using the label
in cell B1 A For-Next loop reads the worksheet data into the arrays
The next Setstatement adds a series to the chart, and the Seriesobject is namedSeries1 The With-End Withblock of code specifies the chart type (a standard column chart), and specifies the data for the series
You’ll find documentation for the OWC objects on your hard drive These help filesare installed when the OWC is installed Or, you can use the Object Browser to learnmore about the properties and methods of these controls
It’s important to understand that the object model for creating a chart in the OWCdoes not correspond to the object model for creating a chart in Excel Chapter 18explains how to use VBA to manipulate “real” Excel charts
Figure 15-14 shows a slightly more sophisticated version of this example In thiscase, the user can choose which data will appear in the chart; this version alsoincludes an option to export the chart as a GIF file
This application is available on the companion CD-ROM You’ll find two versions
on the CD: one for Excel 2000 (using OWC 9.0), and one for Excel 2002 (usingOWC 10.0)
On the CD-ROM Note
Trang 12Figure 15-14: This UserForm contains a ChartSpace control (part of the Office Web
Components)
Displaying a Spreadsheet in a UserForm
Not content to simply display a chart in a UserForm? How about an entire sheet?
spread-Using the Office Web Components
The Office Web Components were designed to create interactive Web pages The nents include a Spreadsheet, a Chart, and a Pivot Table When you create an applicationthat uses the OWC, anyone who uses your application must have the OWC installed on his
compo-or her computer
The OWC is included with Microsoft Office 2000 and Microsoft Office 2002 Installation isnot automatic In other words, you can’t assume that all Microsoft Office 2000 users havethe OWC installed on their system (they may have chosen not to install it) To confuse mat-ters even more, the Small Business Edition of Microsoft Office 2000 does not even includethe OWC
Therefore, you should use caution before deciding to include any OWC controls in yourExcel application If your application will have general distribution, you’ll probably want toavoid using the OWC
Trang 13Figure 15-15 shows an example of a UserForm that contains a Microsoft OfficeSpreadsheet 10.0 control This control can contain an entire interactive spread-sheet, complete with formulas and formatting In fact, this Spreadsheet controlhas a significant advantage over a standard Excel sheet: Its dimensions are 18,278columns by 262,144 rows This is nearly 300 times as many cells as a standard Excel worksheet!
Figure 15-15: This UserForm contains a Spreadsheet control.
Making the Spreadsheet control available
First, you’ll need to add the Spreadsheet control to your Toolbox Right-click thetoolbox to display the Additional Controls dialog box Scroll down the list and place
a check mark next to Microsoft Office Spreadsheet 10.0 (if you’re using Excel 2000,the item will be named Microsoft Office Spreadsheet 9.0) Click OK to add the newicon to your Toolbox
Adding the Spreadsheet control to a UserForm
Adding a Spreadsheet control to your UserForm works just like any of the standardcontrols When the control is added to the UserForm, you’ll see a three-sheetspreadsheet As you’ll see, this spreadsheet can be customized quite a bit
A simple example
This example uses a Spreadsheet control to create a simple loan payment calculator
in a UserForm The finished product is shown in Figure 15-16 The user can enterloan information into column B, and the monthly payment is calculated (using a formula) and displayed in the bottom right cell
Trang 14This example is primarily for illustration only Using a Spreadsheet control isoverkill It is much more efficient to use EditBox controls to get the information,and calculate the loan payment using VBA code.
Figure 15-16: This UserForm uses
a Spreadsheet control for a simple loan payment calculator
To create this UserForm, start with a new workbook and follow the steps presentednext Make sure you’ve added the Spreadsheet control to your Toolbox
1 Insert a new UserForm, and add a Spreadsheet control Don’t change its
default name (Spreadsheet1)
By default, the spreadsheet displays with a toolbar, row and column headings,scroll bars, and a sheet selector tab To keep the interface as clean as possi-ble, we’ll get rid of these items later
2 Select any cell in the Spreadsheet control, then right-click and choose
Commands and Options from the shortcut menu
You’ll see the tabbed dialog box shown in Figure 15-17
3 Click the Workbook tab and delete Sheet2 and Sheet3 Then remove the check
marks from Horizontal scrollbar, Vertical scrollbar, Sheet selector, andToolbar
4 In column A, enter the text shown in Figure 15-16 Then adjust the width of
column A so it’s wide enough to handle the text
5 Enter some number into B1:B3 Then enter the following formula into cell B5:
=PMT(B2/12,B3,-B1)
6 Select B1:B3, and click the Format tab in the Commands and Options dialog
box Click the “key” icon to unlock the selected cells (the other cells willremain locked, which is the default)
7 Click the Sheet tab in the Commands and Options dialog box In the Viewable
range box, enter A1:B5
This essentially hides all of the unused rows and columns
Note
Trang 158 Next, remove the check mark from the check boxes labeled Row headers and
Column headers
9 Finally, add two CommandButton controls One, named CancelButton, will be
the Cancel button The other (named PasteButton) will execute code thatpastes the calculated result to the active cell in the Excel worksheet
Figure 15-17: Use this dialog box to customize
the Spreadsheet control
Now it’s time to add some VBA code In the preceding steps, the three input cellswere unlocked Locking cells, however, has no effect unless the sheet is protected(just like Excel) Therefore, we’ll add some code to protect the sheet when theUserForm is initialized You could protect the sheet at design time (using theCommands and Options dialog box), but that makes it impossible to edit thesheet — and it’s easy to forget to protect it again after you make changes Protectingthe sheet at runtime ensures that the sheet will be protected and the user can onlychange the input cells
The simple code that follows does the job:
Private Sub UserForm_Initialize()Spreadsheet1.ActiveSheet.ProtectEnd Sub
The UserForm button labeled Paste Payment, when clicked, executes the followingcode:
Private Sub PasteButton_Click()ActiveCell.Value = Spreadsheet1.Range(“B5”)Unload Me
End Sub
Trang 16This procedure simply puts the contents of cell B5 (from the Spreadsheet control)into the active cell on the Excel worksheet, and then unloads the UserForm.
Finally, we’ll need an event-handler procedure for the Cancel button:
Private Sub CancelButton_Click()Unload Me
End Sub
I really can’t think of too many good reasons to use a Spreadsheet control in aUserForm However, it’s nice to know that this feature is available should youneed it
An Enhanced Data Form
Next, here is one of the more complex UserForms you’ll encounter I designed it as areplacement for Excel’s Data Form, shown in Figure 15-18 You’ll recall this is thedialog box that appears when you select Data ➪ Form
Figure 15-18: Excel’s Data Form
Like Excel’s Data Form, my Enhanced Data Form works with a list in a worksheet
But as you can see in Figure 15-19, it has a dramatically different appearance andoffers several advantages
Trang 17Figure 15-19: The author’s Enhanced Data Form
Description
The Enhanced Data Form features the following enhancements:
✦ It handles any number of records and fields Excel’s Data Form is limited to 32fields
✦ The dialog box is always the same size, with scrollable fields Excel’s DataForm’s dialog isn’t scrollable, and can take up the entire screen!
✦ The record displayed in the dialog is always visible on-screen, and is lighted so you know exactly where you are Excel’s Data Form doesn’t scrollthe screen for you, and does not highlight the current record
high-✦ At startup, the dialog box always displays the record at the active cell Excel’sData Form always starts with the first record in the database
✦ When you close the dialog, the current record is selected for you Excel’s DataForm doesn’t change your selection when you exit
✦ It lets you insert a new record at any position in the database Excel’s DataForm adds new records only at the end of the database
✦ It includes an Undo button for Data Entry, Insert Record, Delete Record, andNew Record Excel’s Data Form includes only a Restore button
✦ Search criteria are stored in a separate panel, so you always know exactlywhat you’re searching for The search criteria are not always apparent inExcel’s Data Form
✦ Supports approximate matches while searching (*, ?, and #) Excel’s DataForm does not
✦ The complete VBA source code is available, so you can customize it to yourneeds Data Form is not written in VBA and cannot be customized
Trang 18The Enhanced Data Form is a commercial product (sort of) It can be used and tributed freely, but access to the complete VBA source is available only for a mod-est fee.
dis-Installing the add-in
To try out the Enhanced Data Form, install the add-in:
1 Copy the dataform.xla file from the CD-ROM to a directory on your hard drive.
2 In Excel, select Tools ➪ Add-Ins.
3 In the Add-Ins dialog box, click Browse and locate the dataform.xla in the
directory from Step 1
Using the Enhanced Data Form
When the Enhanced Data Form add-in is installed, a new menu command is able: Data ➪ JWalk Enhanced Data Form You can use the Enhanced Data Form towork with any worksheet database
Trang 20Advanced Programming Techniques
The six chapters in this part cover additional topics that
are often considered advanced The first three chaptersdiscuss how to develop utilities and how to use VBA to workwith pivot tables and charts Chapter 19 covers the topic ofevent-handling, which enables you to execute proceduresautomatically when certain events occur Chapter 20describes how to work with other applications, and Chapter
21 discusses the topic of add-ins
In This Part Chapter 16
Developing ExcelUtilities with VBA
Trang 22Developing Excel Utilities with VBA
This chapter is about Excel utilities A utility, in general, is
something that enhances software, adding useful tures or making existing features more accessible As you’llsee, creating utilities for Excel is an excellent way to make agreat product even better
fea-About Excel Utilities
A utility isn’t an end product, such as a quarterly report
Rather, it’s a tool that helps you produce an end product(such as a quarterly report) An Excel utility is (almostalways) an add-in that enhances Excel with new features orcapabilities
Excel is an extraordinary program that gets new featureswith every release But as good as Excel is, many users soondevelop a wish list of features that they would like to seeadded to the software For example, some users who turn offthe grid-line display want a feature that toggles this attribute
so that they don’t have to go through the tedious Tools ➪Options command Users who work with dates might want apop-up calendar feature to facilitate entering dates into cells
And some users desire an easier way to export a range of data
to a separate file
Utilities don’t need to be complicated Some of the most ful ones are actually very simple For example, the followingVBA procedure is a utility that toggles the grid-line display inthe active window:
Where to go formore Excel utilities
Trang 23Sub ToggleGridDisplay()ActiveWindow.DisplayGridlines = _Not ActiveWindow.DisplayGridlinesEnd Sub
You can store this macro in your Personal Macro Workbook so that it’s always able For quicker access, you can assign the macro to a toolbar button, a new menuitem, a right-click shortcut menu, or a keystroke combination
avail-Several of the examples in Part IV are actually utilities, or easily can be turned intoutilities
Using VBA to Develop Utilities
When I received the beta version of Excel 5, I was blown away by VBA’s potential.VBA was light-years ahead of Excel’s powerful XLM macro language, and it madeExcel the clear leader among spreadsheets in terms of programming
In an effort to learn VBA, I wrote a collection of Excel utilities using only VBA I ured that I would learn the language more quickly if I gave myself a tangible goal.The result was a product I call the Power Utility Pak for Excel, which is available toyou at no charge as a benefit of buying this book Use the coupon in the back of thebook to order your copy
fig-I learned several things from my initial efforts on this project:
✦ VBA can be difficult to grasp at first, but it becomes easier with practice
✦ Experimentation is the key to mastering VBA Every project usually involvesdozens of small coding experiments that eventually lead to a finished product
✦ VBA enables you to extend Excel in a way that is entirely consistent withExcel’s look and feel, including menus, toolbars, and dialog boxes
✦ Excel can do almost anything When you reach a dead end, chances arethere’s another path that leads to a solution
Few other software packages include such an extensive set of tools that enable theend user to extend the software
What Makes a Good Utility?
An Excel utility, of course, should ultimately make your job easier or more efficient.But if you’re developing utilities for other users, what makes an Excel utility valu-able? I’ve put together a list of elements that are common to good utilities:
Cross-Reference
Trang 24✦ It adds something to Excel This may be a new feature, a way to combine
exist-ing features, or just a way to make an existexist-ing feature easier to use
✦ It’s general in nature Ideally, a utility should be useful under a wide variety of
conditions Of course, it’s more difficult to write a general-purpose utility than
it is to write one that works in a highly defined environment
✦ It’s flexible The best utilities provide many options to handle various
situations
✦ It looks, works, and feels like an Excel command Although it’s tempting to add
your own special touch to utilities, other users will find them easier to use ifthey look and act like familiar Excel commands
✦ It provides help for the user when needed In other words, it requires
documen-tation that’s thorough and accessible
✦ It traps errors An end user should never see a VBA error message Any error
messages that appear should be ones that you write
✦ Its effects are undoable Users who don’t like the result caused by your utility
should be able to reverse their path
Text Tools: The Anatomy of a Utility
In this section, I describe an Excel utility that I developed (and is part of my PowerUtility Pak) The Text Tools utility enables the user to manipulate text in a selectedrange of cells Specifically, this utility enables the user to do the following:
✦ Change the case of the text (uppercase, lowercase, or proper case)
✦ Add characters to the beginning or the end, or at a specific character position
✦ Remove characters from the beginning or the end, or from a specific positionwithin the string
✦ Remove excess spaces (or all spaces)
Background
Excel has many text functions that can manipulate text strings in useful ways Forexample, you can uppercase the text in a cell, delete characters from text, removespaces, and so on But to perform any of these operations, you have to write formu-las, copy them, convert the formulas to values, and paste the values over the origi-nal text In other words, Excel doesn’t make it particularly easy to modify text
Wouldn’t it be nice if Excel had some text manipulation tools that didn’t require formulas?
Trang 25By the way, many good utility ideas come from statements that begin, “Wouldn’t it
be nice if ”
Project goals for Text Tools
The first step in designing a utility is to envision exactly how you want the utility towork Here’s my original plan, stated in the form of ten goals:
✦ It will have the same look and feel of other Excel commands In other words, itwill have a dialog box that looks like Excel’s dialog boxes
✦ It will be accessible from the Tools menu
✦ It will operate with the current selection of cells (including multiple selections),and it will enable the user to modify the range selection while the dialog box isdisplayed
✦ Its main features will consist of tools to change the case of text, add new text
to the strings, delete a fixed number of characters from the text, and removespaces from the text in each cell
✦ It also will enable the user to display key statistics about selected cells
✦ It will enable the user to request the preceding types of changes to nontextcells as well as to text cells
✦ It will have no effect on cells that contain formulas
✦ It will be fast and efficient For example, if the user selects an entire range, theutility should ignore the empty cells in the column
✦ It will enable the user to undo the changes
✦ It will have online help available
How it works
When the Text Tools workbook opens, it creates a new menu item on the Toolsmenu: Text Tools Selecting this item executes the StartTextToolsprocedure,which checks to make sure that Excel is in the proper context (a worksheet isactive and it is not protected) and then displays the main Text Tools dialog box
The user can specify various modifications and click the Apply button to performthem The changes are visible in the worksheet, and the dialog box remains dis-played Each operation can be undone, or the user can perform additional textmodifications Clicking the Help button displays a help dialog box, and clicking theExit button dismisses the dialog box
Figure 16-1 shows an example of the Text Tools utility in use
Trang 26Figure 16-1: Using the Text Tools utility to change text to proper case
The Text Tools workbook
The Text Tools workbook consists of the following components:
✦ One worksheet Every workbook must have at least one worksheet I take
advantage of this fact and use the worksheet named HelpSheetto store userhelp text
✦ Two VBA modules One (modMenus) contains the code to create and delete themenu item; the other (modMain) contains the code to display the main
UserForm The code that does the actual work is stored in the code modulesfor the UserForms
✦ Two UserForms One (FormMain) is the main dialog box; the other(FormMenus) is used to display help
The Text Tools utility is available on the CD-ROM that accompanies this book This
is a standalone version of the tool that is included with the Power Utility Pak
The FormMain UserForm
When I create a utility, I usually begin by designing the user interface, which in thiscase is the main dialog box Creating the dialog box forces me to think through theproject one more time
On the CD-ROM
Trang 27The MainFormUserForm contains a MultiPage control, with four pages that spond to the main features in the utility Figure 16-2 shows the four pages of theMultiPage control.
corre-Figure 16-2: The FormMain UserForm contains a MultiPage control with four pages.
The controls contained in the MultiPage control are very straightforward, so I won’texplain them (you can refer to the code for details) The MainForm UserForm alsocontains additional controls outside of the MultiPage control:
✦ A RefEdit control The UserForm_Initializeprocedure displays the address
of the current range selection And, of course, the RefEdit control allows theuser to select a different range at any time
✦ Help button This is a CommandButton control that displays an image Clicking
the button displays the FormHelp UserForm
✦ Undo button Clicking this button reverses the effect of the most recent text
manipulation
✦ Stats button Clicking this CommandButton displays a message box that shows
key statistics for the text in the selected cells
Trang 28✦ Exit button Clicking this CommandButton unloads the UserForm.
✦ Apply button Clicking this CommandButton applies the text manipulation
options specified in the current page of the MultiPage control
You may notice that this utility violates one of my design “rules” outlined earlier inthis chapter (see “What Makes a Good Utility?”) Unlike most of Excel’s built-in dia-log boxes, the MainForm dialog box does not have an OK or Cancel button, and
clicking the Apply button does not dismiss the dialog box The original version of Text
Tools had an OK button and was designed so that clicking OK performed the taskand closed the dialog box User feedback, however, convinced me to change thedesign Many people, it turns out, like to perform several different manipulations atone time Therefore, I changed the utility to accommodate user preferences
The modMain module
The modMainmodule contains a simple procedure that kicks off the utility
Declarations
Following are the declarations at the top of the modMainmodule:
Public Const APPNAME As String = “Text Tools”
‘Custom data type for undoingType OrigData
OldText As VariantAddress As StringEnd Type
I declare a public constant containing a string that stores the name of the tion This string is used in the message boxes, and also is used as the caption forthe menu item that’s created (see “Create menu and delete menu procedures” later
applica-in this chapter)
I also create a custom data type named OrigData As you’ll see, this data type isused to store information so an operation can be undone
The StartTextTools procedure
The StartTextToolsprocedure follows:
Trang 29This function takes six arguments (each Boolean):
✦VisWin If True, the function determines whether at least one window is visible
✦Wksht If True, the function determines whether a worksheet is active
✦RngSel If True, the function determines whether a range is selected
✦MultSel If True, the function determines whether the selected range is a tiple selection
mul-✦Chart If True, the function determines whether a chart or Chart sheet isselected
✦Prot If True, the function determines whether the contents of the activesheet are protected
The values of these arguments determine what gets checked by the ValidContextfunction For example, if the first argument (VisWin) is True, the function checks tosee whether at least one window is visible If the second argument (Wksht) is True,the function checks to see whether a worksheet is active If any of these requestedchecks come up negative, the ValidContextfunction does two things: It displays amessage box that describes the problem (see Figure 16-3) and returns False to thecalling procedure
Figure 16-3: The ValidContext function
displays this message if the worksheet
is protected
The Text Tools utility requests the following checks from the ValidContextfunction:
✦VisWin At least one window must be visible
✦Wksht A worksheet must be active
✦Prot The sheet may not be protected
The Text Tools utility doesn’t require a range selection; it uses the RangeSelectionproperty to determine the selected range in the UserForm_Initialize procedurefor FormMain It also works well with a multiple range selection
I wrote the ValidContextfunction to be a “general-purpose” function that can beused in other applications In other words, there is nothing in the function that
Note
Trang 30makes it specific to the Text Tools utility All of the utilities in my Power Utility Pakuse this function.
The ValidContextfunction is shown in Listing 16-1
Listing 16-1: Certifying that the utility can run in the current
context of the worksheet
Function ValidContext(VisWin, Wksht, RngSel, MultSel, _Chart, Prot) As Boolean
Dim VisWinCnt As IntegerDim Win As Window
Const MsgVisWin As String = _
“A workbook must be active in order to use this utility.”
Const MsgWksht As String = _
“A worksheet must be active in order to use this utility.”
Const MsgRngSel As String = _
“This utility requires a range selection.” & vbCrLf & _
“Select a range and try again.”
Const MsgMultSel As String = _
“This utility does not allow a multiple range selection.” _
& vbCrLf & “Select a single range and try again.”
Const MsgChart As String = _
“Select a chart or Chart sheet before using this utility.”
Const MsgProt As String = _
“This utility does not work when the sheet is protected.” _
& vbCrLf & “Unprotect the worksheet and try again.”
ValidContext = True
‘ Check for a visible window?
If VisWin ThenVisWinCnt = 0For Each Win In Application.Windows
If Win.Visible Then VisWinCnt = VisWinCnt + 1Next
If VisWinCnt = 0 ThenMsgBox MsgVisWin, vbCritical, APPNAMEValidContext = False
Exit FunctionEnd If
Continued
Trang 31Listing 16-1 (continued)
Exit FunctionEnd If
Exit FunctionEnd If
End IfEnd IfEnd If
‘ Check for a chart selection?
If Chart Then
If ActiveChart Is Nothing ThenMsgBox MsgChart, vbCritical, APPNAMEValidContext = False
Exit FunctionEnd If
End If
‘ Check for protected sheet?
If Prot Then
If ActiveSheet.ProtectContents ThenMsgBox MsgProt, vbCritical, APPNAMEValidContext = False
Exit FunctionEnd If
End IfEnd Function
The ApplyButton_Click procedure
All work done by the Text Tools utility is performed by VBA code contained in thecode module for the FormMainobject The ApplyButton_Clickprocedure inListing 16-2 is executed when the user clicks the Apply button
Trang 32Listing 16-2: Applying the chosen changes without dismissal
of the dialog box
Private Sub ApplyButton_Click()
‘ Perform the selected operationDim i As Integer
Dim WorkRange As Range
‘ Validate Range reference
If Not ValidReference(RefEdit1.Text) ThenMsgBox “Invalid range.”, vbInformation, APPNAMEApplication.ScreenUpdating = True
With RefEdit1.SelStart = 0.SelLength = 100.SetFocus
End WithExit SubEnd If
‘ Figure out what to doApplication.ScreenUpdating = FalseSelect Case MultiPage1.ValueCase 0: Call ChangeCaseTabCase 1: Call AddTextTabCase 2: Call RemoveTextTabCase 3: Call RemoveSpacesTabEnd Select
Application.ScreenUpdating = TrueEnd Sub
The ApplyButton_Clickprocedure is relatively simple First, it calls a customfunction (ValidReference) to determine whether the RefEdit control contains avalid range address If not, it displays a message, selects the text in the RefEdit control, and makes a quick exit
The ValidReferencefunction follows This function returns True if its single ment contains a valid range reference It relies on the fact that VBA generates anerror when you try to create an invalid Rangeobject
argu-Function ValidReference(ref As String) As Boolean
‘ Returns True if ref is a valid range referenceDim x As Range
On Error Resume NextSet x = Range(ref)
If Err = 0 Then ValidReference = True _Else ValidReference = False
End Function
Trang 33The reason that the ApplyButton_Clickprocedure is so short is because it callsother procedures, depending on the value of the MultiPage control And, the value
of the MultiPage control determines which task the user is requesting (Remember,the first page of a MultiPage control has a value of 0, not 1.) These “task” proce-dures are described and listed in the following section
Notice that the ApplyButton_Clickprocedure does not unload the UserForm.Therefore, the user can perform other text manipulations Clicking the Exit button
is the only way to unload the UserForm The Click event-handler for this button follows:
Private Sub ExitButton_Click()Unload Me
End Sub
The “task” procedures
In this section, I describe the four procedures that actually perform the work forthe Text Tools utility
Changing the case of text
The first page of the MultiPage control (see Figure 16-4) enables the user to changethe case of text in the selected cells The text can be converted to UPPERCASE, lowercase, or Proper Case
Figure 16-4: This page enables the user
to change the case of text
The ApplyButton_Clickprocedure calls the ChangeCaseTabprocedure if theMultiPage’s Valueproperty is 0 (that is, the first page is active) Listing 16-3 shows the complete ChangeCaseTabprocedure
Trang 34Listing 16-3: Altering the case of text in cells
Sub ChangeCaseTab()Dim WorkRange As RangeDim Cell As RangeDim CellCount As LongSet WorkRange = CreateWorkRange(Range(RefEdit1.Text), _True)
If WorkRange Is Nothing Then Exit SubCellCount = 0
‘ Change the case
Select Case TrueCase ChangeCaseProperCell.Value = Application.Proper(Cell.Value)Case ChangeCaseUpper
Cell.Value = UCase(Cell.Value)Case ChangeCaseLower
Cell.Value = LCase(Cell.Value)End Select
Next Cell
‘ Update the Undo buttonUndoButton.Enabled = TrueUndoButton.Caption = “Undo Case Change”
Trang 35r A Rangeobject In this case, it’s the range selected by the user
and displayed in the RefEdit control
TextOnly If True, the created object excludes nontext cells
The CreateWorkRangefunction in Listing 16-4 is a general-purpose function that isnot specific to the Text Tools utility
Listing 16-4: The CreateWorkRange function
Function CreateWorkRange(r As Range, TextOnly As Boolean) AsRange
‘ Creates a range object that consists of nonempty and
‘ nonformula cells If TextOnly is True, the object
‘ excludes numeric cellsSet CreateWorkRange = NothingSelect Case r.Count
Case 1 ‘ one cell is selected
If r.HasFormula Then Exit Function
If TextOnly Then
If IsNumeric(r.Value) ThenExit Function
ElseSet CreateWorkRange = rEnd If
Else
If Not IsEmpty(r) Then Set CreateWorkRange = rEnd If
Case Else ‘More than one cell is selected
On Error Resume Next
If TextOnly ThenSet CreateWorkRange = _r.SpecialCells(xlConstants, xlTextValues)
If Err <> 0 Then Exit FunctionElse
Set CreateWorkRange = _r.SpecialCells(xlConstants, xlTextValues +xlNumbers)
If Err <> 0 Then Exit FunctionEnd If
End SelectEnd Function
The CreateWorkRange function makes heavy use of the SpecialCells property
To learn more about the SpecialCells property, try recording a macro while ing various selections in Excel’s Go To Special dialog box You can display this dialogbox by pressing F5 and then clicking the Special button in the Go To dialog box
mak-Note
Trang 36You’ll notice a quirk when you use the Go To Special dialog box Normally it ates on the current range selection For example, if an entire column is selected,then the result is a subset of that column But if a single cell is selected, it operates
oper-on the entire worksheet Because of this, the CreateWorkRangefunction checksthe number of cells in the range passed to it
Once the WorkRangeobject is created, the ChangeCaseTabprocedure continues toprocess each cell in the WorkRange Before the procedure ends, it enables the Undobutton and adds a descriptive caption
Later in this chapter, I discuss how the Undo feature works
Adding text
The second page of the MultiPage control (see Figure 16-5) enables the user to addcharacters to the contents of the selected cells The text can be added at the begin-ning, at the end, or after a specified character position
Figure 16-5: This page enables the user
to add text to the contents of the selected cells
The ApplyButton_Clickprocedure calls the AddTextTabprocedure if theMultiPage’s Valueis 1 (that is, the second page is active) Listing 16-5 presentsthe complete AddTextTabprocedure
Listing 16-5: Inserting properly filtered text into cells by way
of the dialog box
Sub AddTextTab()Dim WorkRange As RangeDim Cell As RangeDim NewText As String
Continued
Cross-Reference
Trang 37Listing 16-5 (continued)
Dim InsPos As IntegerDim CellCount As LongSet WorkRange = _CreateWorkRange(Range(RefEdit1.Text), cbIgnoreNonText1)
If WorkRange Is Nothing Then Exit SubNewText = TextToAdd.Text
If NewText = “” Then Exit Sub
‘ Check for potential invalid formulas
If OptionAddToLeft And Left(NewText, 1) Like “[=+-]” ThenMsgBox “That text would create an invalid formula.”, _vbInformation, APPNAME
With TextToAdd.SelStart = 0.SelLength = Len(.Text).SetFocus
End WithExit SubEnd If
‘ Add text to the middle?
If OptionAddToMiddle ThenInsPos = Val(InsertPos.Caption)
If InsPos = 0 Then Exit SubEnd If
‘ Loop through the cellsCellCount = 0
ReDim LocalUndo(CellCount)For Each Cell In WorkRangeWith Cell
‘ Store info for undoing
CellCount = CellCount + 1ReDim Preserve LocalUndo(CellCount)With LocalUndo(CellCount)
.OldText = Cell.Value.Address = Cell.AddressEnd With
If OptionAddToLeft Then Value = NewText & Value
If OptionAddToRight Then Value = Value & NewText
If OptionAddToMiddle Then
If InsPos > Len(.Value) Then.Value = Value & NewTextElse
.Value = Left(.Value, InsPos) & NewText & _Right(.Value, Len(.Value) - InsPos)End If
Trang 38End IfEnd WithNext Cell
‘ Update the Undo buttonUndoButton.Enabled = TrueUndoButton.Caption = “Undo Add Text”
End Sub
This procedure is similar in structure to ChangeCaseTab Notice that this dure catches an error that would occur if the user tried to insert a plus, minus, orequals sign as the first character of a cell Such an insertion would cause Excel tointerpret the cell contents as an invalid formula
proce-Removing text
The third page of the MultiPage control (see Figure 16-6) enables the user toremove text from the selected cells A specific number of characters can beremoved from the beginning or end, or starting at a specified character position
Figure 16-6: This page enables the user
to remove characters from the selected text
The ApplyButton_Clickprocedure calls the RemoveTextTabprocedure if theMultiPage’s Valueproperty is 2 (that is, the third page is active) Listing 16-6 presents the complete RemoveTextTabprocedure
Listing 16-6: Removing text from cells by way of the dialog box
Sub RemoveTextTab()Dim WorkRange As RangeDim Cell As Range
Continued
Trang 39Listing 16-6 (continued)
Dim NumToDel As IntegerDim CellCount As LongSet WorkRange = _CreateWorkRange(Range(RefEdit1.Text), cbIgnoreNonText2)
If WorkRange Is Nothing Then Exit SubNumToDel = Val(CharstoDelete.Caption)
If NumToDel = 0 Then Exit Sub
‘ Process the cellsReDim LocalUndo(0)CellCount = 0For Each Cell In WorkRangeWith Cell
‘ Store info for undoing
CellCount = CellCount + 1ReDim Preserve LocalUndo(CellCount)LocalUndo(CellCount).OldText = ValueLocalUndo(CellCount).Address = Address
If Len(Cell.Value) <= NumToDel Then _NumToDel = Len(.Value)
Select Case TrueCase OptionDeleteFromLeft.Value = Right(.Value, Len(.Value) - NumToDel)Case OptionDeleteFromRight
.Value = Left(.Value, Len(.Value) - NumToDel)Case OptionDeleteFromMiddle
.Value = RemoveChars(.Value, _CInt(BeginChar.Caption), NumToDel)End Select
End WithNext Cell
‘ Update the Undo buttonUndoButton.Enabled = TrueUndoButton.Caption = “Undo Remove Text”
End Sub
The RemoveTextTabprocedure is, again, similar in structure to the other dures called by ApplyButton_Click If the characters are to be removed from themiddle of the text, it calls a Function procedure, RemoveChars, to do the work
proce-The RemoveCharsfunction procedure follows This procedure removes a specifiednumber of characters (n), beginning at a specified character position (b) from astring (t)
Trang 40Private Function RemoveChars(t, b, n) As StringDim k As Integer
Dim Temp As StringTemp = “”
For k = 1 To Len(t)
If k < b Or k >= b + n ThenTemp = Temp & Mid(t, k, 1)End If
Next kRemoveChars = TempEnd Function
Removing spaces
The fourth page of the MultiPage control (see Figure 16-7) enables the user toremove spaces from the selected cells
Figure 16-7: This page enables the user
to remove spaces from the selected text
The ApplyButton_Clickprocedure calls the RemoveSpacesTabprocedure if theMultiPage’s value is 3 (that is, the fourth page is active) Listing 16-7 shows thecomplete RemoveSpacesTabprocedure
Listing 16-7: Filtering unnecessary spaces from textual cells
Sub RemoveSpacesTab()Dim WorkRange As RangeDim Cell As RangeDim CellCount As LongSet WorkRange = CreateWorkRange _(Range(RefEdit1.Text), True)
If WorkRange Is Nothing Then Exit Sub
Continued