Search code examples
file-iovbscripttext-filesfilesystemobject

Does CreateTextFile create a race condition over OpenTextFile?


My script iterates over a large amount of data in a .xlsx file and, depending on whether or not the file exists yet, creates/opens a file with respect to the data set it's currently working on.

The code that handled determining whether the FileSystemObject should create/open the text file ended up causing a portion of the data to be repeated in the beginning of the text file. Once changed to working with a single file there were no repeats meaning the logic which handled extraction of data is fine.

Set excel = CreateObject("Excel.Application")
Set excelWorkbook = excel.Workbooks.Open("C:\data.xlsx")
Set excelSheet =  excelWorkbook.Worksheets(1)
Set fso = CreateObject("Scripting.FileSystemObject")

id = ""
sum = 0
row = 2

Do While row < 40500
    'identifier located in column c
    id = excelSheet.Range("C" & row).value

    'followed by numbers in column h
    'column h is empty on the row of an id
    Do While Len(excelSheet.Range("H" & row+1).value) > 0 
        sum = excelSheet.Range("H" & row+1).value + sum
        row = row + 1
    Loop

    WriteToText id,row,sum
    sum = 0
    row = row + 1
Loop

Sub WriteToText(x, y, z)
    fileName = "C:\file" & x & ".txt"
    If fso.FileExists(fileName) Then
        Set file = fso.OpenTextFile(fileName, 8)
        file.WriteLine x & " " & y " " & z
        file.Close
    Else  
        Set file = fso.CreateTextFile(fileName)
        file.WriteLine x & " " & y " " & z
        file.Close
    End If
End Sub

Is this a result of not freeing the memory space once the text file is created, processed, and closed?

Set file = Nothing

...causing a buffer created with CreateTextFile to persist through memory once OpenTextFile is called?


Solution

  • Without seeing where your data comes from and how you pull it there's no telling where duplicate data might come from. I don't see an inherent race condition in your code, since VBScript isn't multi-threaded in the first place. However, you can avoid any issues pertaining to the distinction whether or not the file already exists by simply using the OpenTextFile method with the third parameter set to True. That will automatically create a missing file and otherwise append to it.

    Sub WriteToText(x, y, z)
        fileName = "C:\file" & x & ".txt"
        fso.OpenTextFile(fileName, 8, True).WriteLine x & " " & y " " & z
    End Sub
    

    Setting objects to Nothing inside functions is almost never required, because VBScript usually handles that automatically by itself.