Zip all files in folder except the zip archive itself Zip all files in folder except the zip archive itself vba vba

Zip all files in folder except the zip archive itself


Rather than add all files at once, which will include the zip file you create, loop through the files with the FileSystemObject and compare their names against the zip file name before adding to the zip:

Sub AddFilesToZip()Dim fso As Object, zipFile As Object, objShell As ObjectDim fsoFolder As Object, fsoFile As ObjectDim timerStart As SingleDim folderPath As String, zipName As StringfolderPath = "C:\Users\darre\Desktop\New folder\" ' folder to zipzipName = "myzipfile.zip" ' name of the zip fileSet fso = CreateObject("Scripting.FileSystemObject") ' create an fso to loop through the filesSet zipFile = fso.CreateTextFile(folderPath & zipName) ' create the zip filezipFile.WriteLine Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)zipFile.CloseSet objShell = CreateObject("Shell.Application")Set fsoFolder = fso.GetFolder(folderPath)For Each fsoFile In fsoFolder.Files ' loop through the files...    Debug.Print fsoFile.name    If fsoFile.name <> zipName Then ' and check it's not the zip file before adding them        objShell.Namespace("" & folderPath & zipName).CopyHere fsoFile.Path        timerStart = Timer        Do While Timer < timerStart + 2            Application.StatusBar = "Zipping, please wait..."            DoEvents        Loop    End IfNext' clean upApplication.StatusBar = ""Set fsoFile = NothingSet fsoFolder = NothingSet objShell = NothingSet zipFile = NothingSet fso = NothingMsgBox "Zipped", vbInformationEnd Sub


I would create the zip file in the temporary folder and finally move it to the destination folder. Two notes worth mentioning:

1- The approach of looping until the Item counts are the same in the folder and the zip file is risky, because if the zipping fails for an individual item, it results in an infinite loop. For this reason it's preferable to loop as long as the zip file is locked by the shell.

2- I will use early binding with the Shell because late-binding the Shell32.Application seems to have issues on some installations. Add a reference to Microsoft Shell Controls and Automation

Sub compressFolder(folderToCompress As String, targetZip As String)    If Len(Dir(targetZip)) > 0 Then Kill targetZip    ' Create a temporary zip file in the temp folder    Dim tempZip As String: tempZip = Environ$("temp") & "\" & "tempzip1234.zip"   CreateObject("Scripting.FileSystemObject").CreateTextFile(tempZip, True).Write _        Chr$(80) & Chr$(75) & Chr$(5) & Chr$(6) & String(18, 0)    ' compress the folder into the temporary zip file    With New Shell ' For late binding: With CreateObject("Shell32.Application")        .Namespace(tempZip).CopyHere .Namespace(folderToCompress).Items    End With    ' Move the temp zip to target. Loop until the move succeeds. It won't    ' succeed until the zip completes because zip file is locked by the shell    On Error Resume Next    Do Until Len(Dir(targetZip)) > 0        Application.Wait Now + TimeSerial(0, 0, 1)        Name tempZip As targetZip    LoopEnd SubSub someTest()   compressFolder "C:\SO\SOZip", "C:\SO\SOZip\Test.zip"End Sub


I found zipping via VBA to be hard to control without third party tools, the below may not be a direct answer but may aid as a solution. The below is an excerpt of the code I used to generate epubs which are not much more than zip files with a different extension. This zipping section never failed in hundreds of runs.

Public Function Zip_Create(ByVal StrFilePath As String) As BooleanDim FSO         As New FileSystemObjectDim LngCounter  As LongIf Not FSO.FileExists(StrFilePath) Then    'This makes the zip file, note the FilePath also caused issues    'it should be a local file, suggest root of a drive and then use FSO    'to open it    LngCounter = FreeFile    Open StrFilePath For Output As #LngCounter    Print #LngCounter, "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)    Close #LngCounterEnd IfZip_Create = TrueEnd FunctionPublic Function Zip_Insert(ByVal StrZipFilePath As String, ByVal StrObject As String) As BooleanDim BlnYesNo            As BooleanDim LngCounter          As LongDim LngCounter2         As LongDim ObjApp              As ObjectDim ObjFldrItm          As ObjectDim ObjFldrItms         As ObjectDim StrContainer        As StringDim StrContainer2       As StringIf Procs.Global_IsAPC Then    'Create the zip if needed    If Not FSA.File_Exists(StrZipFilePath) Then        If Not Zip_Create(StrZipFilePath) Then            Exit Function        End If    End If    'Connect to the OS Shell    Set ObjApp = CreateObject("Shell.Application")        'Pause, if it has just been created the next piece of        'code may not see it yet        LngCounter2 = Round(Timer) + 1        Do Until CLng(Timer) > LngCounter2            DoEvents        Loop        'Divide the path and file        StrContainer = Right(StrObject, Len(StrObject) - InStrRev(StrObject, "\"))        StrObject = Left(StrObject, Len(StrObject) - Len(StrContainer))        'Connect to the file (via the path)        Set ObjFldrItm = ObjApp.NameSpace(CVar(StrObject)).Items.Item(CVar(StrContainer))            'Pauses needed to avoid all crashes            LngCounter2 = CLng(Timer) + 1            Do Until CLng(Timer) > LngCounter2                DoEvents            Loop            'If it is a folder then check there are items to copy (so as to not cause and error message            BlnYesNo = True            If ObjFldrItm.IsFolder Then                If ObjFldrItm.GetFolder.Items.Count = 0 Then BlnYesNo = False            End If            If BlnYesNo Then                'Take note of how many items are in the Zip file                'Place item into the Zip file                ObjApp.NameSpace(CVar(StrZipFilePath)).CopyHere ObjFldrItm                'Pause to stop crashes                LngCounter2 = CLng(Timer) + 1                Do Until CLng(Timer) > LngCounter2                    DoEvents                Loop                'Be Happy                Zip_Insert = True            End If        Set ObjFldrItm = Nothing    Set ObjApp = NothingEnd IfEnd Function