UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy [email protected] Developer...

28
UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy [email protected] Developer – Codematic Ltd

Transcript of UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy [email protected] Developer...

Page 1: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Excel VBA Best Practice

Simon [email protected] – Codematic Ltd

Page 2: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Spreadsheet background• Up to 200 Mb size• Up to 1 Million formulas• 1-10,000 unique formulas• 5-10,000 lines of VBA• £Billions in values• Often linked to other technologies such as OLAP,

ADO, COM or .net etc.• Finance, Banking and Sales and Marketing areas• Development cost up to $1M• Active member of Eusprig – European Spreadsheet

Risk group – dedicated to raising awareness of dangers and error rates in commercial spreadsheets www.eusprig.org

Page 3: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Agenda• Security• Fundamental Imperative• Development process• Development environment• Design considerations• High quality code

– General– Modules– Procedures– Blocks– Variables– Excel Specific advice– Classes

• Avoiding common errors• Debugging• Testing• Documentation• Resources

Page 4: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Security• Is everybody’s concern• Spreadsheets can be used as a staging board for privilege

escalation (with your login details!)• Consider SD3 +C

– Secure by• Design• Default• Deployment• Communication

• Threat Modelling – Assets, Threats • Threat Types – STRIDE

– (Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege)

• Threats – rate with DREAD– (Damage potential, Reproducibility, Exploitability, Affected Users,

Discoverability)• Spreadsheets (all flavours) are fairly insecure

– Compiled UDFs (.net, COM, XLL) and Database servers can help• Set macro security to high and use code signing certificates.• See Microsoft MOC 2840A – Implementing security for more info.

Page 5: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Fundamental Imperative• Manage complexity (McConnell)

• Solution complexity grows at 4 x the rate of problem complexity. (Glass)

• [Things] should be as simple as they can be, but no simpler (Einstein)

• K.I.S.S.

• This principle should drive all other work.

• Easier to build, easier to test, easier to document, easier to use, etc… [No conflict]

Page 6: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Development Process• Systems Development lifecycle

– Requirements,– Analysis, – Logical Design,– <Technology Choice>, – Physical Design,– Construction, – Test, – Release, – Maintain. – In some shape or form.

• Understanding the requirements is critical and difficult• Some sort of structured approach is useful• Build a library of useful code and references

Page 7: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Design – 2 Questions, 2 Approaches

• 2 Questions– What will happen when things go right?– What will happen when things go

wrong?

• 2 Approaches:– What will the system do?– What real world objects am I modelling?

Page 8: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Coupling

• How strongly 2 separate elements depend on each other

• Low coupling is better, especially through clearly defined interfaces

• High coupling often means hidden dependencies which generally leads to incorrect modifications (side effects)

• Example: hard coded cell addresses in VBA code

• Example: Gobal/Public variables

Page 9: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Fan in / fan out

• Low fan in – a VBA routine depends on only a few other units– Good because it minimises

dependencies and reduces complexity• High fan out – a VBA routine is used

by many others– Good because it minimises duplication- Good because routine is more

thoroughly exercised

Page 10: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Development Environment• Option explicit• Don’t warn about syntax errors• Actual set up - which windows are visible

etc• Use a code library• Use MZ tools• Other tools – call tree, indenter, reference

checker, BYG• Source control, even just exporting as text

Page 11: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Design Considerations• Simplicity• Testability• Cohesion and coupling• Fan in fan out• Encapsulation and separation• Reusability• What does it do, or what are you modelling?• N tier – especially msgbox and error handling• Consider future changes and/or enhancements• Design patterns eg: singleton, factory, facade• Design ‘normal’ case and ‘error’ case

Page 12: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

High Quality Code – General 1• Naming convention:

– Option 1 fit in with current standards (eg Reddick 3 letter)– Option 2 give everything a simple, distinctive, non abbreviated

descriptive name• Procedures – verb noun combination• Variables – add scope prefix, data type maybe, usage more

useful – eg m_rwCustomer for row in customer table or colMonth for month column.

• Only use a type prefix if you know what it is doing for you and you value that. (eg probably don’t need ‘obj’)

• Avoid most comments – make meaning crystal clear in the code.• Move non standard code and workarounds to named routines, and

comment if necessary• refactor early and often• build test routines as you go, and at least step through in the

debugger.

Page 13: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

High Quality Code – General 2• Recognise when you move from procedure based design to

module/object based (eg procs need to return >1 value, lots of parameters get passed all around)

• Object Oriented designs can be useful, but can cost performance• The biggest factor on performance is design• Be aware of Excel/VBA limitations, and clear on its strengths• Use ‘TODO’ and maybe ‘Enhancement’ comments (don’t release until

TODOs cleared – (use edit find in project)• Use shift+F2 for definitions, F8, Shift+F8 and Ctrl+Shift+F8 (step

out) and stop• Note compiler is weak compared to C++• Use code cleaner regularly• Differentiate style from quality• Use the most restrictive scope that works for variables and routines

Page 14: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

High Quality Code - Modules• As solution complexity increases think in terms of modules

rather than procedures• Use enums to add understanding• Could use types but probably better to go straight to

classes.• Module name should explain what it does, a comment at

the top may be useful.• May need 1 or 2 global variables, but may need lots of

module level variables• A module should represent a bunch of closely related things

eg: use common data• Use Option private module otherwise public routines will be

listed in the user defined functions list.• Forms should usually call straight out to a class or module

to do the real work.

Page 15: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

High Quality Code - Procedures

• Anatomy of a procedure/object – initialisation, process, clear up, error handling

• Short routines 40-50 lines max (one screens worth) (easier to understand – but not proven to reduce errors)

• A procedure should do one thing well• Prefer functions (Boolean success/failure)• Use parameters rather than global variables (max 7+/- 2)• Avoid application.run – breaks VBA error handling• Use separate routines for separate error handling• Consider error handling early, use break on all errors when

testing• Use environ rather than api where possible (simple)• All call tree parents should have error handling• Test performance don’t guess (see perfmon)• Protect procedures from bad input (including malicious

input)

Page 16: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

High Quality Code - Blocks• Code block start and end together• IF using If…then code an Else if, add a comment,

only remove it if you are sure there is no ‘else’ case (missing the else is a common error)

• Code the expected behavoir first, usually.• Use do while and do until loops, be sure they will

end, I generally mainly use for next and for each next, finding out the end first helps with status bar updates.

• In a Select Case always have a default case, possibly with an error warning.

Page 17: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

High Quality Code - Variables• Don’t reuse variables for different purposes, avoid ‘temp’

• Use clear data types, and control them (watch out for implicit coercion)• Variants are often easier to work with than arrays• Pass parameters byVal if they are not to be changed (watch for coercion)• Explicitly use byRef in an input parameter is to be changed, but watch for

signs to redesign• Don’t implicitly use the default property, be explicit (eg range.value)• Magic numbers and strings should be made into constants.• Use explicit data casting Cstr() Cbool() etc• Code with early binding if at all possible (new), change to late binding to

support multiple versions or if component may not be installed. Late can be slower and may need better error handling.

• Can define all variables together at top or just before they are needed both have pros and cons.

• Sometimes a simple i, j, x or y is better than a long datatype prefixed descriptive name for a loop index

• Boolean variable should be named so True or False make sense – eg use done rather than status

• Booleans should be positive eg if not found then… rather than if not notFound then…

• Never mess with a loop counter within the loop.

Page 18: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

High Quality Code – Excel 1• Its usually dangerous to hardcode a range reference in VBA.• Use range names to connect code to worksheet ranges • Choose a single cell range name as a start point• Choose a multi-cell range to allow the user to insert/delete

rows/columns• Use in cell text where possible, closely ties the mechanics to

what the user uses.• Always check cell text thoroughly before depending on it• Note data validation is easily bypassed• Give sheets code names and use them• Take the first few rows and columns for system use, hide them

if necessary• Check the selection type with typeOf if you are going to use it.• Generally avoid selecting and copying – set values instead

where possible.• Be clear and explicit which workbook and worksheet code

should operate on, especially ThisWorkbook v ActiveWorkbook for add-ins.

Page 19: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

High Quality Code – Excel 2• Pulling Range.Value or Range.Formula into a variant is much

faster than looping the cells.• Use worksheet.cells(r,c) structure rather than range(“A” &

someNumber)• Be consistent how you use ranges (I usually use sheet.

[rangeName].value)• Remember the power of R1C1 notation • Its often easier to set the formulaR1C1 than the formula of a

range.• If distributing code with references, consider making it late

bound.• Use standard environment management routines• Use Excel functionality wherever possible• Use doEvents where needed• Work upwards when deleting rows, otherwise counters get

messed up• Watch for inadvertently firing events, don’t hog the

onCalculate event

Page 20: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

High Quality Code - Classes• Classes result from asking ‘what am I modelling?’

rather than ‘what is this system to do?’• Full class based design may be overkill for most

VBA applications• Hard/impossible to combine the best of

spreadsheets with proper OO – data hiding is not possible.

• Classes may be useful when a set of routines share lots of data and it becomes cumbersome to pass around as parameters

• Or when you need to return a complex type from a routine

Page 21: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Avoiding Common Errors• Consider lifetime – initialise, set, use, destroy

(CRUD – Create, read, update, delete)• Off by one errors, especially ranges into variants,

arrays, loops and ubound()• Watch for index cross talk• Dim x, y as integer => x is a variant• StrComp, InStr – check the documentation

Page 22: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Debugging and Testing• Debugging

– Immediate window– Locals– Debug.print debug.assert

• Testing– Pre-conditions and post conditions– Use a ‘test’ module, and application.run for private routines– Test early and test often– Keep all test code – it can act as a specification, and can give

comfort that later changes do not break anything– Get good test data – realistic, test full range including boundary

conditions, but weight testing towards real world use.– Execution testing v static testing and code inspection/review.– Unit testing, system testing, user acceptance testing.

Page 23: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Documentation• If you design for simplicity only very minor additional

documentation is needed• Design and build the user Interface with the Users

needs primary, the documentation will automatically be there

• Design and build the business logic parts with the maintainers needs primary, the main documentation will automatically be there, expand as required.

• Integral tests should explicitly clarify intent.• Reports should contain enough description to be

meaningful.• External documentation is almost always so out of date

its worse than useless.• Excessive documentation is too hard to plod through• Poorly targeted documentation is pointless• Working software is more useful than documentation• Sometimes documentation is important

Page 24: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Documentation• Call tree print out should be enough for most uses• Be clear who the target audience is• Should be auto generated from source code if it is

to be up to date.• Stepping through code is often the easiest way to

understand it.• Download a VBA to HTML addin to pretty up code

for printing.• PUP provides a nice summary, MZ Tools creates a

weighty document.

Page 25: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Extending Excel

• Excel is powerful not perfect• Leverage benefits whilst managing

weaknesses by using complimentary technologies

• Data: VBA, ADO, ODBC, OLAP, .net, COM, Info Bridge, XML, DDE, Web Queries, SOX Solution Accelerator

• Logic: VBA, COM, .net, xll, Pivots, Filters• Search the web for vast array of free or

cheap tips and tools.

Page 26: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Summary• Manage complexity• Consider security carefully• Excel/VBA not the best tool for everything• Be defensive, especially with inputs• Understand your data• Aim for cohesive models with low coupling• Use names to connect VBA to worksheets• Use complimentary technologies where

appropriate• Manage documentation

Page 27: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Resources• Books

– Code complete 2 – Steve McConnell– Professional Excel Development – Stephen Bullen, Rob

Bovey & John Green– VBA Developers Handbook – Ken Getz

• Tools– www.oaltd.co.uk (Stephen Bullen), Call Tree, Smart

Indenter– www.BYGSoftware.com Toolbar creator and back up.– www.appspro.com (Rob Bovey) code cleaner– www.j-walk.com – (John W), PUP– www.MZ-tools.com MZ tools VBA IDE addin.– www.codematic.net reference checker.

Page 28: UK XL User Conference 2006 Excel VBA Best Practice Simon Murphy simon.murphy@codematic.net Developer – Codematic Ltd.

UK XL User Conference

2006

Questions?

[email protected]– Spreadsheet consulting, reviewing,

maintaining, rescuing, migrating, add-in development etc.

– Staff coaching, mentoring and training

• Websites– www.codematic.net– www.xlanalyst.co.uk