A GUID-Based Temporary File Name Generator
The GetTempFileName() Windows API function has a performance problem:
Due to the algorithm used to generate file names, GetTempFileName can perform poorly when creating a large number of files with the same prefix. In such cases, it is recommended that you construct unique file names based on GUIDs.
"Construct unique file names based on GUIDs?" OK, then. Let's do that.
The Code
The GetGuidBasedTempPath
function below depends on the CreateGuid()
function I wrote about here: CreateGuid: A Reliable Way to Generate GUIDs in VBA. For convenience, I included CreateGuid()
as a private function in the code sample below.
'These Declare lines for CreateGUID() go at the very top of the code module
#If VBA7 Then
Private Declare PtrSafe Function CoCreateGuid Lib "ole32" (id As Any) As Long
#Else
Private Declare Function CoCreateGuid Lib "ole32" (id As Any) As Long
#End If
' ----------------------------------------------------------------
' Procedure : GetGuidBasedTempPath
' Date : 9/30/2022
' Author : Mike Wolfe
' Source : https://nolongerset.com/getguidbasedtemppath/
' Purpose : Returns an unused full path in the user's temp folder.
' Requires : CreateGUID() from https://nolongerset.com/createguid/
' Notes - For efficiency, the file name is based on a GUID which
' obviates the need to check for an existing file.
' Usage : ?GetGuidBasedTempPath() 'produces something like:
' C:\Users\Mike\AppData\Local\Temp\11132708-F988-E84A-ADB0-F27F133B2116.tmp
' ----------------------------------------------------------------
Function GetGuidBasedTempPath(Optional FileExt As String = "tmp") As String
'Build the destination folder with trailing slash
Dim foDest As String
foDest = Environ("TMP")
If Right(foDest, 1) <> "\" Then foDest = foDest & "\"
'Build the destination filename with extension
Dim fnDest As String
fnDest = CreateGUID() & "." & FileExt
'Combine the folder and filename to create the full path
GetGuidBasedTempPath = foDest & fnDest
End Function
' ----------------------------------------------------------------
' Procedure : CreateGUID
' Author : Dan (webmaster@1stchoiceav.com)
' Source : http://allapi.mentalis.org/apilist/CDB74B0DFA5C75B7C6AFE60D3295A96F.html
' Adapted by : Mike Wolfe
' Republished: https://nolongerset.com/createguid/
' Date : 8/5/2022
' ----------------------------------------------------------------
Private Function CreateGUID() As String
Const S_OK As Long = 0
Dim id(0 To 15) As Byte
Dim Cnt As Long, GUID As String
If CoCreateGuid(id(0)) = S_OK Then
For Cnt = 0 To 15
CreateGUID = CreateGUID & IIf(id(Cnt) < 16, "0", "") + Hex$(id(Cnt))
Next Cnt
CreateGUID = Left$(CreateGUID, 8) & "-" & _
Mid$(CreateGUID, 9, 4) & "-" & _
Mid$(CreateGUID, 13, 4) & "-" & _
Mid$(CreateGUID, 17, 4) & "-" & _
Right$(CreateGUID, 12)
Else
MsgBox "Error while creating GUID!"
End If
End Function
Benefits
- Efficient because it doesn't need to check to see if the file already exists
- Can quickly create hundreds or thousands of file names
- Avoids race condition where two processes could generate the same file name
- Default file extension of
.tmp
emphasizes temporary nature of the file
Notes About Getting the Temp Folder
There are many ways to get the user's temp folder in VBA, but they're really all just different ways of checking the value of the TMP
environment variable. Which is why I simply use Environ("TMP")
.
UPDATE [2024-04-13]: Added an explicit return type of String
to the GetGuidBasedTempPath()
function.