Jump to content
wraithdu

ZIP UDF (zipfldr.dll library)

Recommended Posts

wraithdu

Here is the rewritten version of this UDF. See my comments HERE.

Please test the shit out of this thing. It was a major headache, and I want to make sure I didn't miss something. Thanks!

Update 2013/05/28

- Fixed missing @error return in _Zip_ItemExists

- Clarified a few @error return value meanings

- Added an additional check and @error code to _Zip_DeleteItem

- Clarified some of the header notes, esp regarding behavior on XP

Update 2011/12/08
- Fixed recursion in ListAll function

Update 2011/12/07
- Fixed recursion error in CountAll function
- updated objects to conform to new COM syntax (parenthesis req'd for methods)

Update 2011/07/01
- Reverted change to AddItem function
- **Adding an item directly to a sub folder on XP will FAIL

Update 2011/06/30
- Fixed traversing namespaces on Windows XP
- Added note that overwrite fails on XP

Update 2011/01/13
- Fixed bug adding items to a subfolder that doesn't exist yet

Update 2010/08/27
- Fixed bug with trailing 's

Update 2010/07/16
- Better error reporting in _Zip_AddItem function

Update 2010/07/02
- Added credits.
- Added trancexxx's suggestion to remove any left over temporary directories.
- Replaced some StringTrim calls with cleaner StringRegExpReplace calls.
- Moved a few repetitive lines of code into functions.
- Moved a few repetitive lines of code into functions.
- Moved a few repetitive lines of code into functions.

===========================

_Zip.au3

Edited by wraithdu
  • Like 4

Share this post


Link to post
Share on other sites
Melba23

wraithdu,

OK, I am suffering for you! :party:

So far it all looks good except for _Zip_CountAll which returns nothing at all - whereas _Zip_ListAll gives an array listing the files (correctly). :mellow:

Thanks for the effort - it will be an excellent addition to the library. :P

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
wraithdu

_Zip_CountAll also returns an array...

Share this post


Link to post
Share on other sites
trancexx

Finally what appears to be a sensible zip UDF.

You are giving far too much credits to torels_ character.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
wraithdu

Thanks. I suppose I should credit PsaltyDS for his original work as well.

Share this post


Link to post
Share on other sites
Melba23

wraithdu.

_Zip_CountAll also returns an array...

:blink:

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
trancexx

Thanks. I suppose I should credit PsaltyDS for his original work as well.

Yes, probably.

If I may say regarding zip thematic. Flags for CopyHere method aren't working prior win7. Also on those systems there would be temporary folder created by the zip engine inside @TempDir. If not deleted possible suffocation could happen because free disk space would/will be eaten in case of repeated unzipings. As far as I remember there are threads on general help forum with issues caused by that (I replied to at least one).

Another thing is available depth of the NameSpace method to reach within zip file to grab the file to extract. I don't think it's very deep. Try it, you'll see.

edit: I had this:

Func _ExtractZip($sZipFile, $sFolderStructure, $sFile, $sDestinationFolder)
    Local $i
    Do
        $i += 1
        $sTempZipFolder = @TempDir & "\Temporary Directory " & $i & " for " & StringRegExpReplace($sZipFile, ".*\\", "")
    Until Not FileExists($sTempZipFolder) ; this folder will be created during extraction
    Local $oShell = ObjCreate("Shell.Application")
    If Not IsObj($oShell) Then Return SetError(1)
    Local $oDestinationFolder = $oShell.NameSpace($sDestinationFolder)
    If Not IsObj($oDestinationFolder) Then Return SetError(2) ; unavailable destionation location
    Local $oOriginFolder = $oShell.NameSpace($sZipFile & "\" & $sFolderStructure) ; FolderStructure is overstatement because of the available depth
    If Not IsObj($oOriginFolder) Then Return SetError(3) ; unavailable location
    ;Local $oOriginFile = $oOriginFolder.Items.Item($sFile)
    Local $oOriginFile = $oOriginFolder.ParseName($sFile)
    If Not IsObj($oOriginFile) Then Return SetError(4) ; no such file in ZIP file
    ; copy content of origin to destination
    $oDestinationFolder.CopyHere($oOriginFile, 4) ; 4 means "do not display a progress dialog box"
    DirRemove($sTempZipFolder, 1) ; clean temp dir if needed
    Return 1 ; All OK!
EndFunc
Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
Melba23

trancexx,

Flags for CopyHere method aren't working prior win7

I wondered why I occasionally got a Progress dialog (Vista - flag 4).

But the other flags I have tried (1, 8, 16) seem to work consistently.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
wraithdu

Also on those systems there would be temporary folder created by the zip engine inside @TempDir.

Is that folder name scheme consistent on all OS's prior to Win7 (Win2k+ anyway)? I'm surprised it's not just a random directory name.

Edited by wraithdu

Share this post


Link to post
Share on other sites
trancexx

Is that folder name scheme consistent on all OS's prior to Win7 (Win2k+ anyway)? I'm surprised it's not just a random directory name.

Well it is on systems, configurations I tested on.

...can't be sure for the rest of the world though :blink:


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
Adrive

hi,

can you add

Func _Zip_AddFolderContents($hZipFile, $hFolder, $flag = 1)

i have some problem here http://www.autoitscript.com/forum/index.php?showtopic=116473

Share this post


Link to post
Share on other sites
Melba23

Adrive,

I have already suggested to you that is important to read UDF headers - in this one you find:

;   The zipfldr library does not allow overwriting or merging of folders in a ZIP archive.  That means
;   if you try to add a folder and a folder with that name already exists, it will simply fail.  Period.
;   As such, I've disabled that functionality.  Suffer.
;
;   I've also removed the AddFolderContents function.  There are too many pitfalls with that scenario, not
;   the least of which being the above restriction.  Suffer.

So you are not going to get that function added. :blink:

M23

P.S. And I know I did not follow my own advice about reading headers carefully earlier in this thread - just do as I say, not as I do! ;)


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
wraithdu

Thanks Melba23 :blink:

As a reward... a small update. See first post ;)

Share this post


Link to post
Share on other sites
Adrive

Ok Thanks for information

i have used this UDF and got an error

#include "zip2.au3"
$zip = _Zip_Create("E:\song.zip", 0)
_Zip_AddItem($zip, "E:\VDOS", "c:\", 1028)

Error

>"C:\Program Files\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "D:\AutoIt\zip_test.au3"

D:\AutoIt\zip.au3 (116) : ==> Badly formated variable or macro.:

Local $

Local ^ ERROR

>Exit code: 1 Time: 3.217

Lines @ 116, 153, 185, 267, 314, 345, 544, 623, 676, 701 are unassigned variables.

Local $

Share this post


Link to post
Share on other sites
wraithdu

You are misusing the function. The sDestDir function is a subdirectory within the zip file in which to place the item. For example "dir1\dir2". I'll try to make that more clear and catch the error.

Edited by wraithdu

Share this post


Link to post
Share on other sites
Adrive

Please provide an example to use it, i was trying to add a folder into zip file.

Share this post


Link to post
Share on other sites
wraithdu

Wait, what UDF are you using? Mine has no such error.

Edited by wraithdu

Share this post


Link to post
Share on other sites
Adrive

i am nt mixing anything, here is what i have

#include-once
; ------------------------------------------------------------------------------
;
; Description:      ZIP Functions.
; Author:           wraithdu, torels
; Date:             2010-07-01
;
; NOTES:
;   This UDF attempts to register a COM error handler if one does not exist.  This is done to prevent
;   any fatal COM errors.  If you have implemented your own COM error handler, this WILL NOT replace it.
;
;   The Shell object does not have a delete method, so some workarounds have been implemented.  The
;   options are either an interactive method (as in right-click -> Delete) or a slower method (slow for
;   large files).  The interactive method is the main function, while the slow method is in the internal
;   function section near the bottom.
;
;   When adding a file item to a ZIP archive, if the file exists and the overwrite flag is set, the slower
;   internal delete method is used.  This is the only way to make this step non-interactive.  It will be
;   slow for large files.  Suffer.
;
;   The zipfldr library does not allow overwriting or merging of folders in a ZIP archive.  That means
;   if you try to add a folder and a folder with that name already exists, it will simply fail.  Period.
;   As such, I've disabled that functionality.  Suffer.
;
;   I've also removed the AddFolderContents function.  There are too many pitfalls with that scenario, not
;   the least of which being the above restriction.  Suffer.
;
;   Did I mention Suffer?  Please do.  I did.  The zipfldr library can suck it.
;
; ------------------------------------------------------------------------------

;;; Start COM error Handler
;=====
; if a COM error handler does not already exist, assign one
If Not ObjEvent("AutoIt.Error") Then
    ; MUST assign this to a variable
    Global Const $_Zip_COMErrorHandler = ObjEvent("AutoIt.Error", "_Zip_COMErrorFunc")
EndIf


; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_AddItem
; Description....:  Add a file or folder to a ZIP archive
; Syntax.........:  _Zip_AddItem($sZipFile, $sFileName[, $sDestDir = ""[, $iFlag = 21]])
; Parameters.....:  $sZipFile   - Full path to ZIP file
;                   $sFileName  - Full path to item to add
;                   $sDestDir   - [Optional] Destination subdirectory in which to place the item
;                   $iFlag      - [Optional] File copy flags (Default = 1+4+16)
;                               |   1 - Overwrite destination file if it exists
;                               |   4 - No progress box
;                               |   8 - Rename the file if a file of the same name already exists
;                               |  16 - Respond "Yes to All" for any dialog that is displayed
;                               |  64 - Preserve undo information, if possible
;                               | 256 - Display a progress dialog box but do not show the file names
;                               | 512 - Do not confirm the creation of a new directory if the operation requires one to be created
;                               |1024 - Do not display a user interface if an error occurs
;                               |2048 - Version 4.71. Do not copy the security attributes of the file
;                               |4096 - Only operate in the local directory, don't operate recursively into subdirectories
;                               |8192 - Version 5.0. Do not copy connected files as a group, only copy the specified files
;
; Return values..:  Success     - 1
;                   Failure     - 0 and sets @error
;                               | 1 - zipfldr.dll does not exist
;                               | 2 - Library not installed
;                               | 3 - Not a full path
;                               | 4 - ZIP file does not exist
;                               | 5 - Destination is not a full path
;                               | 6 - Destination item exists and is a folder (see Remarks)
;                               | 7 - Destination item exists and overwrite flag not set
;                               | 8 - Destination item exists and failed to overwrite
;                               | 9 - Failed to create internal directory structure
;
; Author.........:  wraithdu
; Modified.......:
; Remarks........:  Destination folders CANNOT be overwritten or merged.  They must be manually deleted first.
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_AddItem($sZipFile, $sFileName, $sDestDir = "", $iFlag = 21)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sFileName) Then Return SetError(3, 0, 0)
    If Not FileExists($sFileName) Then Return SetError(4, 0, 0)
    If _IsFullPath($sDestDir) Then Return SetError(5, 0, 0)
    _Zip_StringStripSlash($sDestDir)
    Local $sNameOnly = StringTrimLeft($sFileName, StringInStr($sFileName, "\", 0, -1))
    ; process overwrite flag
    Local $iOverwrite = 0
    If BitAND($iFlag, 1) Then
        $iOverwrite = 1
        $iFlag -= 1
    EndIf
    ; check for overwrite, if target exists...
    Local $sTest = $sZipFile
    If $sDestDir <> "" Then $sTest = $sZipFile & "\" & $sDestDir
    If _Zip_ItemExists($sTest, $sNameOnly) Then
        If @extended Then
            ; get out, cannot overwrite folders... AT ALL
            Return SetError(6, 0, 0)
        Else
            If $iOverwrite Then
                _Zip_InternalDelete($sTest, $sNameOnly)
                If @error Then Return SetError(8, 0, 0)
            Else
                Return SetError(7, 0, 0)
            EndIf
        EndIf
    EndIf
    Local $sTempFile = ""
    If $sDestDir <> "" Then
        $sTempFile = _Zip_AddPath($sZipFile, $sDestDir)
        If @error Then Return SetError(9, 0, 0)
        $sZipFile &= "\" & $sDestDir
    EndIf
    Local $oApp = ObjCreate("Shell.Application")
    ;Local $
    ; copy the file
    $oNS.CopyHere($sFileName, $iFlag)
    Do
        Sleep(250)
        $oItem = $oNS.ParseName($sNameOnly)
    Until IsObj($oItem)
    If $sTempFile <> "" Then _Zip_InternalDelete($sZipFile, $sTempFile)
    Return 1
EndFunc   ;==>_Zip_AddItem

Func _Zip_COMErrorFunc()
EndFunc   ;==>_Zip_COMErrorFunc

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_Count
; Description....:  Count items in the root of a ZIP archive (not recursive)
; Syntax.........:  _Zip_Count($sZipFile)
; Parameters.....:  $sZipFile   - Full path to ZIP file
;
; Return values..:  Success     - Item count
;                   Failure     - 0 and sets @error
;                               | 1 - zipfldr.dll does not exist
;                               | 2 - Library not installed
;                               | 3 - Not a full path
;                               | 4 - ZIP file does not exist
; Author.........:  wraithdu, torels
; Modified.......:
; Remarks........:
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_Count($sZipFile)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Then Return SetError(3, 0, 0)
    Local $oApp = ObjCreate("Shell.Application")
    ;Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    Return $oNS.Items.Count
EndFunc   ;==>_Zip_Count

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_CountAll
; Description....:  Recursively count items contained in a ZIP archive
; Syntax.........:  _Zip_CountAll($sZipFile)
; Parameters.....:  $sZipFile       - Full path to ZIP file
;                   $iFileCount     - [Internal]
;                   $iFolderCount   - [Internal]
;
; Return values..:  Success         - Array with file and folder count
;                                   [0] - File count
;                                   [1] - Folder count
;                   Failure         - 0 and sets @error
;                                   | 1 - zipfldr.dll does not exist
;                                   | 2 - Library not installed
;                                   | 3 - Not a full path
;                                   | 4 - ZIP file does not exist
; Author.........:  wraithdu
; Modified.......:
; Remarks........:
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_CountAll($sZipFile, $iFileCount = 0, $iFolderCount = 0)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Then Return SetError(3, 0, 0)
    Local $oApp = ObjCreate("Shell.Application")
    ;Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    Local $oItems = $oNS.Items, $aCount
    For $oItem In $oItems
        If $oItem.IsFolder Then
            ; folder, recurse
            $iFolderCount += 1
            $aCount = _Zip_CountAll($sZipFile & "\" & $oItem.Name, $iFileCount, $iFolderCount)
            $iFileCount = $aCount[0]
            $iFolderCount = $aCount[1]
        Else
            $iFileCount += 1
        EndIf
    Next
    Dim $aCount[2] = [$iFileCount, $iFolderCount]
    Return $aCount
EndFunc   ;==>_Zip_CountAll

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_Create
; Description....:  Create empty ZIP archive
; Syntax.........:  _Zip_Create($sFileName[, $iOverwrite = 0])
; Parameters.....:  $sFileName  - Name of new ZIP file
;                   $iOverwrite - [Optional] Overwrite flag (Default = 0)
;                               | 0 - Do not overwrite the file if it exists
;                               | 1 - Overwrite the file if it exists
;
; Return values..:  Success     - Name of the new file
;                   Failure     - 0 and sets @error
;                               | 1 - A file with that name already exists and $iOverwrite flag is not set
;                               | 2 - Failed to create new file
; Author.........:  wraithdu, torels
; Modified.......:
; Remarks........:
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_Create($sFileName, $iOverwrite = 0)
    If FileExists($sFileName) And Not $iOverwrite Then Return SetError(1, 0, 0)
    Local $hFp = FileOpen($sFileName, 2 + 8 + 16)
    If $hFp = -1 Then Return SetError(2, 0, 0)
    FileWrite($hFp, Binary("0x504B0506000000000000000000000000000000000000"))
    FileClose($hFp)
    Return $sFileName
EndFunc   ;==>_Zip_Create

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_DeleteItem
; Description....:  Delete a file or folder from a ZIP archive
; Syntax.........:  _Zip_DeleteItem($sZipFile, $sFileName)
; Parameters.....:  $sZipFile   - Full path to the ZIP file
;                   $sFileName  - Name of the item in the ZIP file
;
; Return values..:  Success     - 1
;                   Failure     - 0 and sets @error
;                               | 1 - zipfldr.dll does not exist
;                               | 2 - Library not installed
;                               | 3 - Not a full path
;                               | 4 - ZIP file does not exist
;                               | 5 - Item not found in ZIP file
;                               | 6 - Failed to get list of verbs
;                               | 7 - Failed to delete item
; Author.........:  wraithdu
; Modified.......:
; Remarks........:  $sFileName may be a path to an item from the root of the ZIP archive.
;                   For example, some ZIP file 'test.zip' has a subpath 'some\dir\file.ext'.  Do not include a leading or trailing '\'.
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_DeleteItem($sZipFile, $sFileName)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Then Return SetError(3, 0, 0)
    ; parse filename
    _Zip_StringStripSlash($sFileName)
    If StringInStr($sFileName, "\") Then
        ; subdirectory, parse out path and filename
        $sZipFile &= "\" & StringLeft($sFileName, StringInStr($sFileName, "\", 0, -1) - 1)
        $sFileName = StringTrimLeft($sFileName, StringInStr($sFileName, "\", 0, -1))
    EndIf
    Local $oApp = ObjCreate("Shell.Application")
    ;Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    Local $oFolderItem = $oNS.ParseName($sFileName)
    If Not IsObj($oFolderItem) Then Return SetError(5, 0, 0)
    Local $oVerbs = $oFolderItem.Verbs
    If Not IsObj($oVerbs) Then Return SetError(6, 0, 0)
    For $oVerb In $oVerbs
        If StringReplace($oVerb.Name, "&", "") = "delete" Then
            $oVerb.DoIt
            Return 1
        EndIf
    Next
    Return SetError(7, 0, 0)
EndFunc   ;==>_Zip_DeleteItem

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_ItemExists
; Description....:  Determines if an item exists in a ZIP file
; Syntax.........:  _Zip_ItemExists($sZipFile, $sItem)
; Parameters.....:  $sZipFile   - Full path to ZIP file
;                   $sItem      - Name of item
;
; Return values..:  Success     - 1
;                               @extended is set to 1 if the item is a folder, 0 if a file
;                   Failure     - 0 and sets @error
;                               | 1 - zipfldr.dll does not exist
;                               | 2 - Library not installed
;                               | 3 - Not a full path
;                               | 4 - ZIP file does not exist
; Author.........:  wraithdu
; Modified.......:
; Remarks........:  $sItem may be a path to an item from the root of the ZIP archive.
;                   For example, some ZIP file 'test.zip' has a subpath 'some\dir\file.ext'.  Do not include a leading or trailing '\'.
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_ItemExists($sZipFile, $sItem)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Then Return SetError(3, 0, 0)
    _Zip_StringStripSlash($sItem)
    If StringInStr($sItem, "\") Then
        ; subfolder
        $sZipFile &= "\" & StringLeft($sItem, StringInStr($sItem, "\", 0, -1) - 1)
        $sItem = StringTrimLeft($sItem, StringInStr($sItem, "\", 0, -1))
    EndIf
    Local $oApp = ObjCreate("Shell.Application")
    ;Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    Local $oItem = $oNS.ParseName($sItem)
    ; @extended holds whether item is a file (0) or folder (1)
    If IsObj($oItem) Then Return SetExtended(Number($oItem.IsFolder), 1)
    Return 0
EndFunc   ;==>_Zip_ItemExists

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_List
; Description....:  List items in the root of a ZIP archive (not recursive)
; Syntax.........:  _Zip_List($sZipFile)
; Parameters.....:  $sZipFile   - Full path to ZIP file
;
; Return values..:  Success     - Array of items
;                   Failure     - 0 and sets @error
;                               | 1 - zipfldr.dll does not exist
;                               | 2 - Library not installed
;                               | 3 - Not a full path
;                               | 4 - ZIP file does not exist
; Author.........:  wraithdu, torels
; Modified.......:
; Remarks........:  Item count is returned in array[0].
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_List($sZipFile)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Then Return SetError(3, 0, 0)
    Local $oApp = ObjCreate("Shell.Application")
    ;Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    Local $aArray[1] = [0]
    Local $oList = $oNS.Items
    For $oItem In $oList
        $aArray[0] += 1
        ReDim $aArray[$aArray[0] + 1]
        $aArray[$aArray[0]] = $oItem.Name
    Next
    Return $aArray
EndFunc   ;==>_Zip_List

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_ListAll
; Description....:  List all files inside a ZIP archive
; Syntax.........:  _Zip_ListAll($sZipFile[, $iFullPath = 1])
; Parameters.....:  $sZipFile   - Full path to ZIP file
;                   $iFullPath  - [Optional] Path flag (Default = 1)
;                               | 0 - Return file names only
;                               | 1 - Return full paths of files from the archive root
;
; Return values..:  Success     - Array of file names / paths
;                   Failure     - 0 and sets @error
;                               | 1 - zipfldr.dll does not exist
;                               | 2 - Library not installed
;                               | 3 - Not a full path
;                               | 4 - ZIP file or subfolder does not exist
; Author.........:  wraithdu
; Modified.......:
; Remarks........:  File count is returned in array[0], does not list folders.
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_ListAll($sZipFile, $iFullPath = 1)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Then Return SetError(3, 0, 0)
    Local $aArray[1] = [0]
    _Zip_ListAll_Internal($sZipFile, $aArray, $iFullPath)
    If @error Then
        Return SetError(@error, 0, 0)
    Else
        Return $aArray
    EndIf
EndFunc   ;==>_Zip_ListAll

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_Search
; Description....:  Search for files in a ZIP archive
; Syntax.........:  _Zip_Search($sZipFile, $sSearchString)
; Parameters.....:  $sZipFile       - Full path to ZIP file
;                   $sSearchString  - Substring to search
;
; Return values..:  Success         - Array of matching file paths from the root of the archive
;                   Failure         - 0 and sets @error
;                                   | 1 - zipfldr.dll does not exist
;                                   | 2 - Library not installed
;                                   | 3 - Not a full path
;                                   | 4 - ZIP file or subfolder does not exist
;                                   | 5 - No matching files found
; Author.........:  wraithdu
; Modified.......:
; Remarks........:  Found file count is returned in array[0].
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_Search($sZipFile, $sSearchString)
    Local $aList = _Zip_ListAll($sZipFile)
    If @error Then Return SetError(@error, 0, 0)
    Local $aArray[1] = [0], $sName
    For $i = 1 To $aList[0]
        $sName = $aList[$i]
        If StringInStr($sName, "\") Then
            ; subdirectory, isolate file name
            $sName = StringTrimLeft($sName, StringInStr($sName, "\", 0, -1))
        EndIf
        If StringInStr($sName, $sSearchString) Then
            $aArray[0] += 1
            ReDim $aArray[$aArray[0] + 1]
            $aArray[$aArray[0]] = $aList[$i]
        EndIf
    Next
    If $aArray[0] = 0 Then
        ; no files found
        Return SetError(5, 0, 0)
    Else
        Return $aArray
    EndIf
EndFunc   ;==>_Zip_Search

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_SearchInFile
; Description....:  Search file contents of files in a ZIP archive
; Syntax.........:  _Zip_SearchInFile($sZipFile, $sSearchString)
; Parameters.....:  $sZipFile       - Full path to ZIP file
;                   $sSearchString  - Substring to search
;
; Return values..:  Success         - Array of matching file paths from the root of the archive
;                   Failure         - 0 and sets @error
;                                   |-2 - Failed to extract ZIP file to temporary directory
;                                   |-1 - Failed to create temporary directory
;                                   | 1 - zipfldr.dll does not exist
;                                   | 2 - Library not installed
;                                   | 3 - Not a full path
;                                   | 4 - ZIP file or subfolder does not exist
;                                   | 5 - No matching files found
; Author.........:  wraithdu
; Modified.......:
; Remarks........:  Found file count is returned in array[0].
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_SearchInFile($sZipFile, $sSearchString)
    Local $sTempDir
    Do
        $sTempDir = ""
        While StringLen($sTempDir) < 7
            $sTempDir &= Chr(Random(97, 122, 1))
        WEnd
        $sTempDir = @TempDir & "\~" & $sTempDir & ".tmp"
    Until Not FileExists($sTempDir)
    If Not DirCreate($sTempDir) Then Return SetError(-1, 0, 0)
    Local $aList = _Zip_ListAll($sZipFile)
    If @error Then Return SetError(@error, 0, 0)
    _Zip_UnzipAll($sZipFile, $sTempDir) ; flag = 20 -> no dialog, yes to all
    If @error Then Return SetError(-2, 0, 0)
    Local $aArray[1] = [0], $sData
    For $i = 1 To $aList[0]
        $sData = FileRead($sTempDir & "\" & $aList[$i])
        If StringInStr($sData, $sSearchString) Then
            $aArray[0] += 1
            ReDim $aArray[$aArray[0] + 1]
            $aArray[$aArray[0]] = $aList[$i]
        EndIf
    Next
    DirRemove($sTempDir, 1)
    If $aArray[0] = 0 Then
        ; no files found
        Return SetError(5, 0, 0)
    Else
        Return $aArray
    EndIf
EndFunc   ;==>_Zip_SearchInFile

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_Unzip
; Description....:  Extract a single item from a ZIP archive
; Syntax.........:  _Zip_Unzip($sZipFile, $sFileName, $sDestPath[, $iFlag = 21])
; Parameters.....:  $sZipFile   - Full path to ZIP file
;                   $sFileName  - Name of the item in the ZIP file
;                   $sDestPath  - Full path to the destination
;                   $iFlag      - [Optional] File copy flags (Default = 1+4+16)
;                               |   1 - Overwrite destination file if it exists
;                               |   4 - No progress box
;                               |   8 - Rename the file if a file of the same name already exists
;                               |  16 - Respond "Yes to All" for any dialog that is displayed
;                               |  64 - Preserve undo information, if possible
;                               | 256 - Display a progress dialog box but do not show the file names
;                               | 512 - Do not confirm the creation of a new directory if the operation requires one to be created
;                               |1024 - Do not display a user interface if an error occurs
;                               |2048 - Version 4.71. Do not copy the security attributes of the file
;                               |4096 - Only operate in the local directory, don't operate recursively into subdirectories
;                               |8192 - Version 5.0. Do not copy connected files as a group, only copy the specified files
;
; Return values..:  Success     - 1
;                   Failure     - 0 and sets @error
;                               | 1 - zipfldr.dll does not exist
;                               | 2 - Library not installed
;                               | 3 - Not a full path
;                               | 4 - ZIP file / item path does not exist
;                               | 5 - Item not found in ZIP file
;                               | 6 - Failed to create destination (if necessary)
;                               | 7 - Failed to open destination
;                               | 8 - Failed to delete destination file / folder for overwriting
;                               | 9 - Destination exists and overwrite flag not set
;                               |10 - Failed to extract file
; Author.........:  wraithdu, torels
; Modified.......:
; Remarks........:  $sFileName may be a path to an item from the root of the ZIP archive.
;                   For example, some ZIP file 'test.zip' has a subpath 'some\dir\file.ext'.  Do not include a leading or trailing '\'.
;                   If the overwrite flag is not set and the destination file / folder exists, overwriting is controlled
;                   by the remaining file copy flags ($iFlag) and/or user interaction.
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_Unzip($sZipFile, $sFileName, $sDestPath, $iFlag = 21)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Or Not _IsFullPath($sDestPath) Then Return SetError(3, 0, 0)
    ; parse filename
    _Zip_StringStripSlash($sFileName)
    If StringInStr($sFileName, "\") Then
        ; subdirectory, parse out path and filename
        $sZipFile &= "\" & StringLeft($sFileName, StringInStr($sFileName, "\", 0, -1) - 1)
        $sFileName = StringTrimLeft($sFileName, StringInStr($sFileName, "\", 0, -1))
    EndIf
    Local $oApp = ObjCreate("Shell.Application")
    ;Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    Local $oFolderItem = $oNS.ParseName($sFileName)
    If Not IsObj($oFolderItem) Then Return SetError(5, 0, 0)
    If StringRight($sDestPath, 1) = "\" Then $sDestPath = StringTrimRight($sDestPath, 1) ; remove trailing \
    If Not FileExists($sDestPath) Then
        DirCreate($sDestPath)
        If @error Then Return SetError(6, 0, 0)
    EndIf
    Local $oNS2 = $oApp.NameSpace($sDestPath)
    If Not IsObj($oNS2) Then Return SetError(7, 0, 0)
    ; process overwrite flag
    Local $iOverwrite = 0
    If BitAND($iFlag, 1) Then
        $iOverwrite = 1
        $iFlag -= 1
    EndIf
    Local $sDestFullPath = $sDestPath & "\" & $sFileName
    If FileExists($sDestFullPath) Then
        ; destination file exists
        If $iOverwrite Then
            If StringInStr(FileGetAttrib($sDestFullPath), "D") Then
                ; folder
                If Not DirRemove($sDestFullPath, 1) Then Return SetError(8, 0, 0)
            Else
                If Not FileDelete($sDestFullPath) Then Return SetError(8, 0, 0)
            EndIf
        Else
            Return SetError(9, 0, 0)
        EndIf
    EndIf
    $oNS2.CopyHere($oFolderItem, $iFlag)
    If FileExists($sDestFullPath) Then
        ; success
        Return 1
    Else
        ; failure
        Return SetError(10, 0, 0)
    EndIf
EndFunc   ;==>_Zip_Unzip

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_UnzipAll
; Description....:  Extract all files contained in a ZIP archive
; Syntax.........:  _Zip_UnzipAll($sZipFile, $sDestPath[, $iFlag = 20])
; Parameters.....:  $sZipFile   - Full path to ZIP file
;                   $sDestPath  - Full path to the destination
;                   $iFlag      - [Optional] File copy flags (Default = 4+16)
;                               |   4 - No progress box
;                               |   8 - Rename the file if a file of the same name already exists
;                               |  16 - Respond "Yes to All" for any dialog that is displayed
;                               |  64 - Preserve undo information, if possible
;                               | 256 - Display a progress dialog box but do not show the file names
;                               | 512 - Do not confirm the creation of a new directory if the operation requires one to be created
;                               |1024 - Do not display a user interface if an error occurs
;                               |2048 - Version 4.71. Do not copy the security attributes of the file
;                               |4096 - Only operate in the local directory, don't operate recursively into subdirectories
;                               |8192 - Version 5.0. Do not copy connected files as a group, only copy the specified files
;
; Return values..:  Success     - 1
;                   Failure     - 0 and sets @error
;                               | 1 - zipfldr.dll does not exist
;                               | 2 - Library not installed
;                               | 3 - Not a full path
;                               | 4 - ZIP file does not exist
;                               | 5 - Failed to create destination (if necessary)
;                               | 6 - Failed to open destination
;                               | 7 - Failed to extract file(s)
; Author.........:  wraithdu, torels
; Modified.......:
; Remarks........:  Overwriting of destination files is controlled solely by the file copy flags (ie $iFlag = 1 is NOT valid).
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_UnzipAll($sZipFile, $sDestPath, $iFlag = 20)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Or Not _IsFullPath($sDestPath) Then Return SetError(3, 0, 0)
    Local $oApp = ObjCreate("Shell.Application")
    ;Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    If StringRight($sDestPath, 1) = "\" Then $sDestPath = StringTrimRight($sDestPath, 1) ; remove trailing \
    If Not FileExists($sDestPath) Then
        DirCreate($sDestPath)
        If @error Then Return SetError(5, 0, 0)
    EndIf
    Local $oNS2 = $oApp.NameSpace($sDestPath)
    If Not IsObj($oNS2) Then Return SetError(6, 0, 0)
    $oNS2.CopyHere($oNS.Items, $iFlag)
    If FileExists($sDestPath & "\" & $oNS.Items.Item($oNS.Items.Count - 1).Name) Then
        ; success... most likely
        ; checks for existence of last item from source in destination
        Return 1
    Else
        ; failure
        Return SetError(7, 0, 0)
    EndIf
EndFunc   ;==>_Zip_UnzipAll
#Region INTERNAL FUNCTIONS

; #FUNCTION# ====================================================================================================
; Name...........:  _IsFullPath
; Description....:  Determines if a given path is a fully qualified path (well, roughly...)
; Syntax.........:  _IsFullPath($sPath)
; Parameters.....:  $sPath  - Path to check
;
; Return values..:  Success - True
;                   Failure - False
; Author.........:  torels
; Modified.......:
; Remarks........:
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _IsFullPath($sPath)
    If StringInStr($sPath, ":\") Then
        Return True
    Else
        Return False
    EndIf
EndFunc   ;==>_IsFullPath

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_AddPath
; Description....:  INTERNAL FUNCTION
; Author.........:  wraithdu
; ===============================================================================================================
Func _Zip_AddPath($sZipFile, $sPath)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Then Return SetError(3, 0, 0)
    Local $oApp = ObjCreate("Shell.Application")
    ;Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    ; check and create directory structure
    _Zip_StringStripSlash($sPath)
    Local $sFileName = "", $sNewPath = ""
    If $sPath <> "" Then
        ; create temp dir
        Local $sTempDir = _Zip_CreateTempDir()
        If @error Then Return SetError(5, 0, 0)
        Local $oTemp = $oApp.NameSpace($sTempDir)
        Local $aDir = StringSplit($sPath, "\"), $oNS2
        For $i = 1 To $aDir[0]
            $oNS2 = $oApp.NameSpace($sZipFile & "\" & $aDir[$i])
            If Not IsObj($oNS2) Then
                ; create the directory structure
                For $i = $i To $aDir[0]
                    $sNewPath &= "\" & $aDir[$i]
                Next
                DirCreate($sTempDir & $sNewPath)
                $sFileName = _Zip_CreateTempName()
                FileClose(FileOpen($sTempDir & $sNewPath & "\" & $sFileName, 2))
                $oNS.CopyHere($oTemp.Items)
                ; wait for dir structure
                Do
                    Sleep(250)
                    $ & $sNewPath)
                Until IsObj($oNS)
                ; wait for file
                Do
                    Sleep(250)
                    $oItem = $oNS.ParseName($sFileName)
                Until IsObj($oItem)
                DirRemove($sTempDir, 1)
                ExitLoop
            EndIf
            $sZipFile &= "\" & $aDir[$i]
            $
        Next
    EndIf
    Return $sFileName
EndFunc   ;==>_Zip_AddPath

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_CreateTempDir
; Description....:  INTERNAL FUNCTION
; Author.........:  wraithdu
; ===============================================================================================================
Func _Zip_CreateTempDir()
    Local $s_TempName
    Do
        $s_TempName = ""
        While StringLen($s_TempName) < 7
            $s_TempName &= Chr(Random(97, 122, 1))
        WEnd
        $s_TempName = @TempDir & "\~" & $s_TempName & ".tmp"
    Until Not FileExists($s_TempName)
    If Not DirCreate($s_TempName) Then Return SetError(1, 0, 0)
    Return $s_TempName
EndFunc   ;==>_Zip_CreateTempDir

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_CreateTempName
; Description....:  INTERNAL FUNCTION
; Author.........:  wraithdu
; ===============================================================================================================
Func _Zip_CreateTempName()
    Local $GUID = DllStructCreate("dword Data1;word Data2;word Data3;byte Data4[8]")
    DllCall("ole32.dll", "int", "CoCreateGuid", "ptr", DllStructGetPtr($GUID))
    Local $ret = DllCall("ole32.dll", "int", "StringFromGUID2", "ptr", DllStructGetPtr($GUID), "wstr", "", "int", 40)
    If @error Then Return SetError(1, 0, "")
    Return $ret[2]
EndFunc   ;==>_Zip_CreateTempName

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_DllChk
; Description....:  Checks if the zipfldr library is installed
; Syntax.........:  _Zip_DllChk()
; Parameters.....:  None.
; Return values..:  Success - 1
;                   Failure - 0 and sets @error
;                           | 1 - zipfldr.dll not found
;                           | 2 - Library not installed
; Author.........:  wraithdu, torels
; Modified.......:
; Remarks........:
; Related........:
; Link...........:
; Example........:
; ===============================================================================================================
Func _Zip_DllChk()
    If Not FileExists(@SystemDir & "\zipfldr.dll") Then Return SetError(1, 0, 0)
    If Not RegRead("HKEY_CLASSES_ROOT\CLSID\{E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}", "") Then Return SetError(2, 0, 0)
    Return 1
EndFunc   ;==>_Zip_DllChk

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_InternalDelete
; Description....:  INTERNAL FUNCTION
; Author.........:  wraithdu
; ===============================================================================================================
Func _Zip_InternalDelete($sZipFile, $sFileName)
    If Not _Zip_DllChk() Then Return SetError(@error, 0, 0)
    If Not _IsFullPath($sZipFile) Then Return SetError(3, 0, 0)
    ; parse filename
    _Zip_StringStripSlash($sFileName)
    If StringInStr($sFileName, "\") Then
        ; subdirectory, parse out path and filename
        $sZipFile &= "\" & StringLeft($sFileName, StringInStr($sFileName, "\", 0, -1) - 1)
        $sFileName = StringTrimLeft($sFileName, StringInStr($sFileName, "\", 0, -1))
    EndIf
    Local $oApp = ObjCreate("Shell.Application")
    Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    Local $oFolderItem = $oNS.ParseName($sFileName)
    If Not IsObj($oFolderItem) Then Return SetError(5, 0, 0)
    ; ## Ugh, this was ultimately a bad solution
    ; move file to a temp directory and remove the directory
    Local $sTempDir = _Zip_CreateTempDir()
    If @error Then Return SetError(6, 0, 0)
    $oApp.NameSpace($sTempDir).MoveHere($oFolderItem, 20)
    DirRemove($sTempDir, 1)
    $oFolderItem = $oNS.ParseName($sFileName)
    If IsObj($oFolderItem) Then
        ; failure
        Return SetError(7, 0, 0)
    Else
        Return 1
    EndIf
EndFunc   ;==>_Zip_InternalDelete

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_ListAll_Internal
; Description....:  INTERNAL FUNCTION
; Author.........:  wraithdu
; ===============================================================================================================
Func _Zip_ListAll_Internal($sZipFile, ByRef $aArray, $iFullPath, $sPrefix = "")
    Local $oApp = ObjCreate("Shell.Application")
    Local $
    If Not IsObj($oNS) Then Return SetError(4, 0, 0)
    Local $oList = $oNS.Items
    For $oItem In $oList
        If $oItem.IsFolder Then
            ; folder, recurse
            If $iFullPath Then
                ; build path from root of zip
                _Zip_ListAll_Internal($sZipFile & "\" & $oItem.Name, $aArray, $iFullPath, $sPrefix & $oItem.Name & "\")
                If @error Then Return SetError(4)
            Else
                ; just filenames
                _Zip_ListAll_Internal($sZipFile & "\" & $oItem.Name, $aArray, $iFullPath, "")
                If @error Then Return SetError(4)
            EndIf
        Else
            $aArray[0] += 1
            ReDim $aArray[$aArray[0] + 1]
            $aArray[$aArray[0]] = $sPrefix & $oItem.Name
        EndIf
    Next
EndFunc   ;==>_Zip_ListAll_Internal

; #FUNCTION# ====================================================================================================
; Name...........:  _Zip_StringStripSlash
; Description....:  INTERNAL FUNCTION
; Author.........:  wraithdu
; ===============================================================================================================
Func _Zip_StringStripSlash(ByRef $sString)
    If StringLeft($sString, 1) = "\" Then $sString = StringTrimLeft($sString, 1)
    If StringRight($sString, 1) = "\" Then $sString = StringTrimRight($sString, 1)
EndFunc   ;==>_Zip_StringStripSlash
#EndRegion INTERNAL FUNCTIONS

i just disabled some unassigned variables in it. but i can download your UDF again.

Share this post


Link to post
Share on other sites
wraithdu

Simple example:

#NoTrayIcon
;~ #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include <_Zip.au3>

; create a test directory
$dir = @DesktopDir & "\mydir"
DirCreate($dir)
; create some files
For $i = 1 To 3
    FileWrite($dir & "\file" & $i, "")
Next
; create the ZIP
$file = _Zip_Create(@DesktopDir & "\test.zip", 1)
ConsoleWrite("err: " & @error & @CRLF)
_Zip_AddItem($file, $dir)
ConsoleWrite("err: " & @error & @CRLF)
; add it to a subdir
_Zip_AddItem($file, $dir, "dir1\dir2")
ConsoleWrite("err: " & @error & @CRLF)
; remove dir
DirRemove($dir, 1)

Share this post


Link to post
Share on other sites
wraithdu

I have no idea how you got a copy of the UDF with 'Local $' in it. The ones I have posted / updated do not have such errors. Get the updated copy anyway. And remove the UDF from your post above, it's large and unnecessary.

Edited by wraithdu

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.