Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I increment the last line in a text file; that is, if the last line is 1, indicating we’ve done one backup, I need to increment it to 2, indicating that we’ve now done a second backup.

-- TH

SpacerHey, Scripting Guy! AnswerScript Center

Hey, TH. If you’ve ever been to a carnival then you’ve no doubt been tempted by some of the sideshow games. Throw a baseball and knock down a few milk cans? Toss a dime into a glass bowl? Break a balloon with a dart, for Pete’s sake?!? How hard could that be?

Well, if you’ve never been to a carnival here’s a word to the wise: those things are actually way harder than they look. Just because something sounds like it should be easy doesn’t mean it really is easy. You’d be surprised how hard - and how expensive - it can be to toss a rubber ring onto a glass bottle.

Note. If you’re bound and determined to try these games anyway, you might find some helpful hints here. All part of the Scripting Guys customer service!

We mention all this because your question would make the perfect carnival game. After all, it sounds easy enough: you just open the text file, go to the last line, and change it. How hard could that be? Well, due to the limitations of the FileSystemObject (the scripting technology used to read and write text files) it’s actually much harder than it probably should be. That doesn’t mean this can’t be done; it just means that the script will - at first glance - look a little more complicated than you might expect. Forewarned is forearmed, you know.

In other words, the script will look like this:

Const ForReading = 1
Const ForWriting = 2

Dim arrFileLines()
i = 0

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)

Do Until objFile.AtEndOfStream
     Redim Preserve arrFileLines(i)
     arrFileLines(i) = objFile.ReadLine
     i = i + 1
Loop

objFile.Close

intLastLine = Ubound(arrFileLines)
intNumber = arrFileLines(intlastLine)
intNumber = intNumber + 1

Set objFile = objFSO.OpenTextFile("c:\scripts\test.txt", ForWriting)

For i = 0 to Ubound(arrFileLines) - 1
    objFile.WriteLine arrFileLines(i)
Next

objFile.WriteLine intNumber

objFile.Close

Before we explain how the script works, we’re assuming you have a text file that looks something like this:

A
B
C
D
E
31

Granted, it probably doesn’t look exactly like that, but the point is that you have a few lines of text (and, most likely, you aren’t sure how many lines of text) followed by the backup number. The next time you run the script you want the text file to look like this:

A
B
C
D
E
32

In other words, everything remains the same except for the backup number, which gets incremented from 31 to 32. Given the limitations of the FileSystemObject (having to open a file for reading or for writing, but not for both; being unable to go directly to the last line in a file; etc.) how do we go about doing that?

Well, we start by creating a pair of constants: ForReading and ForWriting. We’ll use these later in the script to open our text file in the appropriate mode. (As we noted a moment ago, you must open a text file for reading or for writing; you can’t perform both operations simultaneously.) We then define an array variable named arrFileLines; we’ll use this variable to store the existing contents of the text file. Why? We’ll explain that momentarily.

After opening the file C:\Scripts\Test.txt, we then use this block of code to read the file line-by-line and store the individual lines as items in the array arrFileLines:

Do Until objFile.AtEndOfStream
     Redim Preserve arrFileLines(i)
     arrFileLines(i) = objFile.ReadLine
     i = i + 1
Loop

We do this for two reasons. First, we need to be able to access - and change - the very last line in the file. The FileSystemObject doesn’t have a method that enables us to jump directly to the last line in the file; by storing the individual lines in an array, however, we cause VBScript to access the last item in the array (which will also be the last line in the file.) In addition, the FileSystemObject doesn’t allow us to change a single line in a text file; instead, we’re going to have to replace the existing contents of Test.txt with a brand-new file. That new file will include the first x lines (unchanged) in Test.txt plus a new, modified last line. By storing the existing contents in an array it will be easy for us to recall all the lines in the file except for the very last line.

That might not make a whole lot of sense right now, but it should become a bit clearer when we actually update the file. And, yes, there are a couple other ways we could have done this, but this way (believe it or not) seemed the simplest and most straightforward.

After reading the file we immediately close it, then use these three lines of code to figure out the current backup number and increment it by 1:

intLastLine = Ubound(arrFileLines)
intNumber = arrFileLines(intlastLine)
intNumber = intNumber + 1

What we’re doing here is using the Ubound function to determine the index number of the last item in the array. (Items in an array are assigned index numbers: the first item in the array is item 0, the second item in the array is item 1, and so on.) Once we know the index number for the last item (in this case it will be 5, because we have 6 items - or lines - in our array) we can then assign the value of the last item to the variable intNumber. That takes place here:

intNumber = arrFileLines(intlastLine)

The value of the last item in the array is 31; that’s because the last line in our text file is 31. We then use this line of code to add 1 to the existing value (which, in this example, will add 1 to 31):

intNumber = intNumber + 1

Make sense? All we’ve done so far is just up the backup number from 31 to 32. But, really, that’s all we need to do: we’re now ready to re-open the file C:\Scripts\Test.txt and replace the current contents with the revised contents. To do that we use this block of code to write all the existing lines except the last line to the file:

For i = 0 to Ubound(arrFileLines) - 1
    objFile.WriteLine arrFileLines(i)
Next

In other words, we’re going to write the following lines to the text file:

A
B
C
D
E

Why didn’t we write the last line? Well, remember, in our array the last line is this:

31

We want our new, incremented value (32) to be the new last line in the file. Therefore, we use this line of code to tack the value 32 (representing the current backup number) to the end of the text file:

objFile.WriteLine intNumber

We then close the file and we’re done. Our text file should now look like this, which just happens to be the way we wanted it to look:

A
B
C
D
E
32

And, yes, it’s a bit unfair that you can get a stuffed bear for tossing a dime into a bowl, yet you probably won’t get a stuffed bear for incrementing the last line in a text file. Life can be very cruel sometimes, can’t it?