Вы находитесь на странице: 1из 47
Course Visual Basic for Applications Course VBA/Excel ©2016 Stelling Consulting. All rights reserved

Course Visual Basic for Applications

Course VBA/Excel

©2016 Stelling Consulting. All rights reserved

Agenda

Agenda Part I “VBA theory” 1. Course goal + Demo 2. Command button and user message

Part I “VBA theory”

1. Course goal + Demo

2. Command button and user message + Exercise

3. Procedures syntax

4. Variables

5. Decisions, loops, exits

6. Debugging

7. Exercise: procedure, variables, decisions, loops, exits, debugging

Part II “VBA and MS Excel”

1.

Reading from and writing to a worksheet + Exercises

2.

User defined formula + Exercise

3.

Increasing run speed

4.

Macro recording + Exercise

5.

Option boxes + Exercise

Appendices

1.

Constants, user defined variable types, optional input variables

2.

String functions

3.

Error handling example

4.

Random number generation (repeatable)

5.

Reading from and writing to text files

6.

Various “How to”

2

Random number generation (repeatable) 5. Reading from and writing to text files 6. Various “How to”

After this course you should be able to create VBA (Visual Basic for Applications) procedures in MS Excel

VBA can be used to

Prevent manual work and human error

Create user defined formula

Create responsive user interfaces

Run a calculation model many times for different inputs (while accumulating results)

Perform complex calculations like route planning, production planning, multi-echelon inventory optimization, demand forecasting, system/queuing simulation, warehouse location optimization, etc.

However, try to use VBA as less as possible

MS Excel offers a huge amount of standard functionality

VBA code errors will eventually occur: users become frustrated and stop using the program

Who will maintain the code if the programmer is not available?

Outside course scope

A.o. VBA user forms

3

– Who will maintain the code if the programmer is not available? • Outside course scope

Exercise 1: create a button that shows a message

• First: via main menu File → Options (1) → Customize ribbon (2) → check Main tab Developer (3)

2 3 1
2
3
1

4

message • First: via main menu File → Options (1) → Customize ribbon (2) → check

Insert a button

Go to tab Developer Insert select the Command Button (Active X control)*

Insert → select the Command Button (Active X control)* • While pressing left mouse button, draw

While pressing left mouse button, draw a rectangle in the worksheet, then release mouse button

draw a rectangle in the worksheet, then release mouse button * In general Form Controls are
draw a rectangle in the worksheet, then release mouse button * In general Form Controls are

* In general Form Controls are recommended. But ActiveX controls are more tightly linked to VBA code and therefore used in this VBA course.

5

are recommended. But ActiveX controls are more tightly linked to VBA code and therefore used in

Change button name (Name) and text (Caption) properties via right mouse click

Set Name and Caption as shown at the right

mouse click • Set Name and Caption as shown at the right • Name (reference to
mouse click • Set Name and Caption as shown at the right • Name (reference to

Name (reference to VBA) and Caption (shown on button itself) should be self-explaining

Use capitals in a Name

Some naming conventions

– Command buttons start with ‘cmd

– Option buttons with 'opt‘

– Check boxes with ‘chk

6

– Command buttons start with ‘ cmd ‘ – Option buttons with 'opt‘ – Check boxes

Left double click on the button to open the VBA programming environment

• Notice the “header and footer” for the button’s Sub procedure have been generated automatically

The VBA programming environment is organized around workbook, sheets, modules

Sheet1 (Sheet2, etc.)

Contains procedures to be executed by pressing buttons on the worksheet

ThisWorkbook

Contains procedures to be executed by opening or closing the Excel-file

Module1 (Module2, etc)

– Contains general procedures (e.g. recorded macro’s)

Modules are added manually via menu Insert. Initially there will be no modules seen in the Project Explorer pane.

there will be no modules seen in the Project Explorer pane. Press Control+R if you don’t

Press Control+R if you don’t see this left pane (or via menu View → Project Explorer)

7

in the Project Explorer pane. Press Control+R if you don’t see this left pane (or via

Type the code shown below, executed when the button is clicked

Add comments (in English) to explain the code. Start with . Comments become green automatically.

code. Start with ‘ . Comments become green automatically. • As soon as you type this

As soon as you type this comma, a list of (self-explanatory) options appears that can be combined with "+“

In general, frequently used is a yes-no-button to ask if the user wants to proceed. If not, then this results in

an “exit” of the procedure.

is a yes-no-button to ask if the user wants to proceed. If not, then this results
is a yes-no-button to ask if the user wants to proceed. If not, then this results

8

is a yes-no-button to ask if the user wants to proceed. If not, then this results

Close VBA (press x in upper right corner), Exit Design Mode and press your button.

Exit the Design mode

This mode has been activated automatically creating the button

In this mode you control VBA, but you cannot press the button)

this mode you control VBA, but you cannot press the button) • Test your code by

Test your code by pressing the button. If the following message appears: congratulations!

cannot press the button) • Test your code by pressing the button. If the following message

9

cannot press the button) • Test your code by pressing the button. If the following message

A Sub procedure performs a task, a Function procedure has also an output value. The

syntax of both is similar. Use a self-explaining procedure name with capitals.

Syntax Sub procedure

Sub NameSubProcedure(InputVariable1 As Type,…,InputVariableN As Type)

Dim LocalVariable1 As Type Dim LocalVariableN As Type

instruction(s) End Sub

Syntax Function procedure

Function NameFunctionProcedure(InputVariable1 As Type,…,InputvariableN As Type) As Type

Dim LocalVariable1 As Type

Dim LocalVariableN As Type

instruction(s) NameFunctionProcedure = output value End Function

Variables are input, output and local memory of procedures

Syntax Function procedure

Function NameFunctionProcedure( InputVariable1 As Type,…, InputvariableN As Type) As Type Dim LocalVariable1 As Type

Dim LocalVariableN As Type

Dim means ‘create’

instruction(s) NameFunctionProcedure = output value (determined by input and instructions) End Function

Example

Function Plus(ByVal NumberOne As Integer, ByVal NumberTwo As Integer) As Integer Dim SumBoth As Integer

SumBoth = NumberOne + NumberTwo Plus = SumBoth End Function

11

As Integer) As Integer Dim SumBoth As Integer SumBoth = NumberOne + NumberTwo Plus = SumBoth

Give variables logical names and declare variable types explicitly

Give variables logical names

– This makes code better understandable and enables ‘find and replace’; e.g. iCustomer is better than i

Declare explicitly, e.g. Dim

iCustomer

as Integer

Variable Type

Data type

Conversion function

Integer

Whole numbers between -32.768 en 32.767

CInt *

Long

Whole numbers between -2.147.483.648 and 2.147.483.647

CLong

Single

Fractional numbers between -3,402823 E38 en 3,40283 E38

CSng

Double

Fractional numbers between -1,7976931486232E308 and 1,7976931486232 E308

DDbl

Currency

Fractional numbers between -922.337.203.685.477,5807 and 922.337.203.685.477,5807 (always 4 decimals, no rounding errors)

CCur

String

Up to 65.000 characters

CStr *

Boolean

True of False

CBool

Date

January 1st 100 to December 31st 9999

CDate

Object/Range

Every object / worksheet cell or ranges

Variant

Variable which automatically detects what type it should become, based on input. Can also be an array. Or Null (empty). Default type, if user hasn’t specified the type.

CVar

12

*

CStr(10)

CInt("10") →

"10"

10

Default type, if user hasn’t specified the type. CVar 12 * CStr(10) CInt ("10") → →

Intermezzo: go into the VBA environment (via ALT-F11), menu Tools -> Options, and check Require Variable Declaration

The line Option

Each variable has now to be declared explicitly, reducing the risk of errors

Explicit will be set automatically each next time you create a new workbook

1 2 3
1
2
3

13

reducing the risk of errors Explicit will be set automatically each next time you create a

You can create array variables (≈ multidimensional table)

Creating a table with 100 random numbers. Each element is controlled via its index, here named iNumber

Dim RandomNumber(100) as Single Dim iNumber as Integer

For iNumber = 1 to 100 RandomNumber(iNumber)= Rnd() Next iNumber

Creating a table with 3 sets of 100 random numbers

Function Rnd() draws a random number between 0 and 1

Dim RandomNumber(1 to 3, 1 to 100) as Single Dim iSet as Integer, iNumber as Integer For iSet = 1 to 3 For iNumber = 1 to 100 RandomNumber(iSet, iNumber)= Rnd() Next iNumber Next iSet

RandomNumber(100) in fact contains 101 elements as 0 is the first index. To start at index 1:

Put Option

or declare as Dim RandomNumber(1 to 100) as Single

Base

1 below Option Explicit

at the top of your code

Storing datasets into array variables (= memory) speeds up execution, as this works faster than reading/writing variable values from/to sheet

14

array variables (= memory) speeds up execution, as this works faster than reading/writing variable values from/to

Create conditional execution with If

… Then … Else

or Select Case

If condition then instruction(s) End If

If condition Then

instruction1

Else

instruction2

End If

Use And and Or and brackets to combine conditions Use Not to create the opposite condition

If ((i1=1) And (x=“abc")) Then

If ((i1=1) Or (x=“abc")) Then

If Not((i1=1) and ((i2=false) Or (x=“abc"))) Then

If condition1 Then

instruction1

ElseIf condition2 Then

instruction2

ElseIf condition3 Then

instruction3

End If

versus

Conditions may contain multiple variables of different types

Select Case VariableValue Case 1: instruction1 Case 2,3:

instruction2

Case 4 to 10:

instruction3

Case Else: instruction4

End Select

Only one variable can be used

15

Example

Select Case strDay Case "MON": dayNr = 1 Case "TUE": dayNr = 2 Case "WED": dayNr = 3 Case "THU": dayNr = 4 Case "FRI": dayNr = 5 Case "SAT": dayNr = 6 Case "SUN": dayNr = 7 End Select

dayNr = 4 Case "FRI": dayNr = 5 Case "SAT": dayNr = 6 Case "SUN": dayNr

Create conditional loops with Do

Use For

While…Loop or Do Until…Loop

Next

for unconditional loops

Do While condition instruction(s) Loop

Do Until condition instruction(s) Loop

Looping at least once:

Do

Do

instruction(s) Loop While condition

instruction(s) Loop Until condition

Use For

Next

in case the number of loops is known beforehand:

For i1=1 to 10 instruction(s) Next i1

Use step if step size is not 1 For i1 = 10 to 20 step 2 For i1 = 20 to 10 step -5

Use For

Next

working with arrays:

Function Ubound gives the array length

working with arrays: Function Ubound gives the array length For Each element In array instruction(s) Next

For Each element In array instruction(s) Next element

For i1 = 1 to Ubound(array) instruction(s) Next i1

16

For Each element In array instruction(s) Next element For i1 = 1 to Ubound( array )

Use exit to exit loops and procedures immediately

Exit loops by Exit For and Exit Do

Exit procedures by Exit Sub and Exit Function

Exit program by End

For i1 = 1 to 100

If ThisValue = ValueToFind then Exit For ContinueSearching

Next i1

Public Sub deleteRecords() If MsgBox(“Delete all records?”, vbYesNo) = vbNo Then Exit Sub DeleteAllRecords

End Sub

17

Sub deleteRecords() If MsgBox (“Delete all records?”, vbYesNo) = vbNo Then Exit Sub DeleteAllRecords End Sub

Exercise: create a prime number generator

A prime number is a number that can only be divided by 1 and itself:

1, 2, 3, 5, 7, 11, 13, 17, 19, 23, etc.

Follow the step-by-step approach. Read all steps first

• Follow the step-by-step approach. Read all steps first • Step 1. Create a button that

Step 1. Create a button that starts a procedure showing numbers 1,2,3,4,etc. until the user wants to exit

Use a variable iNumber that will increase

Loop, Msgbox

Combine text and a variable in a message like

Use Do While True

• Step 2. Create an ‘is odd’ check

Use If

Then

Mod gives the remainder of a division, e.g. (41

and exit sub “Number = ” & str(iNumber). Hard return = vbCrlf

Mod 3) = 2.

Step 3. Create an array primeNumber in which all odd numbers are stored

Use a counter nPrime

Step 4. Replace the 'is odd'-check of step 2 by an 'is prime number'-check and store prime numbers

Use a boolean isPrimeNumber and initiate isPrimeNumber = true.

Use For

( Additional: you may Use Exit

Next and loop to check if the current number can be divided by any of the previous prime numbers.

For to exit the check as soon as a division is possible.)

18

number can be divided by any of the previous prime numbers. For to exit the check

Demonstration: debug by adding breakpoints

Demonstration: debug by adding breakpoints • Define breakpoints by clicking in the grey bar at the

Define breakpoints by clicking in the grey bar at the left of the code

• Put cursor in the 1st line of code, then press F5 or ‘green triangle’

The program will run until it hits the 1st breakpoint.

– The program will run until it hits the 1st breakpoint. • Press F8 to execute

Press F8 to execute a single next line

Press F5 to execute all lines to the next breakpoint

• Press ‘blue square’ to stop executing

Press [BREAK] to kill endless looping

lines to the next breakpoint • Press ‘blue square’ to stop executing • Press [BREAK] to

19

lines to the next breakpoint • Press ‘blue square’ to stop executing • Press [BREAK] to

Demonstration: debug by investigating variable values during execution

debug by investigating variable values during execution • Put the mouse cursor on top of a

Put the mouse cursor on top of a variable to check its value

Open a debug screen (menu Debug Add watch) and add variables

to it to check variable values continuously (even multi dimensional arrays).

20

Debug → Add watch) and add variables to it to check variable values continuously (even multi
Debug → Add watch) and add variables to it to check variable values continuously (even multi

Agenda

Part I “VBA theory”

1. Course goal + Demo

2. Command button and user message + Exercise

3. Procedures syntax

4. Variables

5. Decisions, loops, exits

6. Debugging

7. Exercise: procedure, variables, decisions, loops, exits, debugging

procedure, variables, decisions, loops, exits, debugging Part II “VBA and MS Excel” 1. Reading from and

Part II “VBA and MS Excel”

1.

Reading from and writing to a worksheet + Exercises

2.

User defined formula + Exercise

3.

Increasing run speed

4.

Macro recording + Exercise

5.

Option boxes + Exercise

Appendices

1.

Constants, user defined variable types, optional input variables

2.

String functions

3.

Error handling example

4.

Random number generation (repeatable)

5.

Reading from and writing to text files

6.

Various “How to”

21

Random number generation (repeatable) 5. Reading from and writing to text files 6. Various “How to”

Reading from and writing to a worksheet (object Range)

1. Using cell reference

2. Using named cells

3. Using named ranges

XX

= Range("D5").Value, or

XX = Range("UpperLeft").Value

XX = Range("Tabel_In").Cells(5,4).Value, or

XX

= Cells(5,4).Value

XX

= Range(“Upperleft").Cells(5,4).Value, or

 

XX

= Range(“Upperleft”).Offset(4,3).Value

XX

becomes 76

XX becomes 67

XX becomes 20

Moving the table will cause errors

67 XX becomes 20 Moving the table will cause errors Moving the table does not harm

Moving the table does not harm

the table will cause errors Moving the table does not harm • Writing to sheet is

Writing to sheet is done the reversed way

Moving the table does not harm

is done the reversed way Moving the table does not harm Range(“ Tabel_In").Cells(5,4).Value = XX •

Range(“Tabel_In").Cells(5,4).Value = XX

In case of multiple sheets, you may want to specify the sheet:

XX = Sheets("Sheet1").Range("UpperLeft").Value

22

of multiple sheets, you may want to specify the sheet: XX = Sheets("Sheet1").Range("UpperLeft").Value 22

Exercise: create a single-line-program that puts the sum of values in a cells named InOne and InTwo in a cell named OUT, after pressing button Sum

that puts the sum of values in a cells named InOne and InTwo in a cell

23

that puts the sum of values in a cells named InOne and InTwo in a cell

Exercise: write the prime number generator output to worksheet

Step 5. Write prime numbers to sheet during the execution loop.

Construct this in such a way the user can easily drag the range somewhere else and the program will put numbers at the new location next time, using a named cell Start.

the range somewhere else and the program will put numbers at the new location next time,
the range somewhere else and the program will put numbers at the new location next time,

24

the range somewhere else and the program will put numbers at the new location next time,

Frequently used Range property examples

Range("TABLE").Value = 7

• Range("TABLE").Value = “” Range("TABLE").ClearContents

• Range(“TABLE").Rows.Count / .Columns.Count

• Range(“B:B”).EntireColumn.Hidden = true/false

• Range(“5:9”).EntireRow.Hidden = true/false

For i1 = 1 To Sheets.Count

Sheets(i1).Range("A1") = 9

Next i1

25

all cells in range TABLE become 7

clears values clears values

# rows/columns in a range

hide/show column

hide/show row

looping through all sheets

.value = default , so not really

required as such

in a range hide/show column hide/show row looping through all sheets .value = default , so

Looping through all cells in a range & calling an Excel formula *

all cells in a range & calling an Excel formula * • The first method uses

The first method uses a row and column counter to loop through cells. This way you can control the calculation order (i.e. first by row then by column, or vice versa).

The second method is leaner. It also demonstrates the use of CurrentRegion to determine a variable range size: numbers in adjacent rows and columns - outside named range TABLE_IN - will also become colored.

Use WorksheetFunction. to call Excel functions

• Use WorksheetFunction. to call Excel functions * This looping-example is still valid. But VBA code

Creating your own Excel formula is done by creating a public function in a module (macro’s are also found in a module)

Insert a module and create your functions in there.

• Insert a module and create your functions in there. • Advantages – In general –

Advantages In general

your functions in there. • Advantages – In general – You can add missing functionality, create

You can add missing functionality, create smaller or better readable models

Disadvantages In general

User defined functions execute somewhat slower than standard Excel formula

– Users will have to enable Macro’s. Sometimes they do not know how. This is done via File → Options Trust Centre → Macro security level. You can always press F1 and search for “Macro security level”.

27

→ Trust Centre → Macro security level. You can always press F1 and search for “Macro

Example: road distance estimation between two geographical locations

Easier to read/plug in/copy across than a nasty long standard formula in Excel

in/copy across than a nasty long standard formula in Excel Public Function RoadDistance(LatFrom As Range, LonFrom

Public Function RoadDistance(LatFrom As Range, LonFrom As Range, LatTo As Range, LonTo As Range) As Double Const Pi = 3.14159265358979 Const R = 6371 Dim dLat As Single, dLon As Single, lat1 As Single, lat2 As Single, a As Single lat1 = LatFrom * Pi / 180 lat2 = LatTo * Pi / 180

dLat = (LatTo - LatFrom) * Pi / 180

dLon = (LonTo - LonFrom) * Pi / 180 a = Sin(dLat / 2) * Sin(dLat / 2) + Sin(dLon / 2) * Sin(dLon / 2) * Cos(lat1) * Cos(lat2) RoadDistance = 1.18 * R * 2 * WorksheetFunction.Atan2(Sqr(1 - a), Sqr(a)) End Function

1.18 is a factor to convert the as-the-crow-flies-distance into an estimated road distance.

See also http://www.stellingconsulting.nl/SC_AsTheCrowFliesDistance.php (which presents an MS Excel formula for the as-the-crow-flies-distance)

28

(which presents an MS Excel formula for the as-the-crow-flies-distance) 28

Example: interpolation within a table

Adds functionality difficult to construct with formulas

• Adds functionality difficult to construct with formulas • VBA code of this function is found

VBA code of this function is found on: http://www.stellingconsulting.nl/SC_InterpolateXY.php

29

with formulas • VBA code of this function is found on: http://www.stellingconsulting.nl/SC_InterpolateXY.php 29

Exercise: create a function ClosestLocation using the road distance function

Keeps a model small (single column versus as many as there are locations)

Add the RoadDistance formula to your sheet first (copy from the presentation).

The function ClosestLocation (i.e. closest to the origin of a flow) will have 4 input ranges. First create a

button that runs a closest location procedure for the first flow record. Derive the function from that.

First create a button that runs a closest location procedure for the first flow record. Derive

30

First create a button that runs a closest location procedure for the first flow record. Derive

Increasing run speed

Prevent continuous screen updating:

Application.ScreenUpdating = false

Prevent continuous calculation:

Application.Calculation = xlCalculationManual

Do While

Set input data Recalculate: Calculate Store outcomes Show progress to user: Application.StatusBar = “Calculating item “ & str(iItem) Loop

Reactivate regular Excel behavior at the end of your procedure:

Application.Calculation = xlCalculationAutomatic Application.ScreenUpdating = true Application.StatusBar = ""

If due to a bug the line Application.Statusbar =

"" is not reached/executed, then your last user message will

be shown all the time, instead of regular Excel messages. This is annoying, so make sure this will not happen.

Use variables instead of Excel cells to read/write data during execution

Only if run time still remains too slow, as this requires (a lot) more effort than the above

31

data during execution – Only if run time still remains too slow, as this requires (a

A fast way to generate VBA-code is to Record a Macro (= record your manual actions)

Start macro recording. Perform actions in Excel. Stop Recording.

macro recording. Perform actions in Excel. Stop Recording. • Press ALT+F11 (or press View code on
macro recording. Perform actions in Excel. Stop Recording. • Press ALT+F11 (or press View code on

Press ALT+F11 (or press View code on the Developer tab) to go to the code of Macro1 which is found in Module 1 (press CTRL+R to see the VBA project explorer if it is not visible yet)

Copy (or cut) the code and paste it behind your own button (or refer to this macro)

Minor drawback: macro recording tends to generate longer code, e.g.

Range("A1:B3").Select

Selection.Copy

Range("G4").Select

ActiveSheet.Paste

Compare to

Range("A1:B3").Copy Destination:=Range("G4")

32

Range("G4").Select ActiveSheet.Paste Compare to Range("A1:B3").Copy Destination:=Range("G4") 32

Exercise: create and adjust a Macro

Record a macro that copies values in the selected column to the next column and sorts it

Adjust the Macro code to make sure it always works (regardless the amount of numbers or the column).

Additional exercise: a daily task that could be automated?

33

works (regardless the amount of numbers or the column). • Additional exercise: a daily task that

Exercise: create options that trigger code to (un)hide column C

Besides buttons, options, check boxes and combo boxes are often used in a user interface.

boxes and combo boxes are often used in a user interface. – They come in two

They come in two flavours: Forms and Active-X. Active-X can be controlled directly with VBA code (e.g. me.chkHide true) instead of indirectly via the linked cell (set via right mouse button). But Form controls have less “issues”.

=

Forms
Forms
Active-X
Active-X

Select option and press right mouse button to assign your VBA code to the option

With Active-X you can jump into code by double clicking on it, in Design Mode

Using the linked cell a single line of code can be linked to both options

34

by double clicking on it, in Design Mode • Using the linked cell a single line

Example

Hiding rows or columns you can hide chart data from the user (as data on hidden rows or columns will not appear in a chart if this option is set)

chart data from the user (as data on hidden rows or columns will not appear in
chart data from the user (as data on hidden rows or columns will not appear in

35

chart data from the user (as data on hidden rows or columns will not appear in

Agenda

Part I “VBA theory”

1. Course goal + Demo

2. Command button and user message + Exercise

3. Procedures syntax

4. Variables

5. Decisions, loops, exits

6. Debugging

7. Exercise: procedure, variables, decisions, loops, exits, debugging

procedure, variables, decisions, loops, exits, debugging Part II “VBA and MS Excel” 1. Reading from and

Part II “VBA and MS Excel”

1.

Reading from and writing to a worksheet + Exercises

2.

User defined formula + Exercise

3.

Increasing run speed

4.

Macro recording + Exercise

5.

Option boxes + Exercise

Appendices

1.

Constants, user defined variable types, optional input variables

2.

String functions

3.

Error handling example

4.

Random number generation (repeatable)

5.

Reading from and writing to text files

6.

Various “How to”

36

Random number generation (repeatable) 5. Reading from and writing to text files 6. Various “How to”

Give a variable a correct prefix, and declare at the correct place

Public variables

on top of sheet (or

on top of sheet (or

module)

Private procedure

Private procedure

Public procedure

Public procedure

Local variables within procedure

Local variables within procedure
Constant variable
Constant variable

Input variables in procedure header

Range of use

Prefix

Within procedure

Dim (value is erased from memory) or Static (value is kept in memory hardly ever used) in front of variable

Within sheet/module (Private = invisible for user)

Private in front of variable at the top of the sheet/module or in front of Sub/Function

Put Option Private

Module at the top of a module to make it private

Within all sheets/modules (Private = visible to user)

Public in front of variable at the top of module or in front of Sub/Function

Recorded Macro’s are public procedures found in a module. Leaving out Private or Public means it is Public (default)

37

Recorded Macro’s are public procedures found in a module. Leaving out Private or Public means it

Use ByVal in procedure headers or put () around input variables calling a procedure if you want to make sure input variables do not change, as may happen using ByRef (default, so you may leave it out)

The example below is a weird construct as such

leave it out) The example below is a weird construct as such • Without ByVal typing

Without ByVal typing AddTwo

UserInput would cause original input variable UserInput to

become 9 and then 11 instead of staying 7. Of course, this only happens if the VBA code works directly on the input variable itself.

38

then 11 instead of staying 7. Of course, this only happens if the VBA code works

You can make arrays grow dynamically, saving memory

If the array length is unknown beforehand, you may let it grow dynamically:

Don’t specify dimensions when declaring the array:

Dim RandomNumber() as Integer Suppose you have a first number to be stored

Redim RandomNumber(1) RandomNumber(1) = 7

Use Preserve if you want to keep existing values when re-dimensioning again

Redim Preserve RandomNumber(2) RandomNumber(2) = 28

Functions LBound and UBound give array lowerbound and upperbound (= length)

NumberOfRandomNumbers

= Ubound(RandomNumber)

In case of multidimensional arrays, also specify the set number NumberOfRandomNumbersInSet2 = Ubound(RandomNumber,2)

39

In case of multidimensional arrays, also specify the set number NumberOfRandomNumbersInSet2 = Ubound(RandomNumber,2) 39

You can define constant variables, or create your own types in a module

In sheet (used in that sheet only)

Const conPi = 3.14159

In module (used throughout workbook)

Public Const conPi = 3.14159

Example of using a custom defined variable type

Cities(1).name = “Haarlem”

Cities(1).longitude = 4.666

Cities(1).latitude = 52.353 Cities(2).name = “Alphen” Cities(2).longitude = 4.662 Cities(2).latitude = 52.128

Instead of hard coded input, normally values are

read from sheet or text file

= 4.662 Cities(2).latitude = 52.128 Instead of hard coded input, normally values are read from sheet
= 4.662 Cities(2).latitude = 52.128 Instead of hard coded input, normally values are read from sheet

40

= 4.662 Cities(2).latitude = 52.128 Instead of hard coded input, normally values are read from sheet

Optional variables, Isempty, and IsNull

With IsNull

With IsEmpty you check if a variable has been initialized

you check if an expression contains an invalid value (Null)

IsNull and Isempty are used on variables of type Variant

In such a case these variables have been defined as optional

Optional variables are defined after all non-optional ones in the header of a procedure. You can use them to

overwrite default values. The use of optional variables can cause confusion.

Example

Function TitleName(Name As String, Optional Title As String) As String If IsEmpty(Title) Or IsNull(Title) Then TitleName = “Mr. " & Name

Else

TitleName = Title & " " & Name End If End Function

41

Then TitleName = “Mr. " & Name Else TitleName = Title & " " & Name

String functions

Function and input

Result

left("hello",3)

"hel"

right("hello",2)

"lo"

mid("hello",3,2)

"ll"

(start with 3rd character and give next two characters)

instr("hello",“el")

"hello" & " and good bye"

trim(" hello

Ucase("hello")

")

(start position of searched sub string) "hello and good bye" "hello" "HELLO"

2

Lcase("HELLO")

"hello“

Format(0.8954,”00.00%”)

89.45%

42

"HELLO" 2 • Lcase ("HELLO") "hello“ • Format (0.8954,”00.00%”) 89.45% 42

Use GoTo to bypass code. Often used in combination with On

Use GoTo to bypass code. Often used in combination with On 43 Error
Use GoTo to bypass code. Often used in combination with On 43 Error
Use GoTo to bypass code. Often used in combination with On 43 Error

43

Error

Use GoTo to bypass code. Often used in combination with On 43 Error

Generating random variables

Randomize Initialize the random generator with a seed, e.g. Timer

Rnd Rnd gives a random number between [0,1>, uniform distribution

To generate a number between 1 and 9:

RandomNumber = Int((9 * Rnd) + 1)

Or even better maybe:

RandomNumber = worksheet.function.randbetween(1;9)

Rnd -1

Randomize (RandomSeed)

Use this construct with a fixed Randomseed to create a simulation

which gives the same sequence of random numbers each time you

run it, so you can debug more easily

At the right: code to generate random variables of different

distribution types: constant, uniform, traingular, neg. exponential,

normal, lognormal, erlang-K, weibull, gamma

44

distribution types: constant, uniform, traingular, neg. exponential, normal, lognormal, erlang-K, weibull, gamma 44

Reading text files

Dim FileNumber

Dim ImportFilename as String

FileNumber = FreeFile

ImportFilename = "c:\Program Files\TLN Planner\Search.ANS"

Open ImportFilename For Input As #FileNumber

Do until EOF(FileNumber)

Check if end of file has been reached

Line Input #FileNumber, TextLine

Retrieving a part of the text line, of varying length, dependent on

the position of “:” in the line

Writing text files

Dim FileNumber

Dim ExportFilename as String

FileNumber = FreeFile

ExportFilename = "c:\Program Files\TLN Planner\Search.ASC"

Open ExportFilename For Output As #FileNumber

Print #FileNumber, "text you want to write"

Print #FileNumber, "[client]" & vbCrLf & "REQUEST=TRUE"

Close #FileNumber

DrivingTime = Val(Mid(TextLine, 13, Len(TextLine)-InStr(TextLine,":")-1))

Breaking a text line into separate words

Do Until InStr(TextLine, Sep) = 0

WordRead = Left(TextLine, InStr(TextLine, Sep) - 1)

TextLine = Mid(TextLine, InStr(TextLine, Sep) + 1, 100000)

Loop

Loop

Close #FileNumber

E.g. separator variable Sep = “;”

45

How to delete the old file first:

If Dir(ExportFilename) <> "" Then Kill (ExportFilename)

= “;” 45 How to delete the old file first: If Dir(ExportFilename) <> "" Then Kill

Various how to

Use IsError(C.Value)

Use & _ to cut off long VBA code lines

or IsEmpty(C.Value)

to check on error/empty range values (named C).

If MsgBox("Primenumber" & Str(nPrime) & " = " Str(iNumber) & vbCrLf & vbCrLf & _ "Show next prime number?", vbYesNo) = vbNo Then End

You can refer to the current sheet using

Me

or to the active sheet using

ActiveSheet

Me.range(“Table”).value=“”; If Me.chkReschedule.Value Then

Put code in ThisWorkbook if you want to execute it on opening the workbook (select Workbook and Open)

Several options possible, check out the drop down box values (which are self-explaining)
Several options possible, check out the drop
down box values (which are self-explaining)

You can ask for user input with Inputbox

• You can ask for user input with Inputbox Default value, X-position, y-position inputbox • You

Default value, X-position, y-position inputbox

with Inputbox Default value, X-position, y-position inputbox • You can hide sheets completely, e.g.

You can hide sheets completely, e.g. Sheets("Sheet1").Visible = xlSheetVeryHidden

Create a link to another cell: ActiveCell.Formula = "=" & Cells(123, 27).Address

Even menu “Unhide

will not show these sheets, so users will be unaware of them

46

& Cells(123, 27).Address Even menu “Unhide will not show these sheets, so users will be unaware

Protect your VBA code by locking your project for viewing and setting a password

Do not forget your password, and give it to your colleagues as well.

project for viewing and setting a password • Do not forget your password, and give it

47

project for viewing and setting a password • Do not forget your password, and give it
project for viewing and setting a password • Do not forget your password, and give it