Lesson 4: Getting Tooled Up.
Recording Macros
Range( "A1:I1").Select
Translating Recorded Macros
Keyboard and Mouse to Script Translation
mySheet.Cells(1,1).Value = "Hello World "
mySheet.Range( "A1:A1 ").Value = "Hello World "
mySheet.Range( "A1:I1 ").Select
Range( "A1:I1 ").Select
With Selection.Interior
With mySheet.Range( "A1:I1 ").Interior
Translating Excel Constants
xlAutomatic = -4105
xlSolid = 1
With mySheet.Range( "A1:I1 ").Interor
.ColorIndex = 36
.Patern = xlSolid
.PatternColorIndex = xlAutomatic
End With
Finding And Removing Bugs
For row = 1 To 10
myNumber = (row * row) / (row * 0.25)
Next
For row = 1 To 10
myNumber = (row * row) / (row * 0.25)
Wscript.Echo myNumber
Next
myList = " "
for row = 1 to 10
myNumber = (row * row) / (row * 0.25)
myList = myList & myNumber & ", "
next
Wscript.Echo myList
' Create Excel Etc
...
' Populate a Spreadsheet
for row=1 to 100
value=row * 10
mySheet.Cells(row,1).Value=valeu
next i
Option Explicit
Dim mySheet,row,value
' Create Excel Etc
...
' Populate a Spreadsheet
for row=1 to 100
value=row * 10
mySheet.Cells(row,1).Value=valeu
next i
Lesson 5: Starting To Work With Data
Special Folders
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
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
Saving And Opening From Special Folders
' 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
' 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
Dictionary Objects
Dim myDictionary
Set myDictionary=CreateObject( "Scripting.Dictionary ")
myDictionary.Add "hack and slash ", "123 Fake Street "
Dim address
address = myDictionary.Item( "hack and slash ")
Wscript.Echo address
Simple Merge Script
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
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"
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 "'"
Working Merge Script
Option Explicit
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
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"
Lesson 6: Reading & Writing Files
Writing To A Text File
Option Explicit
Dim myFSO, myTSO,myShell,myName,forWriting
forWriting=2
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
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
Reading From A Text File
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 " 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 _
)
' 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
Set myFSO=CreateObject("Scripting.FileSystemObject")
Set myTS=myFSO.OpenTextFile _
( _
"myFile.txt", _
forReading, _
FALSE _
)
' Read the entire contents at once
fileContents=myTS.ReadAll()
myTS.Close
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
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
With myFile
If _
LCase(Right(.name,4))=".xls" OR _
LCase(Right(.name,5))=".xlsx" _
Then _
myList=myList & .name & vbcrlf
End IF
End With
If _
LCase(Right(.name,4))=".xls" OR _
LCase(Right(.name,5))=".xlsx" _
Then _
myList=myList & .name & vbcrlf
End IF
Lesson 7: Enhanced Data Processing
Subroutines And Functions
Sub MakeYellow(myRange)
With myRange.Interior
.ColorIndex = 6
.Pattern = 1
.PatternColorIndex = -4105
End With
End Sub
Function AddTwoNumbers(a,b)
AddTwoNumbers=a+b
End Function
Option Explicit
WScript.Echo AddTwoNumbers(2,2)
WScript.Echo AddTwoNumbers(3,4)
Function AddTwoNumbers(a,b)
AddTwoNumbers=a+b
End Function
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
' 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
' 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
Death By Dates
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
DateAdd(Interval, Number, Date)
Option Explicit
Dim myExcel,myWorkbook,mySheet,year,month,day,myDate,startDate,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 ' 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 myDate=startDate myDate=DateAdd("YYYY",myYear-2000,myDate) myDate=DateAdd("M",myMonth-1,myDate) myDate=DateAdd("D",myDay-1,myDate) myDate=DateSerial(year,month,day) Option Explicit Dim myDate myDate=DateSerial(2007,2,32) WScript.Echo myDate myDate= "1/1/2007 " myDate=DateAdd("M",2-1,myDate) myDate=DateAdd("D",32-1,myDate) WScript.Echo myDate Importing Data From CSV Files ' 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 ' 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 ' 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,"//","/") mySheet.Cells(row,1).Value=myValue Next ' 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 ' 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") 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 Creating Reports myReportFile.WriteLine("
")
")
Recording Macros
Range( "A1:I1").Select
Translating Recorded Macros
Keyboard and Mouse to Script Translation
mySheet.Cells(1,1).Value = "Hello World "
mySheet.Range( "A1:A1 ").Value = "Hello World "
mySheet.Range( "A1:I1 ").Select
Range( "A1:I1 ").Select
With Selection.Interior
With mySheet.Range( "A1:I1 ").Interior
Translating Excel Constants
xlAutomatic = -4105
xlSolid = 1
With mySheet.Range( "A1:I1 ").Interor
.ColorIndex = 36
.Patern = xlSolid
.PatternColorIndex = xlAutomatic
End With
Finding And Removing Bugs
For row = 1 To 10
myNumber = (row * row) / (row * 0.25)
Next
For row = 1 To 10
myNumber = (row * row) / (row * 0.25)
Wscript.Echo myNumber
Next
myList = " "
for row = 1 to 10
myNumber = (row * row) / (row * 0.25)
myList = myList & myNumber & ", "
next
Wscript.Echo myList
' Create Excel Etc
...
' Populate a Spreadsheet
for row=1 to 100
value=row * 10
mySheet.Cells(row,1).Value=valeu
next i
Option Explicit
Dim mySheet,row,value
' Create Excel Etc
...
' Populate a Spreadsheet
for row=1 to 100
value=row * 10
mySheet.Cells(row,1).Value=valeu
next i
Lesson 5: Starting To Work With Data
Special Folders
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
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
Saving And Opening From Special Folders
' 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
' 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
Dictionary Objects
Dim myDictionary
Set myDictionary=CreateObject( "Scripting.Dictionary ")
myDictionary.Add "hack and slash ", "123 Fake Street "
Dim address
address = myDictionary.Item( "hack and slash ")
Wscript.Echo address
Simple Merge Script
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
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"
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 "'"
Working Merge Script
Option Explicit
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
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"
Lesson 6: Reading & Writing Files
Writing To A Text File
Option Explicit
Dim myFSO, myTSO,myShell,myName,forWriting
forWriting=2
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
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
Reading From A Text File
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 " 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 _
)
' 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
Set myFSO=CreateObject("Scripting.FileSystemObject")
Set myTS=myFSO.OpenTextFile _
( _
"myFile.txt", _
forReading, _
FALSE _
)
' Read the entire contents at once
fileContents=myTS.ReadAll()
myTS.Close
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
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
With myFile
If _
LCase(Right(.name,4))=".xls" OR _
LCase(Right(.name,5))=".xlsx" _
Then _
myList=myList & .name & vbcrlf
End IF
End With
If _
LCase(Right(.name,4))=".xls" OR _
LCase(Right(.name,5))=".xlsx" _
Then _
myList=myList & .name & vbcrlf
End IF
Lesson 7: Enhanced Data Processing
Subroutines And Functions
Sub MakeYellow(myRange)
With myRange.Interior
.ColorIndex = 6
.Pattern = 1
.PatternColorIndex = -4105
End With
End Sub
Function AddTwoNumbers(a,b)
AddTwoNumbers=a+b
End Function
Option Explicit
WScript.Echo AddTwoNumbers(2,2)
WScript.Echo AddTwoNumbers(3,4)
Function AddTwoNumbers(a,b)
AddTwoNumbers=a+b
End Function
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
' 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
' 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
Death By Dates
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
DateAdd(Interval, Number, Date)
Option Explicit
Dim myExcel,myWorkbook,mySheet,year,month,day,myDate,startDate,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 ' 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 myDate=startDate myDate=DateAdd("YYYY",myYear-2000,myDate) myDate=DateAdd("M",myMonth-1,myDate) myDate=DateAdd("D",myDay-1,myDate) myDate=DateSerial(year,month,day) Option Explicit Dim myDate myDate=DateSerial(2007,2,32) WScript.Echo myDate myDate= "1/1/2007 " myDate=DateAdd("M",2-1,myDate) myDate=DateAdd("D",32-1,myDate) WScript.Echo myDate Importing Data From CSV Files ' 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 ' 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 ' 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,"//","/") mySheet.Cells(row,1).Value=myValue Next ' 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 ' 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") 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 Creating Reports myReportFile.WriteLine("
| " & row & "," & column & " | ")
No comments:
Post a Comment