Está en la página 1de 181

HowToBecomeAnExcelGod(withoutreallytrying)

DrAlexanderJTurner2007 1
BabySteps

Dedicatedto:ProfessorI.H.Williams.
Forhistirelesssupportandguidanceofmyselfandmany
othersinoursearchforagreaterunderstandingof
nature'screation.

2 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Table of Contents
Forward:RunTheWorldFromExcel!........................................7
A Dream No Reality......................................................................7
Who can benefit from Excel Scripting Macros?..............................8
Where Does This Idea Come From?................................................8
Why 'Baby Steps'.............................................................................9
Introduction:Whatisthisallaboutthen?...............................10
Do I Need To Be A Programmer?...................................................10
Using This Book............................................................................10
Lesson1:BasicConcepts.........................................................11
'Take Home' Ideas from Lesson 1..................................................14
Lesson2:BuildingBlockConcepts..........................................15
Collections:....................................................................................15
Variables:.......................................................................................17
More On Variables.........................................................................18
With Statements............................................................................20
'Take Home' Ideas from Lesson 2..................................................21
Lesson3:Loops.......................................................................23
Finally we start to make things easier:.........................................23
Drag And Drop Scripting, An Introduction....................................24
For Loops.......................................................................................27
For Each Loops..............................................................................28
'Take Home' Ideas from Lesson 3..................................................29
Lesson4:GettingTooledUp....................................................31
A Quick Note.................................................................................31
Get A Good Text Editor..................................................................31
Recording Macros.........................................................................32
Translating Recorded Macros.......................................................36
Keyboard and Mouse to Script Translation..........................................................36
Translating Excel Constants.................................................................................37
Using The Object Browser.............................................................39
Finding And Removing Bugs.........................................................41
'Take Home' Ideas from Lesson 4..................................................44
Lesson5:StartingToWorkWithData.....................................45
Special Folders..............................................................................45
Using 'SendTo' As A Really Easy Way To Run Scripts..........................................46
Saving And Opening From Special Folders..........................................................47
Merging Between Workbooks........................................................48
Merging Data By Example....................................................................................48
Dictionary Objects.................................................................................................49
Simple Merge Script.............................................................................................51
Working Merge Script...........................................................................................53
Merging Multiple Columns...................................................................................56
'Take Home' Ideas from Lesson 5..................................................57
Lesson6:Reading&WritingFiles...........................................59
What Is A File?..............................................................................59
Writing To A Text File....................................................................60

DrAlexanderJTurner2007 3
BabySteps

Reading From A Text File..............................................................62


Reading And Writing In Chunks....................................................64
Listing Files...................................................................................66
'Take Home' Ideas from Lesson 6..................................................69
Lesson7:EnhancedDataProcessing......................................71
Subroutines And Functions...........................................................71
Death By Dates..............................................................................74
DateAdd And DateSerial Fixing The Problem....................................................77
Importing Data From CSV Files....................................................80
Creating Reports...........................................................................87
'Take Home' Ideas from Lesson 7..................................................92
Lesson8:WorkingWithPivotTables.......................................93
Why Pivot Tables Are So Very Important.......................................93
Understanding Pivot Tables...........................................................93
Creating An Example Pivot Table.........................................................................94
Creating A Pivot Table And Scripting Macro.................................96
Creating Pivot Tables Using Scripts............................................106
Looking At The Recorded Macro........................................................................106
Finished Product.................................................................................................111
Tricks To Improve Data To Help Pivoting....................................113
Banding Data.......................................................................................................113
Cleaning Data......................................................................................................115
The Page Area.....................................................................................................115
Lesson9:Working'OutsideTheBox'.....................................117
Accessing Binary Files.................................................................117
Reading Data From Binary Files An Example..................................................119
ADODB.Stream Summary...................................................................................121
Properties............................................................................................................121
Methods...............................................................................................................122
Sending Key Strokes To Other Applications Through .................123
Stopping Excel From Complaining.....................................................................125
Choice And Decision Processing................................................126
Yes Excel Really Is This Powerful!....................................................................126
What Is Choice/Decision Processing?.................................................................126
First Off Just The Very Minimum Of Logic.......................................................127
TRUE & FALSE....................................................................................................127
Chaining Decisions To Make Rules.....................................................................128
Blocks And Zeds..................................................................................................130
Putting It All Together.........................................................................................131
Moving From One To Many.................................................................................136
Lesson10:SpeedingScriptsUp............................................139
Cell By Cell Access Is Slow..........................................................139
Bulk Data Loading With Arrays...................................................140
What Is An Array?...............................................................................................140
Using Arrays Like Spread Sheets.......................................................................141
Bulk Data Transfer With Copy/Paste...........................................143
Don't Forget Formulae And Fills.................................................143
AppendixA:DifferencesWithExcel2007.............................145
Recording Macros:......................................................................145
Showing The Developer Tab (Accessing VBA).............................146
Creating A Pivot Table.................................................................149

4 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

AppendixB:HowThisBookWasWritten..............................157
AppendixC:WhyScriptWhenExcelHasMacros?................159
One Final Thing...................................................................................................160
AppendixD:VBScriptBuiltInFunctions&Constants...........161
Built In Functions........................................................................161
The Functions Enumerated And Explained........................................................161
Built In Constants................................................................................................170
Built In String Constants.....................................................................................170
AppendixE:NamedArgumentsAndThe:=Symbol.............173
Why This Is Here.........................................................................173
The Where, Why And When Of :=...............................................173
How To Translate From Named Arguments................................174
Errata....................................................................................176
Index.....................................................................................177

DrAlexanderJTurner2007 5
BabySteps

6 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Forward: Run The World From Excel!


Mostcalculationsandnearlyallbusinessprocessesstartoutlifein
Excel. They grown in complexity and slowly require multiple
spreadsheetstofunction. Humanerrorleaksintothemixandthe
wholehouseofcardscomescrashingdown.
Thestandardsolutiontothischallengeistocommissionsomehuge
softwaresystemtosolveallourproblemsinonehit. Thissuper
systemwillbedeliveredlateandwillbeoverbudget.Whatisworse,
therequirementswillhavemovedonsincethesystemwasdesigned.
Thewonderful(wonderfullyexpensive)systemwillsolveyesterday's
problemsandnotaddresstoday's.
ThefinalactinourITtragedyiswheretheinadequaciesofthesuper
systemareovercome by preand postprocessingall thedata with
Excel!
Alltheabovepaincansoeasilybeavoided.ItiscausedbyExcelonly
goingsofar. Excelwillprocessdata,butnotautomaticallychain
processingstepstogether. Thislackofchainingmeansthathumans
endupintheprocesses.Evenhighlytrainedhumansmakemistakes
at the rate of 1 in 200 to 300 hundred repeated actions. Data
processingwhichinvolvesignificanthumaninteractionwillbecome
unstuckirrespectiveofhowhardthepeopletry.
A Dream No Reality
How about a world where data processing and business decisions
take place in Excel without human error? All repetitive tasks are
automatedandefficient.Inthisworld,wewouldhavetheflexibility
and responsiveness of Excel but the reliability and speed of a
dedicatedsystem.
Howaboutaddingtothiswishlist?Itwouldalsobegreatifeventhe
mostcomplexprocesseswererenderedsosimpletosetupthatnon
programmerscoulddoit!
This is not a fantasy world, it exists. The techniques of Excel
ScriptingMacrosdoexactlywhatisrequired.Ibelievethatanentire
business, of thousands of people, could be run with just Excel
ScriptingMacros, Excelandafree database. 90%ofallbusiness
processescanbeperformedevenwithoutthedatabase,allweneedis
ExcelandScriptingMacros.

DrAlexanderJTurner2007 7
BabySteps

Who can benefit from Excel Scripting Macros?


Ifyouareina smallbusiness andwanttoautomated work
flowthisisforyou.
If you are in a huge business and want to process
performancefiguresthisisforyou.
Ifyouareresearchinganimalbehaviourandneedtoanalyse
resultsthisisforyou.
Ifyouwanttoapplyarulesettochoosewho,outof10000
employees,getsaChristmasbonusthisisforyou.
Ifyouwanttodojustaboutanythingthatinvolvednumbers,
dataorrulesthisisforyou!
Where Does This Idea Come From?
The school of hard kicks, thatthis where is comes from. Back in
20012002 I began to realise two things. Firstly, the huge and
complex Java based systems on which I was working just never
providedwhatrealpeoplewanted.Secondly,nearlyallbusinesswas
alreadybeingperformedinExcel.
ItwasatthistimethatIsetupacompany'JDIT'totakeadvantageof
theserealisations. WetookExceland,usingExcelmacros,pushed
waybeyondwhatmostpeoplehaddreamtof.However,despitethe
success of the concept, it was not fully what was needed. The
systemsJDITproducedweretoolargeandtwocomplex. Insome
ways,theyturnedExcelinto thehugeandcomplexsystemsI was
tryingtogetawayfrom.
The key breakthrough came when considering how to directly
interconnectExcelwithalargeweb basedsystemforwhichIwas
architect. IrealisedthatasimplescriptcouldrunExcelandplace
dataintoit.ThetechnologyIhadusedinJDITinsideExcelcould
be put outside Excel in a script. However, the result was much
morepowerfulthanIhadexpectedbecauseitallowedcomplexthings
tobedoneinsimpleways.Contrastthis,ifyouwould,withnormal
ITwheresimplethingsaredoneinextremelycomplexways!
Excel Scripting Macros evolved a fair way from this initial wow
moment. The next challenge was to beat every last ounce of
complexityoutoftheapproach.Thatwasnotasstraightforwardas
one might imagine. But, each time I found an approach which
reduced complexity, the project on which I was working benefited
enormously.Inshort,IknewIwasontherighttrack.

8 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Why 'Baby Steps'


UptothispointIhadthoughtofExcelScriptingMacrosasagood
waytosolveproblemsontheprojectswithwhichIwasinvolved.As
time went on, feedback from my coworkers and my blog
(www.nerdscentral.com) started to indicate they had crossed a
watershed. Nolongerwasthisseenasaprogrammerconceptbut
more as a business tool. The opportunity to devolve data and
decisionprocessingfromprogrammerstothepeoplewhoneededit
wastantalisingtosaytheleast.
I knew that to achieve this breakthrough democratisation of
technology,thelearningcurvewouldhavetobeveryshallow.Hence,
Icameupwiththenotionof'BabySteps';Aseriesoftinystepswhich
takeapersonfrombeingfamiliarwithExcelthroughtobeingableto
performseeminglysuperhumanfeatswithit.
Havingconsideredmanyformatsfrom blog to podcast,Ifigureda
friendlybookformatwasideal.Abookthatisnotfullofpaddingto
getthepagecountup.Abookthatissmallenoughtofitinalaptop
caseandreadonthetrain.Inshort,abookwhich,likeitscontents,
demandsonlytheminimumofeffortinvestedforthemaximumof
benefitgiven.

DrAlexanderJTurner2007 9
BabySteps

Introduction: What is this all about then?


'Babysteps'isallaboutlearninghowtowrite'ScriptingMacros'for
Excel.IamsurethatyouhaveheardofExcelMacros.Thesearelittle
programsembeddedintoanExcelWorkbookwhich automate tasks.
Scriptingmacrosareverysimilar.Thebiggestdifferenceisthatthey
donot'live'insideaWorkbook.Theyaresmallfilesthatexistoutside
WorkbooksbutcanactupononeormoreWorkbooksatonce.
Because Scripting Macros are outside of the Workbooks on which
theyact,theyareverymuchmoreflexiblethantraditionalMacros.
They also get around many of the nasty security problems and
consequentrestrictionsthatarepartandparcelofExcelMacrosthese
days.
Theconceptbehind'BabySteps'isthat,whilstyoucanbesomething
massively complex with Scripting Macros, it is also possible to do
amazingstuffwithmassivelysimpleScriptingMacros.Experiencein
thefieldhasshownthattheapproachhashugebenefitstobusiness
processes which are dependant on people sending data to one
another via Excel spreadsheets. Automation via Scripting Macros
removes'typo'mistakeswhichpeopletendtomakewhenfacedwith
repetitivetasks.Additionally,oneortwosimpleScriptingMacroscan
processdatathatwouldtraditionallybeloadedintoa database and
fromwhichprogrammerswouldwritereports.
Do I Need To Be A Programmer?
100%no.Theideabehind'Babysteps'isthatalittleknowledgewill
takeyouaverylongway.Eachconceptistiedbackto'realworld'
examplesandeveryeffortpossiblehasbeentakentoremovejargon!
IfyoucanuseExcel,youcanunderstand'BabySteps'.
Youdonotneedtobeaprogrammer.
Thisbookwillnottrytoteachyoutobeaprogrammer.
Using This Book
Ifyouhaveneverdoneanycomputerscriptingatall,donotworry.
Everythingyouneedtoknowiscontainedinlessons1,2and3. If
youareslightlyfamiliarwiththeconceptsofscripts,loopsVariables
andallthatstuff,thendiveinatlesson4.
Evenifyouareanexpertprogrammer,youmaygainalotfromthe
laterchapters.Iwouldrecommendalittlespeedreadingatlesson4
topickupafewtipsandthendiveinmoreatlesson5.

10 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 1: Basic Concepts


Letusstartoffconsideringdrinkingaglassofwine...
Toinstructacomputerthatapersonshoulddrinkaglassofwine,it
seemslogicaltotellthecomputerthatthereisa'thing'calledperson
anda'thing'called glass-of-wine.Oncewehaveestablishedthis
setup,wecansaysomethinglike:
persondrinkglassofwine
(Thehyphensareincludedjustforclarity,togroupwords
together)

NowwehavestartedwritingaScriptingMacro. Tomakethisabit
morerealisticweneedtosplitouttheconceptof'aglassofwine'from
'myglassofwine'.Afterall,youwanttoknowwhichglassyourare
drinking(atleastatthestartoftheevening).
Todothis,wemightwritesomethinglikethis:
set my-glass-of-wine to be a-glass-of-wine
set my-person to be a-person
my-person.drink(the-glass-of-wine)

YoucanprobablytellthatIamgoingsomewherewiththelayoutof
these'pseudoscripts';Iamtransformingeverydayspeakintotheway
wetellthecomputertodostuff.Alotofthetime,itisfairlystraight
forwardtodoso.Sometimes,however,historyandconventiongetin
theway.But,fornow,letuscontinuealongthispath.
Key Concept:
Incomputerspeak,wecall'myglassofwine'anObjectandwecall'a
glassofwine'aclassofobjects,orsimplyaClass.
Onereallynicethingaboutcomputingisthatmakingglassesofwine
isverysimpleandjustaboutfree.Ifwewantanewglassofwine,we
just say something like 'Create myglassofwine which is from the
Classof'aglassofwine'.
Makingglassesofwineinascriptmightlooksomethinglikethis:
set my-glass-of-wine = CreateObject(a-glass-of-wine)

Butactually,hyphensbetweenwordsarenotallowedsoweput:

set myGlassOfWinne = CreateObject(aGassOfWine)

DrAlexanderJTurner2007 11
BabySteps

Thatdoesnotlookverymuchlikeeverydayspeakanylonger,but
thereisaclearlineagetobeseen! Onequestionthatcomesupis
whatdoesthe'='signmean?Therearetwothings'='canmeanin
ScriptingMacros:
1) Does x equal y, as in:
if x = y then
2) Make x equal to y, i.e. load the value of y into
x, as in:
Set x = y
or:
set myExcel=CreateObject(Excel.Application)

Nowwecanputallthistogethertomakeanearlycompleteprogram:
' Create the Objects which we require
set myself = CreateObject(People.Person)
set myGlass = CreateObject(Wine.Glass)

' Do stuff with the Objects, in this case


' Object myself, drink the Object myGlass:
' drink is a pre-defined Method which any
' Object from the Class People.Person can do.

mySelf.drink(myGlass)

To explain what is described in the comments to the code above:


.drinkiswhatwecallaMethod.ItisamethodoftheObjectmySelf.
Wedonothavetodefinewhat.drinkisbecauseitsdefinitioncomes
along with Class People.Person. Because mySelf is a Object from
People.Person(itisapersonObject)itwillhavetheMethoddrink.
Methods(doingthings)canhaveparenthesisafterthem. Insidethe
parenthesistherecanbealistofthingsthemethodistoworkwith.
In the above example, the list has one element myGlass. Some
methods,likethe .Add methodofExcel'sWorkbooks collection,have
noelementsinthelistandsoarefollowedbyemptyparenthesisasin
.Workbooks.Add().
IhavecalledtheClassesPeople.PersonandWine.Glass,withthese
doublenames,becausethatisthe Microsoft convention. AnExcel
application is called Excel.Application. To create one you put
CreateObject(Excel.Application).
Nowwehavefiguredouthowtoget'CyberSloshed',letusseeiswe
canapplythesamethingtoExcel!
set myExcel = CreateObject(Excel.Application)

12 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

This simple piece of code actually causes Windows to create a


completelynewExcelapplication.The'Variable'myExcel'refers'toit.
So,laterintheprogram,whenwewanttodosomethingwithExcel,
we can use the Variable 'myExcel' to pass instructions to our new
Excelapplication.
Forourveryfirst'babystep'towardsbeinganExcelgod,wearegoing
todojustthat.WearegoingtocreateaninstanceofExcelanddo
somethingwithit.Thatsomethingwillbesimplytomakeitvisible
(theyarecreatedhidden)andthencreateanew,emptyWorkbook
insideit.
Pleasefollowtheseinstructionstothelettertocreateyourveryfirst
ExcelMacroScript:
1) Open Notepad
2) Type in:

set myExcel = CreateObject(Excel.Application)


myExcel.visible = TRUE
myExcel.Workbooks.Add()

3) Save your magical words as step1.vbs on your desktop.


4) Double click on the Icon that has appeared on your
desktop to represent you new file.
5) Stand back in amazement!

Thispieceofcodecanbedescribedinwordslikethis:
SettheVariable myExcel tobeannewlycreated Object
which is from the Class Excel.Application. Make the
visible Property of that Object be true. Get the
Workbooks Property ofthatObjectandrunitsMethod
Add,whichwillcauseanewWorkbooktobecreated.

DrAlexanderJTurner2007 13
BabySteps

'Take Home' Ideas from Lesson 1


WehaveseenthatMacroScriptscancontrolExcelandthatthey
haveadirectlineagefromnormalEnglish.

Whenwritingscripts,werepresentreal,tangiblethings(like
glassesofwineorworkbooks)asObjects.Theobject
'myGlassOfWine'comesfromtheClassofObjects'aGlassOfWine'.

MacroScriptsaresimpletextfiles.Theyareeditedusingatext
editor(likenotepad)andsavedwiththe'.vbs'fileextension.

WhenwritingaScriptingMacro,beforewedoanythingwith
Excel,weneedtocreateanExcel.ApplicationObject.

14 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 2: Building Block Concepts


Collections:

Fig1:AdigramshowinghowinExcelObjectsoftenhave
CollectionsofObjectsinsidethem.ACollectionholdsalistof
zeroormoreObjectsinsideitandallowsyoutofindthose
Objectsbyindex(e.g.0,1,2etc.,orsometimes:1,2,3etc.)or
name(e.g.sheet1,sheet2etc.).Thisdiagramshowsyouhow
tostartoffwithExcel.Applicationand'drill'allthewaydownto
individualCellsinaSheet.

DrAlexanderJTurner2007 15
BabySteps

Inlessononewelookedathowthings,likeglassesofwineandExcel
Applications,arecalled Objects.'myGlassOfWine'isanObjectwhilst
'aGlassOfWine'definesaClassofObjectsandsowecallitaClass.
WhenworkingwithExcel,weuseObjectsalot;also,wetendtousea
lotofthesameClassofObjectatonce.WhenyoucreateaWorkbook
Object(likewedidwithwithoursimplescript)youseethreeSheets,
notone.Indeed,anExcel.ApplicationcanhavemanyWorkbooksand
eachWorkbookcanhavemanySheetsandeachSheetwillhavemany
Cells.
To handle all these groups of Objects, Microsoft use what it calls
'Collections'. These are numbered, and sometimes named, lists of
Objects. A Collection is also an Object its self. For example, a
CollectionofWorkbooksisanObjectfromtheClassofCollections.
All Collections have the Property .count (note, because it is a
Property,notaMethod,thereisnoparenthesis).Thistellsyouhow
manythingsareinsidetheCollection.SomespecialCollectionshave
other properties and/or Methods. For example, Excel's Workbooks
Collection has .Add() to create a new Workbook and .Open(file
name)toopenanexistingWorkbook.
If we draw out the relationships of Excel.Application, Workbook,
SheetandCell,wegetsomethinglikeFigure1.
TofindtheObjectforaCell,wemightdosomethinglikethis:
' Create an Excel.Application Object
Set myExcel = CreateObject(Excel.Application)
' Cause Excel to create a Workbook (it starts
' with none). This is done by 'adding' one to
' the Collections of Workbooks
myExcel.Workbooks.Add()

' Find the first Workbook in the Collection


' of Workbooks. i.e. this says: set the
' word 'myWorkbook' to refer to the Workbook
' Object at position 1 in the Collection.
Set myWorkbook = myExcel.Workbooks(1)

' Do the same this time but to get a Sheet


Set mySheet = myWorkbook.Sheets(1)

' Finally, find one particular Cell


Set myCell = mySheet.Cells(1,1)

' Now we have the top left Cell of


' the first Sheet. i.e. the Object which represents

16 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

' the Cell at the top left hand corner of the first
' Sheet.
'
' We can use this Object to
' write the value of the contents of the Cell.
myCell.Value = Hello World

KeyConcept:
CollectionsareawayofstoringzeroormoreObjectssothattheycan
beeasilyfoundandused.
Variables:
Whenweput:
Set myExcel= CreateObject(Excel.Application)

Wearesaying:
SetaVariablecalledmyExceltorefertoanewlycreated
Excel.ApplicationObject.
WhenworkingwithObjectsinExcel,weoftensetVariablestoreferto
ObjectstomakeiteasytousetheseObjects.Hereisanexampleasto
why:
' Try to set a Cell's contents without using Variables
' Step 1: Open up Excel and create a new Workbook
' in it
CreateObject(Excel.Application).Workbooks.Add()
' Are, now I am unstuck, because I no longer have a
' way of 'getting to' to the Excel.Application
' Object.

Thesolution,aswesawbefore,istosetaVariabletorefertothe
Excel.Application Object. This approach has other benefits as well.
Oncewegetthehangofitwecan:
1. Saveourselvesalotoftyping.
2. Savethecomputeralotof'thinking'.
3. Make developing (adding to, editing, improving) scripts
mucheasier.
Theseadvantagescomefromtheabilitytostore'working'information
inVariablesjustlikewemightstorenotesonpostits.Ifyouhadto
work out what the square root of 23456 was each morning, you
mightwellwritedowntheanswertosavetheeffort! Variablesare
usedforthispurposeinscripting.

DrAlexanderJTurner2007 17
BabySteps

KeyConcept:
Variablesarelike'postitnotes'forscripts;theyallowustostorethings
sowedonothavetokeeprecreatingthem.
Letusseethis'postitnote'conceptinusebyaddingtoourprevious
script:
' Create an Excel.Application Object
set myExcel = CreateObject(Excel.Application)

' Cause Excel to create a Workbook (it starts


' with none). This is done by 'adding' one to
' the Collection of Workbooks
myExcel.Workbooks.Add()

' Find the first Workbook in the


' Collection of Workbooks
set myWorkbook = myExcel.Workbooks(1)

' Do the same but this time to get a Sheet


set mySheet = myWorkbook.Sheets(1)

' Finally, find one particular Cell


set myCell = mySheet.ells(1,1)

' Now we have an Object for the top left Cell of


' the first Sheet. We can use this Object to
' set the value of the contents of the Cell.
myCell.value = Hello World

' Now we can re-use the mySheet Variable to get


' the Object for the next Cell in the Column
set myCell = mySheet.Cells(2,1)
myCell.value = Hello Again

HerewehavereusedthevalueofmySheetratherthanhavingtore
findtheSheetObject. ThisuseofaVariablehassavedusrewring
andrerunningallthecodewhichfindstheSheet.
More On Variables
VariablesdonotonlyrefertoObjects;theycanholdotherstufflike
Numbers,DatesandStrings(piecesoftextarecalled'Strings'asin'a
stringofcharacters').
When working with Excel Scripting Macros we are using a
programming language called VBScript. VBScript, just like any
programminglanguagethathasbeenaroundforawhile,hashistory;
ithasaccumulatedafewoddities.Whilstthesecanbeexplained,itis

18 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

oftenbettertojustacceptthem. Oneoftheseisthewaywework
withVariablesandthingswhicharenotObjects.
Strings,Numbers,DatesandBooleans(logicalvalues,true/false)are
notObjectsin VBScript. Thisisnotforanyparticularreasonother
thanhistory. Variablesare almostexactly the samewhen working
withObjectsandnonObjects,appartfromonelittlething:wedonot
'set'Variablestononobjects.So:
Set Cell = mySheet.Cells(1,1) ' OK
myString = Hello World ' OK
myNumber = 1.0 ' OK
Set myNumber = 2 ' WRONG (2 is not an object)
myObject = CreateObject(Excel.Application) ' WRONG

One way of thinking about this is to say that Numbers, Strings,


BooleansandDatesaretoosimpletobethoughtofasObjectsandso
aretreateddifferently.Alsonotethatifnumberisinquotesitisused
astext.1.0isnotanumber,itisaString.
Youmighthavealsorealisedbynowthatanytextafter'onalineis
considered to be a comment. Comments are not read by the
computer and have no effect on the script, they are there to help
peoplereadingthescripttoknowwhatisgoingon.Thecomment
goesfromthefirst'totheendoftheline.
NowwehaveareallypowerfultoolbecausewecanletaVariable
readthevaluefromaCellandwecanwriteaVariable'svalueintoa
Cell.ThisisthebasisofmostExcelMacroScriptingdataprocessing.
' Script to show how values can be read and
' written in and out of Cells and Variables
' =========================================
Set myExcel = CreateObject(Excel.Application)
myExcel.Workbooks.Add()
Set myWorkbook = myExcel.Workbooks(1)
Set mySheet = myWorkbook.Sheets(1)

' Start the process by writing a value into


' the top left Cell
Set myCell = mySheet.Cells(1,1)
myCell.value = 1

' We can then take that value and work with it


myValue = myCell.value
' (explain how this is done)
myValue = myValue + 1
' Get the next Cell along (B1)
Set myCell = mySheet.Cells(1,2)

DrAlexanderJTurner2007 19
BabySteps

' This will make the value of B1 be 2


myCell.Value = myValue

With Statements
Withstatements areanotherwayofworkingwithObjectwhichcan
behandyasanadditiontousingVariables.Thisisespeciallysoifwe
wanttodoseveralthingswiththesameObjectintightsequence.It
iseasiesttoshowthisbyanexample;herewewillsetthevaluesof
severalCellsinsequence.
Set myExcel = CreateObject(Excel.Application)
myExcel.Workbooks.Add()
Set myWorkbook = myExcel.Workbooks(1)

' Here is the with, note the extra indentation


' which is here to make the code easier for
' humans to read:
With myWorkbook.Sheets(1)
.Cells(1,1).value="Row=1,Col=1"
.Cells(2,1).value="Row=2,Col=1"
.Cells(1,2).value="Row=1,Col=2"
End With

KeyConcept:
NotehowanythinginsidetheWith(betweentheWithand EndWith)
whichbegins.istreatedasaMethodorpropertyoftheObjecttowhich
theWithstatementrefers.

20 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

'Take Home' Ideas from Lesson 2


ObjectsarestoredinCollectionstomakethemeasiertofind.

InExcel,manyObjectshaveaCollectionofObjectsasoneoftheir
Properties.Thisallowsusto'drilldown'fromatoplevelObject
likeExcel.ApplicationallthewaydowntoCells.

VariablesarenamedcontainersforObjectsornonObjectdata
likeStrings,Booleans,DatesandNumbers.

VariablesareahandywayofbeingabletofindanObjectonce
butuseitseveraltimes.

AnotherhandywayofusingthesameObjectseveraltimesisto
useaWithstatement.

DrAlexanderJTurner2007 21
BabySteps

22 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 3: Loops
Finally we start to make things easier:
Iamnotyou,butifItrytoimaginebeingyou,rightnowIwouldbe
thinking:
Thisisallverywell,butIhavejusttakenanagetodosomethingI
couldhavedoin30secondswithExcelusingjustformulaeorfills.
Thatsentimentisperfectlycorrect!So,itistimetostartdoingsome
stuffwhichiseasierandfastertodowithscriptsthanitisbyhand,
andthatusuallyinvolvesloops.

Fig2:Thelooptapemodelofcomputerloops.Hereweare
makingaloopwhichsays'Add2And2'overandoveragain,for
ever!
People do not normally like doing the same thing over and over
again;computersloveit. Loopsareawayoftellingacomputerto
'loopover'thesamesetofactionsrepeatedly.Youcanthinkofloops

DrAlexanderJTurner2007 23
BabySteps

as 'loop tapes'. Figure 2 shows graphically how this mental model


works.
Theobviousflawinthisapproachisthattheloopwillrunforever.
Thisiscalledan'InfiniteLoop'. Sometimesinprogrammingthisis
exactlywhatyouwant.Mostofthetime,however,wewanttoloop
onlyuntilsomecriterionhasbeenmet.
ForExample:
1. WorkdownColumnAoneCellatatime.
2. AddthecontentsoftheCellyouareontotoitsrownumber.
3. PuttheresultintothesamerowinColumnB.
4. StopwhenyougettoanemptyCellinColumnA.
Thatexampleisexactlythesortofthingonedoesallthetimewhen
Scripting Macros. The way that it automatically stops when a
conditionismet(whenanemptyCellisreached)hintsatthepower
ofthistechniquewhencomparedtojustusingformulaeinExcel.
Drag And Drop Scripting, An Introduction
Tomakemeaningfullexamplesofhowloopscanautomaterepetitive
tasks, we need to be able to load preexisting Excel Workbooks.
Again,fromexperienceinthefield,thebestwaytoachievethisisvia
'draganddropscripting'.
ThisapproachworksbyclickingonaWorkbookfileand dragging it
over the icon for our script. When we 'drop' (release the mouse
button)Windowsrunsthescriptandtellsthescriptthefilenameof
theWorkbookyoudroppedonit. Windows'tells'youthefilename
byaspecialCollectionthatyoucanalwaysusefrominsidethescript.
This is the WScript.Arguments Collection. All scripts of type '.vbs'
(VBScript)haveaspecialObjectprecreatedthatiscalled WScript.
YoucandolotsofhandythingswithWScript;readingthenamesof
fileswhichhavebeendroppedontoascriptisjustoneofthem.

24 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure4:HereistheWorkbookfileBabyStepsExamples.xlsbeing
'draganddropped'ontoaMacroScriptfile.Whenthescriptruns,
thefilenameoftheWorkbookwillbebeplacedinthe
WScript.ArgumentsCollectionofthescriptatindex0.

Now that we have figured out how to tell a script which Excel
Workbooktoopen,weneedtoactuallyopenit.Thispieceofcode
willopenanExcelWorkbookwhichisdroppedontoit:
' Create an Excel application Object and make it
' become visible
Set myExcel = CreateObject("Excel.Application")
myExcel.visible=true

' WScript.Arguments is a special Collection into


' which Windows places a list of the file names of any
' files that were dropped on to the script.
' It is a bit unusual because it starts from index 0,
' rather index 1 like most Collections do.
' You just have to remember it as a special case!
myFileName = Wscript.Arguments(0)

' The Workbooks Collection has a special method


' which loads and Workbook file into a new Workbook.
Set myWorkbook=myExcel.Workbooks.Open(myFileName)

Now that we have automated the loading of a Workbook we can


automateitsprocessingusingascript.Aswehaveseen,eachCell
Object has a Property Value. There isa special Method built into
VBScriptwhichcantellifavalueisempty. ThisMethodiscalled

DrAlexanderJTurner2007 25
BabySteps

IsEmpty(). Itproduces a Booleanvalueof true or false. Itisthis


handymethodthatweusedtocontrolwhenourloopwillexit.Here
isanexamplescript,whichIwilldiscussinmoredetailafterwards:
Set myExcel = CreateObject("Excel.Application")
myFileName = WScript.Arguments(0)
Set myWorkbook=myExcel.Workbooks.Open(myFileName)

' Note that the Sheets Collection starts at


' the more normal index of 1.
Set mySheet=myWorkbook.Sheets(1)

' row is a Variable in which we store the number


' of the current row that the loop is working on.
' We are going to start with row = 2 because
' Row 1 holds the headers. Please also note
' I have called this Variable row just to make
' the script easy to read for humans. It could
' be called anything. For example, I could have
' called the Variable bob as in: bob = 2
row = 2

' This loop will carry on until the current


' Row has an empty Cell in Column 1.
' For a full descripting of this
' loop, see the main text of "Baby Steps"
While Not IsEmpty(mySheet.Cells(row,1).Value)
mySheet.Cells(row,2).value = _
mySheet.Cells(row,1).value * 2.0
row = row + 1
Wend

Note:ifyouendaline_itmeansthatthelineiscontinuedon
thenextline.i.e.:
a = _
b
Isthesameas:
a = b

TotestthisscriptweshouldcreateanExcelWorkbookinwhichthe
firstSheethasvaluessomethinglikethis:
Price Price $
1.5
2.3
0.5

26 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

OncethescripthasrunthefirstSheetwilllooklikethis:
Price Price $
1.5 3.0
2.3 4.6
0.5 1.0

To achieve this the script has performed the following steps


(rememberthatCellsarereferencedy,xi.e.row,column):
1. StartedwiththeVariablerowwithvalue2.
2. CheckedthatValueofCell(2,1)andfoundittobenotempty.
3. TakentheValueofCell(2,1)andmultiplieditby2.
4. PlacedtheresultofthecalculationinCell(2,2).
5. Added1tothevalueofrowandputtheresultbackintorow.
6. CheckedthatValueofCell(3,1)andfoundittobenotempty.
7. TakentheValueofCell(3,1)andmultiplieditby2.
8. PlacedtheresultofthecalculationinCell(3,2).
9. CheckedthatValueofCell(4,1)andfoundittobeempty.
10. Notprocessedtheloopanyfurther(sometimescalled'exiting
theloop').
For Loops
Sofarwehavelookedat While loops. Thesearethemostobvious
form of loop; they say keep doing something while something is
true.Theyarenottheonlyformofloop.Anothersortthatisquite
usefulistheForloop.Theysaydosomethingforacertaincount.
Thefollowingtwoloopsarecompletelyidentical.
' While loop:
bob = 2
While bob < 10
mySheet.Cells(bob,1)= Row number = & bob
bob = bob + 1
Wend

' For loop:


For bob = 2 To 9
mySheet.Cells(bob,1)= Row number = & bob
Next

DrAlexanderJTurner2007 27
BabySteps

Note:ifbob = 3thenRow number = & bobproduces


Row number = 3i.e.thesymbol&joinsaStringtoa
String,Number,BooleanorDate.

Because,inExcelscripting,wearemoreoftenthannotloopingover
data until some data related condition is met, For loops are less
commonthanWhileloops.However,asyoucanseefromtheabove
example,whenyoucanusethemtheytakeuplessspaceanditis
moreobviouswhatishappening.
For Each Loops
WehavejustseenhowForloopsareaneasywayofperformingaset
ofactionsforasetnumberofrepetitions.Howaboutifwewantto
performanactiononeachofthecontentsofaCollection?Inother
wordsForEachelementintheCollection.Happily,VBScriptprovides
uswithareallysimplewayofdoingthis.
WecouldmakethishappenusingaForloop:
For index = 1 To myWorkbook.Sheets.Count
mySheet = myWorkbook.Sheets(index)
mySheet.Cells(1,1).Value = Hello World
Next

However,usinga ForEach ismuchsimpler(andactuallyfasterfor


thecomputertorun)!
For Each mySheet In myWorkbook.Sheets
mySheet.Cells(1,1).vValue = Hello World
Next

28 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

'Take Home' Ideas from Lesson 3


Therearethreetypesofloopswhicharereallyhandy:While,For
andForEach.

TheeasiestwayofsettingupaScriptingMacrotoopenpre
existingWorkbooksistouseDragAndDropScripting.

WScriptisapreexistingObjectwhichisavailablefromall
scripts.Italowsus,amongstmanyotherthings,togetthefile
nameofaWorkbookwhichhasbeen'dropped'ontoourscript.

AlotofthetimewewillwanttoprocessCellsuntilwefindonor
moreemptyones.Thiscanbeachievedusingthehandy
IsEmpty()methodinconjunctionwithaWhileloop.

DrAlexanderJTurner2007 29
BabySteps

30 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 4: Getting Tooled Up.


A Quick Note
From here onward in Baby Steps, there will be times when it is
impossibletofitawholelineofscriptingcodeintoalineonthepage.
To help prevent this being confusing, empty space at the start of
scriptlineswillbefilledwiththisspecialcharacter.Ifyoudo
noseeanyofthisgreystuffatthestartofaline,thenthelineisa
continuationfromthelineabove.
Get A Good Text Editor
Aswehaveseensofar,MacroScriptsarejusttextfiles.Textfilesare
unlikedocumentsfromthingslikeMSWordbecausetheycontainjust
characters;even newlines arestoredjustacharacters.Wecanedit
textfileswithNotepad(likewehavetillnow)butitisnotaverynice
toolfordoingthis.Beforeourscriptsgetmuchmorecomplex,itwill
bemucheasierforustouseamorepowerfultool.Fortunately,there
aremanyfreetexteditorsinexistence.Theyaresoimportanttothe
actofprogramming,thatmanypeoplehavecreatedthem.
MyfavouritetexteditorforWindowsisNotepad++.Itsnamegives
the game away. It is a lot like Notepad but with loads of extra
features like line numbering, text colouring and excellent
find/replacetools.
Notepad++is'OpenSource'andfreeofcharge.Thismeansthatyou
donothavetopayforitatallandyoucanuseitinanywayyou
wantotherthanresellit.

DrAlexanderJTurner2007 31
BabySteps

Figure4:ThisisascreenshotofNotepad++beingusedtoeditone
oftheexamplefilesfromBabySteps.

Todownloadacopy,pleasegotothisURL:
http://www.sourceforge.net/project/showfiles.php?
group_id=95717&package_id=102072.

Alternativelyyoucandotothepackagehomepageandfollowthe
linkstodownloadthebinaryexecutablefiles:
http://notepad-plus.sourceforge.net/uk/download.php

Recording Macros
ItwouldbeahugetasktolearnandrememberhowtogetExceltodo
everythingviaScriptsthatwecangetittodoviatheuserinterface.
Wow, that is scary. Fortunately, we do not have to learn and
rememberallthat!Excelhas(asyoumaywellalreadyknow)areally
handyfeaturecalledthe'MacroRecorder'.
The Macro Recorder records 'Internal' Macros; those being ones
which are embedded into a Workbook. However, Internal Macros
andScriptingMacrosasverysimilar.WecanrecordInternalMacros
andtheneasilytranslatethemintoScriptingMacrosorintopieces
whichcanbeaddedintoScriptingMacros.
First,IwillbrieflydescriberecordingMacrosforthispurpose.Then,
inthenextsection,IwillexplainhowtotranslatetheInternalMacros
intopiecesofScriptingMacro.

32 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure5:HowtostartrecordingaMacro.
Theusualuseofthe MacroRecorder istocreateanInternalMacro
whichwillautomateatask.Usingitrequiresthreesimplesteps:
1. Startrecording.
2. Performthetask.
3. Stoprecording.
Startingtherecording,inmostversionsofExcel,isdoneviatheTools
menuoption. Figure5showsthisbeingdoneandAppendixAhas
detailsofhowtodoitinExcel2007.

Figure6:WhenchoosingaMacroname,youmayaswellusethe
oneExcelsuggestsbecauseyouarenotgoingtokeeptheMacro,
itisgoingtobetranslatedintoyourScript.

DrAlexanderJTurner2007 33
BabySteps

Once we have requested to start the Macro Recorder, we need to


nametheMacro.BecausewearenotgoingtokeepthisMacro(just
translateitintoaScriptingMacro)itisnotveryimportantwhatwe
callit; inmostcases,thenameExcelcreatesautomaticallyisjust
fine.
Oncewehavechosenanameandclicked'OK'(seefigure6)Excel
startsrecording.Eachactionwhichistaken(e.g.eachmouseclickor
button press) will be recorded as Visual Basic code which will
perform the same action. For example, selecting the top Row of
ColumnsAtoIwillcausetheMacroRecordertorecord:
Range(A1:I1).Select

Unfortunately, we cannot actually see the recording happen as it


records. However,itisimportanttothinkverycarefullyasweare
performingthetaskswhichwewantrecorded;everyactionwillbe
recorded,includingmistakes,'undos'andaccidentalCellselections!

Figure7:ThisscreenshotshowsasetofCellsbeingcoloured
whilsttheMacroRecorderisrunning.
RememberthatwearenotwantingtokeeptheMacro.Wearegoing
totranslateitintopartofaMacroScript.Becauseofthis,itismuch
easiertorecordaseparateshortMacroforeachstepofaprocessthan
torecordahugeMacroofanentire,complexprocess.Infigure7we
canseeaMacrobeingrecorded.Thisoneconsistsofselectingsome
Cellsandthencolouringthem.Thisisaboutthelevelofcomplexity
we should be aiming for in any one recording. There are some

34 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

exceptionswhereitisnotpossibletomakereallyshortrecordings.
Forexample,whenwecreatePivotTablesinlesson8.

Figure8:Thisscreenshotshowshow,oncetheactionswewant
recordinghavebeencompletedandtheMacroRecorderstopped,
wecanopentheVisualBasicEditorandviewtheMacrocode.

Figure9:HerewecanseehowthecodefortheMacrohasbeen
writtenintoaModuleofname'Module1'.Byexpandingthe
Modulesnodeinthelefthandtreeviewandthendoubleclicking
on'Module1'wecanseetherecordedcode.

DrAlexanderJTurner2007 35
BabySteps

Translating Recorded Macros


OncewehaverecordedaMacro,wecanusecopyandpastetoput
theMacrocodeintoNodepad++(orwhatevereditorweareusing).
WeareonlyinterestedinthecodebetweenthelinestartingSub
andthelineEndSub. Everythingelse,includingthesetwolines,
canbethrownaway.
The'raw'InternalMacrocodehastobetranslatedbeforeitwillwork
asaScriptingMacro.Translatingmacrosrequiresthreefundamental
steps:
1. The keyboard and mouse based approach of the Macro
shouldbeconvertedtoasimplerformforscripting.
2. Excelconstantsneedtobetranslatedintonumbers.
3. Theresultsof1and2needtobeintegratedintothescriptso
thatitoperatesonthecorrectObjects.
Keyboard and Mouse to Script Translation
InourexampleweliterallyselectedsomeCellsandthenchangedthe
backgroundcolour oftheselection.ThisisexactlywhattheMacro
Recorderhasrecorded.A Range Objectisidenticaltoa Cell Object
(whichwehaveusedbefore)exceptitreferstooneormoreCellsat
once.
mySheet.Cells(1,1).Value = Hello World

Is100%thesameas:
mySheet.Range(A1:A1).Value = Hello World

RangeandCellObjectshaveaMethod Select() whichsimplyselects


themjustasthoughyouhadselectedthemonaWorksheetusingthe
mouse.SotheMacroRecorderhasrecordedtheCellsbeingselected
and converted this action into the code which calls the Select()
MethodonaRange.
mySheet.Range(A1:I1).Select

OncetheCellshavebeenselected,theRecorderrecordsthechanges
tothatselection.Weshouldremovethisuseofaselectionandwork
withtheCellsdirectly:
Range(A1:I1).Select
With Selection.Interior

Becomes:

36 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

With mySheet.Range(A1:I1).Interior

The Interior PropertyofaCellorRangeObjectisaspecialObject


whichExcelusesforcontrollingthe colour, border andothervisual
Cellfeatures.
Translating Excel Constants
Excel constants arenumberswhichhavespecialmeaningstoExcel.
Forexamplethenumber1tellsthe Cell.Interior ObjectthataCell
border shouldbesolid.The MacroRecorder hasspecialnamesfor
theseconstants. Forexampleinsteadofusing1 to signify a solid
border,itwillusexlSolid;Excel'knows'thatxlSolidactuallymeans1.
Unfortunately,aScriptingMacrodoesnot'know'whatxlSolidmeans
sowetotellit.
BeforewecanwritethecodeintoaScriptingMacrotodefinexlSolid,
orany Excelconstant,weneedtofindoutwhatitsvalueis.Whilst
wemightbeabletorememberthevalueofoneortwoconstants,
Excelhashundredsofthem. Fortunatelyforus,Excelalsohasan
easytousetoolforfindingouttheirvalues.

Figure10:TostarttheprocessoffindingthevalueofanExcel
constantrightclickontheconstantintheVisualBasicviewofthe
Macro.
ExcelhasatoolcalledtheObjectBrowser.Wearegoingtolookinto
usingthisinmoredetailinthenextsection.Usingitforfindingthe
valueofExcelconstantsisverysimpleindeed.Thatisexactlywhat
wewilldonow.

DrAlexanderJTurner2007 37
BabySteps

Figure11:ThesecondsteptofindingoutthevalueofanExcel
constantistoclickon'Definition'whencontextmenucomesup.
AllthatisrequiredistoviewthecodeofourrecordedMacro.From
thisview,wecanrightclickonthetextoftheconstantitsself.Inour
example,ifwerightclickonthetext'xlAutomatic'acontextmenu
appears.Allweneedtodoisclickon'Definition'.

Figure12:Oncewehavechosen'Definition'fromthecontextmenu
overanExcelconstant,theObjectBrowserwillopen.Inthebottom
paneoftheObjectBrowser,wecanseethedefinitionoftheExcel
Constant.Inthiscase,xlAutomaticisdefined
as4105.

38 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Oncewehaveclickedon'Definition'Excelwillautomaticallystartup
the Object Browser showing details of the constant on which we
clicked. Constantsareshownasthenumberinournormaldecimal
numbersystemandtheninbracketsusingthemorecomputercentric
hexadecimalsystem.Weonlyneedtoconsiderthedecimalversion.
ForourScriptingMacrotousetheconstantswehavetodefinethem
in the Scripting Macro. Hereis an example of thefinished Script
segment(thisisnotafullscript):
xlAutomatic = -4105
xlSolid = 1
With mySheet.Range(A1:I1).Interior
.ColorIndex = 36
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
End With

Using The Object Browser


IntheprevioussectionwesawhowExcelwillautomaticallylaunch
theObjectBrowserifweaskitforthedefinitionofanExcelconstant.
WecanalsomanuallyopentheusetheObjectBrowser.Thiscanbe
veryhandytohelpworkouthowtodosomethingwithExcel.
The Macro Recorder can be very helpful, however sometimes we
wanttoworkouthowtodosomethingwhichishardorfiddlytodo
withtheMacroRecorder.ThisiswheretheObjectBrowsercomesin
extremelyuseful.
JustabouteverythingExcelcandofromthegraphicalinterfaceitcan
alsodofromtheprogramminginterface.ThismeansthatourMacro
Scriptscandojustaboutanythingwewant.ToallowExceltohave
such excellent programmatic control, there are a huge number of
ObjectsandConstantsinExcel. Theseareallknownaboutbythe
ObjectBrowser.TheObjectBrowsertakesitsinternaldescriptionof
alltheseObjectsandConstantsanddisplaystheminahumanusable
form.Itisnotonlyabrowser,butalsoasearchengine.Youcanuse
ittosearchforObjectsorConstantsbyname.
TogettheObjectBrowserstarted,wefirstneedtobeinVisualBasic
ForApplications view(seefigure13). Fromthere,wecandirectly
opentheBrowserfromthe'View'menu.

DrAlexanderJTurner2007 39
BabySteps

Figure13:WecanstarttheObjectBrowsermanuallyfromthe
Viewmenu.
OncewehavestartedtheBrowserwecanstartlookingaroundinside
theprogrammaticinterfacetoExcelandsolearnalittlemoreabout
justwhatwecandowithScriptingMacros.

Figure14:ThisscreenshotshowswhattheObjectBrowserlooks
likewhenithasbeenopened.AlsohereIhavetyped'xlsolid'
(notethatthesearchisnotcasesensitive)intothesearchbox
andclickedthesearchbutton(ithasbinocularsonit).Inthe
paneatthebottomoftheBowserwecanseetheresultofmy
search.InthemiddlepaneswecanseethatxlSolidisamember
ofConstants.

40 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure15:NotonlycanwesearchusingtheObjectBrowserwe
canbrowsewithit.Thebottomtwopanesallowustomove
aroundtheClassesandCollectionsofExcelandseewhatis
available.
Finding And Removing Bugs
Bugsareafactoflifeinanythingcomputerbased.Basically,abugis
whenourscriptdoesnotdowhatwewantorexpect. Thereisno
simplecureorremedyforbugs.Whenweseetheeffectofabugin
thewayascriptisrunningwemust'findthebug'. Thisisjustlike
fixinganymachine;thefirststepistofindoutwhyitisnotworking
properly.Fixingtheproblemalwayscomessecond.
Thebestadviceforfindinganythingistodevelopthebestpossible
wayoflookingforit.Ifwearelookingforaneedleonacarpet,we
mightuseamagnet. Ifwearelookingforastar,wemightusea
telescope.So,weneedtoolstohelpusfindbugsinScriptingMacros.
Fortunatelyforustherearethree:
1) Ourbrains!Wemustnotmakeanyassumptions.Thehuman
brainisamazingpowerfulattheartoffiguringoutwhatis
goingon,aslongaswedonotassumewealreadyknowwhat
isgoingon.Findingbugsrequiresanopenmindandlotsof
concentration.
2) Wscript.Echo:ThisMethodpopsupalertboxesthatletussee
theinnerworkingsofascript.Onewayoflookingforabug
istoimagineallthevaluesofVariablesasthescriptruns.An
alternativeistoimaginewhichpiecesofcodewillberunning
atwhichpointintime. Placing Wscript.Echo statementsin

DrAlexanderJTurner2007 41
BabySteps

thescriptsallowsusto'see'ifourimaginingsarecorrect.If
they are not, maybe that points to the bug. For example,
whatvalueswillmyNumbertakeon?
For row = 1 To 10
myNumber = (row * row) / (row * 0.25)
Next

Tofindout,simplyjustgetthescripttotellus:
For row = 1 To 10
myNumber = (row * row) / (row * 0.25)
Wscript.Echo myNumber
Next

Ifhavingtenpopupboxesisjusttooannoyingthenthisisan
alternative:
myList =
for row = 1 to 10
myNumber = (row * row) / (row * 0.25)
myList = myList & myNumber & ,
next
Wscript.Echo myList

3) OptionExplicit:Thissasimpledirectivethatwecanputat
the top of scripts. It forces the VBScript interpretor (the
thingthatactuallyrunsourScriptingMacro)tocheckthat
youhaveexplicitlyuseDimtocreateallVariablesbeforeyou
usethem.
Here is an example of the use of Option Explicit to help debug a
script:
Inthisexample,thescriptwillproducemeaninglessresults:
' Create Excel Etc
...
' Populate a Spreadsheet
for row=1 to 100
value=row * 10
mySheet.Cells(row,1).Value=valeu
next i

Amistakelikethisisalargescriptcantakeaverylongtimetospot
usingjustthehumaneye.Thesolutionistodothis:
Option Explicit
Dim mySheet,row,value
' Create Excel Etc

42 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

...
' Populate a Spreadsheet
for row=1 to 100
value=row * 10
mySheet.Cells(row,1).Value=valeu
next i

The'OptionExplicit'atthetopofthescripttellsVBScriptnottousea
Variable unlessit has beencreated witha Dimstatement. In this
case,wehavenotcreatedaVariablevaleusothescriptwillnotrun;
insteaditwillgiveusawarningtellingusthattheVariableisnot
definedandthelineonwhichthebugis.

DrAlexanderJTurner2007 43
BabySteps

'Take Home' Ideas from Lesson 4


Fromnowonscriptswillhaveinsteadofspacesatthestart
ofnewlines.

Scriptsaretextandsoarebesteditedwithatexteditorlike
notepad++.

Excel'sInternalMacrosandScriptingMacrosareverysimilar.A
goodapproachtofiguringouthowtodosomethingwithascript
istorecordanExcelInternalMacroandthentranslateitintoa
ScriptingMacro.

Scripttranslationrequires3steps:

1) Covertfromthekeyboardandmousebasedapproachto
asimplerdirectmethodology.
2) Translateconstants.
3) Integrate.

Totranslateconstants,wecanrightclickontheminExcel'scode
viewandgotoDefinition.

FindingdefinitionsusestheObjectBrowser.TheObjectBrowser
isveryusefulforlookingatotherpartsofExcel'sprogrammatic
interface.

Gettingridofbugstakes3techniques:Keepingandopenmind,
usingWscript.Echoto'see'whatisreallyhappeningandalways
usingOptionExplicit.

44 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 5: Starting To Work With Data


Special Folders
Inthislessonwearegoingtodosomerealdataprocessing. Todo
thisweneedtofindWorkbookstoopenandfindgoodlocationsto
savenewWorkbooks. Todothiswecanuse SpecialFolders. So,
pleasebepatient;thissectionwillonlybebrief,thenwecanstart
withsomerealwork!
Special Folders are folders that are or at least potentially can be
presentonallWindowscomputers;theseincludetheMyDocuments,
FontsandStartMenufolders.TherearetwotypesofSpecialFolders:
Thosethatmapto standarddirectories andthosethatdonot.The
Favourites folder,forexample,mapstoastandarddirectory;the My
Computerfolderdoesnot.WeareonlyinterestedinSpecialFolders
whichmapto(represent)realfolders.
The WScript.Shell SpecialFolders collectioncontainsthefullpathto
eachofthespecialfoldersthatwecanaccessusingScriptingMacros.
Thetablebelowliststhe Keys totheCollectionandthecontentsof
eachofthespecialfoldersintheSpecialFolderscollection.

Identifier Folder Contents


AllUsersDesktop Shortcuts that appear on the
desktop for all users
AllUsersStartMenu Shortcuts that appear on the Start
menu for all users
AllUsersPrograms Shortcuts that appear on the
Programs menu for all users
AllUsersStartup Shortcuts to programs that are run
on startup for all users
Desktop Shortcuts that appear on the
desktop for the current user
Favorites Shortcuts saved as favorites by the
current user
Fonts Fonts installed on the system
MyDocuments Current users documents
NetHood Objects that appear in Network
Neighborhood
PrintHood Printer links
Recent Shortcuts to current users recently
opened documents

DrAlexanderJTurner2007 45
BabySteps

Identifier Folder Contents


SendTo Shortcuts to applications that show
up as possible send-to targets when
a user right-clicks on a file in
Windows Explorer
StartMenu Shortcuts that appear in the
current users start menu
Startup Shortcuts to applications that run
automatically when the current user
logs on to the system
Templates Application template files specific
to the current user

ThewaytousetheSpecialFolderfeatureofaWScript.Shellobjectis
via the .SpeciaFolders.Item() Method. The script below finds the
locationoftheMyDocumentsspecialfolderanddisplaysittous.
Option Explicit
Dim myShell, myPath
Set myShell = WScript.CreateObject("WScript.Shell")
myPath = myShell.SpecialFolders.Item("MyDocuments")
WScript.Echo "MyDocuments='" & myPath & "'"

Using 'SendTo' As A Really Easy Way To Run Scripts


The script below creates a shortcut to a Scripting Macro
'myMacro.vbs'intheSendTospecialfolderwhichmeanswecanthen
rightclickonanyWorkbookfileandsendittothatScriptingMacro.
The script assumes that our Scripting Macro is in
MyDocuments\ScriptingMacros.
Option Explicit
Dim myShell, sendToFolder, myScriptPath, myShortcut

Set myShell = WScript.CreateObject("WScript.Shell")


sendToFolder = myShell.SpecialFolders("SendTo")
myScriptPath = myShell.SpecialFolders("MyDocuments") &
"\myMacro.lnk"

Set myShortcut = myShell.CreateShortcut(sendToFolder &


"myMacro.lnk")
myShortcut.TargetPath = myScriptPath
myShortcut.Save

46 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Saving And Opening From Special Folders


WhenweuseScriptingMacrostoautomateataskwewanttheinput
andoutputfilestobeplacedineasytofindplaces. Microsoft has
carefully moved us into thinking in terms of MyDocuments and
Desktop etc.;thismakes specialfolders likethisidealforautomated
scriptingtasks.
Belowaretwoexamples.ThefirstscriptcreatesanewWorkbook.It
thenplacesthecurrenttimeanddateintooneoftheSheets.Onceit
has done this it saves the Workbook onto the Desktop. It
automaticallyoverwritesanyexistingWorkbookofthesamename.
Youcantellthatithasdonethisbecauseeachtimethescriptrunsthe
dateand/ortimewillbeupdated.
Thesecondscriptisevensimpler;itjustopenstheWorkbookthefirst
scriptcreated.Thescriptrequiresnouserinterventionbecauseitcan
findtheWorkbookusingthespecialfolder'Desktop'.
' This script saves a Workbook to the Desktop
Option Explicit
Dim myShell, myExcel, myWorkbook, mySheet, myShell,
xlNormal

' Open Excel


Set myExcel = CreateObject("Excel.Application")
' Create a Workbook and set myWorkbook to refer to it
' all in one go
Set myWorkbook = myExcel.Workbooks.Add
Set mySheet = myWorkbook.Sheets(1)
mySheet.Cells(1,1).Value="Date"
mySheet.Cells(2,1).Value=Date()
mySheet.Cells(1,2).Value="Time"
With mySheet.Cells(2,2)
.Value=Now()
.NumberFormat = "[$-409]h:mm:ss AM/PM;@"
End With
mySheet.Columns(1).AutoFit

' Tell Excel not to complain about overwrite files and


' other things like that
myExcel.DisplayAlerts = FALSE

' Save Excel Workbook to Desktop


xlNormal = -4143
Set myShell=CreateObject("WScript.Shell")
myWorkbook.SaveAs myShell.SpecialFolders("Desktop") &
"\AutoSaved.xls",xlNormal
myExcel.Quit

DrAlexanderJTurner2007 47
BabySteps

Figure16:ThisscreenshotisresultofthefirstofthetwoDesktop
scripts.ThisistheExcelWorkbookthatIopenedfromdouble
clickingonAutoSaved.xlsonthedesktop.
' This script opens the Workbook saved by the
' previous one
Dim myShell, myExcel,myShell
Set myExcel = CreateObject("Excel.Application")
Set myShell=CreateObject("WScript.Shell")
myExcel.Open myShell.SpecialFolders("Desktop") &
"\AutoSaved.xls"

Merging Between Workbooks


InmyforwardItalkedaboutchainsofExcelspreadsheets.Theseare
causedwheredatapassesthroughmanystepsand/ormanyhands.
Onekeyactioninsuchchainsisdatamerging.Oftenwemusttake
twoorthreedatasetsandmergethemtogether.
MovingColumnsofdataaroundbyhandcanbetedious.Searching
through rows of data to find matches can be soul destroying.
ScriptingMacroscancometotherescue.
Merging Data By Example
Tosetthesceneofdatamerging,agoodexamplewilldonicely.By
looking at a plausible business scenario we can truly imagine the
stepsinvolvedinmerging.
Afairlycommoncause forthe needto mergeis 'incompletedata'.
Considerthatweareinasalesdepartment.Salespeopleareouton

48 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

the road collecting orders. They report the orders back to head
officeonspreadsheetslikethis:

Customer Name Part Number Quantity Date


ABC Engineering 12345 1 11/11/2007
XYZ Fabrication 7234 4 6/11/2007

Our job is to record there orders and get them dispatched to


fulfilmentfromwherethepartswillbesenttothecustomers.
But notice, the order records from the sales people do not tell us
enough for fulfilment to do their job. All we have is a customer
name. To overcome this we have another master customer list.
This is the critical core Workbook from which all customer
information is run. In this Workbook is a Sheet with customer
contactdetailslikethis:

Name Id Address Tel Fax Main


Contact
ABC 5 45 False 01234567 01234567 John
Engineering Road 8 9
XYZ 8 23 08756432 01234567 Jane
Fabrication Nowhere 1 2
Avenue

OurfirstchallengeistowriteaScriptingMacrowhichwilloutputa
Sheettosendtofulfilment.ThisscriptwilltakeeachorderRowfrom
a sales person and match the customer name against the Name
column in the Customer Contact Details Sheet. The output of this
process should have the customer name, address, part number,
quantityandorderdate.
Dictionary Objects
Dictionary Objects are very useful things indeed. They let us just
lookupvaluesratherthanhavingtogoandsearchforthem.Inthe
case of our example, we can storeall the customer addresses and
'lookthemup'bycustomername.Thethingwearelookingupisa
valueandwelookitupbyakey.Hereisadescriptionofallthe
PropertiesandMethodsofaDictionaryObject.
DictionaryObjectProperties:

CompareMode This sets the compare mode for using


different character sets. We can normally

DrAlexanderJTurner2007 49
BabySteps

ignore this.
Count The number of key/value pairs in this
Dictionary.
Item(key) Return the value looked up by key. We can
also set the value for an existing key:

myDictionary.item(fred-wife)= wimla
Key(key) Allows us to change a key. Consider that
Wilma remarried Barny then we could put:

myDictionary.key(fred-wife)=barny-wife

DictionaryObjectMethods:

Add key,value Places a new key/value pair into the


Dictionary.
Exists(key) Returns TRUE is key is in the Dictionary
and FALSE otherwise.
Remove(key) Removes a key/value pair from the
Dictionary.
Items() Returns an array of all the values in
the Dictionary.
Keys() Returns an array of all the keys in the
in the Dictionary.
RemoveAll() Totally empties the Dictionary so it has
no key/value pairs at all.

So,to merge orders with addresses wecanstore allthecustomer


namesaskeys.Foreachcustomernamekeywestoretheaddressas
thevalue.
Letususeacustomercalledhackandslashwithanaddress123
FakeStreet.wecanthenstoretheaddresswiththenamesasakey
likethis:
Dim myDictionary
Set myDictionary=CreateObject(Scripting.Dictionary)
myDictionary.Add hack and slash, 123 Fake Street

Thereverseofthisistolookupthevalueassociatedwithanalready
stored key. We can demonstrate this with a continuation of the
previousscript.

50 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Dim address
address = myDictionary.Item(hack and slash)
Wscript.Echo address

Theabovescriptwillecho123FakeStreet
Simple Merge Script
Tomakeamergescriptworkitwillhaveto:
1) Loadtheordersheet.
2) Loadthecustomerinformationsheet.
3) Createanewsheet.
4) Populatethenewsheetwithamergeddataset.
5) Savethenewsheet.
TomakethisniceandsimpleIwillsaythatthecustomerinformation
WorkbookisalreadyonmyDesktop.Thismeansthatwecanusethe
'specialfolders'wehavealreadylookedattolocatetheWorkbook.To
continuewiththeeasyconcept,IwillputtheoutputWorkbookon
the Desktop aswell. Finally,using'draganddrop'seemsasensible
choiceforloadingthesalesWorkbookintomyScriptingMacro.
Todothedatamergethescriptwillhavetolookupaddressesby
customer name. So it will load a Dictionary; the keys will be
customernamesandthevalueswillbecustomeraddresses.Nextthe
scriptwillworkitswaydownthesalesSpreadsheet(fromthesales
Workbook that was dropped onto it). For each Row on the sales
Spreadsheetthescriptwillreadinthecustomersnameandlookup
theaddress.
Onceithasfoundtheaddressitwillwritethename,address,order
quantityanddateintotheordersSheetintheoutputWorkbook.The
followingscriptperformsthissimplemerge:
Option Explicit
Dim myShell,myExcel,ordersWB
Dim customersWB,outputWB,myDict
Dim desktop,row,ordersSh,customersSh,outputSh
Set myExcel=CreateObject("Excel.Application")
Set myDict =CreateObject("Scripting.Dictionary")
Set myShell=CreateObject("WScript.Shell")
desktop=myShell.SpecialFolders("Desktop")

myExcel.Visible=TRUE

DrAlexanderJTurner2007 51
BabySteps

Set ordersWB=myExcel.Workbooks.Open(desktop &


"\orders.xls")
Set customersWB=myExcel.Workbooks.Open(desktop &
"\customers.xls")
Set outputWB=myExcel.Workbooks.Add()

Set ordersSh=ordersWB.Sheets(1)
Set customersSh=customersWB.Sheets(1)
Set outputSh=outputWB.Sheets(1)

' This loads the dictionary with the


' addresses keyed by name
row=2
While(NOT IsEmpty(customersSh.Cells(row,1)))
myDict.Add
customersSh.Cells(row,1).Value,customersSh.Cells(row,3).
Value
row=row+1
Wend

' Lay out the output sheet


outputSh.Cells(1,1).Value="Customer Name"
outputSh.Cells(1,2).Value="Part Number"
outputSh.Cells(1,3).Value="Quantity"
outputSh.Cells(1,4).Value="Date"
outputSh.Cells(1,5).Value="Address"

' This scans the orders and creates the output


row=2
While(NOT IsEmpty(ordersSh.Cells(row,1)))
outputSh.Cells(row,1).Value=ordersSh.Cells(row,1)
outputSh.Cells(row,2).Value=ordersSh.Cells(row,2)
outputSh.Cells(row,3).Value=ordersSh.Cells(row,3)
outputSh.Cells(row,4).Value=ordersSh.Cells(row,4)
' This is the merge, looking up the address from
' the Dictionary
outputSh.Cells(row,5).Value= _
myDict.Item(ordersSh.Cells(row,1).Value)
row=row+1
Wend

'Clean up output
outputSh.Columns("D:D").NumberFormat = _
"[$-F800]dddd, mmmm dd, yyyy"
outputSh.Columns("A:E").AutoFit
outputSh.Rows("1:1").Font.FontStyle = "Bold"

Thisscriptproducesthisoutputwhenoneoftheordersisforabc
engineering:

52 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Customer Part Quanti


Name Number ty Date Address
ABC 11-
Engineering 12345 1 Nov-2007 45 False Road
XYZ 6- 23 Nowhere
Fabrication 7234 4 Nov-2007 Avenue
abc 15-
engineering 12348 12 Nov-2007

Thisscriptisallwellandgoodbutitwillbenouseintherealworld.
Forexample,thecustomerinformationWorkbookmaywellhavea
customer names as ABC Engineering; however, a sales person
(maybeinarush)mightputabcengineering(seetheabovetable).
Thesalespersonmightevenputabcengineering.Howcanwedeal
withthesesituations?
Thesolution isto this realworld situation isabit ofpragmatism.
Step one is to remove all unnecessary information. ABC
Engineering and abc engineering are clearly the same company.
Wecanchangethescripttoignorethecaseofnamestoreflectthis
reality. Thiscanbedonebymakingallthekeysinthe Dictionary
lowercaseviatheLCase()functionwhichisbuiltintoVBScript.The
other built in Function to use here is Trim() which removed any
unwantedspacesfromthestartorendofaString.
Dim MyString
myString = "VBSCript "
myString = LCase(Trim(myString))
' We can see here that the output is all lower case
' and the trailing space has gone.
Wscript.Echo "'" & myString "'"

Our second issue is where ABC Engineering is written


abcengineeringorevenbcaengineering. Theseareexamplesof
genuinemistakesmadebythesalesperson. Ifwetrytoengineer
somehypercomplexscripttoworkouttheanswerdespiteincorrect
inputs,wewillendupwastingalotoftime.
The only thing really qualified to sort out a real human error is
anotherhuman.SowewillcreateanextraSheetoferrorswecango
throughandfixbyhand.
Working Merge Script
Option Explicit

DrAlexanderJTurner2007 53
BabySteps

Dim
myShell,myExcel,ordersWB,customersWB,outputWB,myDict
Dim desktop,row,ordersSh,customersSh,outputSh,key
Dim errorSh,errorRow,okRow
Set myExcel=CreateObject("Excel.Application")
Set myDict =CreateObject("Scripting.Dictionary")
Set myShell=CreateObject("WScript.Shell")
desktop=myShell.SpecialFolders("Desktop")

myExcel.Visible=TRUE
Set ordersWB=myExcel.Workbooks.Open(desktop &
"\orders.xls")
Set customersWB=myExcel.Workbooks.Open(desktop &
"\customers.xls")
Set outputWB=myExcel.Workbooks.Add()

Set ordersSh=ordersWB.Sheets(1)
Set customersSh=customersWB.Sheets(1)
Set outputSh=outputWB.Sheets(1)
Set errorSh=outputWB.Sheets(2)

' This loads the dictionary with the


' addresses keyed by name
row=2
While(NOT IsEmpty(customersSh.Cells(row,1)))
myDict.Add
LCase(Trim(customersSh.Cells(row,1).Value)),customersSh.
Cells(row,3).Value
row=row+1
Wend

' Lay out the output sheet


outputSh.Cells(1,1).Value="Customer Name"
outputSh.Cells(1,2).Value="Part Number"
outputSh.Cells(1,3).Value="Quantity"
outputSh.Cells(1,4).Value="Date"
outputSh.Cells(1,5).Value="Address"

errorSh.Cells(1,1).Value="Customer Name"
errorSh.Cells(1,2).Value="Part Number"
errorSh.Cells(1,3).Value="Quantity"
errorSh.Cells(1,4).Value="Date"
errorSh.Cells(1,5).Value="Address"

' This scans the orders and creates the output


' We need three different Row Variables because the
' Row we write to is not the same as the number
' as the one we read from any more
row=2

54 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

errorRow=2
okRow=2
While(NOT IsEmpty(ordersSh.Cells(row,1)))
key=Trim(LCase(ordersSh.Cells(row,1).Value))
' Here is the decision if the address can be looked
up or not
If myDict.Exists(key) Then
' Yes it can - so put the Row into the ouput Sheet
outputSh.Cells(okRow,1).Value= _
ordersSh.Cells(row,1)
outputSh.Cells(okRow,2).Value= _
ordersSh.Cells(row,2)
outputSh.Cells(okRow,3).Value= _
ordersSh.Cells(row,3)
outputSh.Cells(okRow,4).Value= _
ordersSh.Cells(row,4)
outputSh.Cells(okRow,5).Value= _
myDict.Item(key)
okRow=okRow+1
Else
' No it cannot - so put the Row into
' the error Sheet
errorSh.Cells(errorRow,1).Value= _
ordersSh.Cells(row,1)
errorSh.Cells(errorRow,2).Value= _
ordersSh.Cells(row,2)
errorSh.Cells(errorRow,3).Value= _
ordersSh.Cells(row,3)
errorSh.Cells(errorRow,4).Value= _
ordersSh.Cells(row,4)
errorRow=errorRow+1
End If
row=row+1
Wend

'Clean up output
outputSh.Columns("D:D").NumberFormat = "[$-F800]dddd,
mmmm dd, yyyy"
outputSh.Columns("A:E").AutoFit
outputSh.Rows("1:1").Font.FontStyle = "Bold"
outputSh.Name="Orders To Process"

errorSh.Columns("D:D").NumberFormat = "[$-F800]dddd,
mmmm dd, yyyy"
errorSh.Columns("A:D").AutoFit
errorSh.Rows("1:1").Font.FontStyle = "Bold"
errorSh.Name="Errors"

Hereisastepbystepapproachtogettingdatamergingtowork:

DrAlexanderJTurner2007 55
BabySteps

1) FindaColumnwhichisinbothSheets
2) WorkoutwhichSheethasthemasterrecordsandwhich
theslave.InourexamplethecustomerinformationSheet
wasthemaster. Donotworryifitisnotobviouswhichis
which;youcanalwaystryitbothwaysandseewhichworks
better.
3) FindtheColumninthemasterwhichissharedwiththeslave
(e.g.customername).
4) Figureoutallthevariabilitywhichcanberemovedfromthe
shared column data. Examples are capitals, spaces,
punctuation.
5) Loadthedatayouwantfromthemasterintoa Dictionary
Object.KeytheDictionarybythesharecolumn.
6) Foreachrowintheslave,lookupthedataintheDictionary.
7) Ifamatchingentryinthe Dictionary isfound,putthedata
fromtheslaveandtheDictionaryintotheoutputSheet.
8) Ifnomatchisfound,putthedatafromtheslaveintothe
'errors'Sheet.
Merging Multiple Columns
Sofarwehavelookedatmergingmultiplecolumnsfromtheslave
Sheet with a single column (e.g. address) from the master. How
couldwe mergemultiple columns frombothSheets? Itwouldbe
quite hard to load more than one Column into the Value of a
key/valuepairintheDictionaryObjectsothatisprobablynotthe
solution.
Asitturnsout,thesolutionisverysimple. Doeverythingthesame
wayasforthesinglemasterColumnmerge,butthistimestorethe
RownumberinthemasternottheColumndata.Eachtimeamatch
isfoundintheDictionary,theRownumbercanbeusedtoextractthe
datafortheoutputdirectlyfromthemasterSheet.

56 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

'Take Home' Ideas from Lesson 5


Wscript.ShellhasaCollectioncalledSpecialFolders.

TheSpecialFolderCollectionisveryusefulindeedforfindingeasy
touseplacesonthecomputer'sharddriveliketheDesktop.

DictionaryObjectsletusstorevaluesandthenlookthesevalues
bykeys.

Mergingdatafrommultiplespreadsheetsisaverycommonand
importantScriptingMacrotask.

Mergingcanbedonequickandeasilywiththehelpof
Dictionaries.

DrAlexanderJTurner2007 57
BabySteps

58 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 6: Reading & Writing Files


What Is A File?
Thismightseemanoddquestion. Weallusecomputerfilesallthe
time.Weopenthem,savetothem,uploadthemanddownloadthem.
However,dowereallyknowwhattheyare? Likemanyeveryday
items,weoftenlearntousethemwithouttrulyknowingthem.
Thankfullyfilesaresimple.Theyaresimplerthanmostpeoplewould
imagine.Afileisjustalonglistofnumbers.Eachnumbercantakea
valuebetween0and255.Thatisit!
We may have extra stuff associated with the file; for example, we
mightgiveitaname.Butthenameisnotpartofthefile;thefileis
just a list of numbers. We might make a place where people or
programs can find our file. We often call these places folders or
directories.However,afolderisnotthefile.Neitheristhenamewe
usetohelplocatethefileinsidethedirectory;thatnameispartofthe
directorynotpartofthefile.Afileisjustalistofnumbers.
AllthisbegsaquestionIffilesaresoverysimple,howcomewecan
dosomanyamazingthingswiththem?
Theanswertothisliesinasimplechild'sgame.Oftenchildrenseek
tomakeaeasytousecypherbyreplacingletterswithnumbers:
a=1,b=2,c=3,d=4etc.
Towritedownabcwecouldput123.Nowthenumbershave
takenonameaning. Theyarestilljust numbers,butwehaveput
specialmeaningsontothem.Usingasimpleschemejustlikethiswe
canstorewhatwethinkofastextasalistofnumbers. Yes,that
meanswecanstoretextinacomputerfile!Thefiledoesnot'know'
thatitcontainstext;itisjustalistofnumbers. However,wecan
interpretthosenumbersasrepresentingcharactersandso,tous,the
filecontainstext.
WecouldconsiderthefilewhichcontainsthedigitalversionofBaby
Steps. This has to hold much more than just text; it as images,
tables and complex structure information. How, how can such
complexitybestoredinasimplelistofnumbersbetween0and256?
This is where format comes into play. Format takes sequences of
numbersandgivethemmeaning.ThisisjustlikeinEnglishwriting
writinghasmoremeaningthanthesumofitindividualletters.

DrAlexanderJTurner2007 59
BabySteps

Fileformatscanbecomeverycomplexindeed. InBabyStepswe
arenotinterestedincomplexsowewillkeepthingssimple. Itis
amazingwhatcanbedonesimplywithfilesandExcel.
Formostoftherestifthisbookwewillonlydealwithwhatarecalled
textfiles.Thesehavedirecttranslationsofthenumbersinthefile
to characters,punctuationandafewlayoutrules. Textfilesareso
simplethattheycanbereadandconvertedtohumanreadablefrom
using Notepad. Notepad (or Notepad++) reads in each number
fromthetextfileandconvertsitintoahumanreadablecharacteretc.
When we write text in Notepad, every so often we will press the
'enterkey'todroptothenextline.Yearsagosomecomputerscalled
the enter key 'newline'. This is because in text file editors like
Notepad,pressingitproducesaspeciallayoutcharacterwhichmeans
start a newline. This is an example ofone of the hand full of
speciallayoutcharactersintextfiles.
Newline characters are stored in the text file as the number 13.
Spaceisanotherexamplewithitsnumberbeing32.Thenumeral1
isrepresentedbythenumber48andtheletterAby64.So123A
is4849503264.
Whenweworkwithtextfileswetendtoletthecomputerprograms
weworkwithdoallthetranslationbetweenthefiles'numbersand
thetextweareworkingwith.Inotherwords,wereadtextfilesinto
StringsandwewriteStringstotextfiles. Towardstheendofthe
book I discuss what are called binary files. These are where the
actualnumbersarereadandwrittendirectly.Wealmostneverneed
todirectlyhandlebinaryfilesinExcelMacroScripting.
Writing To A Text File
MacroScriptingusesaspecialObjecttoaccessfilesdirectly.Towrite
toafilewecreatea System.FileSystemObject. WegivethisObject
informationonwheretoputthefilethatwewillbewriting,itsname
andifitshouldreplaceanypreexistingfilewiththesamenamein
thesamefolder.FromthisinformationtheFileSystemObjectcreates
aTextStreamObject.ItisthisTextStreamObjectwhichactuallydoes
thewriting.
TheexamplebelowwillcreateatextfileontheDesktopadinside
thatfileitwillplacetwolinesoftext.
Option Explicit
Dim myFSO, myTSO,myShell,myName,forWriting
forWriting=2

60 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Set myFSO = CreateObject("Scripting.FileSystemObject")


Set myShell=CreateObject("WScript.Shell")
' The file location (folder) and name are sent to the
' FSO as a single String: Folder Name \ File Name
myName=myShell.SpecialFolders("Desktop") &
\example.txt
' The arguments to the OpenTextFile method here
' give the location\name, that we want to write
' and that it is OK to create the file if it does
' not already exist
Set myTSO = myFSO.OpenTextFile(myName,forWriting,true)
myTSO.WriteLine("Hello this is a text file")
myTSO.WriteLine("It was created by a script")
' It is good practice to always close a TextStream
myTSO.Close

Figure17:ThisiswhatNotepadshowsifweuseittoopenthefile
example.txtcreatedbyourfilefilewritingscript.
Thepreviousscriptwillalwaysreplaceanexistingfilewithanew
one.Thismeansthatit'secretly'performsthefollowingsteps:
1) CheckifafileofthatFolder\Nameexists.
2) Ifitdoes,deleteitpermanently.
3) CreateanewfilewiththesameFolder\Name.
4) Writetothenewfile.
Whathappensifwejustwanttoaddtothefileratherthanreplaceit?
Thisisnotsoodd;wemightwanttowritealineatheendofasfile
everytimeascriptisruntoactasanaudittrailforexample.Todo

DrAlexanderJTurner2007 61
BabySteps

thiswetelltheFileSystemObjectto'Append'ratherthan'Write'when
weopenthefileandcreatetheTextStreamObject.
Thisscriptaddsanewlinegivingthedateandtimethescriptwas
runtoafilescript.log.ThefilewillbecreatedontheDesktopthe
first time the script runs. After that, a line will be added to the
existingfileeachtimeitisrunagain.
Option Explicit
Dim myFSO, myTSO, myShell, myName, forWriting,
forAppending
forWriting = 2
forAppending = 8
Set myFSO = CreateObject("Scripting.FileSystemObject")
Set myShell=CreateObject("WScript.Shell")
' The file location (folder) and name are sent to the
' FSO as a single String: Folder Name \ File Name
myName=myShell.SpecialFolders("Desktop") &
"\script.log"
' The arguments to the OpenTextFile method here
' give the location\name, that we want to write
' and that it is OK to create the file if it does
' not already exist
Set myTSO =
myFSO.OpenTextFile(myName,forAppending,true)
myTSO.WriteLine("Script Run: " & now)
myTSO.Close

Iranthisscriptafewtimeandhereisthecontentsoftheresulting
file:
Script Run: 18/10/2007 13:03:31
Script Run: 18/10/2007 13:04:30
Script Run: 18/10/2007 13:04:31
Script Run: 18/10/2007 13:04:42
Script Run: 18/10/2007 13:04:44
Script Run: 18/10/2007 13:04:45
Script Run: 18/10/2007 13:04:46

Reading From A Text File


Nowthatwecanwritefiles,howabout reading them? Firstofall,
whywouldwewanttoreadone?ExcelcanreadExcelfilessowhy
doweneedadifferentwayofreadingfiles?
Sometimesweneedtouseascripttoreadafile,workwithwhatit
hasreadandthenputtheresultinExcel. Forexample,wemight
haveafilethathasaformatelikethis:
Begin
User = AJT

62 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Date = 01/07/2007
Action = logon
End
Begin
User = FF
Date = 01/08/2007
Action = logoff
End

InthisfileweknowthatalinewhichsaysBeginstartsablockof
lines and a line which says End ends that block. This extra
informationaboutthemeaningofthecontentsofthefileiswhatwe
callformat.ThisformatisnotonethatExcelunderstandssowehave
toloadthedataintoaspreadsheetusingascript:
Option Explicit
Dim
myFSO,myExcel,myWorkbook,mySheet,myTS,row,line,keyWord,d
atum

' Another way of defining Variables which we will not


' change is to use the Const keyword
Const forReading = 1

Set myExcel=CreateObject("Excel.Application")
Set myWorkbook=myExcel.Workbooks.Add()
Set mySheet=myWorkbook.Sheets(1)
myExcel.Visible=TRUE
With mySheet
.Cells(1,1).Value="User"
.Cells(1,2).Value="Date"
.Cells(1,3).Value="Action"
End With

' Set row to the first Row we


' want to write to in Excel
row=2

' Open our file in a TextStream Object


Set myFSO=CreateObject("Scripting.FileSystemObject")

' This is how we open a file reading using the


' FileSystemObject
Set myTS=myFSO.OpenTextFile _
( _
"myFile.txt", _
forReading, _
FALSE _
)

DrAlexanderJTurner2007 63
BabySteps

' This means keep looping until the end of the file
While NOT myTS.AtEndOfStream
' Read a line of text and put it in
' the Variable line
line=myTS.ReadLine()
' Split the line in two iff it has a = in it
line=Split(line,"=")
'See if there are two parts or one
if UBound(line)=1 Then
datum=Trim(line(1))
end if
' It will always have at least one part once split
' Strip spaces off the beginning and end
' at the same time
keyWord=Trim(line(0))
'Make sure the key word is all lower case
keyWord=LCase(keyWord)
' Choose what to do depending on the line
if keyWord="end" Then
' At the end of a block, move down
' one row in Excel
row=row+1
elseif keyWord="user" Then
mySheet.Cells(row,1).Value=datum
elseif keyWord="date" Then
mySheet.Cells(row,2).Value=datum
elseif keyWord="action" Then
mySheet.Cells(row,3).Value=datum
end if
Wend
' For neatness - close the TextStream
myTS.Close
' Tidy up our spreadsheet
mySheet.Columns(1).Autofit
mySheet.Columns(2).Autofit
mySheet.Columns(2).Autofit

Reading And Writing In Chunks


Mostofthetimereadingandwritinglinesisjustfine.Whenweput
myTextStream.Writeline(Fred) the actual file gets two extra
numberswrittentoitinadditiontothoserepresentingFred.These
arecalledCarriageReturnandLineFeed. Theygettheirnames
fromtypewriters.Theyrepresenttheactionofreturningthecarriage
(holdingthepaper)totheleftandfeedingthroughthepaperbyone
lineheight.Nowadaysthesenumbersjustrepresenttheendofaline
andthebeginningofthenext.

64 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

WhenweusemyTextStream.ReadLine()wegetbackthenextlineof
text from a file. Just like a human reading a page of text, the
TextStreamObjectremembersits'place'inthetextandsocangiveus
thenextlinefromthat.
Thereareafewotherthingswhichwemightwanttodowithatext
file.Thesearenotusefulquiteasoftenasworkingwithonelineata
time,buttheycomeinhandyeverysooften:
1) ReadanentirefileatoncetoaString.
2) WriteanentirefileatoncefromString.
3) Readanexactnumberofcharactersfromafile.
4) WriteaStringtoafilewithoutaddingonthecarriagereturn
linefeed.
Whilstthesearefourdifferentthingsweneedonlylearntwonew
techniquestobeabletodothem! WhenweopenaTextStreamfor
readingwecancallcallmyTextStream.Read(count)wherecountisa
number. This is just like Readline in that the TextStream Object
remembers its 'place' in the file and reads on from that place.
However, rather then reading a whole line, it reads exactly count
charactersandreturnstheseasaString.Anotherslightdifferenceis
thatwhenitencounters carriagereturn or linefeed,itwillactually
put these characters in the returned String. Also note that if it
reachestheendofthefilebeforeithasread countcharactersitjust
givesusthecharactersithasreadsofar.
InExcelMacroScriptingIhaveyettocomeacrossaneedtoread
count characters from a file except in one common special case.
SometimewewanttoreadanentirefileintoaStringallinonego.
Again,tomakethissupereasy,wecanjustmissoutcountaltogether.
InthebelowscriptweopenaTextStreamreadingfromafileandcall
ReadAll()whichislikeusingRead(count)wherecountisthenumber
of characters left which can be read. This slurps the entire file's
contentsintoaStringforus(thisisnotanentirescript,justapieceof
one):
Set myFSO=CreateObject("Scripting.FileSystemObject")
Set myTS=myFSO.OpenTextFile _
( _
"myFile.txt", _
forReading, _
FALSE _
)
' Read the entire contents at once

DrAlexanderJTurner2007 65
BabySteps

fileContents=myTS.ReadAll()
myTS.Close

Theexactsamethingcanbedonewithwriting.ByusingtheMethod
Write(myString)onaTextStreamObject(whichwasopenedtowrite
orappend)wesimplywriteoutthenumbersforthecharactersinthe
Stringtothefile. Write(myString)doesnotadd carriagereturn or
newline.Ifwecallitmanytimeswecanaddtothefilesonechunk
atatime.IfweopenaTextStreamforoverwriting(notappending)
and we call Write(myString) just the once before closing the
TextStream,wehavewrittentheentirecontentsofthefilefromour
String.
Hereisascriptwhichreadsanentiretextfileinonego. Itthen
replaceseveryinstanceof/with//.Finally,itwritesanewfile
withtheupdatedcontents.Wewillseeinlesson7(thenext)whywe
mightwanttodothis(again,thisisjustasubsectionofascript):
Set myFSO=CreateObject("Scripting.FileSystemObject")
Set myTS=myFSO.OpenTextFile _
( _
"myFile.txt", _
forReading, _
FALSE _
)
' Read the entire contents at once
fileContents=myTS.ReadAll()
myTS.Close

' Do the replace of / with //


fileContents=Replace(fileContents,"/","//")

' Now write out our new file contents


Set myTS=myFSO.OpenTextFile _
( _
"myFile.txt", _
forWriting, _
TRUE _
)
' Write the entire contents at once
myTS.Write(fileContents)
myTS.Close

Listing Files
I was considering not including this section. Then I suddenly
rememberedaveryimportantsortofapplicationforlistingfiles.Let
us imagine that wehave written a script which takes a 'dragand

66 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

drop'WorkbookandmergesthedatawithasecondWorkbook.This
scriptthencreatesanoutputWorkbookcontainingthemergeddata
(see lesson 5). Whilst this is fine for one, two or even ten input
Workbooks, how about if there were 100 or even 1000. The
alternativetospendingthebalanceofournaturallifedraggingand
droppingistogetourscripttofindtheinputWorkbookfilesitsself.
Thenextscriptdoesexactlythat.Itisabit'dense'inthatitdoesalot
withonlyafewlinesofcode.Ratherthanstuffitfullofcomments,I
havediscussedhowitworksafterthescript.
Option Explicit
Dim fso,myFolder,myFile,myShell,myList

Set myShell=CreateObject("WScript.Shell")
Set fso=CreateObject("Scripting.FileSystemObject")
Set myFolder =
fso.GetFolder(myShell.SpecialFolders.Item("Desktop"))
myList=""
For Each myFile In myFolder.Files
With myFile
If _
LCase(Right(.name,4))=".xls" OR _
LCase(Right(.name,5))=".xlsx" _
Then _
myList=myList & .name & vbcrlf
End IF
End With
Next
WScript.Echo "Excel Files On The Desktop:" & vbcrlf &
myList

ThefirstthingthattheabovescriptdoesistouseSpecialFoldersto
findthepathtotheDesktop.NextitcallstheGetFolder(path)
methodofaFileSystemObjectObject.ThismethodreturnsaFolder
Object.BecausethepathwepasstotheGetFoldermethodisthepath
totheGetFoldermethod,wegetaFolderObejctrepresentingthe
Desktop.
FolderObjectsareusedtoallowustodothingswithFolders.Inthis
case,wewanttofindallthefilesintheFolder.TheFolderObjecthas
aCollectioninitcalled'Files'whichcontainsaFileObject
representingeachoftheFilesintheFolder.ThisbeingaCollectionis
veryusefulbecausewecanuseaForEachlooptoworkthrougheach
ItemintheCollection.
InsidetheForEachloopIhaveplacedanIfstatement.Thisiswhatis
calleda'conditional'.WhatthismeansisthatIfaconditionismet

DrAlexanderJTurner2007 67
BabySteps

Thenapieceofcodeisexecuted.TotryandexplainthisfurtherIcan
takethepieceofscript...
With myFile
If _
LCase(Right(.name,4))=".xls" OR _
LCase(Right(.name,5))=".xlsx" _
Then _
myList=myList & .name & vbcrlf
End If
End With

..andtryanddescribeitasinplainEnglish:
If the name oftheVariable myFileendswith.xlsor
with .xlsx then add that name to the end of the
VariablemyList.Otherwise,donotdoanything.
WehavealreadyseetheVBScriptbuiltinfunction LCase. Another
handybuiltinfunctionisRight.ThisfunctionreturnsjusttheRight
handcharactersfromaString. AppendixDhasadescriptionofall
thesebuiltinfunctions.VBCRLFisabuiltin'Constant'.Itcontainsa
Stringconsistingofcarriagereturn, linefeed. Byaddingthistothe
endofeachFilenameasitisaddedtomyList,itmakesthenames
appearonnewlinesinthepopupboxcreatedattheendofthescript.
Toprocessallthefilesofaparticulartypeinafolderallweneedto
doisreplacethecode...
If _
LCase(Right(.name,4))=".xls" OR _
LCase(Right(.name,5))=".xlsx" _
Then _
myList=myList & .name & vbcrlf
End IF

...with what ever code we require. For example, our Workbook


mergingcode.

68 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

'Take Home' Ideas from Lesson 6


Filesarejustsimplelistsofnumbers.

Byassigningcharacterstothenumberswecanstoretextinfiles.
Wecallthesetextfiles.

TheTextStreamObjectdoestheconversionfromtexttonumbers
(andback)soitletsusreadanwritetextfilesusingStrings.

Byaddingmorerulesabouttheorderofdatainfiles,more
complexinformationcanbestoredinthem.Wecallthese
structurerulesformat.

Whenwritingfileswecanoverwriteolderversionsofthefileor
appendnewstufftothen.

Mostreadingandwritingisdoneonelineatatime.

Beingabletoreadandwritefilesallowsourscriptstoworkwith
fileformatswhichExceldoesnotunderstandbyitsself.

SometimesitishandytoreadawholefileintoaStringorwrite
awholefileoutfromaString.

Wecanlistallthefilesinafoldersothatwecanthenprocess
themall,orasubsetofthem,automatically.

DrAlexanderJTurner2007 69
BabySteps

70 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 7: Enhanced Data Processing


Subroutines And Functions
Beforegoingfurther,letusunderstandonething. Subroutinesand
Functions are here to make our life easier. They are not some
abstractconceptwhichcomputerscientiststhrustuponustoprovea
point;theyarehereonlyforourconvenience.
Thewholeconceptstartsoffromasimpleidea: Itisbesttodoone
thingonetime;itisawasteofefforttodoonethingmanytimes.
ThisappliesdoubleortripletowritingScriptingMacros.Ifwewrite
thesamepieceofcodetwicewehavedoubledtheinputeffort.Then,
ifweneedtochangethatcode,wehavetorememberalltheplaces
weputitandchangeeachandthenfixanytyposwehavemade!
So,writeonethingonetime;itismucheasier.
ASubroutineallowsustowriteapieceofscriptoncebutuseitmany
times.Forexample,wemightwanttomakeapieceofscriptwhich
turns the background of some Cells yellow. To do this as a
Subroutinewecanwrite:
Sub MakeYellow(myRange)
With myRange.Interior
.ColorIndex = 6
.Pattern = 1
.PatternColorIndex = -4105
End With
End Sub

Functionsarea lotlike Subroutinesexcept thatthey givea value.


HereisastupidlysimpleFunction:
Function AddTwoNumbers(a,b)
AddTwoNumbers=a+b
End Function

BymakingthenameoftheFunctionequaltothethingwewantgiven
back,wecontrolwhatitgivesback. TheaboveFunctioncouldbe
usedlikethis:
Option Explicit
WScript.Echo AddTwoNumbers(2,2)
WScript.Echo AddTwoNumbers(3,4)
Function AddTwoNumbers(a,b)
AddTwoNumbers=a+b
End Function

DrAlexanderJTurner2007 71
BabySteps

Thisscriptwillproducetwopopupboxes;thefirstwillsay4and
thesecond7.
Hereisamoreuseful Function. ItlooksdownaColumnandturns
everyCellValueintouppercase.Itwillstopwhenitfindsanentire
Rowwhichisempty,returningthenumberofalteredRows:
Option Explicit
Dim myExcel, myWorkbook,mySheet,col,row

Set myExcel=CreateObject("Excel.Application")
Set myWorkbook=myExcel.Workbooks.Add()
Set mySheet=myWorkbook.Sheets(1)
myExcel.Visible=true

' Create some data to demonstrate the Function


For row=1 to 10
mySheet.Cells(row,1)="Hello"
Next
mySheet.Cells(11,2)="This is not blank"
mySheet.Cells(12,1)="So this should be ucase"
mySheet.Columns(1).Autofit
mySheet.Columns(2).Autofit

' These three lines do all the work, they


' use pop-ups to tell us what is happening and
' call the Function
WScript.Echo "Click OK to make column 1 ucase"
row=UCaseCol(mySheet,1)
WScript.Echo row & " Rows were converted"

' This is the actual Function its self.


Function UCaseCol(theSheet,theCol)
Dim uRow,uCol
' The max number of rows could be bigger
' in Excel 2007 but in all previous versions
' it is 65536, so we will use that
For uRow=1 to 65536
' The max number of columns could bigger
' in Excel 2007 but in all previous versions
' it is 256, so we will use that
For uCol=1 to 256
If Not IsEmpty(theSheet.Cells(uRow,uCol).Value)
Then
' Exit For forces the loop to stop
' in this case, it will stop the
' "For uCol" loop
Exit For
End If
Next

72 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

' If uCol=257 here then all Cells were empty


If uCol=257 Then
' This Exit For will case the "For uRow"
' loop to stop
Exit For
End If
With theSheet.Cells(uRow,theCol)
.Value=UCase(.Value)
End With
Next

' At this point uRow is always the first blank row


' but we want to give back the number of
' changed rows
UCaseCol=uRow-1

End Function

FigureX:HereiswhattheuppercaseaColumnscriptproduces
atthepointwherethefirstpopupappears.
ItisimportanttorememberthatiswecreateaFunctionwhichgives
back(sometimescalled'returns')anObject,wemustuseSet:
' A Function to create a new Excel Object and
' return a new Workbook from it
Function MakeExcelWorkbook()
Dim myExcel
Set myExcel=CreateObject(Excel.Application)
Set MakeExcelWorkbook=myExcel.Workbooks.Add()
End Function

DrAlexanderJTurner2007 73
BabySteps

FigureX:HereiswhattheuppercaseaColumnscriptproduces
onceithasfinishedprocessingtheSheet.

Death By Dates
IhavebeenworkinginITforwhatfeelslikeaverylongtime(over
25 years sob). Over that time, certain patterns have started to
appeartome.Oneoftheseisthatwhenadatasetgoesallweird,it
isusuallybecauseofdates.
Thereasonissimple;dateshavenoconsistentlyappliedstandards.
Wecanillustratethisbycounterexample.Integernumbersdohavea
very consistent standard. Nearly all integer number in data are
representedusingArabicnumeralbasetennotation:
1
11
100
-20
Bywayofcontrast,herearejustafewofthewaysonemightseethe
firstofJulytwothousandandonewritten:
1/7/01
1/7/2001
7/1/01
1-7-01
7/1/2001
1-July-2001

74 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Hereisa good question: If 7/1/01 and 1/7/01 mean exactly the


samething,thenhowcanwetelltheyrepresentthefirstofJulyor
theseventhofJanuary?
TheproblemwithExcelanddatesusuallyturnsupwhenimporting
datawherethesourceofthedatesortheExcelSpreadsheetaresetto
be'outside'theUSA. Thesnagisthatevenifwesetthe Windows
localtobesomewherewheredatesaredd/mm/yyyy(dayday/month
month/yearyearyearyearasin31/01/2002)Exceldoesnotimport
suchdatescorrectly.IfyousetthevalueofaCellto31/01/2001it
maywellnotrecognisethisasadateatall.

Figure20:Hereisthelanguageandregionalconfigurationofmy
test(virtual)computerwhilstwriting'BabySteps'.
Toillustratethisissue,IhavecreatedascriptwhichloadsExcelwith
datesfromthe10thtothe20thofJanuary.Italsousesatricktoforce
ExcelnotitinterpretthevaluesIampassingintoit.ThiswayIcan
getExceltoshowwhatthe'raw'valueIputinitandthenalsowhatit
interpretsitas.Thistrickwillbeusedagainlater.

DrAlexanderJTurner2007 75
BabySteps

Option Explicit
Dim myExcel,myWorkbook,mySheet,row
Set myExcel = CreateObject("Excel.Application")
Set myWorkbook = myExcel.Workbooks.Add()
Set mySheet = myWorkbook.Sheets(1)

' This loop creates strings in dd/mm/yyyy format


' puts them into Cells. To force Excel into not
' interpreting the string in any way, I make it
' into a formula and use the Cell.Formula property
' rather than the Cell.Value property we normally
' use.
For row=1 To 10
' This sets a formula like ="11/01/2001"
mySheet.Cells(row+1,1).Formula = "=""" & (10+row) &
"/01/2001"""
' This will just put in the date string
' like 11/01/2001 and it also sets the Cell
' format to show dates in long format to help
' make it clear what Excel's interpretation is
With mySheet.Cells(row+1,2)
.Value = "" & (10+row) & "/01/2001"
.NumberFormat = "[$-F800]dddd, mmmm dd, yyyy"
End with
Next
' This code puts in the column titles and makes
' them bold
mySheet.Cells(1,1).Value="Input"
mySheet.Cells(1,2).Value="Excel Interpretation"
mySheet.Range("A1:B1").Font.Bold = True
' Now we can autofit the width of the columns
' and as a nice touch, zoom into the spreadsheet
mySheet.Columns(1).Autofit
mySheet.Columns(2).Autofit
myExcel.ActiveWindow.Zoom = 200
' Finally, we had better make Excel visible!
myExcel.Visible = TRUE

76 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure21:HerewecanseehowExcelhasmadeacompletemess
ofinterpretingthevalueswhichourscriptasplacedintoit.
DateAdd And DateSerial Fixing The Problem
FirstwecanlookataVBScriptbuiltinfunctioncalled'DateAdd'.We
canusethistobypassthefaultydateinterpretationinExcel.
DateAdd(Interval, Number, Date)

The DateAdd function adds atime interval to any date. Thereare


threearguments.TheIntervalargumentdefinesthethetypeoftime
intervalyouwishtoaddontothedate. Youmustplacethesetting
inside double quotes. The possible settings are shown in the table
below:
SETTING DESCRIPTION
YYYY Year
Q Quarter
M Month
Y Day Of Year
D Day
W WeekDay
WW Week Of Year
H Hour
N Minute
S Second

TheNumberargumentisamultiplierfortheIntervalargument(i.e.,

DrAlexanderJTurner2007 77
BabySteps

howmanydays,weeks,months,etc.).Ifthisisapositivenumber,you
willgoforwardintime.Anegativenumberwillgobackintime.

TheDateargumentisanactualDate.ThismeansitisnotaStringin
dateformatlike01/02/2001;itisavalueoftypeDate. Wecan
makeDatevaluesfromstringsusingthe VBScript builtinfunction
CDate.
Option Explicit
Dim
myExcel,myWorkbook,mySheet,year,month,day,myDate,start
Date,row
Set myExcel = CreateObject("Excel.Application")
Set myWorkbook = myExcel.Workbooks.Add()
Set mySheet = myWorkbook.Sheets(1)

' This date cannot be confused because the day


' and month are the same, and it is a nice
' simple date.
' We will use it as the starting date from which to
' make our calculations
startDate=CDate("01/01/2000")

For row=1 to 10
' Here we set up the day month and year
myMonth=1
myYear=2001
myDay=row+10

' Write the 'raw' date string into Excel


mySheet.Cells(row+1,1).Formula = "=""" & myDay &
"/01/2001"""

' Compute a true Date value for the date


' We start of with the startDate
myDate=startDate
' Then add in the appropreate number of years
' It does not matter if year < 2000, because this
' will still work OK
myDate=DateAdd("YYYY",myYear-2000,myDate)
' Now we add in the appropreate number of months
myDate=DateAdd("M",myMonth-1,myDate)
' And finally the appropreate number of days
myDate=DateAdd("D",myDay-1,myDate)

' At this point myDate holds a Date type value


' that represents the date we are interested in.
' Excel does not need to interpret this value,
' because it is already a date, so Excel cannot

78 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

' make a mistake.


With mySheet.Cells(row+1,2)
.Value = myDate
.NumberFormat = "[$-F800]dddd, mmmm dd, yyyy"
End With
Next

' This is just the same layout stuff as before


mySheet.Cells(1,1).Value="Input"
mySheet.Cells(1,2).Value="Excel Interpretation"
mySheet.Range("A1:B1").Font.Bold = True
mySheet.Columns(1).Autofit
mySheet.Columns(2).Autofit
myExcel.ActiveWindow.Zoom = 200
myExcel.Visible = TRUE

Figure22:Herewecanseethenewscriptcorrectlycreatesdate
valuesintheExcelCells.
Another(possiblysimpleryetlessinformative)wayofachievingthe
samethingistousethe DateSerial builtinfunction. Thistakes3
arguments,theyear,monthandday.Sothepreviousscriptpiece:
myDate=startDate
myDate=DateAdd("YYYY",myYear-2000,myDate)
myDate=DateAdd("M",myMonth-1,myDate)
myDate=DateAdd("D",myDay-1,myDate)

Becomes:
myDate=DateSerial(year,month,day)

DrAlexanderJTurner2007 79
BabySteps

Iconsideredonlyincludingthissimplerversion.However,themore
complex DateAdd version made such a nice example of date
arithmetic, I chose to include both approaches. Indeed, the the
DateAddmethodisillustrativeofthewayDateSerialactuallyworks.
Forexample,whatdoesthefollowingscriptproduce?
Option Explicit
Dim myDate
myDate=DateSerial(2007,2,32)
WScript.Echo myDate

WhatitcomesupwithisapopupboxgivingthefourthofMarchasa
date.

Figure23:ThisisthepopupshowingthatDateSerialactually
worksjustlikeDateAdd.Here,DateSerial(2007,2,32)yieldsthe
fourthofMarch,i.e.twomonthsand32daysaddedto2007.
ThefourthofMarchbeingtheDateyouwouldgetifyouweretodo
this:
myDate=1/1/2007
myDate=DateAdd("M",2-1,myDate)
myDate=DateAdd("D",32-1,myDate)
WScript.Echo myDate

Importing Data From CSV Files


Welookedatfileformatsinlesson6.Theideaofaformatbeingthat
theorderofnumbersinafileoffersinformationastothemeaningof
thosenumbers. Ifthefileisa textfile,thenwecanconsiderthe
orderofnumberstorepresentanorderofcharacters.Therearesome
textfileformatsthatareusedaverygreatdeal.Oneoftheoldestyet
stillmostcommonlyusedonesisCommaSeparatedValuesorCSV.
FileswhichcontaintextinCSVformatarecalledCSVfilesandthey
turnupeverywhere.
Wecomeacrossthisstandardformatmostwhenwearetransfering
data from one application to another. Forexample, if a customer

80 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

relationshipmanagementsystemmustcreateanoutputwhichwecan
readwithExcel,CVSmightbeanexcellentchoice:

Figure24:ThisshowshowadatabaseviewfromaCRM
(CustomerRelationshipManagement)systemcanbeconvertedto
aCSVfileformat.
IntheaboveexampleaviewinaCRMsystemhasbeenexportedtoa
CSVfile. Excelisabletoread CSV filesandconvertthecontents
directlyintoaspreadsheet.Thereareevensomecleaverstandardsto
avoidthingslikecommasinthedatacausingtrouble.Iftherewasa
comma in the data, the field holding thecomma is surrounded in
quotationmarks:

FigureX:Herewecanseehowwhenadatafieldhasacommain
it,theCSVformatplacesthatfieldinquotationmarkstomakeit
clearwhichcommasareseparatingfieldsandwhichare
containedinsidefields.
Unfortunately,CSVtellsusnothingaboutthenatureofthedata,it
justhascolumnsandrows.However,Exceltriestoguessthenature
ofdatafromitsformat.Aswehavealreadyseen,Exceloftentakes
somethinglikethis5/7/01andtreatsitasadate.Butitalsogets
allconfusedbetweenthefifthofJulyandtheseventhofMay.
Becauseoftheseissues,itissometimesnecessaryto'help'Excelalong
abitwhenreadingCSVfiles. Thiscanbedonewithathreestep
strategy:
1) Change the data in the CSV file so that Excel will treat
everythingassimpletext.
2) OpenExcelandtellittoloadthealteredCSVfile.
3) Change thedata in Excel to the format we wantor insert
formulaewhichoutputtheformatwewant(orboth).

DrAlexanderJTurner2007 81
BabySteps

Forstep1wecanusethefilehandlingtechniqueswelookedatthe
previous lesson. We open the original CSV file as a TextStream
Object andopenanemptyoutput CSV fileasanother TextStream.
Wecanthereadtheoriginalin,alterthecontentsandwritethenew
contentout.
ToillustratethissurvivaltrickIwillgothroughtwoexamples;oneis
forworkingwithdatesandtheforworkingwiththingsthatExcel
mightincorrectlythinkarenumbers.Forexample,ifwetype10e24
intoanExcelCell,Excelwillconvertthisto1.00E25;inotherwords,
Excelhasreadthetextandconsideredittorepresent1x1024.
' Create a CSV file with a load of dates in it.
' This script is here
' only to produce the input file for the next
' script it is not really part of the example
Option Explicit
Dim myFSO, myTS,row
Const forWriting = 2
Set myFSO=CreateObject("Scripting.FileSystemObject")
Set myTS=myFSO.OpenTextFile("Date-
data.csv",forWriting,TRUE)
myTS.WriteLine "SerialNumber,Date"
For row=0 to 99
' This is a numerical trick to produce realistic
' serial numbers from the row Variable and dates
' in US format which a UK Excel setting will get
' wrong.
myTS.WriteLine (NOT ((row + row * 65536) XOR
&H8888)) & ",8/" & (1+row-(31*Int(row/31))) & "/2006"
Next
myTS.Close

HereiswhatthecontentsofthecreatedCSVfilelooklike:
SerialNumber,Date
30583,8/1/2006
96118,8/2/2006
161653,8/3/2006
227188,8/4/2006
292723,8/5/2006
358258,8/6/2006

82 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure26:ThisishowExcelinterpretstheCSVfilewhichour
scriptcreates.Clearly,ithasreadthedatestotallyincorrectly.
' Change the CSV file innards to force Excel
' to treat them as plain text
Option Explicit
Dim
myExcel,myWorkbook,mySheet,row,myValue,myFSO,myTS,file
Contents,myShell,myDesktop,splitted
Const forReading=1
Const forWriting=2

Set myShell=CreateObject("WScript.Shell")
myDesktop=myShell.SpecialFolders("Desktop")

Set myFSO=CreateObject("Scripting.FileSystemObject")
Set myTS=myFSO.OpenTextFile(myDesktop & "/Date-
data.csv",forReading,FALSE)
fileContents=myTS.ReadAll()
myTS.Close
fileContents=Replace(fileContents,"/","//")
Set myTS=myFSO.OpenTextFile(myDesktop & "/Date-data-
fixed.csv",forWriting,TRUE)
myTS.Write(fileContents)
myTS.Close

Theabovescriptworkbyreplacingeveryoccurrenceof/with//.
This means that a date String 1/5/01 will become 1//5//05.
Hereisapieceoftheresultingfile:
SerialNumber,Date
30583,8//1//2006
96118,8//2//2006

DrAlexanderJTurner2007 83
BabySteps

161653,8//3//2006
227188,8//4//2006
292723,8//5//2006
358258,8//6//2006

WhilstthishasstoppedExcelincorrectlyinterpretingdates,ithasnot
performedstep3inourstrategy.Todothatweneedtogothrough
all the fields that should be dates in Excel and convert them into
Excelcorrectdates. Notonlythat,wealsoneedtocorrectalltext
fieldstoundoanychangesthepreviousstepcaused. Forexample,
thechoicewasgreen/bluewillhavebeenchangedtothechoice
wasgreen//blue. Thesefieldsneedchangingback. Thefollowing
script performs this action on our example file. It is actually a
continutationofthepreviousscript. Itmakessensetocombinethe
filecorrectionandloadingintooneScriptingMacro:
' Read the newly updated CSV file into Excel and
' then recreate the dates in a way Excel cannot
' get confused (see previous lesson)
Set myExcel=CreateObject("Excel.Application")
myExcel.Visible=TRUE
' Load the csv usign the Open Method of the
' Workbooks Collection
Set myWorkbook=myExcel.Workbooks.Open(myDesktop &
"/Date-data-fixed.csv")
Set mySheet=myWorkbook.Sheets(1)
' This loop goes down the Rows from the first data
' until the first Row in which the "serial number"
' is blank
For row=2 to 65536
If IsEmpty(mySheet.Cells(row,1).Value) Then Exit For
' Here we use the ever handy Split built in Function
' to split the date String in Excel into
' three bits (0, 1 and 2)
myValue=mySheet.Cells(row,2).Value
splitted=Split(myValue,"//")
' DateSerial can now be used to create a real Date
' value to put back into Excel
myValue=DateSerial _
( _
splitted(2), _
splitted(0), _
splitted(1) _
)
mySheet.Cells(row,2).Value=myValue
' Finally, we correct the other Cell values
myValue=mySheet.Cells(row,1).Value
myValue=Replace(myValue,"//","/")

84 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

mySheet.Cells(row,1).Value=myValue
Next

Hereisthesamesetofscriptsforcorrectingtheproblemscausedby
scientificnotationnumbers:
' The script creates a csv file where the serial
' numbers are interpreted by Excel as scientific
' numbers
Option Explicit
Dim myFSO, myTS,row
Const forWriting = 2
Set myFSO=CreateObject("Scripting.FileSystemObject")
Set myTS=myFSO.OpenTextFile("Serial-
data.csv",forWriting,TRUE)
myTS.WriteLine "SerialNumber,Action"
For row=1 to 100
' Here we use the same numerical trick to produce
' realistic looking serial numbers but with an 'e'
' in them so Excel misinterprets them as scientific
' notation
myTS.WriteLine(NOT ((row + row * 65536) XOR &H8888)) &
"e" & row & ",Incomming"
Next
myTS.Close

HereiswhatthecontentsofthecreatedCSVfilelooklike:
SerialNumber,Action
96118e1,Incomming
161653e2,Incomming
227188e3,Incomming
292723e4,Incomming
358258e5,Incomming
423793e6,Incomming
489328e7,Incomming

Hereisthescripttocorrectthisbehaviour:
' Change the CSV file innards to force Excel
' to treat them as plain text
Option Explicit
Dim
myExcel,myWorkbook,mySheet,row,myValue,myFSO,myTS,file
Contents,myShell,myDesktop,fixed
Const forReading=1
Const forWriting=2

Set myShell=CreateObject("WScript.Shell")
myDesktop=myShell.SpecialFolders("Desktop")

DrAlexanderJTurner2007 85
BabySteps

Set myFSO=CreateObject("Scripting.FileSystemObject")
Set myTS=myFSO.OpenTextFile(myDesktop & "/Date-
data.csv",forReading,FALSE)
fileContents=myTS.ReadAll()
myTS.Close
fileContents=Replace(fileContents,"e","ee")
Set myTS=myFSO.OpenTextFile(myDesktop & "/Date-data-
fixed.csv",forWriting,TRUE)
myTS.Write(fileContents)
myTS.Close

' Read the newly updated CSV file into Excel and
' then recreate the dates in a way Excel cannot
' get confused (see previous lesson)
Set myExcel=CreateObject("Excel.Application")
myExcel.Visible=TRUE
' Load the csv usign the Open Method of the
' Workbooks Collection
Set myWorkbook=myExcel.Workbooks.Open(myDesktop &
"/Date-data-fixed.csv")
Set mySheet=myWorkbook.Sheets(1)
' This loop goes down the Rows from the first data
' until the first Row in which the serial number
' is blank
For row=2 to 65536
If IsEmpty(mySheet.Cells(row,1).Value) Then Exit For
' This time we convert ee into e and the use the
' "Formula" techniques to force Excel not to
' interpret the serial number
myValue=mySheet.Cells(row,1).Value
fixed=Replace(myValue,"ee","e")
mySheet.Cells(row,1).Formula = "=""" & fixed & """"
' Finally, we correct the other Cell values
myValue=mySheet.Cells(row,2).Value
myValue=Replace(myValue,"ee","e")
mySheet.Cells(row,2).Value=myValue
Next

PleasenotethatinVBScript"""""actuallymeansaStringcontaining
justaquatationmark.So"""Hello"""isaString"Hello".Thisiswhat
the"="""&Fixed&""""isdoing;itisputtingtheString="nnnn"into
theCell'sformulawherennnnistheserialnumber.

86 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure27:Again,Excelhasincorrectlyinterpretedthecontentsof
ourCSVfile.Ithasreadtheserialnumbers,andbecausethey
haveeinthem,ithasconvertedthemintostandardnotation
scientificnumbers.

Creating Reports
QuiteoftenExcelspreadsheetsthemselvesmakeverygood reports.
However,sometimewewanttowriteoutreportsinMSWordinstead.
Thereareamyriadofdisturbinglycomplexwaysofdoingthis.I,for
one,liketoavoidcomplexwaysofdoinganythingsohereisanice
simple way of creating reports in MS Word from Excel Macro
Scripting.
Thekeytothismethodisusing HTML. HTML beingthewaythat
web pages arecreated. Using HTML we can lay out text without
usinganywizardry.Really,itisveryeasyindeedtomaketablesand
listsetc.Forexample:
<table border=1>
<tr>
<td>Hello</td><td>World</td>
</tr>
</table>
Makessomethinglikethis:

Hello World

Tomakealistwecanput:

DrAlexanderJTurner2007 87
BabySteps

<ul>
<li>This is the first list element.</li>
<li>This is the second list element.</li>
<li>This is the third list element.</li>
</ul>

This'unorderedlist'willcomeoutsomethinglikethis:
Thisisthefirstlistelement.
Thisisthesecondlistelement.
Thisisthethirdlistelement.
Textthisisjustnormalparagraphwritingcanbelaidoutlikethis:
<p>This is paragraph text. We do not want any special
layout for this.</p>

Wecanputallthistogethertomakesomethinglikethis:
<p>Below is a simple table which I have created using HTML</p>
<table border=1>
<tr>
<td>Hello</td><td>World</td>
</tr>
</table>
<p>Things to remember about HTML are:</p>
<ol>
<li>Text is laid out using 'tags'.</li>
<li>A tag is text between &lt; and &gt;.</li>
<li>To avoid confusion, less than and greater than symbols are
replaced with special sequences of characters as seen in the
previous line.</li>
<li>Tags always come in pairs called 'open' and 'close'. Just
like the &lt;li&gt; and &lt;/li&gt; pairs used to make this
list.</li>
</ol>

InthiscaseIhavecreatedanorderedlistbyusingolrathertan
theunorderedlistul.Ifwesavetheabovetextinafilewithcalled
text.htmlwecanreaditwithawebbrowser.

88 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure28:Hereiswhatawebbrowserdisplayswhenaskedto
openoursimpletest.htmlfile.Wecanseethatthespecial
charactersequence&lt;hasbeenconvertedto<and&gt;has
beenconvertedto>.Thetagsinsidethetextlike<li></li>etc.
havecausedthetexttobelaidoutinthewaywewant.
Thisisallfineandwonderful,butwearesupposedtobecreatinga
MSWordreport,notanHTMLpage.Wellthisiswherealittleknown
featureofMSWord comesinto play. Bysimply savingthe fileas
test.docinsteadoftest.htmlMSWordwillmagicallyreadsitasa
normaldocument.However,MSWordwillstillapplytheHTMLstyle
layoutrules.

Figure29:Herewecanseetheresultsofopeningoursimple
HTMLtextasaMSWorddocument.IsavedtheHTMLinafile
calledtest.docandthenopenedthefileinMSWord.

DrAlexanderJTurner2007 89
BabySteps

So far we have looked at what happens with very simple HTML


indeed. Nowadays HTML has grown to become a rich system for
layingouttextandimages.MSWorddoesnotreallysupportallthis
complexity. However, we can enhance things a little. Also, it is
probablyabouttimewelookedatascriptcreatingthereport!
ThenextscriptwritesoutatableinHTMLintoa'.doc'file.Itusesa
slightlymoresophisticatedwayofdefiningthetableborder.
myReportFile.WriteLine("<TABLE STYLE='border: 0px;
border-top: 1px solid black; border-left: 1px solid
black;' CELLSPACING=0>")
myReportFile.WriteLine("<TBODY>")

for row = 1 to 10
myReportFile.WriteLine("<TR>")
for column = 1 to 2
myReportFile.WriteLine("<TD STYLE='border-bottom:
1px solid black; border-right: 1px solid black;'>" & row
& "," & column & "</TD>")
next
myReportFile.WriteLine("</TR>")
next
myReportFile.WriteLine("</TBODY></TABLE>")
myReportFile.Close

Whilst this script creates the data which it puts in the MS Word
document,itcouldhaveequallywellretrievedthedatafromanExcel
Sheet.

Figure30:ThisscreenshotisofMSWord2007displayingour
testreport.Theslightlymoresophisticateddescriptionofthe
borderscausesthenicesingleborderratherthanthedefault
doubleborderwhichwehaveseenintheearlierexamples.

90 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure31:ThisscreenshotisofMSWord2003displayingour
testreport.ThisolderversionofMSWorddoesaslightlyless
accuratejobofinterpretingtheHTML;theborderontheleftand
topofthetableisthickerthanitshouldbe.Ihaveincludedthis
imagetoillustratethatthistechniqueisusefulandeasybutnot
100%consistentacrossdifferentversionsofMSOffice.

DrAlexanderJTurner2007 91
BabySteps

'Take Home' Ideas from Lesson 7


Rewritingthesamepieceofscriptoverandoverisabigwasteof
time.

SubroutinesandFunctionsletuswriteapieceofscriptoncebut
useitmanytimes.

FunctionsarejustlikeSubroutinesexcepttheygivesomething
back(theyhaveareturnvalue).

Datacontainingdatesisoftenacauseoferrors.

Theseerrorsarebecausedatestandardsareapplied
inconsistently.

Readingafile,changingittostopExcelmakingerrorsand
writingitbackoutagaincanpreventExcelmisinterpretingdata
likedatesorserialnumbers.

ReplaceisaVBScriptbuiltinfunctionwhichreplacesallthe
instancesofonesubstringwithanother.

92 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 8: Working With Pivot Tables


Why Pivot Tables Are So Very Important
Puttingasidepeopleskills,PivotTablesaremanagementembodiedin
apieceofsoftware.Tomanagethesupplyofpumpkinsoneneedsto
knowthetrendsandpatternsin pumpkin deliveries; onedoesnot
need to know above every single pumpkin. Similarly, to manage
hardwarerepaircentresoneneedstoseewhatarethemostcommon
failuresandhowfasttheytendtobefixed. KnowingthatJoBlogs
hasamodemthattook10hourstofixmightwellbetoomuchdetail;
knowing that, on average, 100 modems need fixing each day is
criticalmanagementdata.
APivotTabletakesthe'toomuchdetail'informationandsummarises
it into something intelligible. For pumpkins, it could show the
numberofpumpkinsarrivingeachdayoftheweek.Ifitdidthis,it
wouldbesummarising'countofpumpkins'by'dayofweek'.Herewe
can start to see the core concept behind Pivot Tables. They
summarise one or more data fields by some grouping field. This
summaryisperformedusingoneofanumberofavailable summary
functions.Anotherexamplemightbe'average%ofpumpkinsrotten
on arrival' summarised by 'month of year'. There the data being
summarisedis'rottenpumpkinsonarrival'.Thesummaryfunctionis
'average'andthegroupingfieldis'monthoftheyear'.
Inshort,PivotTablesletone'see'intoamassofdetailandpickout
criticalmanagementinformation.Whatismore,theythenletus'drill
down' to see the underlying detailwhen we need it. Wewill see
moreofthissuperpowerfuldrilldownabilitylater.
Understanding Pivot Tables
TohelpexplainalltheconceptsbehindPivotTableswearegoingto
lookatafictionalexampleofcomputerhardwarerepairtimes. In
thisexample,thereisamultinationalhardwarecompany.Thetime
takentorepairvariousbrokencomponentsismeasuredinhoursfor
theUK,USandChina(Ch)offices.Themanagementchallengehere
isthatonlyrawdataisavailable. Whatwestartoutwithisjusta
Rowinaspreadsheetforeachrepair. Ifweintend,forexample,to
improvetheturnaroundfortheslowestoffice,wewillneedtoknow
whichistheslowestoffice.
Tothrowextrafuelonthisfire,wecanpretendthatthereisanew
companywidedirectivethatrepairsshouldbedoneinfourteenhours
orless.Howdowetrackthedifferentoffices'levelofcomplianceand

DrAlexanderJTurner2007 93
BabySteps

workoutwhatisgoingwrongwherecomplianceisnotmet? Well,
compliance levels can be worked out directly using a Pivot Table.
Then we can use that table to drilldown to the exact failing jobs
numberstothenfollowthemupwitha'phonecalltoelucidatewhat
ishappening.
Inshort,wewilluseaPivotTableto'see'whatishappeninginthe
businessatbothanoverviewanddetailview.
Creating An Example Pivot Table
Belowisascriptwhich'manufactures'data.Ihavehavedonethisso
thatthereisnoneedtohaveasetofdownloadableWorkbookstogo
with Baby Steps. Using a script like this is also a great way to
develop any Excel Scripting Macro project. We can manufacture
somenicecleandataandworkwiththattocreateourscript. Once
ourscriptworkswithcleandata,wecantryitwithrealworlddata.
Aswehaveseenearlier,realworlddatais'dirty';ithashumanerrors
init.Withthistechnique,wecanaddtheabilitytocopewithdirty
dataintoourExcelScriptingMacrosinthesureknowledgethatthey
workjustfinewithcleandata.
Option Explicit
' Script to make some data for Pivot Table work
Dim myExcel,myWorkbook,mySheet
Dim row,rTime,wOffice,wEquipment, office, equipment
Dim r1,r2

Set myExcel=CreateObject("Excel.Application")
Set myWorkbook=myExcel.WorkBooks.Add()
Set mySheet=myWorkbook.Sheets(1)
myExcel.Visible=TRUE

mySheet.Cells(1,1).Value="Office"
mySheet.Cells(1,2).Value="Equipment"
mySheet.Cells(1,3).Value="Repair Time"
mySheet.Cells(1,4).Value="Job Number"

For row=2 To 301


wOffice=Fix(rnd()*4+1)
if wOffice = 1 then
office="UK"
elseif wOffice < 4 then
office="US"
else
office="Ch"
end if
mySheet.Cells(row,1).Value=office

94 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

wEquipment=Fix(rnd()*6+1)
if wEquipment=1 then
equipment="Modem"
elseif wEquipment=2 then
equipment="Hard Drive"
elseif wEquipment=3 then
equipment="Monitor"
elseif wEquipment=4 then
equipment="Keyboard"
else
equipment="Power Supply"
end if
mySheet.Cells(row,2).Value=equipment

rTime=Fix(rnd()*10+1)+Fix(Rnd()*(10+wOffice)+1)
mySheet.Cells(row,3).Value=rTime
mySheet.Cells(row,4).Value=Fix(Rnd()*999+1000) & "-"
& Fix(Rnd()*999+1000)

Next

mySheet.Columns(1).Autofit
mySheet.Columns(2).Autofit
mySheet.Columns(3).Autofit
mySheet.Columns(4).Autofit

Howthisscriptworks:
Fix(Rnd()*n+1) creates an integer number between 1 and n
inclusive. Rnd()makesa random numberbetween0and1. Well,
actuallyitisnottrulyrandom,itfollowsamathematicalpatternthat
appearstoberandom;thisiscalledpseudorandom.Fix()takesany
decimalandreturnsonlytheintegerpart.Forexample,ifRnd()gave
0.52thenRnd()*10wouldbe5.1andFix(Rnd()*10+1)wouldbe6.
Wecanusethisformulatomakeamixofatwhichofficerepairsare
done, what is wrong and the job number. Also, if one takes two
random numbers and adds them together, just like adding the
numberfromthrowingapairofdice,theresultwillfollowtheclassic
Gaussiancurve.Thatmeansthedistributionofresultsisabellshape
withthebulkofresultsinthemiddle.Ihaveusedthistechniqueto
createarealisticdistributionofrepairtimesfromthescript.
Finally, to give us some variation between offices and between
componentswhichneedrepair,Ihavemixedinthenumberswhich
choose office and device into the calculation of repair time. This
meanswegetthetypeofvariationthatwouldbebeinglookedforin
arealsituation.

DrAlexanderJTurner2007 95
BabySteps

Creating A Pivot Table And Scripting Macro


Belowareasetofscreenshotswhichwalkusthroughtheprocessof
creatingaPivotTable.ThetrickistodothiswiththeMacroRecorder
running. Doing so will ensure Excel does all the hard work of
creatingascript forus;weneed only translate and generalise the
Macroitwritesforus.IalwaysstartanewPivotTablebasedproject
by Macro Recording myself creating the table using Excel's Pivot
Tablewizard;itisjustsoeasytouse.InAppendixA,Ihaveshown
thesameprocessbutusingExcel2007.Thereareafewdifferences
intheuserinterfacebutalltheconceptsarethesame.

Figure32:TokickofftheprocessofcreatingaPivotTable,we
mustensurethattheSheetwiththedatainwhichweare
interestedisshowing.Then,selectingDatathenPivotTable
andPivotChartReportwillstartthewizardweneedtocreate
outPivotTable.

96 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure33:NextwewillseethePivotTablewizardstartup.The
importantoptionsonthefirstpageofthewizardarewheretoget
thedatafromandifthewizardshouldcreateatableorachart.
ExcelcancreateaPivotTableoraPivotChartfromexternaldata.An
exampleofthiswouldbetocreateitfroman SQLdatabase.Whilst
thisisfabulouslypowerful,itisveryrarelyuseful. Fornowwewill
choosetotakethedatafromaSheet.Wecanalsoignoretheoption
ofusingmultipleconsolidationrangesbecause,tobehonest,itdoes
notworkverywell.
IhighlyrecommendalwayscreatingaPivotTablefirstbecausewe
canalwaysmakeachartfromitlater.Sothechoicesshouldbe:
1) MicrosoftOfficeExcellistordatabase.
2) PivotTable.

DrAlexanderJTurner2007 97
BabySteps

Figure34:Nowthatthewizard'knows'thatwewantaPivot
TablewehavetotellitfromwheretotaketheSheetdata.Thisis
doneusingastandardCellreferenceasshowabove.Excel
usuallymakesthecorrectguessastotheCellstouse.Ifitgetsit
wrong,wecancorrectitbyselectingtheCellswiththemouseor
typingtheCellreferenceintothewizarddirectly.

Figure35:Excelknowsthebasicsofwhatwewantatthisstage.
ItknowswewantaPivotTableandwhatdatawillbeusedto
createit.NextwemusttellExcelwheretoputthenewtable.By
farthetidiestsolutionistoalwaysputanewPivotTableina
newSheetusingtheNewWorksheetoption.

98 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure36:Thisscreenshotshowsthenewlycreatedbutstill
blankPivotTableandthePivotTableFieldList.
Now the fun starts! We can start laying out our Pivot Table. To
facilitatethis,ExcelhasdrawnforuseanemptyPivotTable. The
tablehas4areas. Thisareasare'droptargets';wecandragfield
namesfromthePivotTableFieldListboxintotheseareasofthePivot
Tabletocontrolthewaythetableworks.
Atthetopoftheblanktableisthe Pagearea;wewilllookatthis
later. Ofmoreimmediateinterestisthe Rowarea totheleftofthe
table.ThissaysDropRowFieldsHere.Thisareaisforcontaining
fieldsagainstwhichdatawillbesummarisedinRowsgoingacross
thetable.AboveandtotherightoftheRowareaistheColumnarea
saying Drop Column Fields Here. This area is for fields against
whichdatawillbesummarisedinColumnsgoingdownthepage.In
themiddleisthe Dataarea. Thisiswherethedatawhichistobe
summarisedisplaced.
Inourexamplewehaverepairtimesfordifferentcomponentfailures
atdifferentoffices. Whatwewanttoknowisinformationonthe
repairtimeforaparticularcomponentataparticularoffice.Wealso
wanttobeabletocomparetheoverallperformanceofofficesand
theoveralltimesfordifferentcomponents.
WecandoallthisbymakingthePivotTablesummarisebyofficein
RowsandcomponentsinColumns. Thisway,tofindthedatafor
modemsintheUSoffice,wecansimplylookdowntheRowsuntilwe
find the US Row and then across the Columns until we find the
modem Column. This will find us the Cell which will hold the
number we are interested in. The Pivot Table will also give us a

DrAlexanderJTurner2007 99
BabySteps

summaryforeachRowoverall(foroffices)andColumnoverall(for
components).Thenextfewscreenshotsshowhowwe'tell'thePivot
Tabletodoallthesethings.

Figure37:Alltheinitiallayoutisdonewithdraganddrop.The
availablefieldsareshowninthePivotTableFieldListdialogue
box.TomakeOfficeaRowfieldweclickonisnameinthe
dialogueboxanddragitovertotheRowareawherewedropit
(asshowninthepicture).
Dropping the Office field name onto the Row area immediately
causes Excel to enumerate the unique values of this field as Row
headers.Itisalsoworthnotingthatshouldwechangeourminds,we
candragthegreyOfficebuttonExceladdsatthetopofthe Row
area.Ifwedragitbacktothedialogueboxfromwhichitcame,itis
theOfficefieldisremovedfromthePivotTable.Ifwedragittoa
differentarea(e.g.theColumnarea)Excelplacesitthereinstead.
Just like with the office field we can now draganddrop the
Equipmentfield.Thisfieldrepresentsthecomponentthatisbeing
repaired.WedragittotheColumnareaanddropitthere.

100 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure38:ThisscreenshotshowsthePivotTablesetupto
summarisebyofficeinRowsandequipmentinColumns.The
nextstepwillbetotellExcelwhatdatatoactuallysummarise.

Figure39:DraggingtheRepairTimefieldfromthePivotTable
FieldListdialoguetotheDataareacausesthetableto
automaticallysummarisethesumofrepairtimesforalloffices
andequipment.
DraggingafieldintotheDataareatellsExcelthatitisthefieldwith
thedatatobesummarised. Excelguessesthemethodofsummary.
Inthiscase,Excelguessesthatitshouldsumthevaluesoftherepair
timefield.Forexample,ittakesalltherepairtimesforharddrivesin
Chinaandaddsthemtogether.Inourscreenshotabove(figure39)
thisgives80hours. Thisisnotactuallymuchusetous. Wecan

DrAlexanderJTurner2007 101
BabySteps

changethemethodofsummaryasisshowninthenextscreenshot.
Forthisexample,Ihavechosentosummarisebyshowingtheaverage
(numericmean)oftherepairtime.

Figure40:ByrightclickingoneoftheCellsintheDataareawe
getthecontextmenushowabove.ByclickingtheFieldSettings
optionwegetthePivotTableFielddialogueasshowninthe
nextscreenshot.

Figure41:ThePivotTableFielddialogueletsuschangetheway
thedataissummarised.

102 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure42:Inthisexample,whenIhadchangedthesummary
methodtoaverageIgottheseverylongdecimalnumbers.To
makethislessugly,IusedthenormalrightclicktheFormat
Cellsmethod.

Figure43:Hereitis,ourPivotTableinitsdefaultlayout.Fora
lotofapplications,thismaywellbesufficient.Shoulditbe
necessarytobeautifythingsfurther,thenCellbackgrounds,
numberformatsandalltheseotherthingscanbesetbyhand.
However,doingsocanmakescriptingabittricky;itmightbe
bettertoinitiallyseeifoneofthebuiltinformatsmightdowhat
wewant.

DrAlexanderJTurner2007 103
BabySteps

Figure44:ClickingtheFormatReportbuttononthePivotTable
toolbarrevealstheAutoFormatdialogue.

Figure45:Therearequiteafewbuiltinformatstochoosefrom.
Itisworthbeingabitcarefulhowever,severalrelayoutthePivot
Tablefieldpositions,whichcanbeannoying.AclickoftheOK
buttonappliesaformattotheactualtable.

104 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure46:OneofthethingsIlikeverymuchaboutPivotTables
isthenumberofbuiltinfeatures.InthisscreenshotIhave
clickedtheEquipmentfieldtab.Thisthenhasletmechoose
whichofthevariousvaluesoftheEquipmentfieldIactuallywant
displayedinthetable.Notonlyisthisacoolfeatureforme,itis
alsoavailabletowhomeverIgivemyfinishedtable.

Figure47:AnothermindblowinglyusefulfeatureofaPivotTable
isdrilldown.TogetthenewlycreatedSheetshownabove,I
doubleclickedontheCh/PowerSupplyDataareaCell.This
causedExceltopopulateanewSheetwithjustthatdatawhich
assummarisedtocreatethatCell.
With a Pivot Table we can use the summarised data to find the
informationweareinterestedinanddrilldowntofindtherawdata

DrAlexanderJTurner2007 105
BabySteps

thatwassummarisedtocreateit.Weshouldnotethateventhough
JobNumberisnotdisplayedinthe PivotTable,itisshowninthe
drilldowndata.
If,forexample,IfeltthattheCh/PowerSupplyaveragewastoo
high,Icould:
1) Drilldowntotherawdata.
2) Sortbyrepairtime.
3) MakeanoteofthetoptenJobNumbers.
4) Call the appropriate manager and discuss what might be
donetofixwhatevermadethesejobstakesolong.
Creating Pivot Tables Using Scripts
Looking At The Recorded Macro
The next block of code is the raw Recorded Macro as Excel 2003
created it from same session from which I took the above screen
shots.Atfirstblushitlooksabitscary(oratleastitdoesnotme).
However, taken step by step, the beast can be tamed. So, my
approachherewillbetodojustthat,lookatthescriptinlittlesteps
figuringoutwhatishappeningaswegoalong.
' Raw Recorded Macro

ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase,
SourceData:= _
"Sheet1!R1C1:R301C4").CreatePivotTable
TableDestination:="", TableName:= _
"PivotTable1", DefaultVersion:=xlPivotTableVersion10

ActiveSheet.PivotTableWizard
TableDestination:=ActiveSheet.Cells(3, 1)

ActiveSheet.Cells(3, 1).Select

ActiveWorkbook.ShowPivotTableFieldList = True
With
ActiveSheet.PivotTables("PivotTable1").PivotFields("Offi
ce")
.Orientation = xlRowField
.Position = 1
End With
With
ActiveSheet.PivotTables("PivotTable1").PivotFields("Equi
pment")
.Orientation = xlColumnField

106 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

.Position = 1
End With

ActiveSheet.PivotTables("PivotTable1").AddDataField
ActiveSheet.PivotTables( _
"PivotTable1").PivotFields("Repair Time"), "Sum of
Repair Time", xlSum

Range("B5").Select

ActiveSheet.PivotTables("PivotTable1").PivotFields("Su
m of Repair Time"). _
Function = xlAverage

Range("B5:G8").Select
Selection.NumberFormat = "0.00"

ActiveSheet.PivotTables("PivotTable1").PivotSelect "",
xlDataAndLabel, True

ActiveSheet.PivotTables("PivotTable1").Format xlTable2

OK brace ourselves we're going in:


ThewholeprocessstartsbysettingupaPivotCache.PivotTablesare
aviewofData,theactualcalculationsthatcreatethatData(i.e.all
thesummarycalculations)aredoneinaspecialObjectfromtheClass
PivotCache. Each Excel Workbook has a Collection of PivtoCache
ObjectsjustlikeithasaCollectionofSheetObjects.Tocreateanew
PivotCache,wecalltheAddMethodofthePivotCachesCollectionof
aWorkbookObject.
ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase,
SourceData:= _
"Sheet1!R1C1:R301C4").CreatePivotTable
TableDestination:="", TableName:= _
"PivotTable1", DefaultVersion:=xlPivotTableVersion10

Whatisthisallabout?HereisastepbystepguidetowhatExcelis
doinghere:
1) TakethePivotCachesCollectionoftheActiveWorkbook(that
whichwearelookingat)andAddanewPivotCache.
2) SetthedatasourcetypeforthisPivotCachetoxlDatabase.
3) Set the Range of Cells for this PivotCache to Sheet1!
R1C1:R301:C4.

DrAlexanderJTurner2007 107
BabySteps

4) NowthatwehavesetupthePivotCache,createaPivotTable
fromit.
5) MakethenewPivotTable'sdestinationbe.Thismakesit
appearinanewSheet.
6) GivethenewPivotTablethenamePivotTable1.
7) Finally, give the new Pivot Table a default layout of
xlPivotTableVersion10.
Soineffect,theselinescreateaPivotCacheObjectwhichworkswith
theRangeofCellswhichcontainstherawdata. Itthencreatesa
PivotTableObjectwhichworkswiththethePivotCachetocreatethe
datasummarywewant.
ActiveSheet.PivotTableWizard
TableDestination:=ActiveSheet.Cells(3, 1)

ActiveSheet.Cells(3, 1).Select
ActiveWorkbook.ShowPivotTableFieldList = True

Thisactuallydoesnothingofuse,itcanbeignored!
With
ActiveSheet.PivotTables("PivotTable1").PivotFields("Offi
ce")
.Orientation = xlRowField
.Position = 1
End With
With

This code uses the PivotTables Collection of the ActiveSheet (that


Sheet which wearecurrentlylooking at) tolocate ourPivotTable.
ThefieldswhichgointocreatingaPivotTablearecalledPivotFields.
EachPivotFieldhasaspecialObjectrepresentingit.ThesePivotField
Objects can be found in the PivotFields Collection of a PivotTable
Object.ThisiswhatthecodedoestofindtheOfficefieldandmake
itaRowfield.
ActiveSheet.PivotTables("PivotTable1").PivotFields("Equipment")
.Orientation = xlColumnField
.Position = 1
End With

Thispieceofcodeisjustthesameasthepreviousone. Theonly
differenceisthatitmaketheEquipmentfieldintoaColumn.

108 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

ActiveSheet.PivotTables("PivotTable1").AddDataField
ActiveSheet.PivotTables( _
"PivotTable1").PivotFields("Repair Time"), "Sum of
Repair Time", xlSum

ThispieceofcodeusesthesamemethodagaintofindthePivotTable
Object.Onceithasdoneso,itcallstheAddDataFieldMethodtoadd
theRepairTimefieldasaDatafieldwithatitleofSumofRepair
TimeandasummaryfunctionofxlSum.
Range("B5").Select

Thisdoesnothingimportanthowever,thenextbitdoes:
ActiveSheet.PivotTables("PivotTable1").PivotFields("Su
m of Repair Time"). _
Function = xlAverage

Theabovecodeconvertsthesummarymethodfromsumtoaverage.
Again,mostoftheactualcodeismadeupoffindingthePivotTable
Object.WhenwetranslateovertoaScriptingMacro,wewillgetrid
ofallthismess.
Range("B5:G8").Select
Selection.NumberFormat = "0.00"

Theaboveisthebitthatsetsthenumberstojusthavetwodecimal
places.I'llshowaneasierwayofdoingthislater.Thesnagwiththis
approachisthatourscriptwillhavetoworkoutwhatRangetouse.
Itisbettertouseanapproachwhichavoidsthis.
ActiveSheet.PivotTables("PivotTable1").PivotSelect "",
xlDataAndLabel, True

Thisisnotdoinganythinguseful.
ActiveSheet.PivotTables("PivotTable1").Format xlTable2

ThisfinalpieceofcodesetstheformatofthePivotTabletothebuilt
informatwewanted.
I did mention that there is a better way of setting the Number
Format totwo decimal places. Thenexttwo screenshotsshould
how this is done from the graphic user interface. Whilst I was
creatingthesescreenshots,IhadtheMacroRecorderrunning,sowe
canseethecodethatcameoutaswell.

DrAlexanderJTurner2007 109
BabySteps

Figure48:WehavealreadyseenthatrightclickingintheData
areaandselectingFieldSettingscausesthePivotTableField
dialoguetobeshown.WecanclicktheNumberbuttononthis
dialoguetosetthenumberformatforthewholetable.

Figure49:ThisistheresultofclickingtheNumberbuttonin
thePivotTableFielddialogue.InthisscreenshotIamsetting
thewholePivotTabletouseatwodecimalplaceformat.
UsingthePivotTableFielddialoguetosetthenumberformatofthe
PivotTableresultsinthefollowingcode:
' Fixing the number format without using a Range
With
ActiveSheet.PivotTables("PivotTable1").PivotFields(
_

110 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

"Average of Repair Time")


.NumberFormat = "0.00"
End With

HereIhavetranslatedthiscodeintoscripting:
' Fixing number format translated
With myTable.PivotFields("Average of Repair Time")
.NumberFormat = "0.00"
End With

Finished Product
OnceweunderstandwhateachpieceoftherecordedMacroisdoing,
itisstraightforwardtotranslateintoaScriptingMacro.HereIhave
placedallthetranslated Constants atthestartofthescript.Ihave
alsoreplacedallthoseclumsylookupstatementswithVariables. In
otherwords,eachtimeitusedtosaysomethinglike:

ActiveSheet.PivotTables("PivotTable1").

Ihavejustput:
myTable.

Thefinishedproduct:
Option Explicit
Dim myWorkbook, myCache, myTable
Const xlPivotTableVersion10 = 1
Const xlRowField = 1
Const xlColumnField = 2
Const xlAverage = -4106
Const xlTable2 = 11
Const xlDatabase = 1

' Here we put code which creates an Excel.Appliation


' Object and which gets the Workbook Object

' Here I split that massive statement in the recorded


' Macro into two steps; this is the first step to
' create the PivotCache. Also note that Excel has
' recorded named arguments (name:=value) we have to
' replace these with unnamed arguments (Appendix E).
Set myCache = myWorkbook.PivotCaches.Add _
( _
xlDatabase, _

DrAlexanderJTurner2007 111
BabySteps

"Sheet1!R1C1:R301C4" _
)
' This is the second step which creates the
' PivotTable from the PivotCache
Set myTable= myCache.CreatePivotTable _
( _
"", _
"PivotTable1", _
TRUE, _
xlPivotTableVersion10 _
)

' Now we have the table in existence, we can add


' the summary methods to it.
With myTable.PivotFields("Office")
.Orientation = xlRowField
.Position = 1
End With

With myTable.PivotFields("Equipment")
.Orientation = xlColumnField
.Position = 1
End With

' There is no point in a script of adding the


' Data field summarised as sum and then changing
' over to average. Here I have added it as average
' to start with.
myTable.AddDataField myTable.PivotFields("Repair
Time"), "Average of Repair Time", xlAverage

' Here is the nice clean number format approach


myTable.PivotFields("Average of Repair Time")
.NumberFormat = "0.00"
End With

' Next we can set the auto-format we want


myTable.Format xlTable2

' Finally, we can clean up a bit by getting rid


' of the field list and the PivotTable command bar
myExcel.CommandBars("PivotTable").Visible = False
myWorkbook.ShowPivotTableFieldList = False

112 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Tricks To Improve Data To Help Pivoting


Banding Data
Backinthedefinitionofourtestdata,thereisasectionthereisa
new company wide directive that repairs should be done in fourteen
hoursorless.Atfirstlook,thereisnothingintherawdatatohelpus
here. Because there is nothing in the raw data, we cannot put
anythinginthePivotTable.So,ScriptingMacroscometotherescue.
WecanuseascripttoaddanewColumnwhichtheappropriatedata.
ThefollowingpieceofscriptputsinanewColumn.Thevalueofthis
Columnis1ifarepairtimewasover14hoursand0ifitwasnot.
mySheet.Cells(1,5).Value = "Over Limit"
mySheet.Cells(2,5).Formula = "=if(C2>14,1,0)"
mySheet.Range("E2:E301").FillDown

IhaveusedaformulaandtheFillDownbecausethisisaveryfast
approach.WecouldmakethescriptinspecteachvalueinColumnC
and put an appropriate value in Column E. The result would be
identical,butitwouldrunhundredsoftimesslower.
NowthatwehaveaColumnindicatingifadatumisovertimeornot,
wecanaddthesenewdataintothe PivotTable. Ihaveaddedthe
OverLimitfieldtotheDataareatwice.ThefirsttimeIhaveadded
it with a summary function of Sum. This results in a number
showing how many repairs were over the limit for a particular
combinationofOfficeandEquipment.ThesecondtimeIhaveadded
itwithasummaryfunctionofCount. Thissimplygivesthetotal
number of repair for a particular combination of Office and
Equipment.
Icallthisapproachbanding.Theideaisthatwetakedatawhichis
continuous(couldbeanythingoutofarangeofvalues)andsortit
intotwoormorebands.Inthisexample,wemaketwobands,over
14hoursandnotover14hours.Anotherexamplemightbepeople's
heights.Withheightswemightmakealessthan1.5meters,1.5to2
metersandgreaterthan2meters.
HereisthecodewhichcreatesthebandingandthePivotTablefor
ourrepairtimeexample:
Option Explicit
' ... Some other code goes here ...

Dim myTable,myCache
Const xlDatabase = 1

DrAlexanderJTurner2007 113
BabySteps

Const xlRowField = 1
Const xlColumnField = 2
Const xlPivotTableVersion10 = 1
Const xlSum = -4157
Const xlCount = -4112
Const xlAverage = -4106

mySheet.Cells(1,5).Value = "Over Limit"


mySheet.Cells(2,5).Formula = "=if(C2>14,1,0)"
mySheet.Range("E2:E301").FillDown

Set myCache = myWorkbook.PivotCaches.Add _


( _
xlDatabase, _
"Sheet1!R1C1:R301C5" _
)

Set myTable=myCache.CreatePivotTable _
( _
"", _
"PivotTable1", _
true, _
xlPivotTableVersion10 _
)

With myTable.PivotFields("Office")
.Orientation = xlRowField
.Position = 1
End With

With myTable.PivotFields("Equipment")
.Orientation = xlColumnField
.Position = 1
End With

myTable.AddDataField _
myTable.PivotFields("Repare Time"), _
"Average of Repare Time",_
xlAverage

myTable.AddDataField _
myTable.PivotFields("Over Limit"), _
"Sum of Over Limit", _
xlSum

myTable.AddDataField _
myTable.PivotFields("Over Limit"), _
"Count Of Jobs", _
xlCount

114 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure50:HerewecanseethePivotTablewithbandeddata.I
haveincludedanenlargedviewoftheCh/HardDrivesummary
data.Wecanseethattherewere6jobsintotalofwhich2were
overthe14hourrepairlimit.However,theaveragerepairtime
is13.33hours,whichmightbeconsideredabitclosetothelimit
forcomfort.Rememberthough,theredataaretotallyinvented!
Cleaning Data
InLesson5wesawthatrealworlddatais'dirty'. PivotTablesare
particularly susceptible to this problem. If we considerour repair
timeexample;whatwouldhappenifinthedatathereisaRowwhich
has'ch'ratherthan'Ch'astheOfficecode?Thiswouldactuallyresult
inawholenewRowinthePivotTable.BoththedatainthenewRow
andintheold'Ch'Rowwouldbeincorrectbecausetheyshouldallbe
summarisedintothesameRow.
Simplyput,cleaninguprealworlddataisthedifferentiatorbetween
awelldonePivotTableMacroScriptandamisleadingmess.
The Page Area
Backwhenwelookedatplacingfieldsintodifferentpartsofablank
PivotTableImentionedthePagearea. Fieldsplacedheremakea
'filter'fortheentiretable.If,forexample,wehaddataondogsand
wewantedtoseeasummaryforjustonebreedatatime,thenwe
wouldputthefieldBreedintothePagearea.

DrAlexanderJTurner2007 115
BabySteps

116 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 9: Working 'Outside The Box'


Accessing Binary Files
SofarinBabyStepswehavelookedatreadingandwritingtextfiles.
Sometimeswemightwanttoaccessbinaryfiles.Anexamplereason
fordoingthismightbetoreadthecommentinamp3file.
Thekeytoaccessingbinaryfilesfromscriptsistousethe ADODB
library which is supplied by Microsoft for free on all Windows
distributions. You will require ADODB 2.5 or later. If you want to
knowifyouhavethisversiothenthefollowingscriptwilltellyou:
dim adodb
set adodb=WScript.CreateObject("ADODB.Connection")
dim v
WScript.echo "Your ADODB Version=" & adodb.version

Anythingat2.5orlatershouldworkfine.
' This is a simple example of managing binary files in
' VBScript using the ADODB object
Dim inStream,outStream
Const adTypeText=2
Const adTypeBinary=1

' We can create the scream object directly, it does


' not need to be built from a record set or anything
' like that
Set inStream=WScript.CreateObject("ADODB.Stream")

' We call open on the stream with no arguments.


' This makes the stream become an empty container
' which can be then used for what operations we want

inStream.Open
inStream.type=adTypeBinary

' Now we load a really BIG file. This should show


' if the object reads the whole file at once or just
' attaches to the file on disk
' You must change this path to something on your
' computer!
inStream.LoadFromFile "C:\temp\test.gif

' Copy the data over to a stream for outputting


set outStream=WScript.CreateObject("ADODB.Stream")
outStream.Open
outStream.type=adTypeBinary

DrAlexanderJTurner2007 117
BabySteps

dim buff
buff=inStream.Read()

' Write out to a file


outStream.Write(buff)

' You must change this path to something on your


' computer!
outStream.SaveToFile "C:\temp\test.gif

outStream.Close
inStream.Close

IntheaboveexampletheStreamobjectisusedtoloadthecontents
ofthefileintomemoryandstoreitasaBytearray(whichisaspecial
way of storing data in memory which VBScript does not normally
use).Thebytearrayisthenpassedtoanotherstreamwhichiswritten
outtodisk.Notverymemoryefficient,butifwewantreallyefficient
binaryfilehandling,thenyoushouldprobablybeprogramminginC!
thistechniquecomesinhandyasaquickandeasyapproachwhich
doesnotrequireanynewcompiledexecutables.
Another way of achieving the same thing is to use the CopyTo
method.Thisdoesnotallowyouaccesstoanyofthedata,butis
moreefficientifyouarewantingtojustcopyafile.Butthen,ifallwe
wanttodoiscopyafile,whynotusetheScripting.FileSystemObject
CopyFilemethod?
OneproblemyoumightfaceusingthisapproachinVBScriptisthat
wecannotcreateaBytearray.Thefollowingscriptfails:
dim outStream
const adTypeText=2
const adTypeBinary=1
dim data

' Copy the dat over to a stream for outputting


set outStream=WScript.CreateObject("ADODB.Stream")
outStream.Open
outStream.type=adTypeBinary

dim buff()
redim buff(255)
dim i
for i=0 to 255
buff(i)=i
next

' Write out to a file - but the script fails here

118 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

outStream.Write(buff)
outStream.SaveToFile "C:\temp\test.gif

outStream.Close
inStream.Close

ThescriptfailsbecausethearraycreatedisaVariantarray,notaByte
array.Whatdoesthatmean?Wellheregoes.
VBScript triestomakelifefortheprogrammersimple. Onewayit
doesthisistosaythatanyVariablecanholdanytypeofdata.Thisis
actuallyasortoftrickthatworksinthebackground. Variablesin
VBScriptarestoredasathingcalleda'Variant'.AVariantholdsnot
onlyavalue,butinformationontype.SoaVariableholdingaString
inVBScriptnotonlyholdsthedatafortheStringitsself,butanextra
datumwhichineffectsaysThisisaString.
Other pieces of software, ADODB being an example, do not use
Variants. VBScriptcantranslateforthem. SoADODB.Streamwill
passdatainafromVBScriptasanArrayofBytes.VBScriptaddsto
the Variablethe datum sayingThis is an Array ofBytes when it
reads from the ADODB.Stream. When VBScript writes to the
ADODB.Streamitstripsthisextradatumoffagain.
Allthis'magic'worksjustfineuntiltocomestocreatingaVariable
which holds a Array to be written to ADODB.Stream. VBScript
cannot create and Array of Bytes. It can only create an Array of
Variants. The magic does not automatically convert an Array of
VariantstoandArrayofBytes.Toworkaroundthisproblem,wecan
getADODB.StreamtocreateanArrayofBytesforusbywritingouta
textfileoftheappropriatelengthandthenreadingitin.Igavethisa
lotofthoughtanddecidedthatwritingupthismethodwouldbejust
fartoohardcorefor'BabySteps'.However,Iwillbehappytoanswer
anyemailsononthesubjectandmightwriteitupinmyblog.
Reading Data From Binary Files An Example
OK,hereweseethatwecanreadbinaryfilesaslongastheyarenot
toolarge.WecanreadthedatainthembygettingaBytearrayfrom
theLoadFromFilemethodoftheStreamobject,andwecanwriteto
them.Forthelastpieceofthissection,letusdosomething'real'with
thistechnology. Thescriptbelowlooksforallthe'.gif'filesin'My
Pictures'andliststhemalongwiththecontentsoftheGIFversion
label. TheGIFversionlabelisstoredatthestartofthe'gif'binary
files.
Option Explicit

DrAlexanderJTurner2007 119
BabySteps

Dim myShell, sendToFolder, myPicturesPath, myShortcut


Dim fso,myFolder, myFile, fileName, comment, myExcel
Dim myWorkbook, myRow, mySheet
' Find "My Pictures"
Set myShell = CreateObject("WScript.Shell")
myPicturesPath = myShell.SpecialFolders("MyDocuments")
& "\My Pictures"

' Open "My Pictures" as a folder so we can see


' which files are inside it
Set fso=CreateObject("Scripting.FileSystemObject")
Set myFolder=fso.GetFolder(myPicturesPath)

' Set Up Excel To receive The Data


Set myExcel=CreateObject("Excel.Application")
Set myWorkbook=myExcel.Workbooks.Add
Set mySheet=myWorkbook.Sheets(1)
myRow=2
mySheet.Cells(1,1).Value="Name"
mySheet.Cells(1,2).Value="GIF Type"
myExcel.Visible=TRUE

' Loop through each file found and see


' if its file extension is .gif
' If a file is a .gif file then call our function
' which opens it as a binary file and reads the
' version label
for each myFile in myFolder.Files
fileName=myFile.name
fileName=Lcase(fileName)
if Right(fileName,4)=".gif" then
' Read the version label
comment=GetGifComment(myFile.path)
' Place the data in the spreadsheet
mySheet.Cells(myRow,1).Value=fileName
mySheet.Cells(myRow,2).Value=comment
' Step down to the next Row
myRow=myRow+1
end if
next

' Make the spreadsheet look a bit nicer


With mySheet.Range("A1:B1").Font
.FontStyle = "Bold"
.Size = 12
End With

mySheet.Columns(1).Autofit
mySheet.Columns(2).Autofit

120 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

'Script ends here

function GetGifComment(gifFilePath)
dim inStream,buff,commentLen,commentStr,myIndex
dim myByte,myByteValue,myCharacter

set inStream=WScript.CreateObject("ADODB.Stream")

inStream.Open
inStream.type=1

inStream.LoadFromFile gifFilePath

buff=inStream.Read()
inStream.Close

commentStr=""
for myIndex = 1 to 6
' Extract 1 byte from the buffer
myByte = MidB(buff,myIndex,1)
' Gets its numeric value
myByteValue = AscB(myByte)
' Convert that numeric value into a character
myCharacter = Chr(myByteValue)
' Append that character to the string
commentStr = commentStr & myCharacter
next
GetGifComment = commentStr
end function

ADODB.Stream Summary
Properties
Property Description
CharSet Sets or returns a value that
specifies into which character set
the contents are to be translated.
This property is only used with text
Stream objects (type is adTypeText)
EOS Returns whether the current position
is at the end of the stream or not
LineSeparator Sets or returns the line separator
character used in a text Stream
object
Mode Sets or returns the available
permissions for modifying data
Position Sets or returns the current position

DrAlexanderJTurner2007 121
BabySteps

(in bytes) from the beginning of a


Stream object
Size Returns the size of an open Stream
object
State Returns a value describing if the
Stream object is open or closed
Type Sets or returns the type of data in a
Stream object
Methods
Method Description
Cancel Cancels an execution of an Open call
on a Stream object
Close Closes a Stream object
CopyTo Copies a specified number of
characters/bytes from one Stream
object into another Stream object -
args Stream,[count]
Flush Sends the contents of the Stream
buffer to the associated underlying
object
LoadFromFile Loads the contents of a file into a
Stream object
Open Opens a Stream object
Read Reads the entire stream or a
specified number of bytes from a
binary Stream object
ReadText Reads the entire stream, a line, or a
specified number of characters from a
text Stream object
SaveToFile Saves the binary contents of a Stream
object to a file
SetEOS Sets the current position to be the
end of the stream (EOS)
SkipLine Skips a line when reading a text
Stream
Write Writes binary data to a binary Stream
object
WriteText Writes character data to a text
Stream object

IfthemodeofastreamisadTypeText(2)wewillgetanerrorifyou
trytouseReadorWrite.Equally,ifthetypeisadTypeBinary(1)the
ReadTextandWriteTextwillfail.Notealsothatifthestreamsareset
toTextandCopyToisusedtocopyafile,thefilewillbeconvertedto

122 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

textevenifitdidnotstartoutthisway.Theendresultisnormallya
corruptfile.IwouldstronglysuggestalwaysusingadTypeBinarywith
ADODB and using the FileSystemObject for all text file
manipulations.
Sending Key Strokes To Other Applications Through
SofarwehaveseentheabilityofscriptstoworkwithExcelusing
COM. How about using a script to work with Excel and another
application? Anexampleapplicationmightbe Notepad. However,
thereisnoCOMinterfacetoNotepad,sowearegoingtohavetouse
the WScript.SendKeys method.Sohereisaquickcribonhowthat
works.
Mostkeyscanberepresentedbythecharacterofthekeyitself.e.g,
thekeysequenceFREDcanberepresentedsimplyby"FRED".Hereis
asimplescriptwhichwillopenNotepadandtypeFREDintoit.Todo
that,itcreatesaObjectfromtheWscript.ShellClass.ThisObjecthas
a Method to 'run' an application. This Method is used to run
Notepad.OnceNotepadisupandrunning,thekeysequenceFRED
issenttoit.
Option Explicit
Dim WshShell

' Open notepad


Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "notepad", 9

' Give Notepad time to load (500 milliseconds)


WScript.Sleep 500

' Write FRED


WshShell.SendKeys "FRED"

Some special keys, such as the control keys, function keys etc are
encodedinastringenclosedby{braces}
Key Code
{ {{}
} {}}
[ {[}
] {]}
~ {~}
+ {+}
^ {^}
% {%}

DrAlexanderJTurner2007 123
BabySteps

Key Code
BACKSPACE {BACKSPACE}, {BS}, or {BKSP}
BREAK {BREAK}
CLEAR {CLEAR}
CAPS LOCK {CAPSLOCK}
DEL or DELETE {DELETE} or {DEL}
DOWN ARROW {DOWN}
END {END}
ENTER {ENTER} or ~
ESC {ESC}
HELP {HELP}
HOME {HOME}
INS or INSERT {INSERT} or {INS}
LEFT ARROW {LEFT}
NUM LOCK {NUMLOCK}
PAGE DOWN {PGDN}
PAGE UP {PGUP}
PRINT SCREEN {PRTSC}
RIGHT ARROW {RIGHT}
SCROLL LOCK {SCROLLLOCK}
TAB {TAB}
UP ARROW {UP}
F1 {F1}
F2 {F2}
F3 {F3}
F4 {F4}
F5 {F5}
F6 {F6}
F7 {F7}
F8 {F8}
F9 {F9}
F10 {F10}
F11 {F11}
F12 {F12}
F13 {F13}
F14 {F14}
F15 {F15}
F16 {F16}

TospecifykeyscombinedwithanycombinationofSHIFT,CTRL,and
ALTkeys,precedethekeycodewithoneormoreofthefollowing:

124 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

For SHIFT prefix with +


For CTRL prefix with ^
For ALT prefix with %

HereisafullerexampleinwhichwecreateasmalltableinandExcel
spreadsheet and use copy and paste to place the contents into
Notepad.
Option Explicit
Dim WshShell, myExcel, myWorkbook, mySheet

' Open Excel


Set myExcel = CreateObject("Excel.Application")
' Create a Workbook and set myWorkbook to refer to it
' all in one go
Set myWorkbook = myExcel.Workbooks.Add()
Set mySheet = myWorkbook.Sheets(1)
mySheet.Cells(1,1).Value="Hellow"
mySheet.Cells(1,2).Value="World"
mySheet.Cells(1,3).Value="This"
mySheet.Cells(2,1).Value="Is"
mySheet.Cells(2,2).Value="An"
mySheet.Cells(2,3).Value="Example"
mySheet.Cells.Copy

' Tell Excel not to ask if the document


' should be saved or to show any other alerts
myExcel.DisplayAlerts = FALSE

' Shut down Excel as we do not require it any more


myExcel.Quit

' Open notepad


Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "notepad", 9

WScript.Sleep 500

' Do The Paste


WshShell.SendKeys "%e"
WshShell.SendKeys "p"

Stopping Excel From Complaining


In theaboveexampleofsendingkeystrokesto Notepad,Iuseda
trick to stop Excel complaining about closing without saving.
Sometimeswhenweareprocessingdata,wewanttouseaninstance
ofExcelbutnotbothersavingthechangeswemaketoit.Thewayto
dothisisbytheApplication.DisplayAlertsProperty.

DrAlexanderJTurner2007 125
BabySteps

Choice And Decision Processing


Yes Excel Really Is This Powerful!
Itisamazingbuttrue,Excelcanperformthesortofcomplexdecision
making tasks we more normally associate with software systems
whichcostmillions.Asasoftwarearchitect,Ihaveoftenbeenasked
to integrate choice/decision processing into software systems.
Achieving this is usually daunting in the extreme. However, with
Excelthechallenge fallsawayleavingastraightforward stepwise
approachandminimalcost.
What Is Choice/Decision Processing?
Should Burt get a newcar this year? Which airconditioner units
should be serviced and which replaced? Which invoices must be
honouredthismonthandwhichcanwaittillnext?
Alloftheseexamplesarechoice/decisionprocessingchallenges. In
computerscienceitiscalledlogicalprogramming.Itturnsoutthat
peoplefindithardtobeconsistentwithlogicaltaskslikethese. It
alsotakesa lotof timeforpeople to processdata throughlogical
sequences. Even when we layout careful rule sets, humans just
struggletoapplythemuniformly. Insomewaysthisisthegreatest
asset of humans. We constantly review decisions and bring in
external factors whilst considering them. Humans do not tend to
blindlyfollowobviouslyincorrectrules.Computersjustprocessdata
andrulesoverandoveragainwithoutvariationorconsideration.For
somesituationsthe'commonsense'ofhumansisideal;forotherswe
needtheuniformity,reliabilityandandspeedofacomputer.
WhilstweoftenthinkofExcelasanumbercrunchingtool,itturns
outtobejustfantasticatprocessinglogicalproblemsaswell.Excel
byitsselfisbrilliantatapplyingcomplex,orevenverycomplexrule
setstoadatatomakechoices.So,byitsself,Excelistheprefectfor
workingoutifBurtgetshisnewcar.MacroScriptingthenaddsthe
ability for Excel to munch through thousands of data sets making
decisionsforeach.
With a simple script, and Excel, we can make logical decision
processingsystemswhichareabletomakethousandsofdecisionsin
averyshortperiodoftime. Thisapproachcouldallocatenewcars,
newcomputersorevennewbenefitpackagestoentirepayrolls.Such
abilitieswithdedicatedsystemscostthousands,ifnotmillions,of
Pounds, Euros or Dollars to implement; most of us already own a
copy of Excel and can implement such a system for the price of
dinner.

126 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

First Off Just The Very Minimum Of Logic


Logic and logicalprogramming arealibrary'sworthofknowledge.
WewanttotakeaBabyStep.So,herewewilllookattheabsolute
minimumoflogicwecangetawaywithandstillbeonehundred
percentcapableofmakingExcelbaseddecisionsystems.
TRUE & FALSE
In this approach, all questions have one of two possible answers:
TRUEorFALSE.
WeaskaquestionbysayingIsthisTRUEorFALSE.Forexample,
takeablankspreadsheetandputthisformulaintothetoplefthand
corner:
=1>0
TheCellshouldshowTRUE.Whatwehavedoneisaskthequestion
Is1greaterthan0.ExcelhasansweredTRUE.
Therearenoprizesthenforfiguringoutwhat...
=1<0
...gives.Yes,itisFALSE.
WecansubstituteCellreferencesintotheseformulae.Soifweplace
thenumber1inCellA1and=A1>0intoA2thenExcelwillreport
thevalueofA2asTRUE. ChangeA1to0andA2willchangeto
FALSE.Figure51showsseveralsuchexamples.

Figure51:ThisscreenshotshowstheconceptofTRUE/FALSE
formulaeinExcel.Itthengoesontoillustratehowtoprocessthe
answerstothese'questios'usingAND,ORandNOT.Inthefirst
columnaretheExcelformulae(displayedvia
Tools/Options/Formulas)andinthesecondcolumnarethe
TRUE/FALSEresults.

DrAlexanderJTurner2007 127
BabySteps

Chaining Decisions To Make Rules


NowthatwecangetExceltoanswerlogicalquestionsitwouldbe
nicetogetittochainthequestionstogether.Ifweconsidertherule:
Yougetacarifyourcarisolderthan2yearsoldAND
youareinthesalesdepartment
Ihavecapitalised'AND'intheaboverulebecauseitdoesthejoining
workwhichchainstwoseparatelogicalquestionstogether.
Isourcareolderthan2years?
AND
Areyouinsales?
Consider,ifyouwould,aspreadsheetlikethis:
A B
1 Age Of Car (Years) 3
2 Department Sales

Wecantakethesedataandusethemtocreateadecision:
A B C
1 Age Of Car (Years) 3
2 Department Sales
3 Choice =B1>2 =AND(B3,B2=Sales)

IntheabovespreadsheetCellC3willdisplayavalueofTRUE.Ifwe
changeB2tobesomethingotherthan'Sales'orwechangeB1tobe2
orless,thenC3willdisplayavalueofFALSE.Inotherwords,Excel
haschainedtwochoicestogethertomakearule.
The key word AND() in an Excel formula means a special Excel
Function. A comma separated list of arguments goes in the
parenthesis. AND()isTRUEifandonlyifeverysingle argument is
TRUE.
=AND(TRUE,TRUE,FALSE) FALSE
=AND(TRUE,TRUE,TRUE) TRUE
=AND(TRUE,FALSE) FALSE
=AND(FALSE,TRUE) FALSE
=AND(TRUE,TRUE) TRUE
etc...

128 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Sometimesismakesmoresensetoaskwhensomethingisnottrue.
ConsiderthatpeopledonotgetacariftheyliveinHolland(itistoo
flat to bother, one should use a bike). One way to look at this
decisionis:
ApersonmaybeeligibleforacariftheydoNOTlivein
Holland
ExcelhasafunctionNOT()thatdoesthisforus:
=NOT(1>2) TRUE

TheaboveformulaasksIsitTRUEorFALSEthat1is NOT greater


than 2. Well, 1 is not greater than 2, so the answer is TRUE.
Likewise,thefollowingformulawillgiveavalueofFALSE:
=NOT(1>0) FALSE

WecanuseournewtooltoaddthenocarsinHollanddecisionto
ourruleprocessingspreadsheet.
A B C D
1 Age Of Car 3
(Years)
2 Department Sales
3 Country France
4 Choice =B1>2 =AND(B3,B2= =AND(C4,
Sales) NOT(B3=Holland))

Intheexampleabove,BurtwillgetanewcarbecausethevalueofD4
willbeTRUE.IfhemovedtoHollandthenhewouldnotgetthecar.
Excelcanmakethatchoiceforususingthissimplestepbysteprule
system.
Thereareprobablythousandsofwaystoloadthisdecisionsystem
into Excel; using the way I have shown it issimple to create and
simpletomaintainthespreadsheet. Theapproachcanbesummed
uplikethis:
PlacedecisionsinaRow.
MakeonlyoneTRUE/FALSEdecisionsineacheachCellof
thatRow.
ChaintheCellstogethersoeachCell'sdecisionischainedby
ANDtotheresultoftheCelltoitsleft.

DrAlexanderJTurner2007 129
BabySteps

TherightmostCellinaRowgivestheactualoutputchoice
TRUE/FALSEoftherule.
Whatwehavedonesofarisbuildsingledecisionsintorulesusing
chaining. How about if there are more outcomes than just
TRUE/FALSEorGetacar/don'tgetacar? Whataboutmaking
Excelpickwhatsortofcartogive? Thisiswhere blocks and zeds
comein.
Blocks And Zeds
Rules are groups of decisions chained together. We place all the
decisionsforaruleinoneRow. Blocks aregroupsofruleswhich
interactwitheachother.Iftheoutcomeofarule hasnoimpacton
theoutcomeofanotherrulethenthetworulesareindifferentblocks.
Butiftheoutcomeofaruleaffectstheoutcomeofanotherrulethen
thetworulesareinthesameblock.
Considerthenextsetofdecisionswhichgotomakeuptworules.
TheideabeingthatifanemployeeisinSalesbutwillnotbegettinga
newcarthisyear,thentheygeta'bustimetableinstead.

A B C D
1 Age Of Car 3
(Years)
2 Department Sales
3 Country France
4 Get Car ? =B1>2 =AND(B3,B2=Sa =AND(C4,
les) NOT(B3=Hollan
d))
5 Get 'Bus =NOT(D4) =AND(B5,B2=Sa
Time Table? les)

NowExcelcomputestheanswerstotwoquestions:
1. DoesBurtgetanewcar?
2. DoesBurtgeta'bustimetable?
CellC5dependsonB5whichdependsonD4whichdependsonC4
whichdependsonB4.IfweconnectuptheseCellsinthisorderwith
aline(likejointhedots)thenwewilldrawaZshape.Plus,therules
inRows4and5makeupablockbecausetheydependoneachother.
So,theserulesmakeablockandazed.

130 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Putting It All Together


Nowweare goingto lookat a completelyfreshexample. Inthis
examplewearegoingtointroducetheuseofmorethanoneblock
andanewfunctionOR.ORisthelastlogicalfunctionwewillneed
tolookat.
=OR(TRUE,TRUE) TRUE
=OR(TRUE,FALSE) TRUE
=OR(FALSE,FALSE) FALSE
=OR(FALSE,FALSE,TRUE) TRUE

ORgivesTRUEifanyofitsargumentsareTRUE.ItsaysIfmyfirst
argument OR my second argument OR my third argument ... are
TRUEthenIamTRUE.
In decision/choice work with Excel, we do not use OR to chain
decisions tomakeaRule. We use OR tocollect togetheranswers
fromRules. Forexample,wemightwanttosaysomethinglikeIf
Rule2OrRule4sayBurtgetsacar,thenhegetsacar.
Hereisthescenarioforournextexample:
ThereisacompanywhichisintendingtoupgradefromMSOffice
2003toMSOffice2007.
However,therearesomecomplexities.Firstoff,noteveryoneistobe
upgraded to 2007; thecompany has a deal by whichsome ofthe
Office2003licensescanberecycledtoallowupgradeofoldOffice
2000licenseforpeoplewhodonotrequirethelatestsoftware.Also,
therearethreetypesofOffice2007licensepackages:
1. Word,Excel,Outlook,PowerPointandAccess
2. Word,Excel,Outlook
3. Word,Excel
Therearethreedepartmentstothiscompany:
1. Admin
2. Sales
3. Supply
Admin require Office 2007 because some of the administration
systemsarebeingupgradedandrequirethethisversionofOfficefor
integration.

DrAlexanderJTurner2007 131
BabySteps

So, here are the rules for choosing what software to install on
people'smachines:
People in Admin who have Access version > 9 get license
package1otherwise,licensepackage2.
PeoplewithPowerPointgetPowerPointagain.
SalesonlyrequireWordandExcelbecausetheytraveland
willuseWebMailforemail.
SupplygetanupgradetoOffice2003(Office11)iftheydo
not already have it. There is only one Office 2003 license
package.
ThisexampleisrunusingthreeSheetsinoneWorkbook.Thefirstis
DataIn.ThisSheetiswheretheinformationabouttheemployeeis
placed. ThenextSheetislogic. Thisiswherealltherulesare
placed.logictakesitsinformationfromDataIn.Finally,thereis
DataOut.ThisSheetisjustapresentationreporttohelpmakethe
resultsunambiguous.
HereisthestructureoftheDataInSheet:
User Information
Title Datum
Name Fred
Department admin

Installed Software
Package Version (0 means Not Installed)
Word 11
Excel 11
Outlook 11
Powerpoint 1
Access 10

HereisthestructureoftheLogicsheet:
Is Admin Has Access > 9 Install L1
=DataIn!.B4="admin" =AND(A2,DataIn!.B12>9) =B2
IsAdmin Has Powerpoint Install L2

132 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

=AND(NOT(C2), =AND(A4,DataIn!.B11>0) =B4


DataIn!.B4="admin")
IsAdmin Install L3
=AND(NOT(C4),NOT(C2),D =A6
ataIn!.B4="admin")
IsSales Has Powerpoint Install L2
=DataIn!.B4="sales" =AND(A8,DataIn!.B11>0) =B8
IsSales Install L3
=AND(NOT(C8),DataIn!.B =A10
4="sales")
IsSupply Has Word < 11 Install 2003
=DataIn!.B4="supply" =AND =B12
(A12,DataIn!.B8<11)
IsSupply Has Excel < 11 Install 2003
=AND(NOT(C12);DataIn!. =AND(A14;DataIn!.B9<11) =B14
B4="supply")

AtthebottomoftheLogicSheet,ORfunctionsareusedtocollect
theoutputoftherules:
Install 2007, L1 =C2
Install 2007, L2 =OR(C4;C8)
Install 2007, L3 =OR(C6;C10)
Install 2003 =OR(C12;C14)

Thenatureoftherulesmeansthataemployeewillgetonlyoneof
thechoices.Inotherwords,onlyoneoftheinstalloptionswillshow
TRUE.

DrAlexanderJTurner2007 133
BabySteps

Figure52:Excelhastheabilitytodrawoutthedependencies
betweenCells.Bydoingthiswecanseethestructureofthe
BlocksandZedsinourWorkbook.Ihaveputdarkborders
aroundeachblocktomakeeasiertoseethestructureoftheLogic
Sheet.

Figure53:WorkingwithZeds!WeloadthechoicesintoExcelby
startingatthetopleftandworkingacrosstotheright.Thenwe
startagainattheleft.Eachlineinagroupislinkedtothe
answerofthelineabovesothatonlyonelineinagroupcanbe
TRUE.Thismeansthedependenciesinbetweenthelinesmakea
Zpattern.

Figure54:Intheabovegroup,therearethreelinesofchoices
yieldingthreepossibleoutcomes.ThebottomlinemakesaZwith
themiddleline.

134 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure55:Herewecanseethegroupwiththreelinesofchoices
again.Thebottomlinecanonlybetrueiftheprevioustwo
choicelinesendupfalse.ThismeansthattherearetwoZeds
whichincludethebottomline.Thereasonthisapproachworksis
thatthetoplineismostselective,thesecondlineisslightlyless
selectiveandthebottomlineistheleastselective.Ifyoucannot
orderthelineslikethis,thechancesarethatyourrulesare
ambiguousandcoulddowithtweakingoralternatively,you
shouldsplitthegroupintotwo.

Figure56:ThenextBlockinourexampleisshownherewithits
ZedsrevealedbyExcel'sCelldependencytracking.

DrAlexanderJTurner2007 135
BabySteps

Figure57:HereisthelastoftheRuleblockswithitsinternal
structuredisplayed.Thedotteddependencylinenearthebottom
showsthewaytheresultoftheblockisreportedforwardontothe
DataOutSheet.

Figure58:InthisexampleIhavemadeaseparateDataOut
Sheetwhichderivesitsdatafromtherulesheetyetpresentsthe
resultsinanunambiguousway.
Moving From One To Many
Sofarinchoice/decisionprocessingwehaveseenanexplanationand
examples of processing for one input data set. In the previous
example that data set represented one person. However, at the

136 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

beginning of this section I discussed how this technique could be


appliedtolargenumbersofdatasets.
Itturnsouttobestraightforwardtojusttaketheworkdonesofar
andconvertittodoingmultipledatasets. Weneednotalterour
approachtothechoice/decisionWorkbookatall. ThethreeSheet
structure(DataIn,Logic,DataOut)isideal.Thetrickistodevelopon
thisWorkbookuntilitgivesthecorrectresultsforeverypossibleset
ofinputdata.Oncethisisdoneweleaveitalone.Themultipledata
setsystem'wraps'ourdecisionWorkbookinascriptwhichdoesthe
following:
1) OpenaWorkbookwithallthedatasets,oneperrowina
Sheet.CallthisWorkbookInput.
2) OpentheLogicWorkbook.CallthisWorkbookDecision.
3) OpenaWorkbookfortherecordingofthedecisions.Callthis
WorkbookOutput.
4) ForeachrowinInputtakethedatainthatRowandplaceit
intheDataInSheetinDecision.
5) ForeachloadingofadatasetintoDecision,taketheresult
fromDataOutinDecisionandplaceitinaRowinOutput.

Figure59:Thisdiagramshowsthewayascriptprocessesdatato
makea'oneatatime'decisionWorkbookturnintoapowerful
decisioncrunchingsystem.

DrAlexanderJTurner2007 137
BabySteps

138 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Lesson 10: Speeding Scripts Up


Cell By Cell Access Is Slow
ThenaturalwaytomanipulatedatainExcelfromaScriptingMacro
isoneCellatatime.Theonlyproblemwiththisapproachisspeed.
It takes an appreciable amount of time to place data into a Cell.
SettingtheValueofasingleCellmightbefastenoughtoseeminstant
tothehumaneye,howeverdoingsoforthousandsofCellscantake
secondsorevenminutes.
Toillustratethisissue,hereisascriptwhichloadsonethousandCells
oneatatimeintoanewlycreatedWorkbook.
set myExcel = CreateObject("Excel.Application")
myExcel.Visible = true
set myWorkbook = myExcel.Workbooks.Add
set mySheet = myWorkbook.Sheets(1)

' Get the start time


startTime = Timer()

' Load values into 1000 Cells directly


for row = 2 to 1001
mySheet.Cells(row,1).Value = "Hello " & row
next

' Get the end time


endTime = Timer

' Lay out the results column headings,


' Work out the result using an Excel formula
' and make the Columns automatically set themselves
' to an appropriate width
With mySheet
.Cells(1,1).Value = "Data"
.Cells(1,2).Value = "Start"
.Cells(1,3).Value = "End"
.Cells(1,4).Value = "Time"

.Cells(2,2).Value = startTime
.Cells(2,3).Value = endTime
.Cells(2,4).Formula = "=C2-B2"

.Columns(1).Autofit
.Columns(2).Autofit
.Columns(3).Autofit
.Columns(4).Autofit
End With

DrAlexanderJTurner2007 139
BabySteps

ThekeypartofthescriptistheForloopinthemiddle. Itplacesa
differentStringintoeachoftheCellsinColumn1fromRow2to
10001.TheVBScript'builtin'functionTimer()isusedtorecordthe
numberofsecondssincemidnightbeforeandaftertheloophasrun.
Thedifferenceinthetworesultsisthetimeittookthelooptorun.
Timer()isusuallyaccuratetowithinaroundtwentymilliseconds,soit
makesquiteahandywaytotimetheperformanceofscript.

Figure60:Thisisascreenshotshowingtheresultofrunningthe
CellbyCellloadingscript.Itshowsthatithastaken51.3seconds
toloadaStringinto1000CellswhenthedataisloadedonCells
atatime.
AswecanseefromFigure60,ithastakennearlyaminutetoload
onethousandCells.IfweweretodothisfortenthousandRowsover
tenColumns,thenitwouldtakearoundonehundredminutes.Ifwe
imagine running a script that takes over an hour, then finding
somethinghasgonewrongandhavingtorunitagain,itiseasytosee
whyspeedingthingsupisgood!
Fortunately,thereareseveralwaystospeedupScriptingMacros.A
goodapproachisoftentodevelopthescriptusingasmallsetofdata
andloadingCellsoneatatime.Onceitisworkingcorrectlyitistime
tostartspeedingitupusingthetechniquescoveredhere.
Bulk Data Loading With Arrays
What Is An Array?
AnArrayisaspecialsortofvalueforaVariable. Wehavealready
seenthatVariablescanholdthingslikeString,Object,Dateetc.What

140 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

happens if we want one Variable to hold lots of Strings or lots of


Objects.ThisiswhereArrayscomein.
ToholdthreeStringswecouldput:
s1 = hello 1
s2 = hello 2
s3 = hello 3

OrwecouldcreateaVariableusingtheVBScript'dim'specialword:
Dim myString(2)
myString(0) = hello 1
myString(1) = hello 2
myString(2) = hello 2

That piece of code has a few things about it which could be


confusing.Ratherthepretendthatitdoesnot,letustackleithead
on.
1. WhydowedimmyString(2)whenwewant3elementsin
ourarray?
2. WhydowestartatmyString(0)?
3. Ithoughtputtingparenthesisaftersomethingmeantitisa
function.
WhenwecreateanArraywedonotdirectlytellVBScripthowmany
elementsitshouldhave;wetellVBScriptwhatthe'upperbound'is.
The'lowerbound'iszerobydefault.So,DimmyString(2)saysmake
anArrayfrom0to2.Thisanswersquestions1and2.Question3is
answered by history. VBScript has it origins in a language called
Beginner'sAllPurposeSymbolicInstructionCodewhichisrather
old nowadays. More recent languages have removed ambiguity
betweenFunctionandArraynotation.AswearestuckwithVBScript,
wehavetorememberwhatnamesdenoteArraysandwhichdenote
Functions. thiscanbemadeeasierbyalwaysusingacapitalfirst
letterforFunctionsandlowercaseforallVariablesincludingArrays.
Using Arrays Like Spread Sheets
set myExcel = CreateObject("Excel.Application")
myExcel.Visible = true
set myWorkbook = myExcel.Workbooks.Add
set mySheet = myWorkbook.Sheets(1)

' Get the start time


startTime = Timer()

DrAlexanderJTurner2007 141
BabySteps

' Create a 1000 by 1 array and load data into it


dim data(999,0)
for row = 0 to 999
data(row,0) = "Hello " & row
next

' Bulk load a 1000 by 1 Cells Range of the spread


' sheet from the array
mySheet.Range _
( _
mySheet.Cells(2,1), _
mySheet.Cells(1002,1) _
).Value=data

' Get the end time


endTime=Timer

' Here I have omitted the result printing and


' formating because it is identical to the previous
' script.

Figure61:Thisisascreenshotshowingtheresultofrunningthe
ArraytoCellloadingscript.Itshowsthatithastakenlessthana
fifthofasecondtoloadaStringinto1000Cellswhenthedatais
loadedonintoanArrayandthentheArraybulkloadedintothe
Cells.Thisis250timesfasterthandoingtheloadoneCellata
time.

142 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Bulk Data Transfer With Copy/Paste


WhenwemovedataaroundbyhandweuseCopyandPasteallthe
time.ItisverymuchfasterthatCellbyCelltransferofvaluesandso
isidealforscripting.Hereisanexample:
Option Explicit
Dim myExcel,myWorkbook,mySheet
Set myExcel=CreateObject("Excel.Application")
myExcel.Visible=TRUE
Set myWorkbook=myExcel.Workbooks.Add()
Set mySheet=myWorkbook.Sheets(1)
mySheet.Cells(1,1).Value="Hello"
' Please note that we must make sure the Sheet from
' which we Copy and that to which we Paste are the
' active (visible) ones. This is done via the
' Sheet.Select Method.
mySheet.Select
mySheet.Cells.Copy
myWorkbook.Sheets(2).Select
myWorkbook.Sheets(2).Paste

Don't Forget Formulae And Fills


Wehaveseenusingfillsbeforeinlesson8.Itismuchfastertofilla
Column witha formula thanto calculateCellvaluesoneby one.
Hereisanexample:
mySheet.Cells(1,5).Value = "Over Limit"
mySheet.Cells(2,5).Formula = "=if(C2>14,1,0)"
mySheet.Range("E2:E301").FillDown

DrAlexanderJTurner2007 143
BabySteps

144 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Appendix A: Differences With Excel 2007


Recording Macros:
RecordingMacrosisprettymuchexactlythesameinExcel2007.The
onlyrealdifferencesrelatetofindingtheoptionsinMicrosoft'snew
layout. Herearesomescreenshotsshowingthebasicsteps. The
conceptsareidenticaltothosedescribedinlesson4.

Figure62:Tostartrecording,wemustclickthe'Macro'pulldown
underthe'View'ribbon.

Figure63:Clickingthe'Macro'pulldowngivesustwooptions.
TorecordaMacro,wejustclick'RecordMacro'.Selectingthe
Macronameetc.isjustthesameasforpreviousversionsofExcel.

DrAlexanderJTurner2007 145
BabySteps

Figure64:Oncewefinishedperformingtheactionswhichwe
wantrecorded,the'View/Macro'pulldowngivesustheoptionto
'StopRecording'.

Figure65:TheView/Macropulldownletsusviewthecodeof
theMacro.Thewholeofthecodeeditorispettymuchidentical
tothatofpreviousversionsofExcel.
Showing The Developer Tab (Accessing VBA)
It would appear that the default install of Excel 2007 hides the
DeveloperTab. Tobeabletoseeit,andsogaineasyaccesstothe
CodeEditorandObjectBrowser,wecanfollowthesesteps.

146 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure66:SteponeistoclickontheMSOfficesymbolinthetop
lefthandcornerofExcel'swindow.Doingsorevealsthemenu
shownabove.Atthebottomrightisabutton(highlightedinthe
picture)namedExcelOptions.Thismustbeclicked.

Figure67:ClickingtheExcelOptionsbuttonrevealstheExcel
Optionswindow.Onceonehasrecoveredfromtheshock,it
becomesvisiblethatthereisanoptionShowDeveloperTabin
theRibbon.ThetrickistoselectthisandthenclickOK.

DrAlexanderJTurner2007 147
BabySteps

Figure68:HerewecanseeournewDeveloperTab.Highlighted
inthisscreenshotistheVisualBasicbutton.Clickingonthis
openstheCodeEditor.TheCodeEditorandallitsoptions(e.g.
theObjectBrowser)aremoreorlessidenticaltothoseofearlier
versionsofExcel.

148 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Creating A Pivot Table


TheconceptsbehindcreatingaPivotTableinExcel2007areidentical
tothoseforpreviousversions. Nevertheless,thestepsinvolvedin
doing so are slightly different and the wizard has changed
considerably. Ihaveshown thestepsinvolvedusingthefollowing
seriesofscreenshotswithcaptions:

Figure69:KickingoffcreatinganewPivotTablecomesfrom
clickingthePivotTablebuttonontheInsertTaboftheRibbon.

Figure70:ThePivotTablewizardstartswiththepopupshown
above.IhighlyrecommendthatNewWorksheetisselected.
MostofthetimeExcelwillautomaticallyguessthecorrectrange
ofCellsfromwhichtotakethedataforourPivotTable.Ifitdoes
not,wecandirectlytypetherangeintotheTableRangetext
box.AndalternativeistoselectarangeofCellsbydraggingthe
mouseovertheSheet.

DrAlexanderJTurner2007 149
BabySteps

Figure71:OncewehaveclickedOKonthefirstpopup,Excel
insertsablankPivotTableandthePivotTableFieldListboxas
showninthisscreenshot.Thisisreallyverydifferentfromthe
previousversionsofExcel.Wenolongerseeareasintheblank
PivotTablefordraganddrop.Constructingthetableisalldone
viathePivotTableFieldListbox.

Figure72:Tosummariseafieldacrossrows,wedragthefield
namefromthetoppaneofthePivotTableFieldListboxtothe
RowLabelsarea.

150 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure73:TosummariseafielddownColumns,wedraganddrop
thefieldnamefromthetoppanetotheColumnLabelsarea.


Figure74:InthebottomrightofthePivotTableFieldListboxis
wheretheDatafieldnamesaredragged.Thisishighlightedinthe
abovescreenshot.ItstartsoutwiththedefaultSumfunction.To
setupthedatawhichwewantsummarisingwefirstdragthatfield
nametothisarea.JustaswiththepreviousversionofExcel,
changingtosummarymethoditsomethingotherthanSumisa
separatestep(describednext).

DrAlexanderJTurner2007 151
BabySteps

Figure75.RightclickingontheDataareaofthePivotTableField
Listboxbringsupthecontextmenushownabove.Atthebottom
ofthismenuistheValueFieldSettingsoption(highlighted).
Clickingthisrevealstheoptionsnecessarytochangethesummary
method(next).

Figure76:WenowgettheValueFieldSettingsbox.Inthe
screenshotabove,IamchoosingAverageformyDatafields
(whichMicrosoftnowsometimescallValuefields,butrelateto
theDataAreaofpreviousversionsofExcel).

152 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Figure77:ValueFieldSettingsboxalsohasatabforShow
valuesas.Underthistabwecanfindabutton(highlighted)
whichbringsuptheFormatCellsboxforthePivotTable.This
canbeusedtosetthenumberformat.InthisexampleIhaveset
itto2decimalplaces(next).

Figure78:HerewecanseeournewPivotTableisdefaultlayout
witha2decimalplacenumberformat.

DrAlexanderJTurner2007 153
BabySteps

Figure79:ByusingtheDesigntab(highlighted)wecanpick
oneofthemanybuiltinlayoutsforourtableifthedefaultisnot
quiteasvisuallyappealingaswewant.
Inlesson8welookedatthe'raw'MacroforcreatingaPivotTablejust
asExcelhadrecordedit. Forinterestssake,hereistherawMacro
whichwasrecordedforthecreationthethePivotTableinthescreen
shotshere.Thereisverylittledifference.Asusual,aMacrosetupto
runforanearlierversionofExcelwill(probably)workinExcel2007,
butweshouldnotexpectthereversetobetrue:
' Raw Macro Recording For Creating A Pivot Table In
Excel 2007
Sheets.Add
ActiveWorkbook.Worksheets("Sheet4").PivotTables("Piv
otTable1").PivotCache. _
CreatePivotTable TableDestination:="Sheet5!R3C1",
TableName:="PivotTable1" _
, DefaultVersion:=xlPivotTableVersion12
Sheets("Sheet5").Select
Cells(3, 1).Select
ActiveWorkbook.ShowPivotTableFieldList = True
With
ActiveSheet.PivotTables("PivotTable1").PivotFields("Offi
ce")
.Orientation = xlRowField
.Position = 1
End With
With
ActiveSheet.PivotTables("PivotTable1").PivotFields("Equi
pment")
.Orientation = xlColumnField
.Position = 1

154 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

End With
ActiveSheet.PivotTables("PivotTable1").AddDataField
ActiveSheet.PivotTables( _
"PivotTable1").PivotFields("Repair Time"), "Sum of
Repair Time", xlSum
With
ActiveSheet.PivotTables("PivotTable1").PivotFields("Sum
of Repair Time")
.Caption = "Average of Repair Time"
.Function = xlAverage
End With
With
ActiveSheet.PivotTables("PivotTable1").PivotFields( _
"Average of Repair Time")
.NumberFormat = "0.00"
End With
ActiveSheet.PivotTables("PivotTable1").TableStyle2 =
"PivotStyleLight19"

DrAlexanderJTurner2007 155
BabySteps

156 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Appendix B: How This Book Was Written


Ifigureditmightbeinterestingtosomereadersofthisbooktoknow
themethodologywhichwentintowritingit.Well,itmightcomeas
somethingofashock. ThisbookwaswrittenonaLinuxcomputer!
ThesoftwareIusedwasasfollows:
Kubuntu7.10(Linuxoperatingsystem)
OpenOfficeWriter2.3(Wordprocessor)
TheGIMP2.4.0rc3(Graphicsmanipulationanddrawing)
Ksnapshot0.7(Screencapture)
Qemu0.9(VirtualMachineforrunningWindowsonLinux)
Inkscape0.45(Drawingpackagefordiagrams)
KPDF(PreviewingPDFcopies)
Filezilla3.0.0(Filetransfersonandoffthevirtualmachine)
TerminalSeverClient0.148(ViewingremoteWindows
machine)
Thebasicprocessofcreatingthebookwasto:
1) Writesectionsofitlonghand.
2) Godothescriptsandscreenshotsforthesection.
3) TypeitupandstickitalltogetherintoOpenOffice.
4) Readandcorrect(lots).
5) Printout.
6) Addstufflonghandtotheprintouts.
7) Repeatasnecessary.
ThekeytogettinggoodscreenshotswasusingQemuandKsnapshot.
Bysettingthedelayintakingasnapshottoaround10seconds,itwas
possible to prepare context menus in the virtual machine and the
Ksnapshotdiditsthing.TheGIMPwasthenkindenoughtoconvert
thesnapshotsintomonochromeanddothealterationsasnecessary.
Pagesizes,andthetemplatesizesforthecoverweresetaccordingto
the guidance from lulu.com publishers. Then exporting to PDF
formatisbuiltintoOpenOffice.
Ichose BitreamCharter and BitstreamVeraSansMono asthemain
twofontsbecauseoftheirclarityandeaseofreadingonthemediaof
thescreenandpaper. Also, BitstreamCharter hasatrueandeasily
identified italic form which helps with comprehension. One final

DrAlexanderJTurner2007 157
BabySteps

goodfeatureofthefontisthatisnarrow,meaningthatBabySteps
doesnothavetokilltoomanytreestobeprinted!
IpersonallyIprefernonseriffontsforheadings,especiallywherethe
body text has serifs. Unfortunately, Bitstream Vera Sans was too
broadforheadingssoIchose Arial (boringbutreliable).AlsoArial
makesaniceheadingfontbecauseitisclearandopensoiseasily
readwithoutdominatingthepage.

Figure80:Hereisme,onmyKubuntulaptop,writingthesection
ofBabyStepsonhowBabyStepswaswritten.

158 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Appendix C: Why Script When Excel Has


Macros?
InBabyStepsIhavebeenshowinghowtowritescriptswhichopen
ExcelapplicationandmanipulateExcelspreadsheetsthroughthese
applications.Oneobviousquestionsiswhybotherwithscripts,why
notuseExcel'sbuiltinMacrosystem.
ThereareseveralreasonswhichIwilldiscussseparately.However,
theyalltendtorelatetoseparationofdataandcode.Anexcel
workbookwithMacrosattachedhasnoseparationofdataandcode;
whereeverthecodegoes,thedatagoeswithit.Thissimpleproblem
hasmyriadrepercussions.
Togooverthererepercussionsandthusthereasonsforscripting,I
shallusetheformatofformalargument.Ipresentaquestionand
answersessionwhereItrytoconvincemyselfthatscriptingisbetter.
Q:Firstoff,whybotheratall.IfIhaveaspreadsheetadIwantto
automateprocessingonit,IcanuseaMacro.
A:Considerthefollowingexample.Anautomateddataexportfroma
databasecreatesacommaseparatedvaluefileeachmorning.You
wantthatloadedintoExcelandprocessedassoonasitturnsup.
BecauseaMacroshastobeattachedtothedata,andyouhaveanew
datafileeachday,aMacroisnousetoyou.
Q:IcouldputtheMacrosintoanemptyWorkbookandloadthedata
intothateachday.
A:Yes,thatwouldwork.However,youwouldhavetoensurethat
youremptyWorkbookwasnotoverwrittenwiththenewfilled
Workbookeachtime.Thiswouldhavetoincludeensuringitdidnot
happenevenifExcelcrashedhalfwaythroughworkingetc.
Q:OK,Icandothat!HowabouttheMacrocontainingWorkbook
automaticallysavesitsselfasanewdocumentthenloadsthedata,
processesitandsavesitsselfagain.
A:Are,thatmightworkquitewell.However,thatisaverycomplex
approach.Tomakeitfunctionsinthefieldyouwillneedtorun
distributetheMacroonlybook.Eachtimeitruns,peoplewillhaveto
permititsMacrostorunbyhand,oryouaregoingtohavetodigitally
signtheWorkbookandthengetpeopletoacceptthecertificate.
Undersomeconditions,theuserswillnotevenbeabletoenablethe
MacrosbecausethesecurityleveloftheirExcelwillbelockedtohigh
andtheywilllackthepermissionstoreduceit.

DrAlexanderJTurner2007 159
BabySteps

Effectively,bythetimeyouhaveanExcelMacrobasedsolution,itis
morecomplexandunwieldythatthescriptbasedone.
Q:ButtheVBAenvironmentissoniceandeasytouseinExcel,andit
alsohastheMacroRecorder.
A:Yes,theVBAenvironmentiswelldesigned.However,a
professionalgradetexteditorlikethefreenotepad++isalsovery
good.Notepad++hassomedisadvantagesoverVBA'seditor,but
alsosomeadvantageslikeexcellentfindandreplace,tabbedediting
etc.
Theotherbigadvantagewhenitcomestoenvironmentisthatscripts
aretextfilesandtextfilesareeasiertoworkwiththatembedded
Macros.Forexample,youcanusefreetoolslikewinmergetofind
thedifferencesbetweentwocopiesofascript.Itiseasierto'cutand
paste'bitsofcodebetweenscriptsandscriptstakeupmassivelyless
spacethanExcelfiles.
WhenitcomestotheMacroRecorder,thatisaveryroughtool.The
beabletoreleaseaRecordedMacrointothefielditneedalotof
polishing.ThismeansthatoncehaveRecordedyourMacro,youwill
havetodosomeeditingonit.Giventhis,youcanjustaseasilycopy
itoverintonotepad++andeditthereasascript.
Theother'cooltool'intheExcelVBAenvironmentistheObject
Explorer.Thereisnothingtostopyoustillusingitalongwith
anythingelse(helpforexample)thatcomeswithExcel.
Q:Whataboutintellectualpropertyprotection?IcanlockMacros
withapassword.Scriptsarejusttextfiles.
A:MSproduceafreeprogram,thescriptencoder.Theoutputisat
leastassecureaspasswordprotectedExcelMacros.
One Final Thing
WithMSOffice2007,thedefaultfileformatforExcelisxlsx.This
formatdoesnotevensupportembeddedMacros.Thisindicateshow
theworldinmovingawayfromtheideaofembeddingcodeinto
documents.

160 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Appendix D: VBScript Built In Functions &


Constants
Built In Functions
VBScripthasmanybuiltinfunctions. Wehaveseensomeofthem
beingusedinBabyStepssofar. Hereisadefinitivelistofthemall
anddescriptionsofwhattheydo.Ihaveaddedintothelistthehow
oftenitismyexperiencethataparticularbuiltinfunctionisactually
usedinExcelMarcoScripting.Itiswellworthtryingtoremember
thosewhichareusedfrequently.
The Functions Enumerated And Explained
Abs(rare)
Givestheabsolutevalueofanumber. ForexampleAbs(1)gives1
whilstAbs(1)alsogivesone.
Array(rare)
GivesaVariantcontaininganarray.
Asc(sometimes)
GivestheANSIcharactercodecorrespondingtothefirstletterina
string.Inchapter6welookedathowfilesarelistsofnumbersand
thatbymakingdifferentnumbersrepresentdifferentcharacters,we
couldencodetextintofiles.Well,Ascreturnsthenumberwithwhich
acharacterwillbeencoded.
Atn(almostnever)
Gives the arctangent ofa number. I have been workingin IT for
twenty seven years and have never used this function in any
computerlanguage,includin
CBool(sometimes)
Tries to convert what we pass to it into a Boolean (TRUE/FALSE)
value.Cbool(TRUE)givestrue.
CByte(almostnever)
GivesanexpressionthathasbeenconvertedtoaVariantofsubtype
Byte. TheuseofthisisbeyondmostthingsonemightdoinExcel
MacroScripting.

DrAlexanderJTurner2007 161
BabySteps

CCur(almostnever)
GivesanexpressionthathasbeenconvertedtoaVariantofsubtype
Currency.TheuseofthisisbeyondmostthingsonemightdoinExcel
MacroScripting.
CDate(often)
TakeswhateverwepasstoitandtriestoconvertitintoaDate.For
example,CDate(10January2007)willgiveadateofthetenthof
Januarytwothousandandsevenifthecomputerissettoworkin
English.
CDbl(sometimes)
ThisishandyforconvertingStringsintonumberswheretheStrings
arebeingreadfromafileforexample.
Chr(sometimes)
This is the logical opposite of Ansi. It converts a number into a
character using the type of encoding that files use to store text.
Chr(Ansi(A))isA.
CInt(almostnever)
UseCdblorCLnginstead.
CLng(rare)
ThisishandyforconvertingStringsintonumberswheretheStrings
arebeingreadfromafileforexample. However,mostofthetime
CDbl is a better choice unless for some odd reason integer (non
decimal)arithmeticisessential.
Cos(rare)
Givesthecosineofanangle. Thisishandyifyouareworkingin
engineeringetc.
CreateObject(Allthetime).
This is one of the first things we looked at. For example
CreateObject(Excel.Application)
CSng(almostnever)
TheuseofthisisbeyondmostthingsonemightdoinExcelMacro
Scripting.

162 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

CStr(rare)
ThisconvertswhateveryoupasstoitintoaString.Onemightthink
thatwewouldusethisallthetime;howeverthe&operatoriseven
more useful and does much the same thing. For example,
CStr(1.23)isthesameas"" & 1.23.
Date(sometimes)
Givesthecurrentsystemdate.
DateAdd(often)
Usetoaddtime(days,secondsetc.)todates.Seechapter7.Touse
putDateAdd(interval,number,myDate)wheretheintervalisonefrom
thisselection:
SETTING DESCRIPTION
YYYY Year
Q Quarter
M Month
Y Day Of Year
D Day
W WeekDay
WW Week Of Year
H Hour
N Minute
S Second

SotoaddoneweektothefirstofMarchtwothousandandsixwe
couldputDateAdd(D,7,DateSerial(2006,3,1)).
DateDiff(sometimes)
Thisfunctionworksoutthedifferencebetweentwodatesandreturns
theanswerasanumberofintervals. Thoseintervalsarethesame
intervalsasareusedinDateAdd.Togetthenumberofdaysbetween
the first of March nineteen ninety seven and thecurrent date, we
couldputDateDiff(D,DateSerial(1997,3,1),Date())
DatePart(rare)
Gives the specified part of a given date. It is called like this
DatePart(interval,date).

DrAlexanderJTurner2007 163
BabySteps

DateSerial(often)
CreatesaDateforaspecifiedyear,month,andday. Seechapter7.
TocreateaDaterepresentingthefirstofMarchnineteenninetyseven
wewouldputDateSerial(1997,3,1).
DateValue(never)
UseCDateorDateSerialinstead.
Day(rare)
Givesawholenumberbetween1and31,inclusive,representingthe
currentdayofthemonth.
Exp(rare)
Givese(thebaseofnaturallogarithms)raisedtoapower.
Filter(rare)
Givesazerobasedarraycontainingsubsetofastringarraybasedon
aspecifiedfiltercriteria. Theuseofthisisbeyondtheexamplesin
thisbook.
Fix(rare)
Gives the integer portion of a number. If we put Wscript.Echo
fix(1.5)wewillgetapopupboxsaying1.
FormatCurrency(almostnever)
Givesanexpressionformattedasacurrencyvalueusingthecurrency
symboldefinedinthesystemcontrolpanel. Formattinglikethisis
betterdoneinExcelitsselfinExcelMacroScripting.
FormatDateTime(almostnever)
Givesanexpressionformattedasadateortime.Formattinglikethis
isbetterdoneinExcelitsselfinExcelMacroScripting.
FormatNumber(almostnever)
Givesanexpressionformattedasanumber. Formattinglikethisis
betterdoneinExcelitsselfinExcelMacroScripting.
FormatPercent(almostnever)
Givesanexpressionformattedasapercentage(multipliedby100)
with a trailing %character. Formattinglike this is better done in
ExcelitsselfinExcelMacroScripting.

164 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

GetObject(rare)
GivesareferencetoaCOMobjectfromafile.Thismeansthatifthe
file has an 'binding' to a COM object (like .xls files are bound to
Excel)thenwecanuseGetObjecttoloadtheCOMobjectandgetthe
COMobjecttoloadthefile.Frankly,thisisamess;pleasedonotuse
it.
Hex(rare)
Gives a String representing the hexadecimal value of a number.
Hex(32)gives20andHex(255)givesFFetc.
Hour(rare)
Givesawholenumberbetween0and23,inclusive,representingthe
currenthouroftheday.
InStr(sometimes)
Givesthepositionofthefirstoccurrenceofonestringwithinanother.
It also allows us to say where to start searching. So, Instr(,
AlexanderJulianTurner)willgive10andInstr(11,,Alexander
JulianTurner)willgive17.
InStrRev(rare)
Givesthepositionofanoccurrenceofonestringwithinanother,from
theendofstring.ItisjustlikeInStrbutitworksinreverse.
Int(almostnever)
Givestheintegerportionofanumber.UseClnginstead.
IsArray(almostnever)
GivesaBoolean(TRUE/FALSE)valuespecifyingwhetheraVariableis
anarray.
IsDate(rare)
Gives a Boolean (TRUE/FALSE) value specifying whether an
expressioncanbeconvertedtoadate.Sometimeswecangetavalue
fromaSheet'sCellanditishandytofindoutifExcelconsideredthis
valuetobeaDate.Thisbuiltinfunctionwilltellus.
IsEmpty(constant)
IfaCellorVariablehasnoteverhadanythinginit,thenthiswill
return TRUE otherwise it returns FALSE. Examples are
IsEmpty(mySheet.Cell(row,1)) or IsEmpty(myVariable). We use
IsEmptytofindemptyrowsinSheets.

DrAlexanderJTurner2007 165
BabySteps

IsNull(sometimes)
Gives a Boolean (TRUE/FALSE) value that indicates whether an
expression contains no valid data. If we work with data from
databasesthenwewillfindtheseusefulsometimes.Itisprobablya
bitbeyondthescopeofBabySteps.
IsNumeric(sometimes)
Gives a Boolean (TRUE/FALSE) value specifying whether an
expressioncanbeevaluatedasanumber.
IsObject(rare)
GivesaBooleanvaluespecifyingwhetheranexpressionreferencesa
validAutomationobject.TheonlytimeIseethisbeingusedifExcel
ScriptingMacrosisifsomethinglikeaWordDocumentisembedded
inaSheet.ThentheValueofaCellwouldactuallybeanObjectso
IsObject(myCell.Value)mightbeusedtodetectthis.
Join(sometimes)
Givesastringcreatedbyjoininganumberofsubstringscontainedin
anarray.Seechapter11.
LBound(rare)
Givesthesmallestavailablesubscriptforthespecifieddimensionof
anarray.
LCase(often)
Givesastringthathasbeenconvertedtolowercase
Left(sometimes)
Givesaspecifiednumberofcharactersfromtheleftsideofastring.
Left(DogWaffle,3)willgiveDog.
Len(sometimes)
Givesthenumberofcharactersinastringorthenumberofbytes
requiredtostoreaVariable.ThisisbyfarthemostusefulforStrings.
Forexample Len(DogWaffle) will give 10, i.e. thelength of the
String.
LoadPicture(almostnever)
Givesapictureobject.
Log(rare)
Givesthenaturallogarithmofanumber.

166 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

LTrim(rare)
Givesacopyofastringwithoutleadingspaces.Normallywejustuse
Trim().
Mid(often)
ReadchunksoutofStrings.Mid(helloworld,6)givesworldand
Mid(helloworld,6,2)giveswo.
Minute(rare)
Givesawholenumberbetween0and59,inclusive,representingthe
currentminuteofthehour.
Month(rare)
Givesawholenumberbetween1and12,inclusive,representingthe
currentmonthoftheyear.
MonthName(rare)
Givesastringspecifyingthespecifiedmonth. MonthName(1)will
giveJanuaryifthecomputerissettouseEnglish.MonthName(1)
willgiveJanvierifthecomputerissettouseFrench.
Now(often)
Gives the current date and time according to the setting of your
computer'ssystemdateandtime.
Oct(almostnever)
Givesastringrepresentingtheoctalvalueofanumber.
Replace(often)
Givesastringinwhichaspecifiedsubstringhasbeenreplacedwith
another substring a specified number of times. For example
Replace(10102007, , /) will give 10/10/2007.
Replace(10102007, , /,1,1) will give 10/102007 and
Replace(10102007,,/,4,1)willgive1010/2007.
Right(sometimes)
GivesaspecifiednumberofcharactersfromtherightsideofaString.
Rnd(sometimes)
Givesarandomnumberbetween0and1.

DrAlexanderJTurner2007 167
BabySteps

Round(sometimes)
Givesanumberroundedtoaspecifiednumberofdecimalplaces.For
exampleRound(Rnd(),2)givesatwodecimalplacerandomnumber
between0and1(e.g.0.24).
RTrim(rare)
Gives a copy of a string without trailing spaces. We tend to use
Trim()instead.
ScriptEngine(almostnever)
Returnsastringrepresentingthescriptinglanguageinuse.
ScriptEngineBuildVersion(almostnever)
Returnsthebuildversionnumberofthescriptengineinuse.
ScriptEngineMajorVersion(almostnever)
Returnsthemajorversionnumberofthescriptengineinuse.
Second(rare)
Givesawholenumberbetween0and59,inclusive,representing
thecurrentsecondoftheminute
Sgn(rare)
Givesanintegerspecifyingthesignofanumber. Ifthenumberis
negative, then this always give 1 otherwise it will give 1.
Sgn(0.0000123) gives 1 whilst Sgn(0) gives 1 and Sgn(131234)
gives1.
Sin(rare)
Givesthesineofanangle.
Space(sometimes)
Givesastringconsistingofthespecifiednumberofspaces.Space(4)
gives"".
Split(often)
Gives a zerobased, onedimensional array containing a specified
number of substrings. It is used Split(StringToSplit,String
Delimiter,MaxNumberOfPieces).myArray=Split(MyDogIsCute,
,3)willgivea3elementarraystartingwithelement0.Sofrom
thearraymyArray(0)willhavethevalueMy,myArray(1)willbe

168 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

DogandmyArray(2)willbeIsCute. IfwemissouttheMax
NumberOfPieces,itreturnsasmanypiecesaspossible.
Sqr(rare)
Givesthesquarerootofanumber.
StrComp(rare)
GivesavaluespecifyingtheresultofaStringcomparison.
String(sometimes)
Gives a repeating character string of the length specified.
String(5,.)willgive......
StrReverse(almostnever)
Gives a string in which thecharacterorderofaspecifiedstringis
reversed.StrReverse(Dog)givesgoD.
Tan(rare)
Givesthetangentofanangle.Thisisnotableonlyinthatitisused
moreoftenthanAtn!
Time(sometimes)
GivesaDatespecifyingthecurrentsystemtime.
TimeSerial(rare).
Gives a Date containing the time for a specific hour, minute, and
second.
TimeValue(rare)
GivesaDatecontainingatimeasworkedoutfromaStringetc.For
exampleTimeValue(12:00:00A.M.)orTimeValue(18:30:00).
Trim(constant)
Givesacopyofastringwithoutleadingandtrailingspaces.
TypeName(rare)
Gives a string that provides type information about a Variable or
Value.ItcanbeusefulforfindingoutwhattypeaCellValueis.
UBound(almostnever)
Givesthelargestavailablesubscriptforthespecifieddimensionofan
array.

DrAlexanderJTurner2007 169
BabySteps

UCase(sometimes)
Givesastringthathasbeenconvertedtouppercase.SeeLCase.
VarType(almostnever)
GivesavaluespecifyingthesubtypeofaVariable.
Weekday(rare)
Givesawholenumberrepresentingthecurrentdayoftheweek.
WeekdayName(rare)
Givesastringspecifyingthespecifiedcurrentdayoftheweek.
Year(rare)
Givesawholenumberrepresentingcurrenttheyear.
Built In Constants
VBScriptbuiltinconstantscanbeuseinplaceofVariablesexceptyou
canonlyreadfromthemyoucannotassigntothem.Forexamplethe
followingisOK:
dim myString
myString=vbcrlf

Butthisisnot:
dim myString
myString = "abc"
vbcrlf="abc"

TherearequiteafewVBScriptbuiltinconstants. Tobecompletely
honest,mostarenotreallymuchuseinExcelMacroScripting;they
are designed for other things using VBScript (like making web
pages). However, the String constants are quite useful so I have
describedthemhere.
Built In String Constants
Constant Value Description
vbCr Chr(13) Carriage return.
Chr(13) & Carriage returnlinefeed
VbCrLf
Chr(10) combination.
Form feed, this is never really
vbFormFeed Chr(12) used nowadays (it relates to old
style printers).
vbLf Chr(10) Line feed.
vbNewLine Chr(13) & Same as VbCrLf.

170 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Constant Value Description


Chr(10)
vbNullChar Chr(0) Character having the value 0.
Not the same as a zero-length
String having string (""), used for calling
vbNullString
value 0 external procedures and not really
in Excel Macro Scripting.
Horizontal tab, like pressing the
vbTab Chr(9)
'tab' key.
Vertical tab, this is never really
vbVerticalTab Chr(11) used nowadays (it relates to old
style printers).

DrAlexanderJTurner2007 171
BabySteps

172 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Appendix E: Named Arguments And The :=


Symbol
Why This Is Here
ByallrightsthissectionshouldbeinLesson4.Afterall,itisabout
translationofrecordedMacrosintoScriptingMacros. Theproblem
beingthatthereisalreadytoomuchinLesson4.Notonlythat,the
issuefacedhereisnotcommonlyfacedandrequiresmorefiddling
around than the rest of the translation stuff. So, I have it to an
appendix.
The Where, Why And When Of :=
:=isallaboutnamedarguments. IfweconsideraMethodthat
instructsanObjecttoboilanegg.ThisMethodwillhavearguments
thetellitabouthowtheeggshouldbeboiled:
Boiler.BoilEgg(egg,hardness,coolAfter)

Inmysillyexampletheargumentsaretheeggtobeboiled,howhard
theeggshouldbeandiftheeggshouldbecooleddownafterwards.
Ofthese,theeggargumentmustalwaysbepassedtoBoiler.BoilEgg;
however,thehardnessandcoolAfterargumentscouldhavedefault
values.Inotherwords,ifwedonotspecifythem,theBoilerjustdoes
thedefault.Forexample:
Boiler.BoilEgg(myEgg)

Thismightactuallymean,boilmyEgg,softandcoolafterwards.We
only need to specify the other arguments if we do not want the
default.So,tohardboilandcoolafterwardswecouldput:
Boiler.BoilEgg(myEgg,xlHard)

TohardboilmyEggandnotleaveittocoolwecouldput:
Boiler.BoilEgg(myEgg,xlHard,FALSE)

Theinterestingbitcomesifwewanttosoftboiltheeggbutnotnot
coolitafterwards. InExcelScriptingMacroswewouldhavetoput
somethinglikethis:
Boiler.BoilEgg(myEgg,xlSoft,FALSE)

EventhoughxlSoftisthedefault,westillhavetospecifyit. Thisis
becauseweneedtospecifythethirdargument(coolAfter)andthe

DrAlexanderJTurner2007 173
BabySteps

onlywayofdoingsoistospecifyallthreearguments.Ifmighttryto
put:
Boiler.BoilEgg(myEgg,FALSE)

Butthiswillcauseanerror.VBScriptwillnotbeabletotellthatwe
meantFALSEforcoolAfter;itwilltryandmakethehardnessFALSE
whichmakesnosenseatall.
MostofthetimeVBScript(whichisusedforScriptingMacros)and
VBA(whichisusedbytheMacroRecorder)asprettymuchidentical.
However,thereisafeatureinVBAwhichcouldhelpwiththeegg
boilingsituation. VBAsupportsnamedarguments. So,inVBAone
couldactuallyput:
Boiler.BoilEgg(egg := myEgg, coolAfter := FALSE)

Why specifies only two of the three arguments but by using the
argumentnamesstillworksjustfine.However,itisfarfromfinefor
usbecausewewanttotranslateitintoVBScript.Thisisarealworld
problem because the Macro Recorder sometimes uses named
arguments which we have to translate into the simpler argument
systemofVBScript.
How To Translate From Named Arguments
BackinLesson8welookedatcreatingPivotTableswithascript.The
rawrecordedMacrolookedsomethinglikethis:
CreatePivotTable _
( _
TableDestination:="", _
TableName:= "PivotTable1", _
DefaultVersion:=xlPivotTableVersion10 _
)

IntheabovecodewecanthattheMacroRecorderasusednamed
arguments for the CreatePivotTable Method. In general we can
assumethatithascreatedthisinthecorrectorderforusingasnon
namedargument. However,wecannotassumethatithasspecified
allthearguments.Inthiscase,simplyremovingthenameswillnot
work:
' This will fail!
CreatePivotTable _
( _
"", _
"PivotTable1", _
xlPivotTableVersion10 _

174 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

The solution is to use the Object Browser. We can Search for


CreatePivotTableintheObjectBrowser.Itwillthenshowuswhat
thefullsetofargumentsis,andwecanusethattocorrectlytranslate
therecordedMacrointoaScriptingMacrobelow:
CreatePivotTable _
( _
"", _
"PivotTable1", _
TRUE, _
xlPivotTableVersion10 _
)

Figure81:HereIhavesearchedforthedefinitionofthe
CreatePivotTableMethod.Ihavehighlightedthedefinitioninthe
picture.Wecanseethatittakes4argumentsratherthanthe3
thattheMacroRecordersupplied.

DrAlexanderJTurner2007 175
BabySteps

Errata
ThecodewhichgeneratedtheexampleforPivotTables(Lesson8and
AppendixA)incorrectlyusedthewordsreparetimewhichshould
have been repair time. Whilst the text of the book has been
corrected,someofthescreenshotsshowtheincorrectspelling.

176 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Index
256.................................................72 CDate............................................78
65536.............................................72 Cell.................................................36
ActiveWindow.Zoom......................76 Cell reference................................98
ActiveWorkbook..........................107 Cell.Formula..................................76
Add.................................12p., 16, 50 Cell.Interior...................................37
AddDataField...............................109 Cells...............................................15
ADODB........................117, 119, 123 CELLSPACING..............................90
ADODB.Connection.....................117 Chains............................................48
AdTypeBinary......................117, 123 Characters.................59p.,60, 69, 80
AdTypeText..........................117, 122 Choice.........................................126
Alert boxes.....................................41 Class..................................11, 13, 16
AllUsersDesktop............................45 CLEAR.........................................124
AllUsersPrograms.........................45 Close........................................62, 64
AllUsersStartMenu........................45 Collections...............................16, 21
AllUsersStartup.............................45 ColorIndex.....................................39
ALT...........................................124p. Colour............................................37
AND.................................127p., 129 Column area................................100
Append....................................62, 69 COM.............................................123
Arabic numeral..............................74 Comma Separated Values.............80
Argument.....................................128 Comments...............................12, 19
Arguments...................................128 CompareMode...............................49
Array............................................140 Conditional....................................67
AtEndOfStream.............................64 Const.......................................63, 82
Audit..............................................61 Constants...................37, 40,68, 111
Auto Format.................................104 Copy....................................125, 143
Autofit................................47, 64, 76 CopyFile......................................118
Automate.......................................10 Count...............................16, 50, 113
Average.....................................102p. CreateObject...........................12, 17
Background...................................71 CreatePivotTable.................107, 112
Background colour........................36 CreateShortcut..............................46
Backgrounds................................103 CRM..............................................81
BACKSPACE................................124 CSV....................................81, 82pp.
Banding.......................................113 CSV Files.......................................80
Bands...........................................113 CTRL.........................................124p.
Binary..........................................119 Customer Relationship
Binary files..................................117 Management..................................81
Binoculars......................................40 D..............................................77, 79
Black..............................................90 Data area...........99, 101p., 105, 110
Blocks.................................130, 134 Data field............................109, 112
Blog........................................9, 119 Database....................................7, 10
Booleans........................................19 Date...............................................47
Border.........................37, 87p., 90p. Date standards..............................92
Border-bottom...............................90 DateAdd.............................77, 78pp.
Border-left.....................................90 Dates.......................................74, 84
Border-right...................................90 DateSerial......................77, 79p., 84
Border-top.....................................90 Day...........................................77, 79
BREAK.........................................124 Day Of Week..................................93
Browse...........................................41 Day Of Year....................................77
Bugs...............................................41 Days...............................................80
Capitals..........................................56 Death.............................................74
CAPSLOCK..................................124 Decision......................................126
Carriage-return..............64, 65p., 68 Definition.......................................38
Case sensitive................................40 DELETE.......................................124

DrAlexanderJTurner2007 177
BabySteps

Democratisation..............................9 Folder Object................................67


Dependency tracking..................135 Folders.....................................47, 59
Desktop........45, 47p., 51, 57, 67, 83 Fonts..............................................45
Detail view.....................................94 For.................................................29
Developer Tab.....................146, 147 For Each............................28, 29, 67
Dice................................................95 For Each Loops..............................28
Dictionary................49, 51, 53, 56p. For loops.....................................27p.
Dictionary Object Methods...........50 ForAppending................................62
Dictionary Object Properties........49 Format....................59, 69, 80p., 112
Dictionary Objects.........................49 Format Cells................................103
Directory........................................59 Format Report.............................104
DisplayAlerts.........................47, 125 Formats....................................103p.
Double border...............................90 Formula...........76, 86, 113, 128, 143
DOWN..........................................124 Formulae..............23p., 81, 127, 143
Download.......................................59 ForReading.....................63, 83, 85p.
Drag and drop.................24, 51, 100 ForWriting......................60, 82p., 85
Drag-And-Drop-Scripting..............29 Function....................71, 72, 84, 128
Dragging........................................24 Functions.............................71, 92p.
Drill-down..........................94, 105p. Gaussian........................................95
Drop...............................................24 Generalise.....................................96
Dropped.........................................29 GetFolder.......................................67
Editor.............................................14 Graphical Interface.......................39
END.............................................124 Grouping........................................93
End Function..........................71, 73 H....................................................77
End If.............................................68 HELP...........................................124
End Sub.........................................71 Hexadecimal..................................39
End With.......................................20 HOME..........................................124
ENTER.........................................124 Hour...............................................77
Enter key.......................................60 HTML.......................................87pp.
Equal..............................................12 Human error..................................53
ESC..............................................124 Icon................................................24
Excel 2003...................................106 If........................................67, 68, 84
Excel 2007.....................................72 In...................................................28
Excel constant.........................36, 37 Incomplete data.............................48
Excel Macros.................................10 Indentation....................................20
Excel.Application........................12p. Index..............................................15
Exists.............................................50 Infinite Loop..................................24
Exit For..........................................84 Information....................................93
Exiting the loop.............................27 INSERT........................................124
Expert programmer......................10 Insert Tab....................................149
External data.................................97 Integer...........................................95
Favorites........................................45 Interior....................................37, 71
Favourites......................................45 Internal Macro...................32,44, 36
Field List........................................99 Interior..........................................39
Field Settings.....................102, 110 Interpret........................................75
File.................................................59 Interpreting.......................76, 84, 91
File Object.....................................67 Interpretor.....................................42
Files...............................................69 Interval..........................................77
FileSystemObject60, 62, 67, 83, 123 IsEmpty.......................26, 29, 72, 84
Fill................................................143 Item...............................................50
FillDown......................................113 Jargon............................................10
Fills........................................23, 143 Java..................................................8
Filter............................................115 JDIT..................................................8
Find bugs.......................................41 Key.................................................50
Fix.................................................95 Key Strokes.................................123
Folder.......................................67pp. Keyboard.......................................36

178 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

Keys.........................................45, 50 Ol...................................................88
Language.......................................75 Open......................................16, 117
Layout..................................100, 103 Open Source..................................31
Layout character...........................60 Opening.........................................47
LCase....................................53, 67p. OpenTextFile............62p., 82p., 85p.
LEFT............................................124 Option Explicit.....................42, 43p.
Li.............................................88, 89 OR.......................................127, 131
Line Feed.......................................64 Ordered list...................................88
Line-feed..................................65, 68 Orientation..........................108, 112
Listing............................................66 Overview........................................94
LoadFromFile..............................117 Overwrite.......................................69
Logic....................................127, 134 Overwriting...................................66
Logical programming.........126, 127 P....................................................88
Loop...............................................23 Page...............................................89
Loop tape.......................................23 Page area..............................99, 115
Loops.............................................23 Paragraph......................................88
M.............................................77, 79 Parenthesis....................................16
Macro Recorder......32p., 37, 39, 96 Paste...................................125, 143
Management Information.............93 Pattern...........................................39
Merge............................................50 PatternColorIndex.........................39
Merging.............................48, 57, 68 Performance................................140
Method....................................12, 16 PGDN...........................................124
Microsoft.........................12, 47, 117 PGUP...........................................124
Microsoft Office.............................97 Pivot Cache.................................107
Milliseconds................................140 Pivot Chart.................................96p.
Minute...........................................77 Pivot Table. 93p., 96p., 100p., 103p.,
Misinterpreting.............................92 106, 108, 113
Module...........................................35 Pivot Table ....................................98
Month......................................77, 79 Pivot Table Field..........................102
Month Of Year...............................93 Pivot Table Field List................100p.
Mouse......................................24, 36 Pivot Table Field List box.............99
Mp3.............................................117 Pivot Table tool bar.....................104
MS Word......................31, 87, 89, 90 Pivot Tables..............................105p.
MS Word 2003...............................91 PivotCache.......................107p., 111
MS Word 2007 ..............................90 PivotCache Object.......................108
My Computer.................................45 PivotCaches.........................107, 111
My Documents...............................45 PivotField....................................108
MyDocuments..........................45pp. PivotField Object........................108
N....................................................77 PivotFields........................109p., 112
Named Arguments......................173 PivotFields Collection.................108
NetHood........................................45 PivotTable Field...........................110
Network Neighborhood................45 PivotTable Object.....................108p.
New Worksheet.............................98 Podcast............................................9
New-line..................................60, 66 Position................................108, 112
New-lines.......................................31 PrintHood......................................45
Nodepad++...................................36 Programmatic interface................40
NOT..................26, 82, 85, 127, 129 Programmer..................................10
Notepad............14, 31, 60, 123, 125 Programming language.................18
Notepad++.................31, 32, 44, 60 Properties......................................21
Now...............................................47 Property...................................13, 16
NumberFormat................47, 79, 111 PRTSC..........................................124
Numeric mean.............................102 Pseudo scripts...............................11
NUMLOCK..................................124 Pseudo-random.............................95
Object......................................11, 13 Pumpkin........................................93
Object Browser......37, 38, 39pp., 44 Punctuation...................................56
Objects...........................................16 Q....................................................77

DrAlexanderJTurner2007 179
BabySteps

Quarter..........................................77 Space.............................................60
Quit................................................47 Spaces...........................................56
Quotation marks............................81 SpeciaFolders.Item.......................46
Random.........................................95 Special Folder................................46
Range............................................36 Special Folders...........45, 47, 51, 67
Raw................................................75 SpecialFolders......45, 57, 67, 83, 85
Read..............................65, 118, 122 Split...............................................84
ReadAll.................................65p., 83 SQL Database................................97
Reading...................................59, 62 Standard Directories.....................45
Readline......................................64p. Start Menu.................................45p.
ReadText......................................122 StartMenu.....................................46
Real world.....................................53 Startup...........................................46
Recent............................................45 Stream.........................................118
Recorded.....................................106 Strings...........................................18
Recorder........................................36 Strip Spaces..................................64
Recording Macros.........................32 Style....52, 55, 89p., 120, 155, 170p.
Regional configuration..................75 Sub................................................71
Remove..........................................50 Subroutines.............................71, 92
RemoveAll......................................50 Sum...........................................112p.
Replace...........................83p., 86, 92 Summarises...................................93
Report.........................................89p. Summary.......................................93
Reports..........................................87 System.FileSystemObject.............60
Researching.....................................8 TAB..............................................124
Restrictions...................................10 TABLE...............................87, 88, 90
Returns..........................................73 Tables.............................................59
Ribbon................................147, 149 Tags...............................................89
RIGHT.................................67p., 124 TBODY...........................................90
Rnd................................................95 Td..................................................87
Row area...............................99, 100 Template Files...............................46
Rule.........................................8, 130 Templates......................................46
Rules...............................8, 128, 130 Text..........................................14, 90
S....................................................77 Text Editor.....................................31
SaveToFile...................................118 Text File.......................60, 62, 69, 80
Saving............................................47 TextStream...............60, 65p., 69, 82
Scientific notation.........................85 TextStream Object.....60, 62, 65, 69,
Script translation..........................44 82
Scripting Macros...........................44 Then........................................68, 84
Scripting.FileSystemObject. .86, 118 Time...............................................47
SCROLLLOCK.............................124 Timer...........................................140
Search........................................40p. Translate........................................96
Search engine................................39 Translated.....................................36
Second...........................................77 Translating....................................37
Security.........................................10 Translation....................................36
Select.............................................36 Trim...............................................64
Selection........................................36 Typos.............................................71
Send-to..........................................46 UCase............................................73
SendKeys.............................123, 125 Ul...................................................88
SendTo...........................................46 Unordered list...............................88
Sheet..............................................15 UP................................................124
Sheet.Select................................143 Upload...........................................59
SHIFT.......................................124p. Upper case....................................72
Shortcut.........................................46 Upper-case.................................73p.
ShowPivotTableFieldList.............112 Value..............................................50
Sleep............................................123 Variable...................................13, 43
Small business.................................8 Variables.................................17, 18
Solid...............................................90 Variant.........................................119

180 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)

VBCRLF.........................................68 WScript.Shell.................45p., 57, 67


VBScript. .18, 19, 24, 42p., 53, 77p., WW................................................77
92, 119 Www.nerds-central.com..................9
View............................................39p. XlAutomatic................................38p.
Visible............................................13 XlAverage....................................109
Visual Basic...................................34 XlColumnField.....................108, 112
Visual Basic Editor........................35 XlDatabase..........................107, 111
Visual Basic For Applications........39 XlPivotTableVersion10.....107p., 112
W...................................................77 XlRowField..........................108, 112
Web browse...................................89 XlSolid..................................37, 39p.
Week Of Year.................................77 XlSum..........................................109
WeekDay........................................77 Xlsx................................................68
Wend..............................................26 XlTable2.......................................112
While.......................................26, 29 XOR..........................................82, 85
While Loops..........................27p., 29 Y....................................................77
Windows.......................13, 24p., 117 Year..........................................77, 79
Windows Explorer.........................46 YYYY........................................77, 79
Windows local................................75 Zeds.................................130, 134p.
With...............................................20 Zoom..............................................76
With statements............................20 _.....................................................26
Wizard.....................................96, 98 :=.................................................173
Work flow.........................................8 .doc................................................90
Workbook.......................................16 .vbs................................................24
Workbooks............................12p., 16 .xls.................................................68
Workbooks.Add..............................12 &....................................................28
Write...........62, 66, 83, 86, 118, 122 &gt;................................................89
WriteLine...........................64, 85, 90 &lt;.................................................89
WriteText.....................................122 <....................................................89
Writing...........................................59 =....................................................12
WScript....................................24, 29 >....................................................89
WScript.Arguments..................24pp. ~..................................................124
Wscript.Echo....................41, 42, 44 ...........................................31, 44
WScript.SendKeys.......................123

DrAlexanderJTurner2007 181

También podría gustarte