Introduction to Excel VBA - Portal
Transcription
Introduction to Excel VBA - Portal
Centre for Staff & Educational Development (CSED) Discover your potential Excel Introduction to VBA Introduction to Excel VBA Version 1.01 Dave Knock (CSED) September 2013 This document is produced by the Centre for Staff and Educational Development at UEA. It provides instruction in more advanced techniques using Excel (part of the Microsoft Office suite of programs) for those who have some experience of Excel. ---------- University of East Anglia 1999 to 2013---------This material may not be used in part or whole for financial gain without prior permission. It may otherwise be freely copied provided that due acknowledgement is given to the Centre for Staff and Educational Development, UEA Norwich, and that the wording of this statement of copyright is reproduced. Introduction to Excel VBA CONTENTS 1. Introduction Using These Notes ...................................................................................1 Course Files .............................................................................................1 Conventions and Symbols .......................................................................1 Practical Work .........................................................................................2 Ribbons ....................................................................................................2 Disclaimer ...............................................................................................2 2. Visual Basic basics Objects .................................................................................................... 3 The Editor ............................................................................................... 3 Setting up the Editor ............................................................................... 4 The Immediate Window ......................................................................... 5 The Range Object ................................................................................... 5 The cells Object ...................................................................................... 7 Active ..................................................................................................... 8 3. VBA sub-routine/macro Record a Macro .......................................................................................9 R1C1 ......................................................................................................10 Methods .................................................................................................12 Code Windows ......................................................................................13 4. Variables and Loops Why Use Variables ? .............................................................................15 Types of Variable ..................................................................................15 Declaring Variables ...............................................................................16 Loops .....................................................................................................16 Loops within Loops ...............................................................................18 For…Each…In ......................................................................................19 Do…While Loop ...................................................................................20 Selection ................................................................................................21 Centre for Staff and Educational Development UEA 5. Branching and Interaction If…Then ................................................................................................23 GoTo .....................................................................................................25 Message Boxes ......................................................................................26 Exiting From Loops ..............................................................................30 Input Box...............................................................................................32 Calling one Procedure from Another ....................................................33 6. Controls and Events Buttons ..................................................................................................35 Shortcut Keys ........................................................................................36 Objects as Controls ...............................................................................37 Events ....................................................................................................38 Workbook Events ..................................................................................38 With…End With ...................................................................................39 Worksheet Events .................................................................................41 7. Useful Objects, Properties, Methods and Constants Range Objects .......................................................................................44 Properties of Range Objects ..................................................................44 Excel ColorIndex Constants..................................................................46 VBA Color Constants ...........................................................................46 Methods of Range Objects ....................................................................46 Centre for Staff and Educational Development UEA Introduction to Excel VBA 1 - Introduction Using these notes This document provides self-paced tuition in the use of VBA in Excel for Windows, previous significant experience of using Excel spreadsheets is assumed and a basic understanding of Microsoft Windows is required. Setting up course files The exercises in this course use blank files which should be created by the reader using Excel. The best way of working with the course files is to save them to an easily identified directory on your computer’s hard disk or your central file store but a memory stick or other removable drive is sometimes a useful alternative. Excel files containing macros or VBA code must be saved either in the older xls format or the new xlsm format. The default xlsx format will remove all macros and code for security, and cannot be used to save these files. When first saving a macro enabled file, change the file type to xlsm or xls using the Save As dialogue, subsequent saves of the same file will automatically use the correct type. Conventions and symbols used in this tutorial A major change in Office 2010 is the introduction of the File tab. This tab appears at the topleft of any Office window and it is used in place of the File menu or Office Orb that appeared in previous versions. This tab opens a menu screen known as the Backstage menu where you will find the now familiar commands, such as Open, Save, Save As, New, Print and Close. In this document keyboard instructions are given in the following way: Press: Ctrl & b or Ctrl + b means hold down the [Ctrl] key then press the b key once Press: Spacebar, means press the [Spacebar] then press the [] (enter) key Type: “The cat sat” means type the text within the quotes but not the quotes Commonly used keys are indicated as follows: , Enter or Return The Enter or Return key Ctrl Either Ctrl key (bottom left or right of the alphabetic keyboard) Alt The Alt key (just left of the spacebar) Fn The function key numbered n, e.g. [F5] (across the top of the keyboard) The left, right, up, down cursor keys Centre for Staff and Educational Development UEA 1 1. Introduction Practical work At various points in the course you are expected to do practical work in Excel and these places are indicated by boxed and shaded text like this. Numbered instructions should be followed in sequence and care should be exercised not to miss any lines of instruction. Ribbons In Office 2010, Ribbons provide access to the various features available. The Ribbon is a band that runs across the top of the window and it contains commands that are divided into sets of commonly used features. Ribbons are selected by clicking on a tab. For example, the main set of frequently used commands is displayed on the Ribbon selected by the Home tab. When isolated reference is made to controls on Ribbons the Ribbon name will be given followed by the Group and then the Control name e.g. Home, Font, Bold References to controls made in the text of an exercise or example will give information according to the context, so if the font is being modified the ribbon and group would be assumed and reference will just be made to Bold, Italic or Underline. Disclaimer The information in this document and the accompanying course is provided in good faith and has been tested thoroughly in Excel 2010 on Windows 7. Due to the nature of VBA it is possible that some of the procedures will not work with other combinations of operating system and Office version and may yield unexpected results. VBA is a powerful programming language and can cause serious loss of data and/or functionality if misused, the reader is advised to make sure that suitable backups of important work have been made and that care is taken to follow instructions accurately. Neither CSED or the author can be held responsible for losses caused by not following this advice. 2 Centre for Staff and Educational Development UEA Introduction to Excel VBA 2 – Visual Basic basics Objects When working in VBA we refer to the various parts of Excel as objects. These objects have a hierarchy which works very much like the folders in your e-mail inbox or on your computer whereby one object ‘contains’ others which in turn may contain more. A group of objects at one level of the hierarchy is referred to as a Collection. For the purposes of this course we will concern ourselves only with the Worksheet and Range objects which have the fairly obvious hierarchy of a Worksheet containing Ranges of Cells. We will use two different styles of addressing the individual cells in the worksheet using both Range and Cells to explore the differences between them and some of the advantages of each over the other. To identify the objects in their hierarchy we use a separator, usually the full stop or period character, between levels, and brackets to contain the names of the objects, usually defined with double quotes. A typical reference to a cell, in this case G14 on Sheet1 might look like this: Worksheets("Sheet1").Range("G14") The Worksheets collection The separator The name of the worksheet The name of the Range The Range collection There are many ways to refer to objects but they all use a very similar structure. There are also several options to refer to objects directly, relative to the current object, or as the active object. This allows us to restrict the effect of any code we write to an individual object or a collection of objects. The Editor The VBA editor is embedded in Excel, you may have already seen, or even used it when recording and editing macros. Centre for Staff and Educational Development UEA 3 2. Visual Basic basics Your editor may look slightly different to the one shown here but there are several main components which will be present and which we will be using throughout this course. The editor is available from the Developer ribbon which is an optional ribbon. If the Developer ribbon is not displayed on your Excel profile use the following procedure to turn it on. 1. Click on the File tab 2. Click on Options 3. Click on Customize Ribbon 4. Tick the box next to Developer in the right hand pane 5. Click on OK With the Developer ribbon selected you can open the VBA editor by clicking on the Visual Basic control, alternatively you can use the keyboard shortcut which is [ALT]+F11. Setting up the Editor To ensure that the editor has all the features you need to complete the exercises in this course we will spend a few moments setting it up. It may already look like the example above in which case you could skip this section but it is useful to know how to turn features on and off anyway. The VBA editor does not use the ribbon navigation seen in the rest of Excel; instead it uses the older menu and toolbar system. The controls we need to set it up are mostly in the View menu. 1. Open the editor 2. Select View – Code (or press F7) 3. Select View – Immediate Window 4 (or press [CTRL]+G) Centre for Staff and Educational Development UEA Introduction to Excel VBA 4. Select View – Project Explorer (or press [CTRL]+R) 5. Make sure that View – Toolbars – Standard is selected 6. Close any other windows within the editor using the close button on each individual title bar. The editor is now ready for us to start exploring some of the features of Excel VBA The Immediate Window Using the immediate window allows us to test some simple lines of code individually. This can be a very efficient way of testing ideas or checking individual instructions. 1. In the Immediate Window type this line of text Worksheets("Sheet1").Range("A1") = 100 2. Press Enter or Return at the end of the typing Assuming all went well you will see the value 100 in Cell A1. This process is known as assigning a value and uses the = symbol to say “this object equals this value”. Note that there is no Undo feature when you assign values using VBA, this is one reason why care needs to be exercised and important data should be backed up carefully before running any code. The Range Object 1. Make sure that Sheet1 is selected in Excel 2. In the Immediate Window type this line of text below what you already typed Range("A1:B4") = "Hello" 3. Press Enter or Return at the end of the typing 4. Observe the result on Sheet1 then select Sheet2 in Excel 5. Click anywhere in the line you just typed in the Immediate Window 6. Press Enter or Return The text now appears in Sheet2 Because we didn’t specify a sheet, VBA uses the active sheet. Centre for Staff and Educational Development UEA 5 2. Visual Basic basics Notice how we can type numbers directly into code, but literal text (that is text used as a value rather than an instruction) has to be enclosed in quotes. 1. Still with Sheet2 selected in Excel 2. On the next line in the Immediate Window type: ? Range("A2") 3. Observe the result in the Immediate Window The question mark instructs the editor to display the result of the following code, in this case the word Hello which we previously entered. We can use this effect to check the value of expressions in our code without having to assign them to anything. So far we have been using the value of the cell or cells in our code, either assigning a value or reading the value. Cells have many other properties which we can use as well, but for the purposes of an introductory course we will only use a few of these. The property that you want to use is specified after the object, separated by another full stop, so the full syntax (grammatical structure) of the command: Range("A2")=100 Is Range("A2").Value = 100 You may like to include the Value property in your code just to remind you what you are using but it is common practice to leave it out and let VBA use its default setting. 4. Try the line Range("A2").Value = 100 in the Immediate Window 5. Change the line to: Range("A2").Font.Size = 100 6. Press Enter or Return This is another property of the range, the size of font used. Notice that the font itself has properties, in this case the size, and full stops are used throughout to separate the different levels of the hierarchy. 7. Try: Range("A2").Font.Color = 100 Note the American spelling The Color Property of the Font sets the colour to 100 or dark red. Whilst you can set colours this way, often the decimal number is difficult to remember and not very easy to interpret, for example UEA blue is 8345856. We generally prefer to set these values as three numbers 6 Centre for Staff and Educational Development UEA Introduction to Excel VBA representing the Red, Green and Blue proportions, each with values between 0 and 255. These are referred to as the RGB values and UEA blue becomes 0,89,127, a little bit easier to remember, but not much! 8. Using the Immediate Window, set the colour of the font in A2 to UEA blue using this line of code: Range("A2").Font.Color = RGB(0,89,127) You can experiment with different values of red, green and blue, remembering to only use values between 0 and 255. There are over 16 million possible combinations so subtle changes may not be very easy to see. 9. Use ? Range("A2").Font.Color to see the single decimal value created by the three RGB values The Cells Object The Range object is a very easy way to address cells in a worksheet but there is an alternative method which has some advantages. The Cells object allows us to address cells using just numbers in what we refer to as R1C1 format. The first number represents the row and the second represents the column. In the Immediate Window type: Cells(1,4)= "This is Cell D1" This line of code instructs Excel to place the text in the first row and fourth column, cell D1 in our usual format. Using numbers for both parts of the reference can be very useful, particularly when we start to program loops and sequences which write to, or read from, many cells, as we can manipulate numbers much more easily than letters. A range of more than one cell can be addressed using the Cells object to provide the addresses to a Range object. In the Immediate Window type: Range(Cells(1,4),Cells(4,6))=100 In this example we have used two Cells statements to define a range from D1 to F4. Note the comma to separate the two Cells statements; Range has three possible syntaxes which can be used to achieve different outcomes. Range("A1:B4") refers to A1:B4 as we have already seen. Range("A1,B4") refers to A1 and B4 as two ranges – just as A1,B4 behaves in a formula. Range("A1","B4") refers to A1:B4 – this is the syntax used in the example above using two Cells statements to define the range. Centre for Staff and Educational Development UEA 7 2. Visual Basic basics Active Certain components of Excel are considered to be active at any one time, for example there is an active sheet which contains the active cell. In VBA we often find it useful to refer to the active object in a collection as this is where the operator is expecting something to happen or where they are entering data to be processed. 1. In the immediate window type the following line and press enter ? activecell.address The absolute address of the currently active cell is returned 2. Type the following line in the immediate window and press enter ? activesheet.name The name of the active sheet is returned 3. Experiment with these commands by changing the active cell and sheet. We now understand the principle involved in setting and reading properties in Excel using VBA. We have used the Immediate Window to enter and run single lines of code and we have identified part of the hierarchical structure of objects which make up Excel. In the next chapter we will start to use the Code Window to generate repeatable sequences of VBA code, unlocking more of the capabilities of this powerful and versatile language. 8 Centre for Staff and Educational Development UEA Introduction to Excel VBA 3 – VBA sub-routine One of the easiest ways to start understanding the structure of VBA in Excel is to record something using the macro recorder and then to examine the code. 1. Close the current workbook – you don’t need to save it 2. Open a new workbook 3. Select A1 on Sheet1 We will record a short, simple macro which will place some text in one cell, a number in another and then concatenate the two in a third cell. This is not a useful macro but it will serve to illustrate the structure we need to use when writing our own code. 4. Start the Macro Recorder from the Developer ribbon 5. Leave the name and all the other settings in the dialogue box as they are 6. Click on OK 7. In cell B3 enter Text 8. In cell B4 enter 123 9. In cell B5 enter =B3&B4 10. Select Cell B6 11. Stop the Macro Recorder using the button on the status bar This sequence has now been recorded as a macro in VBA and we can examine and edit it using the VBA editor. 1. Clear the contents of cells B3:B5 2. Run the macro using the Macros control on the Developer ribbon 3. Observe that the contents of the cells are written exactly as if you’d typed them again Macros in Excel are recorded in a special folder shown in the VBA editor as a Module. 4. Open the VBA editor 5. Click on the expander for the Modules folder in the left pane 6. Double Click on the Module displayed (probably called Module 1) The code which you recorded is now displayed in the Code Window Centre for Staff and Educational Development UEA 9 3. The sub-routine The following table describes the code in some detail. Sub Macro1() This line defines the start of a subroutine, a sequence of code. ' All the lines starting with an apostrophe are comments to help you understand the code. ' Macro1 Macro ' Blank lines are also used to make code more readable. ' Range("B3").Select ActiveCell.FormulaR1C1 = "Text" Range("B4").Select Select B3 then insert the characters “text” using the formula =”text” Select B4 then insert the characters “123” using the formula =”123” ActiveCell.FormulaR1C1 = "123" Range("B5").Select Select B5 then insert the formula ActiveCell.FormulaR1C1 = "=R[-2]C&R[-1]C" = B3&B4 (using the R1C1 notation) Range("B6").Select Select B6 (by pressing Enter in B5) End Sub This line marks the end of the subroutine The use of the formula property rather than simply setting the value of the cell is interesting as it means that any value; number, text or formula, can be entered using the same basic structure in VBA. Selecting the cell and then entering the formula in the active cell is analogous to the actual keystrokes and mouse clicks we used, although it may not be the most efficient code it does make sense for the recorder to use a standard system. R1C1 The formula using R1C1 notation may look a little confusing but it is recorded this way in VBA mainly because numbers are easier to manipulate than letters. R[-2] means the row two above this one, C (no square brackets or number) means this column, R[-1] means the row above this one so the whole formula reads as; concatenate the cell two above this one and the cell above this one, exactly the same as =B3&B4. After the line containing the words End Sub type the following lines of code Sub Macro2() Range("B3") = "text" Range("B4") = 123 Range("B5") = "=B3&B4" Range("B6").Select End Sub 10 Centre for Staff and Educational Development UEA Introduction to Excel VBA This simple routine does exactly the same job as the recorded macro, you can even see it in the macro dialogue box and run it like a recorded macro, but it uses the simpler, more direct, commands we used in the Immediate Window earlier. This is an example of a simple sequence of code, it runs from top to bottom and carries out the instructions on each line before moving on to the next. We have so far just set cell properties to constant or typed values but we have seen that we can read values using the question mark in the Immediate Window, and we can also set a property to the value from another cell or cells using simple VBA code in the Code Window. Add these lines of code to the Code Window below the End Sub line of macro2 Sub Macro3() Range("C3") = Range("B3") Range("C4") = Range("B4") Range("C5") = Range("B5") Range("C6").Select End Sub This macro does what we have told it to; it copies the values of the three cells in column B to the equivalent cells in column C. In C5 it places the value of B5 which is the result of the formula, this may be what we wanted but if it isn’t then we need to use a different property. Replace the line Range("C5") = Range("B5") With Range("C5") = Range ("B5").formula We are now taking the formula property of the cell B5 and placing that into C5 This has worked but look carefully at the formula in C5; it is exactly the same as that in B5, relative references have been used but they have not behaved as we might expect and the copy still refers to the original cells B3 and B4. To find the alternative code, record a macro to copy B5 and paste it into C5, remembering to cancel the copy mode (press [Esc] after the paste). The code should look something like this: Range("B5").Select Selection.Copy Range("C5").Select ActiveSheet.Paste Application.CutCopyMode = False Centre for Staff and Educational Development UEA 11 3. The sub-routine Methods The actions in the code above are fairly obvious and we can learn from them how to make our latest macro copy the formula using Excel’s relative referencing. Range("B5").Select will select the cell referenced in that range. This is not actually a property but a method; methods are things you can do to an object, effectively they are instructions. Selection.Copy invokes the copy method of the selection object. We could replace these two lines with one and use Range("B5").Copy if we want to keep our code as small and tidy as possible. Range("C5").Select selects C5 ActiveSheet.Paste uses another object, the active sheet, in this case simply as a container for the Paste method. Finally Application.CutCopyMode = False is the instruction to turn off the copy mode and introduces a new Object and a new type of data. The Application object is Excel itself and setting the CutCopyMode property is a Boolean or binary property which can only be true or false. If the property is true then there is an active selection on the clipboard, if it is false then the selection is cancelled. Change Macro3 so the code looks like this (you can use copy and paste between macros) Sub Macro3() Range("C3") = Range("B3") Range("C4") = Range("B4") Range("B5").Copy Range("C5").Select ActiveSheet.Paste Application.CutCopyMode = False Range("C6").Select End Sub Try the macro again and observe that the formula in C5 is now correct This technique has resulted in working code but it is a little clumsy, try the code shown below which uses just the copy and paste technique. Often when developing code you will want to refine what you have written, even if it works, when you identify new techniques. Sub Macro5() Range("B3:B5").Copy Range("C3").Select ActiveSheet.Paste Application.CutCopyMode = False Range("C6").Select End Sub 12 Centre for Staff and Educational Development UEA Introduction to Excel VBA This code can be reduced even further if we use the destination range as an argument to the Copy method. This also speeds up the code because we no longer need to actually select the destination. Try this version: Sub Macro6() Range("B3:B5").Copy Range("C3") Range("C6").Select End Sub If we need to use the earlier structure of setting values with the equals sign we can still produce the relative reference effect by using the same type of code as Excel did when we recorded our first macro earlier in this chapter. The R1C1 notation, using offset numbers in square brackets, produces properly structured relative references, based on the location of the formula. Range("C5").FormulaR1C1 = Range("B5").FormulaR1C1 This code will copy the formula from B5 as an R1C1 formula into C5 where it will be interpreted as =C3&C4, exactly what we needed. Code Windows We have been using the Code Window attached to the Module where the original macro was recorded, but if you look in the Project Window on the left of the editor you will see each sheet and the workbook listed. All of these objects have their own code window which you can open by double clicking on the object in the Project Window. It doesn’t matter which code window is open when you use the Immediate Window but it will affect the scope of any code in the Code Window. 1. Make sure Sheet1 is the active sheet in Excel 2. In the VBA Editor 3. Double click on Sheet3 in the Project Window 4. Enter this subroutine: Sub test() Range("a1") = 10 End Sub 5. In the Macro dialogue box this new subroutine is identified with the sheet name as well as the macro name 6. Run the new macro and observe that the effect is limited to Sheet3 even though the sheet object is not specified and Sheet1 is active If we had placed the code above in to the ThisWorkbook code window the scope would have been the whole workbook, so A1 in the active sheet would be set to 10 in the same way as using a module’s code window. Centre for Staff and Educational Development UEA 13 3. The sub-routine In this chapter we have explored the structure of a VBA sub-routine, seen how macros and VBA are very closely related to each other and delved further into the Object model and the VBA Editor. We have seen how objects have both properties and methods and we have seen how using the macro recorder can give us a head start when we write code, although it often produces code which is more complex than we need. 14 Centre for Staff and Educational Development UEA Introduction to Excel VBA 4 – Variables and Loops Why use variables? Variables are used in programming to hold a value which is used during the routine. This may be a counter, or an interim value, or simply a convenient way of labelling a value which is going to be used several times such as a colour. Variables can be given names which indicate their function and, as there are several types of variable, the name is often used to indicate the type of data as well. A typical variable name might be something like; intLoopCounter. Notice the lack of spaces, the use of capital letters to separate the words which identify the function of the variable (to count the iterations through a programme loop), and the ‘int’ prefix which indicates that the variable is an integer or whole number. We don’t have to follow this, or any other, convention in naming, but it does help when we need to revisit code later or when someone else needs to change or update our code. Variables could be called X, Y and Z or var1, var2, var3, etc. but this would not make it easy to work out the function of the routine or to identify issues which may arise. Types of variable The variables we will be using will be numbers or text but a whole range of possible types are available to us, including several different numeric types although just two of these will suffice for all normal purposes. This table shows some of the types commonly encountered and describes each. Type Prefix Description String str Text, up to a maximum of about 63,000 characters Date dte A date or time which Excel will interpret as a formatted date/time Integer int A whole number from -32,768 to +32,767 Long lng A whole number from -2,147,483,648 to 2,147,483,647 Single sng 7 digit accuracy decimal numbers (roughly ±3.4*1038) Double dbl 15 digit accuracy decimal numbers (roughly ±1.8*10308) We use the expression 3.4*1038 to represent the number: 340,000,000,000,000,000,000,000,000,000,000,000,000 as the full version is both tedious to type and difficult to read. It means 3.4 multiplied by 10 to the power of 38 or; ten times ten times ten… 38 times. Excel normally works with 15 digit accuracy so the types of variable we will use most will be; Integer for things like counters (Long if we are counting very big numbers such as rows in a worksheet), Double for numbers containing fractions (as this is the default accuracy for Excel anyway) and String for text values. Occasionally we might need dates or one of the other types not listed here but these three types will suffice for our initial efforts. We can also declare a variable to hold an Excel object such as a range or a worksheet which we will do later in this chapter. Centre for Staff and Educational Development UEA 15 4. Variables and Loops Declaring variables Before we use a variable we should (or in some cases, we must) declare it by name and type using a Dim (short for dimensioning) statement. This is done at the very beginning of the code just after the Sub statement where the name of the routine is declared. 1. Clear the contents of the Worksheets or open a new Workbook 2. Open the VBA editor 3. In the Sheet1 Code Window type: Sub FirstVariable() Dim strWelcome As String strWelcome = "Hello everybody!" Range("A1") = strWelcome Range("A2") = strWelcome End Sub 4. Run this code using the Macro dialogue The text we assigned to the variable appears in the two cells to which we then assigned the variable. We could use the same variable as many times as we want once it has been declared, either keeping the initial value or assigning new values whenever we need them. 5. Change the code so it reads: Sub FirstVariable() Dim strWelcome As String strWelcome = "Hello everybody!" Range("A1") = strWelcome strWelcome = "Hello again everybody!" Range("A2") = strWelcome End Sub 6. Run this code using the Macro dialogue This time the variable is changed before the second cell value is assigned, this illustrates how a variable can be used to hold data temporarily in a programme although this trivial example would be easy to reproduce without using a variable. Loops One of the most common reasons to use code is to create a loop which performs the same operation many times. There are several types of loop available in VBA, we will concentrate here on some of the common ones starting with the For…Next loop. 16 Centre for Staff and Educational Development UEA Introduction to Excel VBA This type of loop uses a variable which is assigned an initial value, an end value and an incremental value in a line of code which looks like this: For intLoopCounter = 1 to 101 step 5 In this line of code the variable intLoopCounter which has already been declared starts with a value of 1, has a maximum value of 101 and is incremented by 5 in every iteration of the loop. The lines of code following this line will then be executed until a line which looks like this is reached: Next intLoopCounter Once this line is reached the variable is incremented and the code returns to the initial line to repeat the process, this will happen until the maximum value is reached at which point the code simply continues after the line containing the Next instruction. 7. In the Sheet1 Code Window 8. Type the sub routine Sub Looping() Dim intLoopCounter As Integer For intLoopCounter =1 to 101 step 5 Cells(intLoopCounter,1) = "Hello!" Next intLoopCounter End Sub 9. Run this from the Macro Dialogue The loop has set the value of every fifth cell from A1 to A101 to the value “Hello!” Note the use of Cells rather than Range in this instance as it makes the code easier to write. We can combine the various techniques we have used so far to write code which reads values from the worksheet and then uses those values in a loop. This code is more complex than we have used previously but it serves to show how several simple techniques can be combined. 1. On Sheet2 enter the following data 2. In the Sheet2 Code Window type the following subroutine Centre for Staff and Educational Development UEA 17 4. Variables and Loops Sub looping2() 'Declare variables Dim intLoopCounter As Integer Dim intLoopStep As Integer Dim intLoopEnd As Integer Dim strText As String 'Set variables intLoopStep = Range("B1") intLoopEnd = Range("B2") strText = Range("B3") 'Main loop For intLoopCounter = 1 To intLoopEnd Step intLoopStep Cells(intLoopCounter, 3) = strText & " row " & intLoopCounter Next End Sub Notice the use of comments prefixed with the apostrophe, empty lines between sections of code and the indented action within the For…Next loop. We have also chosen to omit the variable name in the Next line as there is no possible ambiguity here and VBA will accept this form of the statement. These are all techniques used to make code easier to read. Run this code and observe the effect, the values of the variables are set from the cells on the sheet, then used in the loop. In the case of intLoopCounter it is used twice; once as a value in the Cells statement, and once as a part of the concatenation with the value of strText taken from C3 and the literal text " row ". Delete the contents of column C and try different values in B1:B3 Loops Within Loops Just as functions in an Excel formula can be nested, loops in VBA can be nested. The same principle applies; one loop must be fully enclosed by the other so they don’t merely overlap each other. In the following example we will set the background colour of a range of cells using some simple code within a pair of nested loops. We will work on the range of cell A1:Y25 which is 25 columns wide by 25 rows deep. We will use two variables, both integers, to represent the row and column. These variables will be called intRow and intColumn. 18 Centre for Staff and Educational Development UEA Introduction to Excel VBA We will work with the Interior.Color property of the cells, notice the American spelling of colour as it was in the earlier example of Font.Color. This is the code we will enter, take a little time to look through it and see how it will work. The two loops are properly nested, it would make no difference if we used them the other way round and looped through the columns then the rows but this way seems more logical given the Cells statement using row followed by column. The red and green values are determined using the row and column variables multiplied by ten, this gives a good spread within the range of 0255 which is the range allowed in RGB. The blue value is set to zero but feel free to experiment with any value between 0 and 255 if you want to change it. Sub Colours() ‘Declare variables for row and column Dim intRow As Integer Dim intColumn As Integer ‘Two nested loops to select the row and column of each cell For intRow = 1 To 25 For intColumn = 1 To 25 ‘Set the interior colour of each cell to an RGB value determined by its position Cells(intRow, intColumn).Interior.Color = RGB(intRow * 10, intColumn * 10, 0) Next intColumn Next intRow End Sub 1. Enter the code above carefully in the code window for Sheet1 on a new workbook 2. Run the code from the Editor by clicking on the “play” button 3. Observe the effect on the worksheet Note: You could use the macro dialogue to run the code but the button in the editor is often a convenient alternative, for those who prefer it F5 is the keyboard shortcut for the play button. Running the code in this way will run whatever subroutine the cursor is in at the time so care must be taken if you have several macros in one window. For…Each…In A particularly useful variation on the For…Next loop is the For…Each…In loop which loops through all the items in a collection, Cells in a Range, Worksheets in a Workbook, etc. To use this type of loop we must first understand the structure we are working with, the object hierarchy described in chapter 1. The worksheets collection comprises all the worksheets in the workbook, this sometimes makes it confusing when we refer to the collection, as it appears to be the next object up in the hierarchy but in fact as the workbook can contain other objects such as chart sheets and the code window the collection concept makes good sense. Centre for Staff and Educational Development UEA 19 4. Variables and Loops This example shows a subroutine which places the names of all the worksheets in to the first row of Sheet2. 1. Using the workbook from above 2. In the Sheet2 code window enter these lines of code Sub ListSheets() Dim Item As Worksheet Dim intCol As Integer intCol = 1 For Each Item In Worksheets Cells(1, intCol) = Item.Name intCol = intCol + 1 Next Item End Sub 3. Run the sub-routine and observe the results The two variables are dimensioned first, one is an integer to hold the column number, the other is an object variable used to hold the properties of an object, in this case a worksheet. We can use any name here but Item is often used as it helps to make the code more understandable. We then assign a value of 1 to the column, for column A The loop will work through all the worksheets in the worksheets collection assigning the name of each one to a cell in row 1. Note the use of Item.Name, the name property of the worksheet represented by the Item variable. Then we add 1 to the value of the intCol variable and go round the loop again using the next column until we have worked through all the sheets in the collection. This type of loop is useful because it does not require us to know how many items there are in the collection, add a few more sheets and run the code again to see what happens. When referring to cells in a collection we use an object variable dimensioned as a range because a cell is a specific instance of a range. Do…While loop Another common structure for looping code is Do…While. As the name implies this type of loop will continue all the while a condition is met, this is more versatile than the For…Next loop as it uses a condition rather than a counter to determine when the loop ends. In this example we will use Do…While to add the numbers in column A until the total reaches 100. The total will be placed in column B alongside the last number included in the total 20 Centre for Staff and Educational Development UEA Introduction to Excel VBA 1. In the Sheet3 code window enter this code: Sub Reached100() Dim dblTotal As Double Dim intRow As Integer intRow = 1 dblTotal = 0 Do While dblTotal < 100 dblTotal = dblTotal + Cells(intRow, 1) intRow = intRow + 1 Loop Cells(intRow - 1, 2) = dblTotal End Sub 2. Type a few numbers in column A of Sheet3 making sure that they add up to over 100 to test this code 3. Observe the results when the numbers add up to 100 or more and when they add up to less than 100 and when there is a gap in the sequence. In this code loop the variable dblTotal is used as a running total and intRow is used to hold the row number being processed. If dblTotal is less than 100 when the Loop command is reached the loop repeats, another cell is added to the total, and the row number is incremented. If the total is 100 or more the total is assigned to the cell in column B in the previous row (hence the -1). This simple code assumes that the numbers will add up to 100, if they don’t then the VBA will generate an unhelpful error message because the integer variable becomes too large. There is a variation on this type of loop which involves putting the While condition after the Loop command rather than after the Do command, this means that the code must be executed at least once as the condition is not tested until the end of the loop. The difference, if any is subtle but can be important. In the case above, changing the code in this way makes no practical difference at all. Selection There is a special range object called Selection, this is the selected range (as opposed to the active cell). 1. Select a range of cells on the active worksheet 2. In the Immediate Window type 3. Selection.Interior.Color = 255 4. The selection is coloured red Centre for Staff and Educational Development UEA 21 4. Variables and Loops This shows the effect of setting properties for the Selection, in practice we can use Selection just like Range but obviously without the arguments. 5. With a range of cells selected, try these commands in the Immediate Window: ? Selection.Row ? Selection.Rows.Count ? Selection.Address These properties allow you to use the Selection object in a routine like this 6. In the code window for Sheet1 type: Sub AlternateRows() Dim intRow As Integer Dim intRowStart As Integer Dim intColStart As Integer Dim intRowEnd As Integer Dim intColEnd As Integer intRowStart = Selection.Row intRowEnd = Selection.Row + Selection.Rows.Count - 1 intColStart = Selection.Column intColEnd = Selection.Column + Selection.Columns.Count - 1 For intRow = intRowStart To intRowEnd Step 2 Range(Cells(intRow, intColStart), Cells(intRow, intColEnd)) _ .Interior.Color = RGB(200, 200, 200) Next End Sub Note the use of a space followed by an underscore character at the end of one of the lines to indicate that the code continues on the next line, this is another useful tool when writing more complex code as it allows long lines of text to be used without horizontal scrolling. If you prefer to keep the line together just miss out the underscore and the carriage return/new line. This routine shades alternate rows in the selected range, spend a little while examining the code and seeing how it works. Observe the structure; declare and then initialise the variables then perform the actions, this is a very common structure in programming. In this chapter we have learned how to write a sequence of code to be repeated a fixed number of times, until a condition ceases to be true, or once for each object in a collection. We have seen how to declare and then use variables to hold values within a subroutine, and how to lay out code in the code windows to make it easier to follow and understand. 22 Centre for Staff and Educational Development UEA Introduction to Excel VBA 5 – Branching and Interaction If…Then To make branching code, sometimes known as conditional or decision making code, we use a test of some description to determine what action to take. One of the most common forms of code used in this way is the If…Then structure which uses a simple true/false test to determine which branch of the code will be executed. The syntax of the If…Then structure is: If True/False test Then Action if True ElseIf True/False test Then Action if alternative is True Else Action if False End if The True/False test will usually take the form of a comparison between two values such as dteCurrentDate>dteDueDate or intCounter>=intMaximum the nature of such comparisons means that the result can only be true or false. Very much like the condition used in the Do…While loop earlier If the test result is true then the code in the following lines will be executed until the Else line is reached at which point the code jumps to the End If line and continues from there. If the test result is false then the code jumps straight to the Else line and executes the code following that line, continuing past the End If line when it reaches it. The If…Then structure is often used within a loop to test multiple values and there are several ways to extend the structure to allow more possible outcomes. If…Then statements can be nested to add more conditions and outcomes or, more usually the structure is extended with extra lines of ElseIf True/False test Then. Either technique requires that tests which are not mutually exclusive (intMark>40 and intMark>60, for example) have to be in the right order. This table illustrates the structure and why the order matters. Correct Code Incorrect Code Comment on incorrect code If intMark>60 Then If intMark>40 Then strResult=”Distinction” strResult = “Pass” ElseIf intMark>40 Then ElseIf intMark>60 Then strResult = “Pass” strResult=”Distinction” If the mark is over 40 a pass is issued and the code jumps to the End If line This test is never performed as the mark cannot be over 60 without being over 40 Else Else strResult = “Fail” strResult = “Fail” End If End If If the tests are mutually exclusive such as intMark>60 and intMark<40 then the order in which they appear is immaterial. Care needs to be exercised, particularly when editing code using these structures, to make sure that tests are left in a working order. Centre for Staff and Educational Development UEA 23 5. Branching and Interaction Note that End If is written as two words whereas ElseIf is written as one, the editor will correct your typing in most cases but it is better to get it right anyway. As an exercise we will arrange some code to highlight the rows and columns in a ten by ten grid where the value of the intersecting cell is 100 like this: We will need to use two nested loops from 1 to 10 to test all the cells, when we find a cell which equals 100 we will need to set the interior colour of the cells from 1 to 10 in that row and 1 to 10 in that column to yellow. The code will look like this: Sub Target100() 'Declare variables for row and column Dim intRow As Integer Dim intColumn As Integer 'Loop through the Rows For intRow = 1 To 10 'Loop through the Columns For intColumn = 1 To 10 'Test the intersecting cell If Cells(intRow, intColumn) = 100 Then 'if the cell =100 'Highlight the row Range(Cells(intRow, 1), Cells(intRow, 10)).Interior.Color = RGB(255, 255, 0) 'Highlight the column Range(Cells(1, intColumn), Cells(10, intColumn)).Interior.Color = RGB(255, 255, 0) End If 'End the nested Loops in the right order Next intColumn Next intRow End Sub Notice how we have omitted some of the code; we have not set a step value so this will default to one, and we have not used Else in the IF…Then structure because we are only concerned with what to do if the condition is true, the Else would be superfluous as there are no instructions to follow it. 24 Centre for Staff and Educational Development UEA Introduction to Excel VBA 1. Enter the code above in the code window of a blank worksheet (You can skip the comments to save typing as you can refer to this book if you need them) 2. Enter some numbers in the first ten rows and columns including 100 somewhere 3. Run the code to test it 4. Delete the number 100 from the sheet 5. Run the code again We can improve the code by adding a line to clear the formatting before starting to test the cells, this way we can avoid having highlights left over after the number has changed. 6. Add this line of code just after the variable declarations: 7. Range("A1:J10").ClearFormats 8. Test the code again by changing some numbers and running it The ClearFormats method does the same job as selecting Clear, Formats from the Home Ribbon, and it is useful to remember in any code where you are changing formats as it gives the code a clean start. Be careful however as it will clear all formats including number formatting such as Date or Currency. Goto Another type of branching in code uses the keyword Goto. Early versions of Basic used line numbers and the Goto statement caused the code to jump forwards or backwards to the line number required. VBA does not use line numbers but we can still use Goto with labels which we define with the colon character. Like this: Label: We can also use a number as a label, in which case the colon is not required but this is less common as it is harder to understand than a descriptive label. Goto is often an action within an If…Then structure allowing the same labelled block of code to be used for several outcomes although this is frowned upon as bad practice by programmers who would suggest calling other procedures instead. Certainly if you intend using VBA very much you will build a library of useful procedures and simply calling one of those is easier and more consistent than using GoTo. We can also use the Goto statement to create loops in code, maybe using an If…Then to test for the end of the looped code. This can seem easier than using Do…While but it is again not seen as good practice as you can easily create a loop of code like this: Sub ProblemCode() StartOfLoop: Goto StartOfLoop End Sub This code will simply repeat the second and third lines ad infinitum locking the workbook and preventing you from doing anything else. It is best to avoid this type of problem altogether but Centre for Staff and Educational Development UEA 25 5. Branching and Interaction if you do accidentally create a loop like this you can usually break out of it, or any procedure which is taking longer than expected, by pressing CTRL + Break. Be warned however that occasionally the break key doesn’t work and the only way to regain control is to shut down Excel forcibly, which can cause work to be lost. Message Boxes The message box is a fundamental tool for user interaction, providing a means for the programme to instruct the operator or request confirmation of an action. In VBA the message box command is MsgBox and the basic syntax is: MsgBox prompt, buttons, title There are two other arguments which allow advanced users to attach helpfiles in a particular context but we will not use those in this course. The only required argument is the prompt, or message, itself, the other two may be omitted if they are not needed. Prompt is literal text with a maximum of about 1,000 characters being allowed, it should be enclosed in double quotes just like any other literal text. Buttons is a numeric argument which is often replaced by the built in constant representing the value required. The more common values are: Group Constant Value Description vbOKOnly 0 Display OK button only. vbOKCancel 1 Display OK and Cancel buttons. VBAbortRetryIgnore 2 Display Abort, Retry, and Ignore buttons. A vbYesNoCancel 3 Display Yes, No, and Cancel buttons. vbYesNo 4 Display Yes and No buttons. vbRetryCancel 5 Display Retry and Cancel buttons. vbCritical 16 Display Critical Message icon. vbQuestion 32 Display Warning Query icon. vbExclamation 48 Display Warning Message icon. vbInformation 64 Display Information Message icon. vbDefaultButton1 0 First button is default. vbDefaultButton2 256 Second button is default. vbDefaultButton3 512 Third button is default. vbDefaultButton4 768 Fourth button is default. B C Constants are like variables but they don’t change value, so the name vbOKOnly always tells the message box to just display an OK button. The number 0 could be used instead but is much 26 Centre for Staff and Educational Development UEA Introduction to Excel VBA harder to interpret if you revisit your code later. Likewise you could use vbOKOnly any time you needed the value 0 but it would make your code very hard to understand if you did. In use, the values from the three groups are added together to make a unique number defining the message box characteristics. Title is another text string which appears as the title of the message box. A message box returns a value to the code which indicates which of the buttons has been clicked, this allows the code to branch to the appropriate action using If...Then and GoTo. These are the values returned by the various buttons and the associated VB constants: Button Constant Value Button Constant Value OK vbOK 1 Ignore vbIgnore 5 Cancel vbCancel 2 Yes vbYes 6 Abort VBAbort 3 No vbNo 7 Retry vbRetry 4 In the Immediate Window type these examples of Message Boxes Msgbox "Hello World! ", vbOKOnly, "Greeting" Msgbox "Hello again everybody, this time with a longer message. ", vbOKCancel Msgbox "Bye for Now" Note the effect of the various arguments and of missing them out. If we want to see the value returned by the message box we must use the alternative syntax which places the arguments inside a set of brackets. Again in the Immediate Window type: ? Msgbox ("Click on a button",vbYesNoCancel) You should see the numeric value of the button you click appear below the line of code in the immediate window. In this example No was clicked. To display one of the message box icons in the box, add one of the constants from group B in the table above. In the Immediate Window type: ? Msgbox ("Click on a button",vbYesNoCancel + vbQuestion) This time the message box displays the question mark icon 9. To make the third button (Cancel) the default, add the appropriate constant from group C like this Centre for Staff and Educational Development UEA 27 5. Branching and Interaction ? Msgbox ("Click on a button",vbYesNoCancel + vbQuestion + vbDefaultButton3) This is exactly the same as: ? Msgbox ("Click on a button",547) The message box combined with a label, a GoTo statement, and a couple of If...Then statements, allows us to write code which interacts with the operator. Try this example: In the Code Window for Sheet1 type: Sub Messages() Dim intResponse1 As Integer Dim intResponse2 As Integer Dim intResponse3 As Integer StartOver: intResponse1 = 0 intResponse2 = 0 intResponse3 = 0 intResponse1 = MsgBox("Click on one of the three buttons below.", _ vbYesNoCancel, "Test Responses") If intResponse1 = vbCancel Then intResponse2 = MsgBox("Are you sure you want to cancel already?", _ vbYesNo + vbQuestion, "Are You Sure?") ElseIf intResponse1 = vbYes Then intResponse3 = MsgBox("You chose Yes, do you want to go again?", vbYesNo, "Yes") ElseIf intResponse1 = vbNo Then intResponse3 = MsgBox("You chose No, do you want to go again?", vbYesNo, "No") End If If intResponse2 = vbNo Or intResponse3 = vbYes Then GoTo StartOver End If End Sub Just play with this for a few minutes to see how the code reads the button clicks and responds appropriately to them. Let’s look at this code bit by bit to see how it was put together: 28 Centre for Staff and Educational Development UEA Introduction to Excel VBA Dim intResponse1 As Integer Dim intResponse2 As Integer Dim intResponse3 As Integer This section just declares the three variables as integers StartOver: This is a label, defined by the colon, which acts as a destination for GoTo later in the code. intResponse1 = 0 intResponse2 = 0 intResponse3 = 0 These three lines set or reset the variables to zero to avoid values being held over. intResponse1 = MsgBox("Click on one of the three buttons below.", _ vbYesNoCancel, "Test Responses") The first variable is set to the response from the message box. If intResponse1 = vbCancel Then intResponse2 = MsgBox("Are you sure you want to cancel already?", _ vbYesNo + vbQuestion, "Are You Sure?") If the first variable is the numeric equivalent of Cancel then another message box is generated asking for confirmation. We could use the number 2 here instead of vbCancel. ElseIf intResponse1 = vbYes Then intResponse3 = MsgBox("You chose Yes, do you want to go again?", vbYesNo, "Yes") If the response was Yes then an appropriate message box is generated asking if the operator wants to have another go. ElseIf intResponse1 = vbNo Then intResponse3 = MsgBox("You chose No, do you want to go again?", vbYesNo, "No") If the response was No then an appropriate message box is generated asking if the operator wants to have another go. End If The If…Then statement is ended here. If intResponse2 = vbNo Or intResponse3 = vbYes Then GoTo StartOver Another If…Then statement checks whether the operator has responded that they want to start again in any of the message boxes, if so then the code returns to the StartOver label above End If This ends the If…Then statement and the code will exit from here as the operator has not asked to go again. This code could be written in several ways; it could use just one If…Then rather than two, or it could use the variables in a different way, but it is a suitable illustration of the way in which code can be made to interact with the operator. Exiting from Loops Here’s an example of a loop using Goto and a variable in the If…Then structure: Centre for Staff and Educational Development UEA 29 5. Branching and Interaction Sub TenGreen() Dim intLoop As Integer Dim strVerse As String Dim intMore As Integer intLoop = 10 NextVerse: strVerse = intLoop & " green bottles hanging on a wall" Range("A1:A2") = strVerse Range("A3") = "And if 1 green bottle should accidentally fall..." intLoop = intLoop - 1 Range("A4") = "There'll be " & intLoop & " bottles hanging on a wall" intMore = MsgBox("Another verse?", vbYesNo, "Another?") If intMore = 6 And intLoop > 0 Then GoTo NextVerse End If End Sub Read the code above carefully and enter it in the code window if you want to see it working. Note the use of concatenation (&) with numbers and text. Note the use of the number 6 rather than vbYes, these are completely interchangeable. Note the line which decrements the variable by one each time; intLoop=intLoop-1, this is a common structure when loops are made in this way. Note the If…Then statement checking to see if there are any bottles left as well as whether the operator requests another verse using And to combine the two conditions, meaning both must be true. As the GoTo statement is regarded as poor programming we may decide to use an alternative. The same code could be written using a For…Next loop but if we want to be able to leave the loop using a message box as we can in the example above we need a new command, Exit For, which will leave the loop at any point. 30 Centre for Staff and Educational Development UEA Introduction to Excel VBA You can try these alternative versions as well by entering them in to the code window. Sub TenGreen_mk2() Dim intLoop As Integer Dim strVerse As String Dim intMore As Integer For intLoop = 10 to 1 step -1 strVerse = intLoop & " green bottles hanging on a wall" Range("A1:A2") = strVerse Range("A3") = "And if 1 green bottle should accidentally fall..." Range("A4") = "There'll be " & intLoop -1 & " bottles hanging on a wall" intMore = MsgBox("Another verse?", vbYesNo, "Another?") If intMore = vbNo Then Exit For End If Next intLoop End Sub This code does the same thing but without the Goto by using the Exit For to leave the loop at will. We could also use Do…While like this with an Exit Do command to leave the loop when there are no bottles left: Sub TenGreen_mk3() Dim intLoop As Integer Dim strVerse As String Dim intMore As Integer intLoop=10 intMore=vbYes Do strVerse = intLoop & " green bottles hanging on a wall" Range("A1:A2") = strVerse Range("A3") = "And if 1 green bottle should accidentally fall..." intLoop = intLoop - 1 Range("A4") = "There'll be " & intLoop & " bottles hanging on a wall" intMore = MsgBox("Another verse?", vbYesNo, "Another?") If intloop=0 Then Exit Do End If Loop While intMore = vbYes End Sub Note that the condition is placed at the end of the loop so we see at least the first verse. Centre for Staff and Educational Development UEA 31 5. Branching and Interaction Input Box Another way to get input from an operator is by using the VBA InputBox function. There is an application based alternative to this function which allows different data types to be entered but the standard VBA version always returns a string or text input and that is what we will use. The simple syntax for InputBox is: InputBox Prompt, Title, Default Again further arguments can be used, this time to set the position of the box and to add a helpfile and context. We will not be using these extra arguments in this course. Prompt, as before is the text displayed in the box as an instruction to the operator. Title is again the same as for a message box. Default is text which is loaded in to the part of the input box where the user types, if the user simply clicks on OK the default is the value returned by the input box. Just like MsgBox, InputBox also has an alternative syntax using brackets when the value is to be returned, in the case of input boxes however this is almost always a requirement so the bracketed syntax is the one we will explore. In the Code Window for Sheet2 type: Sub Messages() Dim strResponse As String strResponse = InputBox("Welcome to Excel VBA please enter your name", _ "Greeting", "Type your name here") If strResponse = "Type your name here" Or strResponse = "" Then Range("B2") = "Welcome anonymous operator" Else Range("B2") = "Welcome " & strResponse End If End Sub When you run this code VBA checks the resulting string using If…Then to see if it is either still the default text or is empty, in either case cell B2 is set with an appropriate greeting to an anonymous operator. If the variable contains any other value this is assumed to be the requested name and the greeting is set accordingly. The OR between the two conditions means that either or both must be true to appear as a true condition to the If…Then statement. Another useful word in this type of situation when more than one condition is involved, is AND which means that both conditions must be true to appear as true to the IF…Then statement. In both cases you can use as many conditions as you require, combining AND and OR using brackets to determine the sequence in which the conditions are combined. For example; an If…Then which needs to test that a person is over 17 and is a member, or is under 18 and accompanied by a member, or has paid an entrance fee, might look like this: 32 Centre for Staff and Educational Development UEA Introduction to Excel VBA If (intAge >17 And strMember = "Yes") Or (intAge <18 And strAccompMember <>"") Or _ dblFeePaid >0 Then This, rather complicated, condition could be expressed differently as an If...Then followed by two Else If…Then lines each with a GoTo action referring to the rest of the code. Either structure is acceptable and the choice of which to use may depend on the surrounding code, maybe the fee needs to be processed or the accompanying member needs to be checked against a list, in which case it may be more practical to break the If...Then into smaller parts. Calling one Procedure from Another When discussing GoTo it was mentioned that a preferred alternative is to use multiple sub routines which call each other. This is an example of Structured Programming and whilst the topic is more involved that we can cover in an introductory course, some of the techniques can be useful at any level. The brackets after the name of a sub routine allow arguments to be passed to it when it is run, we can use these arguments when we call one sub routine from another to pass information. We can also move the variable declaration, so far all our variables have been declared as part of a sub routine and they are not available from anywhere else but we can declare a variable at a higher level to make it available to other code. 1. In a new Workbook 2. Open the VBA editor 3. Click on Insert, Module to add a module to the Project Window 4. In the code window for the new module type the following two variable declarations: Public intCol As Integer Public intRow As Integer Note the use of Public rather than Dim to indicate that these variables are to be made available to any code. 5. Add the following sub routine below the declarations Sub SetColours(Red As Integer, Green As Integer, Blue As Integer) Cells(intRow, intCol).Interior.Color = RGB(Red, Green, Blue) End Sub 6. Note the three arguments inside the brackets, defined as integers and named Red Green and Blue, they are used just like variables in the RGB statement which follows. 7. In the code window for Sheet1 add the following sub routine Sub D4Red() intRow = 4 intCol = 4 Call SetColours(255, 0, 0) End Sub Centre for Staff and Educational Development UEA 33 5. Branching and Interaction Note the Call to the sub routine SetColours in the module, which includes the three values to pass to that sub routine as arguments. 8. Run the code on Sheet1 and observe the effect which depends on Global variables and passing arguments between routines 9. Experiment with similar code on another sheet to show that the SetColours routine is available from any project in this workbook In this example the code in the module does not specify the sheet, so it is applied to the active sheet. This means that if you make Sheet2 active and then run the code on Sheet1 it is Sheet2!D4 which is formatted. If this behaviour is not what you want you can make the code specific to the sheet or you can pass another argument to the SetColours sub routine to specify which sheet is intended. In this chapter we have explored some of the techniques used to interact with the operator producing code which responds to input and allows the flexibility of different processes for different situations. We have seen alternative types of loop and introduced the concept of constants which can make code easier to understand. 34 Centre for Staff and Educational Development UEA Introduction to Excel VBA 6 – Controls and Events So far we have written code in the form of subroutines which we have then run using the macro dialogue box. The run button in the VBA editor is an alternative method we can use to run our code, or the shortcut key F5 when the editor is open will also work, but only when the editing cursor is in the code we want to run. In this chapter we will explore alternative ways to run our code, either on demand by clicking a control such as a button, or in response to an event in Excel such as entering data in a cell or selecting a worksheet. Buttons Running a macro from a button is a simple process in Excel 1. In a new workbook 2. Add the code below to the code window for sheet1 Sub WhereIsThis() ActiveCell.Value = ActiveCell.Address End Sub This simple routine just puts the cell address in the active cell as text 3. Select the Developer ribbon 4. Select Insert, Form Controls, Button 5. Add a control button to the worksheet by clicking somewhere near the top left corner 6. In the resulting Assign Macro dialogue box select your subroutine from above and click on OK 7. Drag the sizing handles to make the button as large as you want it Centre for Staff and Educational Development UEA 35 Controls and Events 8. Right click on the button and select Edit Text 9. Replace the default text with a suitable label for the button 10. Click elsewhere on the worksheet to make the button active 11. Select a cell on the worksheet then click on your new button to test it Creating buttons to run your code makes it possible to interface with the operator in a way which is familiar and easy to understand. Shortcut Keys Macros can also be assigned to a shortcut key, not technically a control but another useful way to run your code, particularly for code which formats or populates the active cell. 1. Open the Macro Dialogue box 2. Select your macro 3. Click on Options 4. Assign a key combination to your macro Here we have assigned Ctrl + Shift + A, the Ctrl key is already selected, so you just type a capital A to assign the shortcut key 5. Click on OK 6. Close the Macro Dialogue box 36 Centre for Staff and Educational Development UEA Introduction to Excel VBA Select a cell and type Ctrl + Shift + A to test the key assignment, again this is a very ‘user friendly’ way to run code for people who may not be comfortable using the macro dialogue as well as a quick way for you to access your routines. Objects as Controls Drawing objects in Excel can also be used as controls to run a macro. 1. Still using Sheet1 2. Draw a filled red circle approximately three rows high 3. Copy the circle twice and colour the copies green and blue 4. Place these three circles near the top of the worksheet close together like this 5. Add the following lines of code to the code window for Sheet1 Sub SetColourRed() ActiveCell.Interior.Color = RGB(255, 0, 0) End Sub Sub SetColourGreen() ActiveCell.Interior.Color = RGB(0, 255, 0) End Sub Sub SetColourBlue() ActiveCell.Interior.Color = RGB(0, 0, 255) End Sub 6. These three routines will colour the active cell red, green or blue respectively 7. Right click on the red circle and select Assign Macro 8. Use the dialogue box to assign the SetColourRed macro 9. Repeat the above steps to assign the SetColourGreen and SetColourBlue macros to the appropriate coloured circles The circles now act as controls and clicking on one will assign the chosen colour to the active cell. Test the effect by selecting various cells and colouring them also observe that cells can be assigned both a value using the button and a colour using the shape because these are different properties of the cell. Centre for Staff and Educational Development UEA 37 Controls and Events Events Excel has a limited number of events which are accessible to VBA, particularly when compared to Access where some individual objects have ten or more events of their own, but there are still some useful techniques to be employed. Workbook Events When an event occurs such as the location of the active cell being changed, a new sheet being added, or an existing one being selected, Excel checks to see if any code is associated with that event and runs it if there is. 1. In a new workbook 2. Open the VBA editor 3. Select ThisWorkbook in the Project Window with a double click 4. At the top of the code window 5. Drop down the left list (with (General) in it) 6. Select Workbook 7. Drop down the right list (probably now with Open in it) 8. Select NewSheet You should see some code like this in the code window: Private Sub Workbook_NewSheet(ByVal Sh As Object) End Sub 38 Centre for Staff and Educational Development UEA Introduction to Excel VBA There may also be a similar block of code for the Workbook_Open event, you can ignore or delete this. Any code which we add between the Private Sub… and End Sub lines will be run whenever a new sheet is created. 9. Add the code below between the two existing lines Range("A1:H1").MergeCells = True Range("A1") = "This information is confidential" Range("A1").Font.Bold = True Range("A1").Font.Size = 18 Range("A1").RowHeight = 24 Range("A1").HorizontalAlignment = xlCenter These lines of code carry out the following actions from top to bottom: The text "This information is confidential" is added to Cell A1 Cells A1:H1 are merged The font in A1 is made Bold The font in A1 is increased to 18 point text The height of row 1 is set to 24 points The contents of A1 are centred (note American spelling of the constant) The result of this code in the NewSheet event of the workbook is that every new sheet created will automatically have the information added like this: Other potentially useful workbook events include: SheetActivate: Triggers whenever a sheet is selected in the workbook. SheetChange: Triggers when the value of any cell on a sheet in the workbook is changed. SheetSelectionChange: Triggers when the position of the active cell is changed on any sheet in the workbook. With…End With The code we used above repeatedly refers to the range A1, this means that we have to type this value several times and when the code runs Excel must evaluate the range each time. We can make the code quicker and perhaps easier to type by using the With…End With structure. This structure defines a block of code which all refers to a particular object, in this case the range A1, and allows us to just use the properties and methods of that object without referring to it every time. Centre for Staff and Educational Development UEA 39 Controls and Events We can rewrite the code using a With…End With structure like this: 10. After the line which merges the cells add a new line containing the command: With Range("A1") This instructs VBA to use the value Range("A1") in the following lines until the End With is reached Modify the following five lines by removing the reference to the range, they should look like this when you’ve finished: .Value = "This information is confidential" .Font.Bold = True .Font.Size = 18 .RowHeight = 24 .HorizontalAlignment = xlCenter Note that they all start with the dot and we have used the Value property in the first line as the default no longer applies 11. Add the End With line after the rows you just edited The final code should look like this: This structure will speed up code where it saves VBA processing references multiple times, the saving in this case is negligible but it could be significant in a long loop or if the reference was longer. The advice usually given is to try to minimise the number of dots to be processed, as each dot represents a step in the hierarchy and therefore takes time while VBA looks up the reference. 40 Centre for Staff and Educational Development UEA Introduction to Excel VBA Worksheet Events The events above all operate at the workbook level and therefore apply to every worksheet, if you want code to run on just one sheet you use the code window for that sheet in a similar way. 1. In the VBA editor 2. Select Sheet1 in the Project Window with a double click 3. In the left hand drop down list above the code window select Worksheet 4. In the right hand drop down list select SelectionChange (this may already be selected) Two lines of code are generated as before but this time the event procedure is Worksheet_SelectionChange which means that the event is triggered only when the selected cell on this worksheet changes. We will write a routine to highlight any cells containing the same value as the selected cell within the range A1:T40. This represents 40 rows and 20 columns; 800 cells in all. First we will generate some random numbers to use for testing 5. On sheet1 select A1:T40 6. Type the formula: =RANDBETWEEN(1,10) 7. Press Ctrl + Enter This will generate 800 random numbers between 1 and 10 in the selected cells 8. Copy the selection and paste it in the same location as values only This will fix the numbers so they don’t recalculate 9. Press Esc to clear the active selection and Ctrl + Home to select A1 We now have a set of data with which to experiment. Generating a large set of random number this way is a useful technique to remember when you want to test code but unless the dataset is quite large you should still make sure that you test with specific values to make sure that the code behaves as intended. Centre for Staff and Educational Development UEA 41 Controls and Events 10. In the code window for Sheet1, between the two existing lines of code, type Dim intX As Integer Dim intY As Integer Range("A1:T40").Interior.ColorIndex = xlColorIndexNone Range("A1:T40").Font.ColorIndex = xlColorIndexAutomatic For intY = 1 To 40 For intX = 1 To 20 If Cells(intY, intX) = ActiveCell Then Cells(intY, intX).Interior.Color = RGB(255, 255, 0) Cells(intY, intX).Font.Color = RGB(255, 0, 255) End If Next intX Next intY Test the code by selecting any cell in the range A1:T40 and observe all the cells with the same value changing colour This is a breakdown of how the code works; remember it runs every time you select a different cell on this sheet. Dim intX As Integer Dim intY As Integer These two lines declare the variables used for X and Y coordinates Range("A1:T40").Interior.ColorIndex = xlColorIndexNone Range("A1:T40").Font.ColorIndex = xlColorIndexAutomatic These two lines set the background colour to none and the font colour to automatic within the range A1:T40 using constants, resetting the cells ready to be formatted again by the following code. For intY = 1 To 40 For intX = 1 To 20 Two nested loops are initiated to work through each cell in the range. If Cells(intY, intX) = ActiveCell Then Cells(intY, intX).Interior.Color = RGB(255, 255, 0) Cells(intY, intX).Font.Color = RGB(255, 0, 255) End If The If…Then statement checks each cell against the active one and if the value is the same sets the background and font colours to yellow and red respectively. Next intX Next intY These lines close the two loops. 42 Centre for Staff and Educational Development UEA Introduction to Excel VBA In the last example we saw several of the techniques we have been practicing being used together; the nested loops, the If…Then, constants, variables, and both the Range and Cells techniques for selecting cells. In this chapter we have explored ways in which we can run our code either ‘on demand’ using a mouse click or key stroke, or automatically using the built in events in Excel, we have added to the properties and methods we can use and seen several new actions in use. We have also begun to explore ways to optimise our code using structures such as With…End With. In this course we have provided a very basic introduction to the use of VBA, it is not intended to describe best practice in programming or to offer solutions to practical problems. Many of the techniques can be applied in different ways to achieve the same results and often there is no preference for one procedure over another. Centre for Staff and Educational Development UEA 43 Objects, Properties, Methods and Constants Useful Objects, Properties, Methods and Constants These tables show a small selection of the objects, properties and methods available in Excel VBA. Those used in this course are included together with others which you should find relatively easy to use as they follow similar rules. Range Objects Name Description Range Any range of cells, uses an argument in the form of the range address as a standard string e.g. Range(“A1:C4”) Cells ActiveCell Selection A single cell addressed by row and column number e.g. Cells(2,4) The active cell in the active worksheet The selected cells in the active worksheet (including multiple selections) Properties of Range Objects Name Description Value The value of the cell as displayed without formatting. e.g. A cell showing 25% would have a value of 0.25, a cell containing a formula has a value of the formula result. Formula The formula in a cell as a string e.g =A1*G4 or the value if the cell does not contain a formula FormulaR1C1 Row Column Rows.Count Columns.Count As above but the formula is in the R1C1 notation. The number of the first row in the range The number of the first column in the range The number of rows in the range The number of columns in the range Cells.Count The number of cells in the range EntireRow Extends the effect of following properties or methods to the entire row(s) corresponding to the range. E.g. Range(“C3”).EntireRow refers to the entire row 3 EntireColumn As above but refers to the entire column(s) Interior Any following properties refer to the characteristics of the interior or background of the cells in the range. See following table for more detail. Font Any following properties refer to the characteristics of the font used in the cells in the range. See following table for more detail. Note: Range and Cells can also be properties of range objects, when used this way they treat the parent range object as if it was a worksheet so all addresses are relative to the top left corner of the parent range. 44 Centre for Staff and Educational Development UEA Introduction to Excel VBA Properties of Interior Name Description Color Sets or reads the foreground colour of the font using a decimal number or sets it using RGB values as described below. ColorIndex Uses a constant to define colour properties such as Automatic or None Properties of Font Name Description Bold Boolean value (true or false) corresponding to the Bold setting of the font used in the range. Returns Null if the range contains some bold and some normal cells. Italic As above but for the Italic setting of the font. Underline This property can be set using true or false but also accepts and returns numeric values representing the various types of underlining available in Excel. Color Sets or reads the foreground colour of the font using a decimal number or sets it using RGB values as described below. ColorIndex Uses a constant to define colour properties such as Automatic or None The size of the font in points Size The name of the font e.g. Calibri as a literal string Name When a colour is to be read or set using decimal values the number represents the red, green and blue proportions as numbers between 0 and 255 where 0 is none of that colour and 255 is fully saturated colour. When the three numbers are the same the colour is a shade of grey somewhere between black (all zero) and white (all 255). The decimal number can be calculated using this formula: (red value) + (256*green value) + (256*256*blue value) Pure red is 255 Pure green is 65280 Pure Blue is 16711680 White is therefore 255+256*255+256*256*255 or 255+65280+16711680 or 16777215 Fortunately VBA has a function to calculate these values for us, we can use RGB(#,#,#) to specify any of the available colours using the three values between 0 and 255. If you have a very large number of RGB functions you could speed your code up slightly be replacing them with the decimal equivalents at the expense of making it harder to read the code. Centre for Staff and Educational Development UEA 45 Objects, Properties, Methods and Constants Excel Constants for ColorIndex Property Name Value Description xlColorIndexAutomatic n/a Sets the font colour to automatic xlColorIndexNone n/a Sets the background colour of a range to none VBA Color Constants Name Value vbRed 255 vbGreen 65280 vbBlue 16711680 vbCyan 16776960 Standard colours created by mixing red green and blue values of 0 or 255. These constants can be used instead of 16711935 the decimal or RGB values to define the standard colours. 65535 vbMagenta vbYellow vbBlack 0 vbWhite 16777215 Description Methods of Range Objects Name Select Selects the range as defined by the range object Clear The equivalent of Clear All on the Home ribbon ClearContents The equivalent of Clear Contents on the Home ribbon or the Delete key ClearFormats The equivalent of Clear Formats on the Home ribbon Copy Cut 46 Description Copies the contents of the range to the clipboard in the same way as Ctrl+C. Accepts a range as an argument which becomes the paste destination top left corner. As above but moves the contents rather than copies them. Merge Applied to multiple adjacent cells in a rectangular range will merge them. Applied to a multiple selection merges each range within the selection. Autofit Applies to columns or rows property of a range object to automatically resize the relevant dimension to fit the range contents. Centre for Staff and Educational Development UEA CSED has delivered staff development courses in practical computing for many years. These help people from a wide range of backgrounds to get to grips with using computers in their jobs. Our small team of skilled tutors comprises computing practitioners who actually use the IT in their work, so the sessions are based not only on theory but on practical experience. Our IT workbooks, which are designed for self-paced learning, are available from the ‘Resources’ section of our website. Centre for Staff & Educational Development The Registry, Floor 0, University of East Anglia, Norwich Research Park, Norwich, NR4 7TJ 01603 593039 www.uea.ac.uk/csed