Post on 18-Dec-2015
description
HowToBecomeAnExcelGod(withoutreallytrying)
DrAlexanderJTurner2007 1
BabySteps
Dedicatedto:ProfessorI.H.Williams.
Forhistirelesssupportandguidanceofmyselfandmanyothersinoursearchforagreaterunderstandingof
nature'screation.
2 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Table o f C o nt ent s
Forward:RunTheWorldFromExcel!........................................7A Dream No Reality......................................................................7Who can benefit from Excel Scripting Macros?..............................8Where Does This Idea Come From?................................................8Why 'Baby Steps'.............................................................................9
Introduction:Whatisthisallaboutthen?...............................10Do I Need To Be A Programmer?...................................................10Using This Book............................................................................10
Lesson1:BasicConcepts.........................................................11'Take Home' Ideas from Lesson 1..................................................14
Lesson2:BuildingBlockConcepts..........................................15Collections:....................................................................................15Variables:.......................................................................................17More On Variables.........................................................................18With Statements............................................................................20'Take Home' Ideas from Lesson 2..................................................21
Lesson3:Loops.......................................................................23Finally we start to make things easier:.........................................23Drag And Drop Scripting, An Introduction....................................24For Loops.......................................................................................27For Each Loops..............................................................................28'Take Home' Ideas from Lesson 3..................................................29
Lesson4:GettingTooledUp....................................................31A Quick Note.................................................................................31Get A Good Text Editor..................................................................31Recording Macros.........................................................................32Translating Recorded Macros.......................................................36
Keyboard and Mouse to Script Translation..........................................................36Translating Excel Constants.................................................................................37
Using The Object Browser.............................................................39Finding And Removing Bugs.........................................................41'Take Home' Ideas from Lesson 4..................................................44
Lesson5:StartingToWorkWithData.....................................45Special Folders..............................................................................45
Using 'SendTo' As A Really Easy Way To Run Scripts..........................................46Saving And Opening From Special Folders..........................................................47
Merging Between Workbooks........................................................48Merging Data By Example....................................................................................48Dictionary Objects.................................................................................................49Simple Merge Script.............................................................................................51Working Merge Script...........................................................................................53Merging Multiple Columns...................................................................................56
'Take Home' Ideas from Lesson 5..................................................57Lesson6:Reading&WritingFiles...........................................59
What Is A File?..............................................................................59Writing To A Text File....................................................................60
DrAlexanderJTurner2007 3
BabySteps
Reading From A Text File..............................................................62Reading And Writing In Chunks....................................................64Listing Files...................................................................................66'Take Home' Ideas from Lesson 6..................................................69
Lesson7:EnhancedDataProcessing......................................71Subroutines And Functions...........................................................71Death By Dates..............................................................................74
DateAdd And DateSerial Fixing The Problem....................................................77Importing Data From CSV Files....................................................80Creating Reports...........................................................................87'Take Home' Ideas from Lesson 7..................................................92
Lesson8:WorkingWithPivotTables.......................................93Why Pivot Tables Are So Very Important.......................................93Understanding Pivot Tables...........................................................93
Creating An Example Pivot Table.........................................................................94Creating A Pivot Table And Scripting Macro.................................96Creating Pivot Tables Using Scripts............................................106
Looking At The Recorded Macro........................................................................106Finished Product.................................................................................................111
Tricks To Improve Data To Help Pivoting....................................113Banding Data.......................................................................................................113Cleaning Data......................................................................................................115The Page Area.....................................................................................................115
Lesson9:Working'OutsideTheBox'.....................................117Accessing Binary Files.................................................................117
Reading Data From Binary Files An Example..................................................119ADODB.Stream Summary...................................................................................121Properties............................................................................................................121Methods...............................................................................................................122
Sending Key Strokes To Other Applications Through .................123Stopping Excel From Complaining.....................................................................125
Choice And Decision Processing................................................126Yes Excel Really Is This Powerful!....................................................................126What Is Choice/Decision Processing?.................................................................126First Off Just The Very Minimum Of Logic.......................................................127TRUE & FALSE....................................................................................................127Chaining Decisions To Make Rules.....................................................................128Blocks And Zeds..................................................................................................130Putting It All Together.........................................................................................131Moving From One To Many.................................................................................136
Lesson10:SpeedingScriptsUp............................................139Cell By Cell Access Is Slow..........................................................139Bulk Data Loading With Arrays...................................................140
What Is An Array?...............................................................................................140Using Arrays Like Spread Sheets.......................................................................141
Bulk Data Transfer With Copy/Paste...........................................143Don't Forget Formulae And Fills.................................................143
AppendixA:DifferencesWithExcel2007.............................145Recording Macros:......................................................................145Showing The Developer Tab (Accessing VBA).............................146Creating A Pivot Table.................................................................149
4 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
AppendixB:HowThisBookWasWritten..............................157AppendixC:WhyScriptWhenExcelHasMacros?................159
One Final Thing...................................................................................................160
AppendixD:VBScriptBuiltInFunctions&Constants...........161Built In Functions........................................................................161
The Functions Enumerated And Explained........................................................161Built In Constants................................................................................................170Built In String Constants.....................................................................................170
AppendixE:NamedArgumentsAndThe:=Symbol.............173Why This Is Here.........................................................................173The Where, Why And When Of :=...............................................173How To Translate From Named Arguments................................174
Errata....................................................................................176Index.....................................................................................177
DrAlexanderJTurner2007 5
BabySteps
6 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Forward: Run The World From Excel!MostcalculationsandnearlyallbusinessprocessesstartoutlifeinExcel. They grown in complexity and slowly require multiplespreadsheetstofunction. Humanerrorleaksintothemixandthewholehouseofcardscomescrashingdown.
Thestandardsolutiontothischallengeistocommissionsomehugesoftwaresystemtosolveallourproblemsinonehit. Thissupersystemwillbedeliveredlateandwillbeoverbudget.Whatisworse,therequirementswillhavemovedonsincethesystemwasdesigned.Thewonderful(wonderfullyexpensive)systemwillsolveyesterday'sproblemsandnotaddresstoday's.
ThefinalactinourITtragedyiswheretheinadequaciesofthesupersystemareovercomebypreandpostprocessingall thedatawithExcel!
Alltheabovepaincansoeasilybeavoided.ItiscausedbyExcelonlygoingsofar. Excelwillprocessdata,butnotautomaticallychainprocessingstepstogether. Thislackofchainingmeansthathumansendupintheprocesses.Evenhighlytrainedhumansmakemistakesat the rate of 1 in 200 to 300 hundred repeated actions. Dataprocessingwhichinvolvesignificanthumaninteractionwillbecomeunstuckirrespectiveofhowhardthepeopletry.
A Dream No RealityHowaboutaworld where data processing andbusiness decisionstakeplace inExcelwithouthumanerror? All repetitive tasksareautomatedandefficient.Inthisworld,wewouldhavetheflexibilityand responsiveness of Excel but the reliability and speed of adedicatedsystem.
Howaboutaddingtothiswishlist?Itwouldalsobegreatifeventhemostcomplexprocesseswererenderedsosimpletosetupthatnonprogrammerscoulddoit!
This is not a fantasy world, it exists. The techniques of ExcelScriptingMacrosdoexactlywhatisrequired.Ibelievethatanentirebusiness, of thousands of people, could be run with just ExcelScriptingMacros, Excelandafree database. 90%ofallbusinessprocessescanbeperformedevenwithoutthedatabase,allweneedisExcelandScriptingMacros.
DrAlexanderJTurner2007 7
BabySteps
Who can benefit from Excel Scripting Macros? Ifyouareina smallbusinessandwanttoautomated work
flowthisisforyou.
If you are in a huge business and want to processperformancefiguresthisisforyou.
Ifyouareresearchinganimalbehaviourandneedtoanalyseresultsthisisforyou.
Ifyouwanttoapplyarulesettochoosewho,outof10000employees,getsaChristmasbonusthisisforyou.
Ifyouwanttodojustaboutanythingthatinvolvednumbers,dataorrulesthisisforyou!
Where Does This Idea Come From?Theschoolofhardkicks, thatthis where iscomesfrom. Back in20012002 I began to realise two things. Firstly, the huge andcomplex Java based systems on which I was working just neverprovidedwhatrealpeoplewanted.Secondly,nearlyallbusinesswasalreadybeingperformedinExcel.
ItwasatthistimethatIsetupacompany'JDIT'totakeadvantageoftheserealisations. WetookExceland,usingExcelmacros,pushedwaybeyondwhatmostpeoplehaddreamtof.However,despitethesuccess of the concept, it was not fully what was needed. ThesystemsJDITproducedweretoolargeandtwocomplex. Insomeways,theyturnedExcel intothehugeandcomplexsystemsIwastryingtogetawayfrom.
The key breakthrough came when considering how to directlyinterconnectExcelwithalargewebbasedsystemforwhichIwasarchitect. IrealisedthatasimplescriptcouldrunExcelandplacedataintoit.ThetechnologyIhadusedinJDITinsideExcelcouldbeputoutsideExcel inascript. However, theresult wasmuchmorepowerfulthanIhadexpectedbecauseitallowedcomplexthingstobedoneinsimpleways.Contrastthis,ifyouwould,withnormalITwheresimplethingsaredoneinextremelycomplexways!
Excel ScriptingMacros evolveda fair way fromthis initial wowmoment. The next challenge was to beat every last ounce ofcomplexityoutoftheapproach.Thatwasnotasstraightforwardasone might imagine. But, each time I found an approach whichreducedcomplexity, theprojectonwhich I wasworkingbenefitedenormously.Inshort,IknewIwasontherighttrack.
8 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Why 'Baby Steps'UptothispointIhadthoughtofExcelScriptingMacrosasagoodwaytosolveproblemsontheprojectswithwhichIwasinvolved.Astime went on, feedback from my coworkers and my blog(www.nerdscentral.com) started to indicate they had crossed awatershed. Nolongerwasthisseenasaprogrammerconceptbutmore as a business tool. The opportunity to devolve data anddecisionprocessingfromprogrammerstothepeoplewhoneededitwastantalisingtosaytheleast.
I knew that to achieve this breakthrough democratisation oftechnology,thelearningcurvewouldhavetobeveryshallow.Hence,Icameupwiththenotionof'BabySteps';AseriesoftinystepswhichtakeapersonfrombeingfamiliarwithExcelthroughtobeingabletoperformseeminglysuperhumanfeatswithit.
Havingconsideredmanyformatsfrom blog to podcast, Ifiguredafriendlybookformatwasideal.Abookthatisnotfullofpaddingtogetthepagecountup.Abookthatissmallenoughtofitinalaptopcaseandreadonthetrain.Inshort,abookwhich,likeitscontents,demandsonlytheminimumofeffortinvestedforthemaximumofbenefitgiven.
DrAlexanderJTurner2007 9
BabySteps
Introduction: What is this all about then?'Babysteps'isallaboutlearninghowtowrite'ScriptingMacros'forExcel.IamsurethatyouhaveheardofExcelMacros.ThesearelittleprogramsembeddedintoanExcelWorkbookwhich automate tasks.Scriptingmacrosareverysimilar.Thebiggestdifferenceisthattheydonot'live'insideaWorkbook.TheyaresmallfilesthatexistoutsideWorkbooksbutcanactupononeormoreWorkbooksatonce.
Because Scripting Macros are outside of the Workbooksonwhichtheyact,theyareverymuchmoreflexiblethantraditionalMacros.They also get around many of the nasty security problems andconsequentrestrictionsthatarepartandparcelofExcelMacrosthesedays.
Theconceptbehind'BabySteps'isthat,whilstyoucanbesomethingmassivelycomplexwithScriptingMacros, it is alsopossible to doamazingstuffwithmassivelysimpleScriptingMacros.Experienceinthefieldhasshownthattheapproachhashugebenefitstobusinessprocesses which are dependant on people sending data to oneanother via Excel spreadsheets. Automation via Scripting Macrosremoves'typo'mistakeswhichpeopletendtomakewhenfacedwithrepetitivetasks.Additionally,oneortwosimpleScriptingMacroscanprocessdatathatwouldtraditionallybeloadedintoa databaseandfromwhichprogrammerswouldwritereports.
Do I Need To Be A Programmer?100%no.Theideabehind'Babysteps'isthatalittleknowledgewilltakeyouaverylongway.Eachconceptistiedbackto 'realworld'examplesandeveryeffortpossiblehasbeentakentoremovejargon!
IfyoucanuseExcel,youcanunderstand'BabySteps'.
Youdonotneedtobeaprogrammer.
Thisbookwillnottrytoteachyoutobeaprogrammer.
Using This BookIfyouhaveneverdoneanycomputerscriptingatall,donotworry.Everythingyouneedtoknowiscontainedinlessons1,2and3. Ifyouareslightlyfamiliarwiththeconceptsofscripts,loopsVariablesandallthatstuff,thendiveinatlesson4.
Evenifyouareanexpertprogrammer,youmaygainalotfromthelaterchapters.Iwouldrecommendalittlespeedreadingatlesson4topickupafewtipsandthendiveinmoreatlesson5.
10 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Lesson 1: Basic ConceptsLetusstartoffconsideringdrinkingaglassofwine...
Toinstructacomputerthatapersonshoulddrinkaglassofwine,itseemslogicaltotellthecomputerthatthereisa'thing'calledpersonanda'thing'called glass-of-wine.Oncewehaveestablishedthissetup,wecansaysomethinglike:
persondrinkglassofwine
(Thehyphensareincludedjustforclarity,togroupwordstogether)
NowwehavestartedwritingaScriptingMacro. Tomakethisabitmorerealisticweneedtosplitouttheconceptof'aglassofwine'from'myglassofwine'. Afterall,youwanttoknowwhichglassyouraredrinking(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)
YoucanprobablytellthatIamgoingsomewherewiththelayoutofthese'pseudoscripts';Iamtransformingeverydayspeakintothewaywetellthecomputertodostuff.Alotofthetime,itisfairlystraightforwardtodoso.Sometimes,however,historyandconventiongetintheway.But,fornow,letuscontinuealongthispath.
Key Concept:Incomputerspeak,wecall'myglassofwine'anObjectandwecall'aglassofwine'aclassofobjects,orsimplyaClass.
Onereallynicethingaboutcomputingisthatmakingglassesofwineisverysimpleandjustaboutfree.Ifwewantanewglassofwine,wejust saysomething like 'Createmyglassofwinewhich is fromtheClassof'aglassofwine'.
Makingglassesofwineinascriptmightlooksomethinglikethis:
set my-glass-of-wine = CreateObject(a-glass-of-wine)
Butactually,hyphensbetweenwordsarenotallowedsoweput:
set myGlassOfWinne = CreateObject(aGassOfWine)
DrAlexanderJTurner2007 11
BabySteps
Thatdoesnotlookverymuchlikeeverydayspeakanylonger,butthereisaclearlineagetobeseen! Onequestionthatcomesupiswhatdoesthe'='signmean?Therearetwothings'='canmeaninScriptingMacros:
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 = yor: 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 codeabove:.drinkiswhatwecallaMethod.ItisamethodoftheObjectmySelf.Wedonothavetodefinewhat.drinkisbecauseitsdefinitioncomes alongwithClass People.Person. Because mySelf is a Objectfrom People.Person (it is a personObject) it will have theMethoddrink.
Methods(doingthings)canhaveparenthesisafterthem. Insidetheparenthesistherecanbealistofthingsthemethodistoworkwith.In the above example, the list has one element myGlass. Somemethods,likethe.AddmethodofExcel's Workbookscollection,havenoelementsinthelistandsoarefollowedbyemptyparenthesisasin.Workbooks.Add().
IhavecalledtheClassesPeople.PersonandWine.Glass,withthesedoublenames,becausethatisthe Microsoft convention. AnExcelapplication is called Excel.Application. To create one you putCreateObject(Excel.Application).
Nowwehavefiguredouthowtoget'CyberSloshed',letusseeiswecanapplythesamethingtoExcel!
set myExcel = CreateObject(Excel.Application)
12 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
This simple piece of code actually causes Windows to create acompletelynewExcelapplication.The'Variable'myExcel'refers'toit.So,laterintheprogram,whenwewanttodosomethingwithExcel,wecanuse theVariable 'myExcel' topass instructions to ournewExcelapplication.
Forourveryfirst'babystep'towardsbeinganExcelgod,wearegoingtodojustthat.WearegoingtocreateaninstanceofExcelanddosomethingwithit.Thatsomethingwillbesimplytomakeitvisible(theyarecreatedhidden)andthencreateanew,emptyWorkbookinsideit.
PleasefollowtheseinstructionstothelettertocreateyourveryfirstExcelMacroScript:
1) Open Notepad2) 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 Objectwhich is fromthe Class Excel.Application. Make thevisible Property of that Object be true. Get theWorkbooks Property ofthatObjectandrunitsMethodAdd,whichwillcauseanewWorkbooktobecreated.
DrAlexanderJTurner2007 13
BabySteps
'Take Home' Ideas from Lesson 1WehaveseenthatMacroScriptscancontrolExcelandthattheyhaveadirectlineagefromnormalEnglish.
Whenwritingscripts,werepresentreal,tangiblethings(like glassesofwineorworkbooks)asObjects.Theobject 'myGlassOfWine'comesfromtheClassofObjects'aGlassOfWine'.
MacroScriptsaresimpletextfiles.Theyareeditedusingatexteditor(likenotepad)andsavedwiththe'.vbs'fileextension.
WhenwritingaScriptingMacro,beforewedoanythingwithExcel,weneedtocreateanExcel.ApplicationObject.
14 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Lesson 2: Building Block ConceptsCollections:
Fig1:AdigramshowinghowinExcelObjectsoftenhaveCollectionsofObjectsinsidethem.ACollectionholdsalistof zeroormoreObjectsinsideitandallowsyoutofindthose Objectsbyindex(e.g.0,1,2etc.,orsometimes:1,2,3etc.)or
name(e.g.sheet1,sheet2etc.).ThisdiagramshowsyouhowtostartoffwithExcel.Applicationand'drill'allthewaydownto
individualCellsinaSheet.
DrAlexanderJTurner2007 15
BabySteps
Inlessononewelookedathowthings,likeglassesofwineandExcelApplications,arecalledObjects.'myGlassOfWine'isanObjectwhilst'aGlassOfWine'definesaClassofObjectsandsowecallitaClass.
WhenworkingwithExcel,weuseObjectsalot;also,wetendtousealotofthesameClassofObjectatonce.WhenyoucreateaWorkbookObject(likewedidwithwithoursimplescript)youseethreeSheets,notone.Indeed,anExcel.ApplicationcanhavemanyWorkbooksandeachWorkbookcanhavemanySheetsandeachSheetwillhavemanyCells.
Tohandle all these groups of Objects, Microsoft usewhat it calls'Collections'. Thesearenumbered, andsometimesnamed, lists ofObjects. A Collection is also an Object its self. For example, aCollectionofWorkbooksisanObjectfromtheClassofCollections.
All Collections have the Property .count (note, because it is aProperty,notaMethod,thereisnoparenthesis).ThistellsyouhowmanythingsareinsidetheCollection.SomespecialCollectionshaveother properties and/orMethods. For example, Excel's WorkbooksCollection has .Add() to create a new Workbook and .Open(filename)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:
CollectionsareawayofstoringzeroormoreObjectssothattheycanbeeasilyfoundandused.
Variables:Whenweput:
Set myExcel= CreateObject(Excel.Application)
Wearesaying:
SetaVariablecalledmyExceltorefertoanewlycreatedExcel.ApplicationObject.
WhenworkingwithObjectsinExcel,weoftensetVariablestorefertoObjectstomakeiteasytousetheseObjects.Hereisanexampleastowhy:
' 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,istosetaVariabletorefertotheExcel.ApplicationObject. Thisapproachhasother benefits aswell.Oncewegetthehangofitwecan:
1. Saveourselvesalotoftyping.
2. Savethecomputeralotof'thinking'.
3. Make developing (adding to, editing, improving) scriptsmucheasier.
Theseadvantagescomefromtheabilitytostore'working'informationinVariablesjustlikewemightstorenotesonpostits. Ifyouhadtowork out what the square root of 23456was each morning, youmightwellwritedowntheanswertosavetheeffort! Variablesareusedforthispurposeinscripting.
DrAlexanderJTurner2007 17
BabySteps
KeyConcept:Variablesarelike'postitnotes'forscripts;theyallowustostorethingssowedonothavetokeeprecreatingthem.
Letusseethis'postitnote'conceptinusebyaddingtoourpreviousscript:
' 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
HerewehavereusedthevalueofmySheetratherthanhavingtorefindtheSheetObject. ThisuseofaVariablehassavedusrewringandrerunningallthecodewhichfindstheSheet.
More On VariablesVariablesdonotonlyrefertoObjects;theycanholdotherstufflikeNumbers,DatesandStrings(piecesoftextarecalled'Strings'asin'astringofcharacters').
When working with Excel Scripting Macros we are using aprogramming language called VBScript. VBScript, just like anyprogramminglanguagethathasbeenaroundforawhile,hashistory;ithasaccumulatedafewoddities.Whilstthesecanbeexplained,itis
18 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
oftenbettertojustacceptthem. OneoftheseisthewayweworkwithVariablesandthingswhicharenotObjects.
Strings,Numbers,DatesandBooleans(logicalvalues,true/false)arenotObjectsin VBScript. Thisisnotforanyparticularreasonotherthanhistory. VariablesarealmostexactlythesamewhenworkingwithObjectsandnonObjects,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,BooleansandDatesaretoosimpletobethoughtofasObjectsandsoaretreateddifferently.Alsonotethatifnumberisinquotesitisusedastext.1.0isnotanumber,itisaString.
Youmighthavealsorealisedbynowthatanytextafter'onalineisconsidered to be a comment. Comments are not read by thecomputer andhavenoeffect onthescript, theyaretheretohelppeoplereadingthescripttoknowwhatisgoingon.Thecommentgoesfromthefirst'totheendoftheline.
NowwehaveareallypowerfultoolbecausewecanletaVariablereadthevaluefromaCellandwecanwriteaVariable'svalueintoaCell.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 StatementsWithstatementsareanotherwayofworkingwithObjectwhichcanbehandyasanadditiontousingVariables.ThisisespeciallysoifwewanttodoseveralthingswiththesameObjectintightsequence.Itiseasiesttoshowthisbyanexample;herewewillsetthevaluesofseveralCellsinsequence.
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(betweentheWithandEndWith)whichbegins.istreatedasaMethodorpropertyoftheObjecttowhich theWithstatementrefers.
20 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
'Take Home' Ideas from Lesson 2ObjectsarestoredinCollectionstomakethemeasiertofind.
InExcel,manyObjectshaveaCollectionofObjectsasoneoftheir Properties.Thisallowsusto'drilldown'fromatoplevelObject likeExcel.ApplicationallthewaydowntoCells.
VariablesarenamedcontainersforObjectsornonObjectdatalikeStrings,Booleans,DatesandNumbers.
VariablesareahandywayofbeingabletofindanObjectoncebutuseitseveraltimes.
AnotherhandywayofusingthesameObjectseveraltimesistouseaWithstatement.
DrAlexanderJTurner2007 21
BabySteps
22 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Lesson 3: LoopsFinally we start to make things easier:Iamnotyou,butifItrytoimaginebeingyou,rightnowIwouldbethinking:
Thisisallverywell,butIhavejusttakenanagetodosomethingIcouldhavedoin30secondswithExcelusingjustformulaeorfills.
Thatsentimentisperfectlycorrect!So,itistimetostartdoingsomestuffwhichiseasierandfastertodowithscriptsthanitisbyhand,andthatusuallyinvolvesloops.
Fig2:Thelooptapemodelofcomputerloops.Herewearemakingaloopwhichsays'Add2And2'overandoveragain,for
ever!
People do not normally like doing the same thing over and overagain;computersloveit. Loopsareawayoftellingacomputerto'loopover'thesamesetofactionsrepeatedly.Youcanthinkofloops
DrAlexanderJTurner2007 23
BabySteps
as 'looptapes'. Figure2showsgraphically howthismentalmodelworks.
Theobviousflawinthisapproachisthattheloopwillrunforever.Thisiscalledan'InfiniteLoop'. Sometimesinprogrammingthisisexactlywhatyouwant.Mostofthetime,however,wewanttolooponlyuntilsomecriterionhasbeenmet.
ForExample:
1. WorkdownColumnAoneCellatatime.
2. AddthecontentsoftheCellyouareontotoitsrownumber.
3. PuttheresultintothesamerowinColumnB.
4. StopwhenyougettoanemptyCellinColumnA.
ThatexampleisexactlythesortofthingonedoesallthetimewhenScripting Macros. The way that it automatically stops when aconditionismet(whenanemptyCellisreached)hintsatthepowerofthistechniquewhencomparedtojustusingformulaeinExcel.
Drag And Drop Scripting, An IntroductionTomakemeaningfullexamplesofhowloopscanautomaterepetitivetasks, we need to be able to load preexisting Excel Workbooks.Again,fromexperienceinthefield,thebestwaytoachievethisisvia'draganddropscripting'.
ThisapproachworksbyclickingonaWorkbookfileanddragging itover the icon for our script. Whenwe 'drop' (release the mousebutton)WindowsrunsthescriptandtellsthescriptthefilenameoftheWorkbookyoudroppedonit. Windows'tells'youthefilenamebyaspecialCollectionthatyoucanalwaysusefrominsidethescript.This is the WScript.Arguments Collection. All scripts of type'.vbs' (VBScript) have a special Object precreated that is calledWScript. YoucandolotsofhandythingswithWScript;readingthenamesoffileswhichhavebeendroppedontoascriptisjustoneofthem.
24 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Figure4:HereistheWorkbookfileBabyStepsExamples.xlsbeing'draganddropped'ontoaMacroScriptfile.Whenthescriptruns,
thefilenameoftheWorkbookwillbebeplacedintheWScript.ArgumentsCollectionofthescriptatindex0.
Now that we have figured out how to tell a script which ExcelWorkbooktoopen,weneedtoactuallyopenit.ThispieceofcodewillopenanExcelWorkbookwhichisdroppedontoit:
' 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)
Nowthat wehaveautomated the loadingof a Workbookwecanautomateitsprocessingusingascript. Aswehaveseen,eachCellObjecthasaProperty Value. There is aspecial Methodbuilt intoVBScriptwhichcantellifavalueisempty. ThisMethodiscalled
DrAlexanderJTurner2007 25
BabySteps
IsEmpty(). It producesaBooleanvalueof true or false. It isthishandymethodthatweusedtocontrolwhenourloopwillexit.Hereisanexamplescript,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_itmeansthatthelineiscontinuedonthenextline.i.e.: a = _ bIsthesameas: a = b
TotestthisscriptweshouldcreateanExcelWorkbookinwhichthefirstSheethasvaluessomethinglikethis:
Price Price $1.52.30.5
26 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
OncethescripthasrunthefirstSheetwilllooklikethis:
Price Price $1.5 3.02.3 4.60.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'exitingtheloop').
For LoopsSofarwehavelookedat While loops. Thesearethemostobviousformof loop; they say keepdoing somethingwhile something istrue.Theyarenottheonlyformofloop.AnothersortthatisquiteusefulistheForloop.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&joinsaStringtoaString,Number,BooleanorDate.
Because,inExcelscripting,wearemoreoftenthannotloopingoverdata until some data related condition is met, For loops are lesscommonthanWhileloops.However,asyoucanseefromtheaboveexample,whenyoucanusethemtheytakeuplessspaceanditismoreobviouswhatishappening.
For Each LoopsWehavejustseenhowForloopsareaneasywayofperformingasetofactionsforasetnumberofrepetitions.HowaboutifwewanttoperformanactiononeachofthecontentsofaCollection?InotherwordsForEachelementintheCollection.Happily,VBScriptprovidesuswithareallysimplewayofdoingthis.
WecouldmakethishappenusingaForloop:
For index = 1 To myWorkbook.Sheets.Count mySheet = myWorkbook.Sheets(index) mySheet.Cells(1,1).Value = Hello World Next
However,usinga ForEach ismuchsimpler(andactuallyfasterforthecomputertorun)!
For Each mySheet In myWorkbook.Sheets mySheet.Cells(1,1).vValue = Hello World Next
28 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
'Take Home' Ideas from Lesson 3Therearethreetypesofloopswhicharereallyhandy:While,ForandForEach.
TheeasiestwayofsettingupaScriptingMacrotoopenpreexistingWorkbooksistouseDragAndDropScripting.
WScriptisapreexistingObjectwhichisavailablefromall scripts.Italowsus,amongstmanyotherthings,togetthefile nameofaWorkbookwhichhasbeen'dropped'ontoourscript.
AlotofthetimewewillwanttoprocessCellsuntilwefindonormoreemptyones.ThiscanbeachievedusingthehandyIsEmpty()methodinconjunctionwithaWhileloop.
DrAlexanderJTurner2007 29
BabySteps
30 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Lesson 4: Getting Tooled Up.A Quick NoteFromhere onward in Baby Steps, there will be times when it isimpossibletofitawholelineofscriptingcodeintoalineonthepage.Tohelppreventthis beingconfusing, emptyspaceat thestartofscriptlineswillbefilledwiththisspecialcharacter. Ifyoudonoseeanyofthisgreystuffatthestartofaline,thenthelineisacontinuationfromthelineabove.
Get A Good Text EditorAswehaveseensofar,MacroScriptsarejusttextfiles.TextfilesareunlikedocumentsfromthingslikeMSWordbecausetheycontainjustcharacters;even newlines arestoredjustacharacters.WecanedittextfileswithNotepad(likewehavetillnow)butitisnotaverynicetoolfordoingthis.Beforeourscriptsgetmuchmorecomplex,itwillbemucheasierforustouseamorepowerfultool.Fortunately,therearemanyfreetexteditorsinexistence.Theyaresoimportanttotheactofprogramming,thatmanypeoplehavecreatedthem.
MyfavouritetexteditorforWindowsisNotepad++.Itsnamegivesthe game away. It is a lot like Notepad but with loads of extrafeatures like line numbering, text colouring and excellentfind/replacetools.
Notepad++is'OpenSource'andfreeofcharge.Thismeansthatyoudonothavetopayforitatallandyoucanuseitinanywayyouwantotherthanresellit.
DrAlexanderJTurner2007 31
BabySteps
Figure4:ThisisascreenshotofNotepad++beingusedtoeditoneoftheexamplefilesfromBabySteps.
Todownloadacopy,pleasegotothisURL:
http://www.sourceforge.net/project/showfiles.php?group_id=95717&package_id=102072. Alternativelyyoucandotothepackagehomepageandfollowthelinkstodownloadthebinaryexecutablefiles:
http://notepad-plus.sourceforge.net/uk/download.php
Recording MacrosItwouldbeahugetasktolearnandrememberhowtogetExceltodoeverythingviaScriptsthatwecangetittodoviatheuserinterface.Wow, that is scary. Fortunately, we do not have to learn andrememberallthat!Excelhas(asyoumaywellalreadyknow)areallyhandyfeaturecalledthe'MacroRecorder'.
The Macro Recorder records 'Internal' Macros; those being oneswhichareembedded intoaWorkbook. However, Internal MacrosandScriptingMacrosasverysimilar.WecanrecordInternalMacrosandtheneasilytranslatethemintoScriptingMacrosorintopieceswhichcanbeaddedintoScriptingMacros.
First,IwillbrieflydescriberecordingMacrosforthispurpose.Then,inthenextsection,IwillexplainhowtotranslatetheInternalMacrosintopiecesofScriptingMacro.
32 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Figure5:HowtostartrecordingaMacro.
Theusualuseofthe MacroRecorder istocreateanInternalMacrowhichwillautomateatask.Usingitrequiresthreesimplesteps:
1. Startrecording.2. Performthetask.3. Stoprecording.
Startingtherecording,inmostversionsofExcel,isdoneviatheToolsmenuoption. Figure5showsthisbeingdoneandAppendixAhasdetailsofhowtodoitinExcel2007.
Figure6:WhenchoosingaMacroname,youmayaswellusetheoneExcelsuggestsbecauseyouarenotgoingtokeeptheMacro,
itisgoingtobetranslatedintoyourScript.
DrAlexanderJTurner2007 33
BabySteps
Oncewehave requested to start theMacroRecorder, weneedtonametheMacro.BecausewearenotgoingtokeepthisMacro(justtranslateitintoaScriptingMacro)itisnotveryimportantwhatwecall it; inmostcases,thenameExcelcreatesautomaticallyisjustfine.
Oncewehavechosenanameandclicked'OK'(seefigure6)Excelstartsrecording.Eachactionwhichistaken(e.g.eachmouseclickorbutton press) will be recorded as Visual Basic code which willperformthe sameaction. For example, selecting the top RowofColumnsAtoIwillcausetheMacroRecordertorecord:
Range(A1:I1).Select
Unfortunately, we cannot actually see the recording happen as itrecords. However,itisimportanttothinkverycarefullyasweareperformingthetaskswhichwewantrecorded;everyactionwillberecorded,includingmistakes,'undos'andaccidentalCellselections!
Figure7:ThisscreenshotshowsasetofCellsbeingcolouredwhilsttheMacroRecorderisrunning.
RememberthatwearenotwantingtokeeptheMacro.WearegoingtotranslateitintopartofaMacroScript.Becauseofthis,itismucheasiertorecordaseparateshortMacroforeachstepofaprocessthantorecordahugeMacroofanentire,complexprocess.Infigure7wecanseeaMacrobeingrecorded.ThisoneconsistsofselectingsomeCellsandthencolouringthem.Thisisaboutthelevelofcomplexitywe should be aiming for in any one recording. There are some
34 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
exceptionswhereitisnotpossibletomakereallyshortrecordings.Forexample,whenwecreatePivotTablesinlesson8.
Figure8:Thisscreenshotshowshow,oncetheactionswewantrecordinghavebeencompletedandtheMacroRecorderstopped, wecanopentheVisualBasicEditorandviewtheMacrocode.
Figure9:HerewecanseehowthecodefortheMacrohasbeenwrittenintoaModuleofname'Module1'.Byexpandingthe
Modulesnodeinthelefthandtreeviewandthendoubleclickingon'Module1'wecanseetherecordedcode.
DrAlexanderJTurner2007 35
BabySteps
Translating Recorded MacrosOncewehaverecordedaMacro,wecanusecopyandpastetoputtheMacrocodeintoNodepad++(orwhatevereditorweareusing).WeareonlyinterestedinthecodebetweenthelinestartingSubandthelineEndSub. Everythingelse,includingthesetwolines,canbethrownaway.
The'raw'InternalMacrocodehastobetranslatedbeforeitwillworkasaScriptingMacro.Translatingmacrosrequiresthreefundamentalsteps:
1. The keyboard and mouse based approach of the Macroshouldbeconvertedtoasimplerformforscripting.
2. Excelconstantsneedtobetranslatedintonumbers.
3. Theresultsof1and2needtobeintegratedintothescriptsothatitoperatesonthecorrectObjects.
Keyboard and Mouse to Script TranslationInourexampleweliterallyselectedsomeCellsandthenchangedthebackgroundcolour oftheselection.ThisisexactlywhattheMacroRecorderhasrecorded.A RangeObjectisidenticaltoa CellObject(whichwehaveusedbefore)exceptitreferstooneormoreCellsatonce.
mySheet.Cells(1,1).Value = Hello World
Is100%thesameas:
mySheet.Range(A1:A1).Value = Hello World
RangeandCellObjectshaveaMethodSelect()whichsimplyselectsthemjustasthoughyouhadselectedthemonaWorksheetusingthemouse.SotheMacroRecorderhasrecordedtheCellsbeingselectedand converted this action into the code which calls the Select()MethodonaRange.
mySheet.Range(A1:I1).Select
OncetheCellshavebeenselected,theRecorderrecordsthechangestothatselection.WeshouldremovethisuseofaselectionandworkwiththeCellsdirectly:
Range(A1:I1).SelectWith Selection.Interior
Becomes:
36 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
With mySheet.Range(A1:I1).Interior
The Interior PropertyofaCellorRangeObjectisaspecial ObjectwhichExcelusesforcontrollingthe colour, borderandothervisualCellfeatures.
Translating Excel ConstantsExcel constants arenumberswhichhavespecialmeaningstoExcel.Forexamplethenumber1tellsthe Cell.Interior ObjectthataCellborder shouldbesolid.The MacroRecorder hasspecial namesfortheseconstants. Forexampleinsteadofusing1tosignifyasolidborder,itwillusexlSolid;Excel'knows'thatxlSolidactuallymeans1.Unfortunately,aScriptingMacrodoesnot'know'whatxlSolidmeanssowetotellit.
BeforewecanwritethecodeintoaScriptingMacrotodefinexlSolid,oranyExcelconstant,weneedtofindoutwhatitsvalueis.Whilstwemightbeabletorememberthevalueofoneortwoconstants,Excelhashundredsofthem. Fortunatelyforus,Excelalsohasaneasytousetoolforfindingouttheirvalues.
Figure10:TostarttheprocessoffindingthevalueofanExcel constantrightclickontheconstantintheVisualBasicviewofthe
Macro.
ExcelhasatoolcalledtheObjectBrowser.Wearegoingtolookintousingthisinmoredetailinthenextsection.UsingitforfindingthevalueofExcelconstantsisverysimpleindeed.Thatisexactlywhatwewilldonow.
DrAlexanderJTurner2007 37
BabySteps
Figure11:ThesecondsteptofindingoutthevalueofanExcel constantistoclickon'Definition'whencontextmenucomesup.
AllthatisrequiredistoviewthecodeofourrecordedMacro.Fromthisview,wecanrightclickonthetextoftheconstantitsself.Inourexample,if werightclickonthetext 'xlAutomatic' acontextmenuappears.Allweneedtodoisclickon'Definition'.
Figure12:Oncewehavechosen'Definition'fromthecontextmenuoveranExcelconstant,theObjectBrowserwillopen.InthebottompaneoftheObjectBrowser,wecanseethedefinitionoftheExcel
Constant.Inthiscase,xlAutomaticisdefinedas4105.
38 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Oncewehaveclickedon'Definition'Excelwillautomaticallystartupthe Object Browser showing details of the constant on which weclicked. Constantsareshownasthenumberinournormaldecimalnumbersystemandtheninbracketsusingthemorecomputercentrichexadecimalsystem.Weonlyneedtoconsiderthedecimalversion.
ForourScriptingMacrotousetheconstantswehavetodefinethemintheScriptingMacro. Hereisanexampleof thefinishedScriptsegment(thisisnotafullscript):
xlAutomatic = -4105xlSolid = 1With mySheet.Range(A1:I1).Interior.ColorIndex = 36.Pattern = xlSolid.PatternColorIndex = xlAutomatic End With
Using The Object BrowserIntheprevioussectionwesawhowExcelwillautomaticallylaunchtheObjectBrowserifweaskitforthedefinitionofanExcelconstant.WecanalsomanuallyopentheusetheObjectBrowser.ThiscanbeveryhandytohelpworkouthowtodosomethingwithExcel.
The Macro Recorder can be very helpful, however sometimes wewanttoworkouthowtodosomethingwhichishardorfiddlytodowiththeMacroRecorder.ThisiswheretheObjectBrowsercomesinextremelyuseful.
JustabouteverythingExcelcandofromthegraphicalinterfaceitcanalsodofromtheprogramminginterface.ThismeansthatourMacroScriptscandojustaboutanythingwewant.ToallowExceltohavesuchexcellent programmatic control, there are a huge number ofObjectsandConstantsinExcel. TheseareallknownaboutbytheObjectBrowser.TheObjectBrowsertakesitsinternaldescriptionofalltheseObjectsandConstantsanddisplaystheminahumanusableform.Itisnotonlyabrowser,butalsoasearchengine.YoucanuseittosearchforObjectsorConstantsbyname.
TogettheObjectBrowserstarted,wefirstneedtobeinVisualBasicForApplications view(seefigure13). Fromthere,wecandirectlyopentheBrowserfromthe'View'menu.
DrAlexanderJTurner2007 39
BabySteps
Figure13:WecanstarttheObjectBrowsermanuallyfromtheViewmenu.
OncewehavestartedtheBrowserwecanstartlookingaroundinsidetheprogrammaticinterfacetoExcelandsolearnalittlemoreaboutjustwhatwecandowithScriptingMacros.
Figure14:ThisscreenshotshowswhattheObjectBrowserlooks likewhenithasbeenopened.AlsohereIhavetyped
'xlsolid'(notethatthesearchisnotcasesensitive)intothesearchboxandclickedthesearchbutton(ithasbinocularsonit).InthepaneatthebottomoftheBowserwecanseetheresultofmysearch.InthemiddlepaneswecanseethatxlSolidisamember
ofConstants.
40 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Figure15:NotonlycanwesearchusingtheObjectBrowserwecanbrowsewithit.ThebottomtwopanesallowustomovearoundtheClassesandCollectionsofExcelandseewhatis
available.
Finding And Removing BugsBugsareafactoflifeinanythingcomputerbased.Basically,abugiswhenourscriptdoesnotdowhatwewantorexpect. Thereisnosimplecureorremedyforbugs.Whenweseetheeffectofabuginthewayascriptisrunningwemust'findthebug'. Thisisjustlikefixinganymachine;thefirststepistofindoutwhyitisnotworkingproperly.Fixingtheproblemalwayscomessecond.
Thebestadviceforfindinganythingistodevelopthebestpossiblewayoflookingforit.Ifwearelookingforaneedleonacarpet,wemightuseamagnet. Ifwearelookingforastar,wemightuseatelescope.So,weneedtoolstohelpusfindbugsinScriptingMacros.Fortunatelyforustherearethree:
1) Ourbrains!Wemustnotmakeanyassumptions.Thehumanbrainisamazingpowerfulattheartoffiguringoutwhatisgoingon,aslongaswedonotassumewealreadyknowwhatisgoingon.Findingbugsrequiresanopenmindandlotsofconcentration.
2) Wscript.Echo:ThisMethodpopsupalertboxesthatletusseetheinnerworkingsofascript.OnewayoflookingforabugistoimagineallthevaluesofVariablesasthescriptruns.Analternativeistoimaginewhichpiecesofcodewillberunningatwhichpointintime. Placing Wscript.Echo statementsin
DrAlexanderJTurner2007 41
BabySteps
thescriptsallowsusto'see'ifourimaginingsarecorrect.Iftheyarenot,maybethatpoints tothebug. Forexample,whatvalueswillmyNumbertakeon?
For row = 1 To 10myNumber = (row * row) / (row * 0.25)Next
Tofindout,simplyjustgetthescripttotellus:
For row = 1 To 10myNumber = (row * row) / (row * 0.25)Wscript.Echo myNumberNext
Ifhavingtenpopupboxesisjusttooannoyingthenthisisanalternative:
myList = for row = 1 to 10myNumber = (row * row) / (row * 0.25)myList = myList & myNumber & ,nextWscript.Echo myList
3) OptionExplicit:Thissasimpledirectivethatwecanputatthe top of scripts. It forces the VBScript interpretor (thethingthatactuallyrunsourScriptingMacro)tocheckthatyouhaveexplicitlyuseDimtocreateallVariablesbeforeyouusethem.
Here is anexampleof theuseof OptionExplicit tohelpdebugascript:
Inthisexample,thescriptwillproducemeaninglessresults:
' Create Excel Etc...' Populate a Spreadsheetfor row=1 to 100value=row * 10mySheet.Cells(row,1).Value=valeunext i
Amistakelikethisisalargescriptcantakeaverylongtimetospotusingjustthehumaneye.Thesolutionistodothis:
Option ExplicitDim mySheet,row,value' Create Excel Etc
42 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
...' Populate a Spreadsheetfor row=1 to 100value=row * 10mySheet.Cells(row,1).Value=valeunext i
The'OptionExplicit'atthetopofthescripttellsVBScriptnottouseaVariable unlessit hasbeencreatedwithaDimstatement. Inthiscase,wehavenotcreatedaVariablevaleusothescriptwillnotrun;insteaditwillgiveusawarningtellingusthattheVariableisnotdefinedandthelineonwhichthebugis.
DrAlexanderJTurner2007 43
BabySteps
'Take Home' Ideas from Lesson 4Fromnowonscriptswillhaveinsteadofspacesatthestartofnewlines.
Scriptsaretextandsoarebesteditedwithatexteditorlike notepad++.
Excel'sInternalMacrosandScriptingMacrosareverysimilar.Agoodapproachtofiguringouthowtodosomethingwithascript istorecordanExcelInternalMacroandthentranslateitintoaScriptingMacro.
Scripttranslationrequires3steps:
1) Covertfromthekeyboardandmousebasedapproachto asimplerdirectmethodology.
2) Translateconstants.3) Integrate.
Totranslateconstants,wecanrightclickontheminExcel'scodeviewandgotoDefinition.
FindingdefinitionsusestheObjectBrowser.TheObjectBrowserisveryusefulforlookingatotherpartsofExcel'sprogrammatic interface.
Gettingridofbugstakes3techniques:Keepingandopenmind, usingWscript.Echoto'see'whatisreallyhappeningandalwaysusingOptionExplicit.
44 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Lesson 5: Starting To Work With DataSpecial FoldersInthislessonwearegoingtodosomerealdataprocessing. TodothisweneedtofindWorkbookstoopenandfindgoodlocationstosavenewWorkbooks. Todothiswecanuse SpecialFolders. So,pleasebepatient;thissectionwillonlybebrief,thenwecanstartwithsomerealwork!
Special Folders are folders that are or at least potentially can bepresentonallWindowscomputers;theseincludetheMyDocuments,FontsandStartMenufolders.TherearetwotypesofSpecialFolders:Thosethatmapto standarddirectories andthosethatdonot.TheFavourites folder,forexample,mapstoastandarddirectory;theMyComputer folderdoesnot. WeareonlyinterestedinSpecialFolderswhichmapto(represent)realfolders.
The WScript.ShellSpecialFolders collectioncontainsthefullpathtoeachofthespecialfoldersthatwecanaccessusingScriptingMacros.Thetablebelowliststhe Keys totheCollectionandthecontentsofeachofthespecialfoldersintheSpecialFolderscollection.
Identifier Folder ContentsAllUsersDesktop Shortcuts that appear on the
desktop for all usersAllUsersStartMenu Shortcuts that appear on the Start
menu for all usersAllUsersPrograms Shortcuts that appear on the
Programs menu for all usersAllUsersStartup Shortcuts to programs that are run
on startup for all usersDesktop Shortcuts that appear on the
desktop for the current userFavorites Shortcuts saved as favorites by the
current userFonts Fonts installed on the systemMyDocuments Current users documentsNetHood Objects that appear in Network
NeighborhoodPrintHood Printer linksRecent Shortcuts to current users recently
opened documents
DrAlexanderJTurner2007 45
BabySteps
Identifier Folder ContentsSendTo 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.Shellobjectisvia the .SpeciaFolders.Item() Method. The script below finds thelocationoftheMyDocumentsspecialfolderanddisplaysittous.
Option ExplicitDim myShell, myPathSet myShell = WScript.CreateObject("WScript.Shell")myPath = myShell.SpecialFolders.Item("MyDocuments")WScript.Echo "MyDocuments='" & myPath & "'"
Using 'SendTo' As A Really Easy Way To Run ScriptsThe script below creates a shortcut to a Scripting Macro'myMacro.vbs'intheSendTospecialfolderwhichmeanswecanthenrightclickonanyWorkbookfileandsendittothatScriptingMacro.The script assumes that our Scripting Macro is inMyDocuments\ScriptingMacros.
Option ExplicitDim 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 = myScriptPathmyShortcut.Save
46 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Saving And Opening From Special FoldersWhenweuseScriptingMacrostoautomateataskwewanttheinputandoutputfilestobeplacedineasytofindplaces. Microsoft hascarefully moved us into thinking in terms of MyDocuments andDesktopetc.;thismakesspecialfolders likethisidealforautomatedscriptingtasks.
Belowaretwoexamples.ThefirstscriptcreatesanewWorkbook.ItthenplacesthecurrenttimeanddateintooneoftheSheets.Onceithas done this it saves the Workbook onto the Desktop. ItautomaticallyoverwritesanyexistingWorkbookofthesamename.Youcantellthatithasdonethisbecauseeachtimethescriptrunsthedateand/ortimewillbeupdated.
Thesecondscriptisevensimpler;itjustopenstheWorkbookthefirstscriptcreated.ThescriptrequiresnouserinterventionbecauseitcanfindtheWorkbookusingthespecialfolder'Desktop'.
' This script saves a Workbook to the DesktopOption ExplicitDim myShell, myExcel, myWorkbook, mySheet, myShell, xlNormal
' Open ExcelSet myExcel = CreateObject("Excel.Application")' Create a Workbook and set myWorkbook to refer to it' all in one goSet myWorkbook = myExcel.Workbooks.AddSet 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 WithmySheet.Columns(1).AutoFit
' Tell Excel not to complain about overwrite files and ' other things like thatmyExcel.DisplayAlerts = FALSE
' Save Excel Workbook to DesktopxlNormal = -4143Set myShell=CreateObject("WScript.Shell")myWorkbook.SaveAs myShell.SpecialFolders("Desktop") & "\AutoSaved.xls",xlNormalmyExcel.Quit
DrAlexanderJTurner2007 47
BabySteps
Figure16:ThisscreenshotisresultofthefirstofthetwoDesktopscripts.ThisistheExcelWorkbookthatIopenedfromdouble
clickingonAutoSaved.xlsonthedesktop.
' This script opens the Workbook saved by the' previous oneDim myShell, myExcel,myShellSet myExcel = CreateObject("Excel.Application")Set myShell=CreateObject("WScript.Shell")myExcel.Open myShell.SpecialFolders("Desktop") & "\AutoSaved.xls"
Merging Between WorkbooksInmyforwardItalkedaboutchainsofExcelspreadsheets.Thesearecausedwheredatapassesthroughmanystepsand/ormanyhands.Onekeyactioninsuchchainsisdatamerging. Oftenwemusttaketwoorthreedatasetsandmergethemtogether.
MovingColumnsofdataaroundbyhandcanbetedious.Searchingthrough rows of data to find matches can be soul destroying.ScriptingMacroscancometotherescue.
Merging Data By ExampleTosetthesceneofdatamerging,agoodexamplewilldonicely.Bylooking at a plausible business scenario wecan truly imagine thestepsinvolvedinmerging.
Afairlycommoncausefortheneedtomergeis 'incompletedata'.Considerthatweareinasalesdepartment.Salespeopleareouton
48 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
the road collecting orders. They report the orders back to headofficeonspreadsheetslikethis:
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 tofulfilmentfromwherethepartswillbesenttothecustomers.
Butnotice, theorder records fromthesales peopledonot tell usenough for fulfilment to dotheir job. All wehave is acustomername. Toovercomethis wehaveanother master customer list.This is the critical core Workbook from which all customerinformation is run. In this Workbook is a Sheet with customercontactdetailslikethis:
Name Id Address Tel Fax Main Contact
ABC Engineering
5 45 False Road
012345678
012345679
John
XYZ Fabrication
8 23 Nowhere Avenue
087564321
012345672
Jane
OurfirstchallengeistowriteaScriptingMacrowhichwilloutputaSheettosendtofulfilment.ThisscriptwilltakeeachorderRowfroma sales person and match the customer name against the Namecolumninthe CustomerContact Details Sheet. Theoutputof thisprocess should have the customer name, address, part number,quantityandorderdate.
Dictionary ObjectsDictionaryObjects areveryuseful things indeed. They letus justlookupvaluesratherthanhavingtogoandsearchforthem.Inthecaseofourexample, wecanstoreall thecustomeraddressesand'lookthemup'bycustomername.Thethingwearelookingupisavalueandwelookitupbyakey.HereisadescriptionofallthePropertiesandMethodsofaDictionaryObject.
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 orderswith addresseswecanstore allthecustomernamesaskeys.Foreachcustomernamekeywestoretheaddressasthevalue.
Letususeacustomercalledhackandslashwithanaddress123FakeStreet.wecanthenstoretheaddresswiththenamesasakeylikethis:
Dim myDictionarySet myDictionary=CreateObject(Scripting.Dictionary)myDictionary.Add hack and slash, 123 Fake Street
Thereverseofthisistolookupthevalueassociatedwithanalreadystored key. We can demonstrate this with a continuation of thepreviousscript.
50 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Dim addressaddress = myDictionary.Item(hack and slash)Wscript.Echo address
Theabovescriptwillecho123FakeStreet
Simple Merge ScriptTomakeamergescriptworkitwillhaveto:
1) Loadtheordersheet.
2) Loadthecustomerinformationsheet.
3) Createanewsheet.
4) Populatethenewsheetwithamergeddataset.
5) Savethenewsheet.
TomakethisniceandsimpleIwillsaythatthecustomerinformationWorkbookisalreadyonmyDesktop.Thismeansthatwecanusethe'specialfolders'wehavealreadylookedattolocatetheWorkbook.Tocontinuewiththeeasyconcept,IwillputtheoutputWorkbookontheDesktopaswell. Finally,using'draganddrop'seemsasensiblechoiceforloadingthesalesWorkbookintomyScriptingMacro.
Todothedatamergethescriptwillhavetolookupaddressesbycustomer name. So it will load a Dictionary; the keys will becustomernamesandthevalueswillbecustomeraddresses.NextthescriptwillworkitswaydownthesalesSpreadsheet(fromthesalesWorkbookthat wasdroppedonto it). ForeachRowonthesalesSpreadsheetthescriptwillreadinthecustomersnameandlookuptheaddress.
Onceithasfoundtheaddressitwillwritethename,address,orderquantityanddateintotheordersSheetintheoutputWorkbook.Thefollowingscriptperformsthissimplemerge:
Option Explicit Dim myShell,myExcel,ordersWBDim 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 DictionaryoutputSh.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"
Thisscriptproducesthisoutputwhenoneoftheordersisforabcengineering:
52 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Customer Name
Part Number
Quantity Date Address
ABC Engineering 12345 1
11-Nov-2007 45 False Road
XYZ Fabrication 7234 4
6-Nov-2007
23 Nowhere Avenue
abc engineering 12348 12
15-Nov-2007
Thisscriptisallwellandgoodbutitwillbenouseintherealworld.Forexample,thecustomerinformationWorkbookmaywellhaveacustomer names as ABC Engineering; however, a sales person(maybeinarush)mightputabcengineering(seetheabovetable).Thesalespersonmightevenputabcengineering.Howcanwedealwiththesesituations?
Thesolutionis tothis real world situationis abit ofpragmatism.Step one is to remove all unnecessary information. ABCEngineeringandabcengineeringareclearlythesamecompany.Wecanchangethescripttoignorethecaseofnamestoreflectthisreality. Thiscanbedonebymakingallthekeysinthe DictionarylowercaseviatheLCase()functionwhichisbuiltintoVBScript.Theother built in Function to use here is Trim() which removed anyunwantedspacesfromthestartorendofaString.
Dim MyStringmyString = "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 writtenabcengineeringorevenbcaengineering. Theseareexamplesofgenuinemistakesmadebythesalesperson. Ifwetrytoengineersomehypercomplexscripttoworkouttheanswerdespiteincorrectinputs,wewillendupwastingalotoftime.
The only thing really qualified to sort out a real human error isanotherhuman.SowewillcreateanextraSheetoferrorswecangothroughandfixbyhand.
Working Merge ScriptOption 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 errorRow=2
54 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
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:
1) FindaColumnwhichisinbothSheets
DrAlexanderJTurner2007 55
BabySteps
2) WorkoutwhichSheethasthemasterrecordsandwhichtheslave.InourexamplethecustomerinformationSheetwasthemaster. Donotworryifitisnotobviouswhichiswhich;youcanalwaystryitbothwaysandseewhichworksbetter.
3) FindtheColumninthemasterwhichissharedwiththeslave(e.g.customername).
4) Figureoutallthevariabilitywhichcanberemovedfromtheshared column data. Examples are capitals, spaces,punctuation.
5) Loadthedatayouwantfromthemasterintoa DictionaryObject.KeytheDictionarybythesharecolumn.
6) Foreachrowintheslave,lookupthedataintheDictionary.
7) Ifamatchingentryinthe Dictionary isfound,putthedatafromtheslaveandtheDictionaryintotheoutputSheet.
8) Ifnomatchisfound,putthedatafromtheslaveintothe'errors'Sheet.
Merging Multiple ColumnsSofarwehavelookedatmergingmultiplecolumnsfromtheslaveSheet with a single column(e.g. address) from the master. HowcouldwemergemultiplecolumnsfrombothSheets? Itwouldbequite hard to load more than one Column into the Value of akey/valuepairintheDictionaryObjectsothatisprobablynotthesolution.
Asitturnsout,thesolutionisverysimple. DoeverythingthesamewayasforthesinglemasterColumnmerge,butthistimestoretheRownumberinthemasternottheColumndata.EachtimeamatchisfoundintheDictionary,theRownumbercanbeusedtoextractthedatafortheoutputdirectlyfromthemasterSheet.
56 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
'Take Home' Ideas from Lesson 5Wscript.ShellhasaCollectioncalledSpecialFolders.
TheSpecialFolderCollectionisveryusefulindeedforfindingeasytouseplacesonthecomputer'sharddriveliketheDesktop.
DictionaryObjectsletusstorevaluesandthenlookthesevalues bykeys.
MergingdatafrommultiplespreadsheetsisaverycommonandimportantScriptingMacrotask.
Mergingcanbedonequickandeasilywiththehelpof Dictionaries.
DrAlexanderJTurner2007 57
BabySteps
58 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Lesson 6: Reading & Writing FilesWhat Is A File?Thismightseemanoddquestion. Weallusecomputerfilesallthetime.Weopenthem,savetothem,uploadthemanddownloadthem.However,dowereallyknowwhattheyare? Likemanyeverydayitems,weoftenlearntousethemwithouttrulyknowingthem.
Thankfullyfilesaresimple.Theyaresimplerthanmostpeoplewouldimagine.Afileisjustalonglistofnumbers.Eachnumbercantakeavaluebetween0and255.Thatisit!
Wemayhaveextrastuff associatedwiththefile; forexample, wemightgiveitaname.Butthenameisnotpartofthefile;thefileisjust a list of numbers. Wemight make a place where people orprogramscan find our file. Weoften call these places folders ordirectories.However,afolderisnotthefile.Neitheristhenameweusetohelplocatethefileinsidethedirectory;thatnameispartofthedirectorynotpartofthefile.Afileisjustalistofnumbers.
AllthisbegsaquestionIffilesaresoverysimple,howcomewecandosomanyamazingthingswiththem?
Theanswertothisliesinasimplechild'sgame.Oftenchildrenseektomakeaeasytousecypherbyreplacingletterswithnumbers:
a=1,b=2,c=3,d=4etc.
Towritedownabcwecouldput123.Nowthenumbershavetakenonameaning. Theyarestilljust numbers,butwehaveputspecialmeaningsontothem.Usingasimpleschemejustlikethiswecanstorewhatwethinkofastextasalistofnumbers. Yes,thatmeanswecanstoretextinacomputerfile!Thefiledoesnot'know'thatitcontainstext;itisjustalistofnumbers. However,wecaninterpretthosenumbersasrepresentingcharactersandso,tous,thefilecontainstext.
WecouldconsiderthefilewhichcontainsthedigitalversionofBabySteps. This has to hold muchmore than just text; it as images,tables and complex structure information. How, how can suchcomplexitybestoredinasimplelistofnumbersbetween0and256?This is where format comes intoplay. Format takessequencesofnumbersandgivethemmeaning.ThisisjustlikeinEnglishwritingwritinghasmoremeaningthanthesumofitindividualletters.
DrAlexanderJTurner2007 59
BabySteps
Fileformatscanbecomeverycomplexindeed. InBabyStepswearenotinterestedincomplexsowewillkeepthingssimple. It isamazingwhatcanbedonesimplywithfilesandExcel.
Formostoftherestifthisbookwewillonlydealwithwhatarecalledtextfiles.Thesehavedirecttranslationsofthenumbersinthefileto characters,punctuationandafewlayoutrules. Textfilesaresosimplethattheycanbereadandconvertedtohumanreadablefromusing Notepad. Notepad (or Notepad++) reads in each numberfromthetextfileandconvertsitintoahumanreadablecharacteretc.
Whenwewrite text in Notepad, every so oftenwewill press the'enterkey'todroptothenextline.Yearsagosomecomputerscalledthe enter key 'newline'. This is because in text file editors likeNotepad,pressingitproducesaspeciallayoutcharacterwhichmeansstartanewline. This isanexampleofoneof thehandfull ofspeciallayoutcharactersintextfiles.
Newline characters are stored in the text file as the number 13.Spaceisanotherexamplewithitsnumberbeing32.Thenumeral1isrepresentedbythenumber48andtheletterAby64.So123Ais4849503264.
Whenweworkwithtextfileswetendtoletthecomputerprogramsweworkwithdoallthetranslationbetweenthefiles'numbersandthetextweareworkingwith.Inotherwords,wereadtextfilesintoStringsandwewriteStringstotextfiles. Towardstheendofthebook I discuss what are called binary files. These are where theactualnumbersarereadandwrittendirectly.WealmostneverneedtodirectlyhandlebinaryfilesinExcelMacroScripting.
Writing To A Text FileMacroScriptingusesaspecialObjecttoaccessfilesdirectly.Towritetoafilewecreatea System.FileSystemObject. WegivethisObjectinformationonwheretoputthefilethatwewillbewriting,itsnameandifitshouldreplaceanypreexistingfilewiththesamenameinthesamefolder.FromthisinformationtheFileSystemObjectcreatesaTextStreamObject.ItisthisTextStreamObjectwhichactuallydoesthewriting.
TheexamplebelowwillcreateatextfileontheDesktopadinsidethatfileitwillplacetwolinesoftext.
Option ExplicitDim myFSO, myTSO,myShell,myName,forWritingforWriting=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 NamemyName=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 existSet 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 TextStreammyTSO.Close
Figure17:ThisiswhatNotepadshowsifweuseittoopenthefile example.txtcreatedbyourfilefilewritingscript.
Thepreviousscriptwillalwaysreplaceanexistingfilewithanewone.Thismeansthatit'secretly'performsthefollowingsteps:
1) CheckifafileofthatFolder\Nameexists.
2) Ifitdoes,deleteitpermanently.
3) CreateanewfilewiththesameFolder\Name.
4) Writetothenewfile.
Whathappensifwejustwanttoaddtothefileratherthanreplaceit?Thisisnotsoodd;wemightwanttowritealineatheendofasfileeverytimeascriptisruntoactasanaudittrailforexample.Todo
DrAlexanderJTurner2007 61
BabySteps
thiswetelltheFileSystemObjectto'Append'ratherthan'Write'whenweopenthefileandcreatetheTextStreamObject.
Thisscriptaddsanewlinegivingthedateandtimethescriptwasruntoafilescript.log.ThefilewillbecreatedontheDesktopthefirst time the script runs. After that, a line will beadded to theexistingfileeachtimeitisrunagain.
Option ExplicitDim myFSO, myTSO, myShell, myName, forWriting, forAppendingforWriting = 2forAppending = 8Set 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 NamemyName=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 existSet myTSO = myFSO.OpenTextFile(myName,forAppending,true)myTSO.WriteLine("Script Run: " & now)myTSO.Close
Iranthisscriptafewtimeandhereisthecontentsoftheresultingfile:
Script Run: 18/10/2007 13:03:31Script Run: 18/10/2007 13:04:30Script Run: 18/10/2007 13:04:31Script Run: 18/10/2007 13:04:42Script Run: 18/10/2007 13:04:44Script Run: 18/10/2007 13:04:45Script Run: 18/10/2007 13:04:46
Reading From A Text FileNowthatwecanwritefiles,howabout reading them? Firstofall,whywouldwewanttoreadone?ExcelcanreadExcelfilessowhydoweneedadifferentwayofreadingfiles?
Sometimesweneedtouseascripttoreadafile,workwithwhatithasreadandthenputtheresultinExcel. Forexample,wemighthaveafilethathasaformatelikethis:
BeginUser = AJT
62 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
Date = 01/07/2007Action = logonEndBeginUser = FFDate = 01/08/2007Action = logoffEnd
InthisfileweknowthatalinewhichsaysBeginstartsablockoflines and a line which says End ends that block. This extrainformationaboutthemeaningofthecontentsofthefileiswhatwecallformat.ThisformatisnotonethatExcelunderstandssowehavetoloadthedataintoaspreadsheetusingascript:
Option Explicit Dim myFSO,myExcel,myWorkbook,mySheet,myTS,row,line,keyWord,datum
' Another way of defining Variables which we will not' change is to use the Const keywordConst 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 ' FileSystemObjectSet 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 ChunksMostofthetimereadingandwritinglinesisjustfine.WhenweputmyTextStream.Writeline(Fred) the actual file gets two extranumberswrittentoitinadditiontothoserepresentingFred.ThesearecalledCarriageReturnandLineFeed. Theygettheirnamesfromtypewriters.Theyrepresenttheactionofreturningthecarriage(holdingthepaper)totheleftandfeedingthroughthepaperbyonelineheight.Nowadaysthesenumbersjustrepresenttheendofalineandthebeginningofthenext.
64 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
WhenweusemyTextStream.ReadLine()wegetbackthenextlineoftext froma file. Just like a human reading a page of text, theTextStreamObjectremembersits'place'inthetextandsocangiveusthenextlinefromthat.
Thereareafewotherthingswhichwemightwanttodowithatextfile.Thesearenotusefulquiteasoftenasworkingwithonelineatatime,buttheycomeinhandyeverysooften:
1) ReadanentirefileatoncetoaString.
2) WriteanentirefileatoncefromString.
3) Readanexactnumberofcharactersfromafile.
4) WriteaStringtoafilewithoutaddingonthecarriagereturnlinefeed.
Whilstthesearefourdifferentthingsweneedonlylearntwonewtechniquestobeabletodothem! WhenweopenaTextStreamforreadingwecancallcallmyTextStream.Read(count)wherecount isanumber. This is just like Readline in that the TextStreamObjectremembers its 'place' in the file and reads on from that place.However, rather then readinga whole line, it readsexactly countcharactersandreturnstheseasaString.Anotherslightdifferenceisthatwhenitencounters carriagereturn or linefeed,itwillactuallyput these characters in the returned String. Also note that if itreachestheendofthefilebeforeithasreadcountcharactersitjustgivesusthecharactersithasreadsofar.
InExcelMacroScriptingIhaveyettocomeacrossaneedtoreadcount characters from a file except in one common special case.SometimewewanttoreadanentirefileintoaStringallinonego.Again,tomakethissupereasy,wecanjustmissoutcountaltogether.InthebelowscriptweopenaTextStreamreadingfromafileandcallReadAll()whichislikeusingRead(count)wherecountisthenumberof characters left whichcanberead. This slurps the entire file'scontentsintoaStringforus(thisisnotanentirescript,justapieceofone):
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.ByusingtheMethodWrite(myString)onaTextStreamObject(whichwasopenedtowriteorappend)wesimplywriteoutthenumbersforthecharactersintheStringtothefile. Write(myString)doesnotadd carriagereturn ornewline.Ifwecallitmanytimeswecanaddtothefilesonechunkatatime.IfweopenaTextStreamforoverwriting(notappending)and we call Write(myString) just the once before closing theTextStream,wehavewrittentheentirecontentsofthefilefromourString.
Hereisascriptwhichreadsanentiretextfileinonego. It thenreplaceseveryinstanceof/with//. Finally,itwritesanewfilewiththeupdatedcontents.Wewillseeinlesson7(thenext)whywemightwanttodothis(again,thisisjustasubsectionofascript):
Set myFSO=CreateObject("Scripting.FileSystemObject") Set myTS=myFSO.OpenTextFile _( _"myFile.txt", _forReading, _FALSE _) ' Read the entire contents at oncefileContents=myTS.ReadAll()myTS.Close
' Do the replace of / with //fileContents=Replace(fileContents,"/","//")
' Now write out our new file contentsSet myTS=myFSO.OpenTextFile _( _"myFile.txt", _forWriting, _TRUE _) ' Write the entire contents at oncemyTS.Write(fileContents)myTS.Close
Listing FilesI was considering not including this section. Then I suddenlyrememberedaveryimportantsortofapplicationforlistingfiles.Letus imaginethatwehavewrittenascriptwhichtakesa 'dragand
66 DrAlexanderJTurner2007
HowToBecomeAnExcelGod(withoutreallytrying)
drop'WorkbookandmergesthedatawithasecondWorkbook.ThisscriptthencreatesanoutputWorkbookcontainingthemergeddata(see lesson5). Whilst this is fineforone, twooreventen inputWorkbooks, how about if there were 100 or even 1000. ThealternativetospendingthebalanceofournaturallifedragginganddroppingistogetourscripttofindtheinputWorkbookfilesitsself.
Thenextscriptdoesexactlythat.Itisabit'dense'inthatitdoesalotwithonlyafewlinesofcode.Ratherthanstuffitfullofcomments,Ihavediscussedhowitworksafterthescript.
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
ThefirstthingthattheabovescriptdoesistouseSpecialFolderstofindthepathtotheDesktop.NextitcallstheGetFolder(path)methodofaFileSystemObjectObject.ThismethodreturnsaFolderObject.BecausethepathwepasstotheGetFoldermethodisthepathtotheGetFoldermethod,wegetaFolderObejctrepresentingtheDesktop.
FolderObjectsareusedtoallowustodothingswithFolders.Inthiscase,wewanttofindallthefilesintheFolder.TheFolderObjecthasaCollectioninitcalled'Files'whichcontainsaFileObjectrepresentingeachoftheFilesintheFolder.ThisbeingaColl