Excel VBA - City University Continuing Education VBA for Microsoft Excel – Part 7 Table of Contents 1 2 3 4 5 6 7 8 Creating User Defined Functions ................................................................ 1 1.1 The Function Declaration .................................................................... 1 1.2 Defining a function ................................................................................ 1 1.3 Testing the function .............................................................................. 2 1.4 Using the function on a worksheet ..................................................... 2 1.5 A function to calculate NetPay ............................................................ 2 1.6 Calling a function from VBA code ...................................................... 3 Do loops .......................................................................................................... 4 2.1 Do While Example ................................................................................ 4 2.2 Do Until Example .................................................................................. 4 2.3 The Conditional statement in a Do loop ............................................ 4 2.4 Avoiding ‘runaway’ loops ..................................................................... 5 WorksheetFunction method ......................................................................... 5 Creating a command button ......................................................................... 6 4.1 Attaching code to a button ................................................................... 6 Calling a procedure from another procedure ............................................ 7 Events .............................................................................................................. 7 VBA functions ................................................................................................ 8 Showing the Developer Tab (Excel 2010 /2013) ...................................... 10 1 Creating User Defined Functions There are two types of procedure –Subs and there are also Functions. The characteristic feature of a function is that it returns a value to the location where the function is called. Secondly, if you create a function you can use it on the worksheet as a formula. 1.1 The Function Declaration The opening line is called the function declaration. For example the first line of a function to find the area of a circle might look like: Function AreaCircle(rad as Single) As Single Argument 1.2 data type of argument data type of return value Defining a function The whole function might look like: Function AreaCircle(rad as Single) As Single AreaCircle = 3.14159 * rad * rad 'this line returns the value End Function The calculation in the body of the function uses the argument that must be supplied to it, i.e., rad – a variable here is not necessary. The whole point of a function is to return a value; therefore the function must include a line somewhere that does this. In the above example that line is AreaCircle = 3.14159 * rad * rad It is essential to note that in this expression the return value is the same word as the function name, i.e., AreaCircle Page 1 of 10 Excel VBA - City University Continuing Education 1.3 Testing the function You can test the function in the Immediate window before you attempt to use it, e.g., In the next step click in the textbox and click the cell that contains the radius, then click OK ?AreaCircle(10) The example is supplying 10 as the argument, so the function returns the area of a circle with radius 10 1.4 Using the function on a worksheet You cannot run a function in the same way you would run a Sub. You must call it. You can directly use it in a formula: Type ‘=AreaCircle( ‘ into a cell, click a cell that contains a number , then click the Enter button (the tick) 1.5 A function to calculate NetPay Let's say you want to create a function that calculates how much your Net Pay is after deductions. The function would involve these values: Or you can click the InsertFunction button, choose UserDefined from the dropdown, select the function from the list and click OK GrossPay: how much you earn before deductions Income Tax as a percentage National Insurance as a percentage Pension Fund as a percentage NetPay is how much you take home after IncomeTax, National Insurance and Pension Fund contributions have been deducted. The arithmetic would look like this in code: Deductions = (GrossPay * IncomeTax) _ + (GrossPay * NI) _ + (GrossPay * Pension) NetPay = GrossPay - Deductions Page 2 of 10 Excel VBA - City University Continuing Education The full function would look like this: Function NetPay _ (GrossPay As Single, _ IncomeTax As Single, _ NI As Single, _ Pension As Single) As Single Dim Deductions As Single Deductions = (GrossPay * IncomeTax) + _ (GrossPay * NI) + _ (GrossPay * Pension) NetPay = GrossPay - Deductions End Function Note that NetPay is the return value for the function and the function name. Again, select a cell and choose the Insert Function icon Choose the User Defined category and select NetPay and click OK Put the cell references into the textboxes and click OK As another example, you could write a function which named PriceChange to calculate the percentage change in a share price. The function might look as follows: Function PriceChange _ (opening As Single, closing As Single) As Single PriceChange = (closing - opening) / opening End Function It really doesn’t matter what you call the arguments, as long you use them in a way that is consistent with the logic of the function. 1.6 Calling a function from VBA code The following sub is designed to work with the worksheet Prices in the week 7 workbook. To simplify the code, cell D2 would need to be preselected To call a function in code use it on the RHS of an equals sign, e.g. variable = Function(argument list) or RangeObject=Function(argument list) Sub CalcReturns() Do ActiveCell = PriceChange _ (ActiveCell.Offset(0, -2), ActiveCell.Offset(0, -1)) ActiveCell.NumberFormat = "0.00%;[Red]-0.00%" ActiveCell.Offset(1, 0).Select Loop Until ActiveCell.Offset(0, -3).Value = "" End Sub Above, we have ActiveCell = PriceChange(Arg1, Arg2) The function is designed to accept two arguments. The repetition is controlled by Do .. Loop Until. The call to the function is on line 3, and the two required arguments are supplied. Crucially, the two arguments are the cell that is two to the left and the cell that is one to the left of the active cell. Page 3 of 10 Excel VBA - City University Continuing Education 2 Do loops We have previously encountered two types of For loop: For Each iterates through a range of selected cells, or a collection For loops enable actions to be repeated a specified amount of times Do Loops can be used when the programmer cannot be sure how many times the repetition needs to take place. The syntax of a Do loop requires a condition, which evaluates to True or False and the condition determines how many times to repeat code. There are two variants of a Do loop: Do While - the loop can run while some condition is true – when it becomes false, the loop stops. An example would be to carry out some arithmetic while there is data 2.2 Do Until Example Sub CalcSquares_until() Do Until IsEmpty(ActiveCell) ActiveCell.Offset(0, 1) = ActiveCell ^ 2 ActiveCell.Offset(1, 0).Select Loop End Sub Note that both these loops use ActiveCell, and require that you select the next cell down, otherwise the loop will never terminate. Here is an example that uses a variable in the conditional statement. Do loops use a conditional expression, like an If statement e.g., Sub DWL() Dim x As Integer x = 0 Do While x < 5 Debug.Print x x = x + 1 Loop End Sub 2.3 Do Until – the initial condition is false and the loop runs until it becomes true - when it becomes true, the loop stops. An example would be to sum values in cells until a certain figure is reached. In truth, however, a programmer can usually arrive at a solution using either. Do While Total <= 100 Do Until Total >= 100 Do loops are often set up to repeat code until an empty cell is encountered. Do Until IsEmpty(ActiveCell) The following two programs do the same thing, they iterate through a range of cells (take care they contain numbers) in a column, and write the square of the number to the adjacent cell on the right. 2.1 Do While Example Sub CalcSquares_while() Do While Not IsEmpty(ActiveCell) ActiveCell.Offset(0, 1) = ActiveCell ^ 2 ActiveCell.Offset(1, 0).Select Loop End Sub x < 5 is the condition which initially evaluates to True The key word Loop returns control to the Do While statement which re-evaluates the condition; The Conditional statement in a Do loop Actually, there are two further variations on Do While and Do Until The programs above have the condition at the beginning of the loop. It is also possible to have the condition at the end of the loop. In the majority of cases it doesn’t make any difference! Change the above code by assigning the value 6 to the variable x, and run the code again – nothing prints, because the condition is never True. So, a characteristic of the Do . . While loop is that, depending on circumstances, it may never execute the statements at all. The next code has the conditional statement at the end of the loop Page 4 of 10 Excel VBA - City University Continuing Education Sub DLW() Dim x As Integer x = 0 Do Debug.Print x x = x + 1 Loop While x < 5 End Sub ActiveCell = WorksheetFunction.Average(Range(“B2:B9”)) or there is no condition at this stage so the statements to be executed happen at least once. If you write the code so that the condition is evaluated at the end, the loop is guaranteed to execute the statements at least once. To illustrate, assign 6 to the variable x immediately before the Do statement. Avoiding ‘runaway’ loops 2.4 Note the statement x = x + 1 which eventually changes the outcome of the condition - otherwise the loop would run ‘forever’. Similarly, it the loop is coded to terminate when a blank cell is encountered, forgetting to select the next cell down would mean the loop can never terminate. If there is a mistake in the programmer’s logic it is possible to write a loop that never terminates. If you have a runaway loop press Escape. Otherwise you may need to use Windows Task Manager and terminate Excel and lose unsaved work. Loops can contain control statements such as If Then or other loops If statements can contain loops You can break out of a Do loop if necessary by using the Exit Do keywords 3 WorksheetFunction method If you want to use Excel’s worksheet functions in your code, the Application has a WorksheetFunction method. The syntax is: Application.WorksheetFunction.FunctionName(arg1,arg2) where FunctionName is the name of an Excel function. (You can drop Application from the reference) For example, ActiveCell = WorksheetFunction.Max(Worksheets(“Exams”).Range(“C6:C22”)) Range(“B10”) = WorksheetFunction.Average(Selection) You can make use of the Union operator (,) with the arguments to the function ActiveCell = WorksheetFunction.Average(Range(“B2:B9”), Range(“D2:D9”)) The limitation with WorksheetFunction is that the functions don’t recalculate unless you re-run the macro - for dynamic data, it is better to use Excel’s formulas. On the other hand these statements are quicker to run than a solution that uses loops You might put the return value into a variable e.g., variable = WorksheetFunction.Sum(Selection) Sub SumNumbersInSelection() Dim Total As Single Total = WorksheetFunction.Sum(Selection) Range(“D12”) = Total MsgBox "The sum of numbers in the selection is " _ & Total End Sub You can combine WorksheetFunction with a loop, e.g., the following calculates the average of numbers in the two columns to the left of the active cell. Sub LoopAverage() Do While Not IsEmpty (ActiveCell.Offset(0, -1)) ActiveCell = WorksheetFunction.Average _ (ActiveCell.Offset(0, -1).Value, _ ActiveCell.Offset(0, -2).Value) ActiveCell.Offset(1, 0).Select Loop End Sub WorksheetFunction.Pi Excel’s Pi( ) function can be used to provide in calculations. For example, Circumference = 2 * WorksheetFunction.Pi * Radius Page 5 of 10 Excel VBA - City University Continuing Education 4 Creating a command button Use the Insert button on the Developer tab (see section 8). If you use the Insert button you will display the available controls, divided into two categories: Form controls and Active X controls. While they look identical, they work in a different way. Form controls have been superseded by the Active X controls; the main difference is that you can write code directly for an Active X control, whereas with a Form control you can only assign an existing macro. The most immediate properties are: • Name – the name of the button which is how you refer to it in VBA code • Caption – the text as displayed on the button itself By changing the caption, you can see that the button display changes - spaces are not allowed in names, but are allowed in captions. Close the Properties window when you have finished with it. 4.1 To place a command button on your worksheet, click the command button tool then draw a rectangle on your worksheet to the size that you want. Attaching code to a button At the moment there is no code is attached to the button. To create code, in Design mode double-click the button. You will see the beginning and end of a procedure. The programmer’s job is to write the code, or call an existing macro. Private Sub CommandButton1_Click() End Sub This code is known as an event procedure, specifically the Click event of the button. The first line has the optional keyword Private - this means the code can only run when the button is clicked, it is not otherwise available. When you create the Command button, the Design mode button is automatically turned on. In Design mode you can resize the button, move it, and customise its properties. Click the Properties button to display the Properties window. The name of the sub consists of: the name of the button, an underscore, the event, i.e. Click and the brackets. All event handling code follows this pattern. Also notice the location of the code – it is on the module for the sheet that contains the button. Page 6 of 10 Excel VBA - City University Continuing Education 5 Calling a procedure from another procedure One sub can call another Sub, merely by typing the sub’s name on a line – you can optionally use the keyword Call. For example, Private Sub cmdCalcPrices_Click() Range("D2").Select Call CalcReturns End Sub You will note the above code is attached to the click of a button. It selects the appropriate cell, and calls the program CalcReturns. In this way you can reuse the program CalcReturns elsewhere in the workbook, because it is free of references that tie it to a specific location. Calling a Sub from another sub is not restricted to button code, you can use the technique in any module. In fact, it is good programming practice. Don’t try to make one procedure do too much – divide a complex task into ‘chunks’, write a separate Sub for each chunk, and call the other subs from a main program as necessary. 6 Double click here to opent the workbook module The module is initially empty; click the dropdown control at the top left of the window, and click Workbook. Events As well as properties and methods, objects have Events. An Event is a change of state which can be interrupted by some user defined code. Strictly speaking a command button is not an Excel object, it as an Ms Office object. However you can use events of Excel objects, usually Application, Workbook and Worksheet. An intuitive example is the Workbook’s Open event.To create some code for the Workbook’s Open event, double click the ThisWorkbook icon in the Project Explorer window and this will open the module that belongs to the workbook. This creates an empty procedure for the Open event, merely type in any code that you wish to be executed every time the workbook is opened. Private Sub Workbook_Open() MsgBox "Welcome " & Application.UserName & vbCr & _ "The workbook was opened " & Now() End Sub Tip! To open the workbook and bypass the event code, hold down Shift when you double-click the file icon to launch the file. This can be a lifesaver if the code you create has unintended effects. Page 7 of 10 Excel VBA - City University Continuing Education 7 VBA functions VBA provides many inbuilt functions, some of which are the same as in Excel. They are divided into categories, here is a selection. VBA Date and Time functions Function Date() or Now() Day() Month() Year() Weekday() Description returns the current system date returns an Integer representing the day from a Date value returns an Integer that represents the month of a Date value returns an Integer that represents the year of a Date value returns day of the week (Sunday = 1) Example (You can use # instead of “ in examples) Date() Day(“31-Jan-2004”) returns 31 Month(“31-Jan-2004”) returns 1 Year(“31-Jan-2004”) returns 2004 Weekday(“31/01/2004”) returns 7 DateAdd() returns a data to which a specified time interval has been added; all three arguments are required DateAdd("yyyy", 1, date()) returns the date 1 year from today DateAdd("ww", -3, ”4 Mar 2004”) returns the date 3 weeks earlier than 4th March 2004 DateDiff() DateSerial() returns an Integer representing the difference between two dates returns a date given three integers that specify year, month, day in that order VBA Text manipulation functions LCase() UCase() Trim() LTrim() RTrim() Len() returns lower case version of a string returns upper case version of a string removes leading and trailing spaces from a string removes leading spaces from a string removes trailing spaces from a string returns number of characters in a string Left() returns leftmost characters of a string DateDiff(“d”, Date(), ”31-Jan-2004”) returns the number of days between 31-Jan-2004 and the current date DateSerial(2004, 1,31) returns 31/01/2004 Example LCase(“ABCD”) UCase(“abcd”) Trim(“ ABC “) LTrim(“ ABC”) RTrim(“ABC “) Len(“Manchester”) returns 10 Left(“Manchester”,4) returns Manc Page 8 of 10 Excel VBA - City University Continuing Education Right() returns rightmost characters of a string Mid() returns characters within a string StrComp() compares two strings for equivalence and returns the integer result of comparison: 0 if strings are equal, -1or 1 if strings are different StrConv converts the case of a string Val() returns numeric value of a string Right(“ABCDEF,3”) returns DEF Mid("Lindsey Davenport",9,4) returns Dave i.e. start at the 9th character and return a string 4 characters long Mathematical functions Abs() returns absolute value of numeric field Int() returns numeric value with the decimal fraction discarded returns a number rounded to a specified number of decimal places. syntax is: Round() Round(expression, numdecimalplaces) where the numdecimalplaces argument Rnd() is optional; the function returns an integer if it is omitted. creates random number (single) between 0 and 1 StrComp(“ABC,”abc”) returns 1 (strings are not considered to be the same) StrComp(“ABC,”abc”,vbTextCompare) returns 0 (strings are are considered to be the same; vbTextCompare performs case insensitive comparison) StrConv(“london”, vbProperCase) returns “London” you could also use vbUpperCase and vbLowerCase for the conversion argument Val(“123.45”) Example Abs(-1234.5) returns 1234.5 Int(13.9) returns 13 round(12.459, 2) returns 12.46 round(12.9) returns 13 to generate a random whole number between 0 and 9 you can use: Int(Rnd()*10) Other maths functions are: Atn , Cos , Exp, Log, Sgn, Sin, Sqr, Tan Page 9 of 10 Excel VBA - City University Continuing Education Array function You can use the Array() function to write a value to a range of cells instead of coding each cell separately. For example, to generate headings you could have Range(“A1:D1”) = Array (“First Name”,”Last Name”,”Dept”,”Pay Rate”) You can also use Array() to group worksheets Worksheets(Array("Prices", "Exams", "net_pay")).Select or Worksheets(Array(1, 3, 5)).Select The next code example shows how to create a loop that processes grouped worksheets. Sub GroupSheets() Dim w As Worksheet Worksheets(Array("Prices", "Exams", "net_pay")).Select For Each w In ActiveWindow.SelectedSheets w.Cells(1).Interior.Color = vbGreen Next w End Sub The reference you need to remember is For Each variable In ActiveWindow.SelectedSheets 8 Showing the Developer Tab (Excel 2010 /2013) To display the Developer tab in the Ribbon, follow these steps: 1. 2. 3. 4. click the File menu in Excel choose Options in the list on the left click Customize Ribbon in the List on the right check the entry for Developer The Developer tab gives you additional buttons to record and stop recording macros, and access to the Visual Basic Editor. There is also an Insert button which you can use to place controls on worksheets like Command buttons, Combo boxes and more. The Developer Tab (Excel 2007) To show the Developer tab for Excel 2007, follow these steps: 1. 2. 3. 4. click the icon to display the Office toolbar choose Excel options at the bottom of the display in the window that appears ensure that Popular is highlighted tick the checkbox that says Put the Developer Tag in the Ribbon Page 10 of 10