53
15 Aug 2011 1 Visual Basic for Applications Programming language Very similar to Visual Basic Embedded in Microsoft Office applications “Object oriented” Automate Office operations Build macros and functions We will only learn enough VBA to write simple functions

15 Aug 20111 Visual Basic for Applications Programming language Very similar to Visual Basic Embedded in Microsoft Office applications “Object oriented”

Embed Size (px)

Citation preview

15 Aug 2011 1

Visual Basic for Applications

Programming language Very similar to Visual Basic Embedded in Microsoft Office

applications “Object oriented” Automate Office operations Build macros and functions

We will only learn enough VBA to write simple functions

15 Aug 2011 2

Program

Program = code call = run = execute = launch = start List of instructions

Input Got at program’s start Asked to the user Got from Excel table

Does some predetermined operations Output

Written in Debug window or Message Box Written in Excel table “returned” like Excel functions

15 Aug 2011 3

Variables

Memory places to store values Types

Integer numbers: Integer and Long Real number: Single and Double Dates: Date True/False: Boolean Sentences: String

15 Aug 2011 4

Ask user values of x and y and print x+y

Variables: x Single, y Single, z Single

Example

Start sub example1

Get value from userand store in x (Single)

Get value from user and store in y (Single)

Calculate x+yand store in z (Single)

Print value of z

End

15 Aug 2011 5

Ask user values of x and y, calculate x+y, ask user for integer value a and print (x+y)*a

Variables: x Single, y Single, z Single, a Integer, result Single

Example

Get value from userand store in a (Integer)

Print value of result

End

Calculate z*aand store in result (Single)

Start sub example2

Get value from userand store in x (Single)

Get value from user and store in y (Single)

Calculate x+yand store in z (Single)

15 Aug 2011 6

Why should we rewrite a program that we have already written?

We can give the subroutine a name, MySum, to be able to later reuse it.

This reusable subroutine may have parameters, used to “communicate” with the other programs

Reusing programs

End

Start subroutine MySumparameters: z (Single)

Get value from userand store in x (Single)

Get value from user and store in y (Single)

Calculate x+yand store in z

15 Aug 2011 7

We “call” the subroutine MySum inside the main program and use its parameter

Reusing programs

Get value from userand store in a (Integer)

Print value of result

End

Calculate z*aand store in result (Single)

Start sub example2bis

z(Single)

End

Start subroutine MySumparameters: z (Single)

Get value from userand store in x (Single)

Get value from user and store in y (Single)

Calculate x+yand store in z

15 Aug 2011 8

We could use the subroutine also to get the values only and leave the calculation to the main program

Reusing programs

Get value from userand store in a (Integer)

Print value of result

End

Calculate z*aand store in result (Single)

Start sub example2ter

x(Single), y(Single)

End

Start subroutine GetXYparameters: x (Single), y (Single)

Get value from userand store in x

Get value from user and store in y

Calculate x+yand store in z (Single)

15 Aug 2011 9

Homeworks

Write a program which asks for a an amount of money, an interest rate and a number of years and prints the compound interest

Rewrite the previous program using a separate subroutine GetData to get the data.

Rewrite the previous program using also a separate subroutine PrintInterest to print the compound interest.

Rewrite the previous program using a sub called main which does nothing else but calling subroutines GetData, CalculateInterest, PrintInterest, which do all the job.

Write a program which asks for a an amount of money, an interest rate and two dates StartDate and EndDate. Using the expressionNumberOfYears = DateDiff( “yyyy”, StartDate, EndDate ) to get the difference in years, re-use the previous subroutines CalculateInterest and PrintInterest to print the compound interest.

15 Aug 2011 10

IF-THEN-ELSE condition

We want to branch the flow according to the value of a variable

If (condition)Then (operations if true)

Else (operations if false)End If

15 Aug 2011 11

Start with already values for x (Single) and y (Single). If x<y, print y-x, else print sentence “sorry”

Variables: x Single, y Single, diff Single, sentence String

Example

Start with x (Single), y (Single)

Print value of diff

Calculate y-x and store in diff (Single)

Put “sorry” in sentence (String)

Print value of sentence

End

true

falsex < y

15 Aug 2011 12

Ask integer value. If it is positive, print “positive”, if it is not positive, ask for a real value and print it

Variables: x Integer, y Single, sentence String

Example

Start

Print value of y

Put “positive” in sentence (String)

Print value of sentence

End

true x > 0

false

Get value from userand store in x (Integer)

Get value from userand store in y (Single)

15 Aug 2011 13

Build sub example5 which asks for an integer value. If it is positive, it prints “positive”. If it is negative, it asks for a real value and prints it. If it is zero it does nothing.

Variables: x Integer, y Single, sentence String

Example

Start

Put “positive” in sentence (String)

Print value of sentence

End

Print value of y

true x > 0

false

Get value from userand store in x (Integer)

Get value from userand store in y (Single)

true

falsex < 0

15 Aug 2011 14

Suppose there are two taxation systems, A and B.

Build sub CalculateTax with flowchart which asks for the chosen taxation system and for the income and then prints the tax according to the rule:

Class exercise

System

Income level

Tax

A < 20000 3000

>=20000 15% of income

B <50000 9000

>=50000 20% of income

15 Aug 2011 15

Solution of class exerciseStart sub CalculateTax

tax (Double)

EndPrint value of tax

falsesystem

= “A”

true

Get value from userand store in system (String)

true

falseincome< 20000

Get value from userand store in income (Long)

tax=3000 tax=income*0.15

true

falseincome< 50000

tax=9000 tax=income*0.2

Use operator &to concatenatestrings:”result is ” & tax

15 Aug 2011 16

In order to help subroutine CalculateTax, use a subroutine DoCalc which needs

income, income level, fixed tax, tax percentage

and calculates the tax.

Improvement

15 Aug 2011 17

Solution of improvementStart sub CalculateTax

tax (Double)

EndPrint value of tax

falsesystem

= “A”

true

Get value from userand store in system (String)

Get value from userand store in income (Long)

End

Start subroutine DoCalcparameters: income (Long), incomeLevel (Long),

fixedTax (Long), taxPercentage (Single), tax (Double)

tax=fixedTax

tax=income*taxPercentage

true

falseincome < incomeLevel

Call DoCalc(income,

20000,3000,0.15,tax)

Call DoCalc(income,

50000,9000,0.2,tax)

15 Aug 2011 18

Whenever a subroutine1. does not interact with the user2. gets its input from the parameters3. returns only one variable as output

it is much more efficient to use a function instead of a subroutine

Function calcTax2( … parameters … ) as Single… do the calculations here and put the result in a variable with the same name as the function …

End Function

Function

15 Aug 2011 19

FunctionStart sub CalculateTax

tax (Double)

End

Print value of tax

falsesystem

= “A”

true

Get value from userand store in system (String)

Get value from userand store in income (Long)

End returning calcTax

Start function calcTax (Double)parameters: income (Long), incomeLevel (Long),

fixedTax (Long), taxPercentage (Single)

calcTax=fixedTax

calcTax=income*taxPercentage

true

falseincome < incomeLevel

tax=calcTax(income, 20000,3000,0.15)

tax=calcTax(income, 50000,9000,0.2)

Print value of calcTax(income,

20000,3000,0.15)

15 Aug 2011 20

Functions are much more versatile and can be used directly in calculations and other functions or commands

Usage of functionsStart sub CalculateTax

tax (Double)

Print value of calcTax(income, 50000,9000,0.2)

falsesystem

= “A”

true

Get value from userand store in system (String)

Get value from userand store in income (Long)

End

15 Aug 2011 21

Homeworks Write a program with flowchart which asks for a an amount of money,

an interest rate and two dates StartDate and EndDate. Using a function to calculate the compound interest and a subroutine to get the data, print the compound interest.

Write function TaxDeduction (flowchart is too long) which gets as input children, income and age and returns the Italian tax deduction according to:

ChildrenAge of youngest child

Deduction

1 below 3 years 900 · (95,000 – income) / 95,000 3 years and more

800 · (95,000 – income) / 95,000

2 below 3 years 900 · (110,000 – income) / 110,000 3 years and more

800 · (110,000 – income) / 110,000

3 below 3 years 900 · (125,000 – income) / 125,000 3 years and more

800 · (125,000 – income) / 125,000

4 below 3 years 1,100 · (140,000 – income) / 140,000 3 years and more

1,000 · (140,000 – income) / 140,000

more than 4

Same formulas as above but 140,000 is increased by 15,000 for every child after the fourth.

Important: when the deduction is negative, it becomes 0.

15 Aug 2011 22

Write the squares of the numbers from 1 to 20

Example

Start

Set n (Integer) to 1

Print value of y

Calculate n*n and store value in y (Long)

Increment n by 1

Print value of y

Calculate n*n and store value in y

Increment n by 1

End

15 Aug 2011 23

FOR-NEXT loop

We want to repeat the same procedure in a similar way several times

FOR: SET UP A COUNTER(operations)NEXT: INCREMENT AND GO BACK

To go out of the loop before its end: EXIT FOR

15 Aug 2011 24

Write the squares of the numbers from 1 to 20

Variables: n Integer, y Long

Example6

Start

Set n (Integer) to 1 and loop

Print value of y

End

Calculate n*n and store value in y (Long)

Increment n by 1 and loop until n does not exceed 20

15 Aug 2011 25

Write the square root of the numbers from 3126 to 1087 going backwards with steps of 31

Variables: n Integer, y Long

Example7

Start

Set n (Integer) to 3126 and loop

Print value of y

End

Calculate sqr(n) and store value in y (Single)

Increment n by -31 and loop until n does not go below 1087

15 Aug 2011 26

Write the square root of the numbers from 3126 to 1087 going backwards with steps of 31, asking the user at each step whether he wants the program to end.

Example7bisStart

Set n (Integer) to 3126 and loop

Print value of y

End

Calculate sqr(n) and store value in y (Single)

Increment n by -31 and loop until n does not go below 1087

true

false

goon=“yes”

Get value from userand store in goon

goon (String)

Exit Fo

r

15 Aug 2011 27

Homework

Write function isEven with flowchart, which wants an integer as input and returns a Boolean (a variable with value True or False, without quotations!). To detect whether a number is even, use as condition Int(number/2)=number/2 .

Write a program with flowchart which asks the user for a positive integer and computes the following sequence for 20 times: if the number is even, halve it; if it's odd, multiply by 3 and add 1. Repeat this process until 20 times have been reached or until the value is 1, printing out each value. Finally print out how many of these operations have been performed.

Typical output might be: initial value is 9; next values are: 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1; number of steps 19

15 Aug 2011 28

Using functions

A function may be used: by a subroutine (or by another function), via direct

usage such as variable=functionName(parameters), where the subroutine is responsible for providing the parameters

inside an Excel sheet, exactly like any other Excel function, where parameters are written directly or indicated as cell reference, such as =functionName(D7;E5;27;0;A1)

Not run directly via Run button, since there is no way to pass parameters and no way to gather the function’s returned output

15 Aug 2011 29

Reading data from Excel sheet

To access Excel sheet we use Range(“E2:H9”).Cells(3,2)

which corresponds to cell F4, since (3,2) are the row and column of the range! Therefore E2 is (1,1), F2 is (1,2), F3 is (2,2) and F4 is (3,2).

Range(“E2:H9”).Count

which tells us the number of cells in the range (in this case 32)

15 Aug 2011 30

Example

Write program Multiplic which reads number in cell D5, multiplies it by the number in cell D6 and prints the result.

Compact it using a single instruction.

Start

End

a (Single)a= Range(“D5”).Cells(1,1)

Print value of a*b

a = Range(“D1:D20”).Cells(5,1)

b = Range(“D5:D6”).Cells(2,1) b (Single)b= Range(“D6”).Cells(1,1)

15 Aug 2011 31

Example

Write program FixCell which asks the user for a cell reference and a real number and puts that number in that cell.

Start

End

get a string from user and store it in cellReference (String)

Range(cellReference).Cells(1,1)=value

get a single from user and store it in value (Single)

15 Aug 2011 32

Array

We want to store many values of the same type

ARRAY

It always needs to be prepared It is accessed directly indicating the

index

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

15 Aug 2011 33

Ask the user 20 real numbers and store them into an array. Ask the user which value he wants to be printed and print it.

Variables: x Array of Single, j Integer, n Integer

Example11Start

Print value in n-th position of x

Get value from user andstore in n (Integer)

End

Set j (Integer) to 1 and loop

Prepare an array xcontaining 20 single

Get value from user and store in j-th position of x

Increment j by 1and loop until j exceeds 20

15 Aug 2011 34

Ask the user 20 real values. When you have all of them, calculate their sum. Then print it.

Variables: x Array of Single, j Integer, sum Single

Example11bis

Start

Print value of sum

End

Set j (Integer) to 1 and loop

Prepare an array xcontaining 20 single

Get value from user and store in j-th position of x

Increment j by 1and loop until j exceeds

20

sum (Single)sum = 0

j=1 and loop

Increment j by 1and loop until j exceeds 20

sum = sum + x (at j-th position)

15 Aug 2011 35

Improve the previous program using only one loop and telling each time which number the user is entering (4th, 5th, …)

Improve it further more using 1st, 2nd, 3rd instead of 1th, 2th, 3th and do not use an array!

Example11ter

15 Aug 2011 36

Example15

Read numbers in range D3:D13 and put them in array x with indexes 1 to 11. Then print the fifth element of the array

Start

End

Set j (Integer) to 1 and loop

Increment j by 1and loop until j exceeds 11

x array of Single 1 To 11

x(j)= Range(“D3:D13).Cells(j,1)

Print value of x(5)

For j=3 To 13x(j–2)=Range(“D1:D13”).Cells(j,1)

For j=1 To 11x(j)=Range(“D1:D13”).Cells(j+2,1)

15 Aug 2011 37

Get 20 values from D1:D20 and put them into an array. When you have all of them, ask the user for a bound. Then print how many of the 20 values exceed that bound.

Example12

Start

Print value of count

End

Set j (Integer) to 1 and loop

Prepare an array xcontaining 20 single

x(j)=Range(“D1:D20”).Cells(j,1)

Increment j by 1and loop until j exceeds

20

count (Integer)count= 0

j=1 and loop

Increment j by 1and loop until j exceeds 20

count = count+1

Get value from user and store in bound (Single)

true

false

x(j) > bound

15 Aug 2011 38

Whenever we are not sure of from where to where the array index goes, we can use functions LBound(x) and UBound(x) which automatically take the value of the first and the last index of the array x

Rewrite the previous program using LBound(x) and UBound(x) instead of 1 and 20

LBound and UBound

15 Aug 2011 39

Build a function countLargerThanLimit which accepts as input an array of singles and a limit and returns how many elements of the array are larger than the limit In this function you must use LBound and

UBound because the function cannot know a priori the array bounds

Example12ter

15 Aug 2011 40

Ask the user 20 real numbers. When you have all of them, calculate the average of the positive ones. Then print it.

Hints First build a program which simply calculates the average Use count (Integer) variable to count how many are positive Start setting count=0 (exactly as sum is set equal to

0) Use IF-THEN-ELSE condition to check whether each

number is positive (and therefore should be summed and counted)

Example13

15 Aug 2011 41

SolutionStart

Print value of average

End

Set j (Integer) to 1 and loop

Prepare an array xcontaining 20 single

Get value from user and store in j-th position of x

Increment j by 1and loop until j exceeds 20

sum (Single)sum = 0

j=1 and loop

Increment j by 1and loop until j exceeds 20

sum = sum + x(j)

average (Single)average = sum / count

count (Integer)count = 0

count = count + 1

truex(j)>0

false

15 Aug 2011 42

What happens when all 20 values are negative? The computer crashes since a division by

zero was found!

We need to check that count be positive before dividing!

Problem of the solution

15 Aug 2011 43

Better solutionStart

Print value of average

End

Set j (Integer) to 1 and loop

Prepare an array xcontaining 20 single

Get value from user and store in j-th position of x

Increment j by 1and loop until j exceeds 20

sum (Single)sum = 0

j=1 and loop

Increment j by 1and loop until j exceeds 20

sum = sum + x(j)

average (Single)average = sum / count

count (Integer)count = 0

count = count + 1

truex(j)>0

false

true count>0

false

Print value of sentence

sentence (String)sentence = “sorry no positive”

15 Aug 2011 44

Build a function which receives d (array of 20 Date), m (Single) and r

(array of 20 Single). For each d and r,

if d is in the past and r is positive, calculate the interest from d to now, using m as money amount and the corresponding r as interest rate.

Otherwise, do not consider this data. Return the average of the calculated interests.

Hints You can use And operator (like in Access) To get current date, there is Now() function Write also a program which reads the data from

columns G, H, I of Excel sheet and tests the function.

Homework (example 14)

15 Aug 2011 45

Solution sum (Single)sum = 0

Start with d (array of 20 Date),m (Single), r (array of 20 Single)

count (Int)count = 0

End returning average

Set j (Integer) to 1 and loop

Increment j by 1and loop until j exceeds 20

false

true

d(j)<Now()And

r(j)>0count = count +1

interest (Single)interest = m * ( 1+r(j) ) (Now – d(j)) / 365 – m

sum = sum + interest

Starting variables: d (array of 20

Date) m (Single) r (array of 20

Single) Used variables:

interest (Single) count (Integer) sum (Single) average (Single)

average (Single)average = sum / count

15 Aug 2011 46

Homework

Build function MaxOfArray which receives an array of singles and returns the maximum Hint: try to think at how would you do

this task manually step by step and then replicate it on a program

Build a subroutine to test the function, using the data in column D

15 Aug 2011 47

Solution Start function MaxOfArrayParameters: x array of Single

End returning maxCandidate

Set j (Integer) to second index of array and loop

maxCandidate (Single)maxCandidate=first element of array

Increment j by 1and loop until j exceeds

the last index of the array

maxCandidate = x(j)

true x(j)>maxCandidate false

15 Aug 2011 48

WHILE-WEND loop

We want to repeat the same procedure in the same way until something happens

WHILE: (condition) (operations)WEND: GO BACK

15 Aug 2011 49

Ask the user a real value. If it is negative, print “bye” and stop. If it is positive or zero, tell the user its square root and ask another. Go on over and over.

Variables: y Single, squareroot Single, sentence String

Example16Start

End

While y >=0

Print value of squareroot

go back

Get value from userand store in y (Single)

Calculate sqr(y) and store in squareroot (Single)

Get value from userand store in y

Print value of sentence

sentence (String)sentence = “bye”

15 Aug 2011 50

Do not use WHILE-WEND loop but use IF instead.

You need to “jump” to another place in the program and it is not possible (for the moment)

Variables: y Single, squareroot Single, sentence String

Equivalent exampleStart

End

Print value of squareroot

Get value from userand store in y (Single)

Calculate sqr(y) and store in squareroot (Single)

Get value from userand store in y

true y >= 0

false

Print value of sentence

sentence (String)sentence = “bye”

15 Aug 2011 51

Build a function which receives x (array of Single). It goes through each value of x calculating the sum of the values, stopping when a zero value is found. Then it returns the sum.

Hints The loop can end for two reasons: a zero value is found

or all 30 values have been examined You can use the FOR-NEXT loop, but in this case you must

add a condition which “jumps” to the end of the program when a zero is found

You can instead use the WHILE-WEND loop, but in this case you must add a manual counter to go through x which takes care of ending when it reaches 30

Build a sub which takes data from column D to test the function

Homework (example17)

15 Aug 2011 52

Solutions

End returning sum

sum (Single)sum = 0

Start with x (Array of 30 Single)

Set j (Integer) to first index and loop

Increment j by 1 and loop until j exceeds last index

true x(j) <> 0

false

sum = sum + x(j)

End returning sum

sum (Single)sum = 0

Start with x (Array of 30 Single)

sum = sum + x(j)

Do only ifx(j)<>0 and j<=last index

go back

j (Integer)j = first index

j = j + 1

15 Aug 2011 53

Build a program which reads an array of singles (for example D1:D22) and reprints them sorted from smallest to largest

Hints First think at how you would do this task step by

step manually Then rethink carefully at each step of the

manual procedure Then, according to the algorithm you have

invented, it might be useful either to build a separate array to put the data or to build a subroutine which accepts an array and two indexes and switches the position of the elements in the array

Extremely difficult homework