15 aug 20111 visual basic for applications programming language very similar to visual basic...
TRANSCRIPT
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