Zipping selected files from a folder using native windows

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Gewerd_Strauss
Posts: 24
Joined: 12 Nov 2020, 02:34

Zipping selected files from a folder using native windows

16 Apr 2021, 06:12

Hello,

I have a problem. I need a way to zip selected files into a zipped folder located in the current directory. The current approach does work, but it is a) slow, and b) reliant on the existence of 7-zip on the PC. The first problem I suspect is just due to the number of files I tend to zip isn't exactly low, and I can live with that. The second problem is okay as long as I can work on my own machine, where I can ensure 7zip exists.
I suspect there are native ways to do this, but I don't have any idea as to how I'd do this :/

Thank you.
Sincerely,
~Gw





Note on fClip:
fClip is just a much more reliable way of using the clipboard, and in this case, effectively only copies the selected file paths onto the clipboard, and then outputs them to this variable, reverting the last clipboard change. For this case, it is synonymous with pressing Ctrl+C before running this code without this step, with the exception that I would lose the original clipboard. The code is below. Works 95% of the time for me.

Code: Select all

#z:: ; FileZipper || Zip Selected Files into directory

gui_control_options := "xm w220 " . cForeground . " -E0x200"  ; remove border around edit field
Gui, Margin, 16, 16
Gui, +AlwaysOnTop -SysMenu -ToolWindow -caption +Border
cBackground := "c" . "1d1f21"
cCurrentLine := "c" . "282a2e"
cSelection := "c" . "373b41"
cForeground := "c" . "c5c8c6"
cComment := "c" . "969896"
cRed := "c" . "cc6666"
cOrange := "c" . "de935f"
cYellow := "c" . "f0c674"
cGreen := "c" . "b5bd68"
cAqua := "c" . "8abeb7"
cBlue := "c" . "81a2be"
cPurple := "c" . "b294bb"
Gui, Color, 1d1f21, 373b41, 
Gui, Font, s11 cWhite, Segoe UI 
;Gui, Font, s11 cComment, Segoe UI 
gui, add, text,xm ym, Enter Name of zipped directory
Gui, add, Edit, %gui_control_options% -VScroll vfileName
Gui, add, Button, default gSubmitFileZipper h0 w0  xs-50  ys -50
Hotkey, Esc, gui_destroy_FileZipper, On ; Escape Key FileZipper-Gui
gui, show,, FileZipper
return
gui_destroy_FileZipper:
Hotkey, Esc, gui_destroy_FileZipper, Off ; Escape Key FileZipper-Gui
gui, destroy
return


SubmitFileZipper:
gui, submit
gui, destroy
Store:=ClipboardAll
fileList := ""
FilesToZip:=fClip() ;; fClip is just a much more reliable way of using the clipboard, and in this case effectively only copies the selected file paths onto the clipboard, and then outputs them to this variable, reverting the last clipboard change . It is synonymous to pressing Ctrl+C before running this code without this step, with the exception that I would loose the original clipboard.
sevenZip := A_ProgramFiles "\7-zip\7z.exe" 
loop parse, % RTrim(FilesToZip, "`r`n"), `n, `r
    	fileList .= " " quote(dir := A_LoopField)
SplitPath dir,, dir
fileList := StrReplace(fileList, dir "\")
Run % sevenZip " a -tzip " quote(fileName ".zip") fileList, % dir
WinWaitActive ahk_exe 7z.exe
WinMinimize 
Clipboard:=Store
return


quote(str)
{
	return """" str """"
}
return

Code: Select all

; Clip() - Send and Retrieve Text Using the Clipboard
; by berban - updated February 18, 2019
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=62156

; adapted by Gewerd Strauss
fClip(Text="", Reselect="")
{
	
	;MsgBox, %A_ThisLabel%`n%A_ThisFunc%
	; msgbox, Text imported:`n|%Text%|
	if RegExMatch(Text,"[&|]") ; check if needle contains cursor-pos. 
	{
		move := StrLen(Text) - RegExMatch(Text, "[&|]")
		Text := RegExReplace(Text, "[&|]")
		sleep, 20
		MoveCursor=true
	}
	Static BackUpClip, Stored, LastClip
	If (A_ThisLabel = A_ThisFunc)
	{
		If (Clipboard == LastClip)
			Clipboard := BackUpClip
		BackUpClip := LastClip := Stored := ""
	} 
	Else 
	{
		If !Stored 
		{
			Stored := True
			BackUpClip := ClipboardAll ; ClipboardAll must be on its own line
		} 
		Else
			SetTimer, %A_ThisFunc%, Off
		LongCopy := A_TickCount, Clipboard := "", LongCopy -= A_TickCount ; LongCopy gauges the amount of time it takes to empty the clipboard which can predict how long the subsequent clipwait will need
		If (Text = "") 
		{
			SendInput, ^c 
			ClipWait, LongCopy ? 0.6 : 0.2, True
		} 
		Else 
		{
			Clipboard := LastClip := Text
			ClipWait, 10
			SendInput, ^v
			;msgbox, fclip:`n %Clipboard%
			if MoveCursor
			{
				/*
					Date: 04 April 2021 17:59:25:
					stupid hotfix for uni mail below, because the
					parsing doesn't work if there is NO MSGBOX in this
					code. WTF
				*/
				if WinActive("E-Mail – [email protected] - Google Chrome")
				{
					WinActivate
					MsgBox, %A_Space%,BS-msgbox
					sleep, 20
					WinActivate, "E-Mail – [email protected] - Google Chrome"
					WinClose, BS-msgbox-msgbox
					SendInput, % "{Left " move-1 "}"
				}	
				else
					SendInput, % "{Left " move-1 "}"
			}
		}
		SetTimer, %A_ThisFunc%, -700
		Sleep 20 ; Short sleep in case Clip() is followed by more keystrokes such as {Enter}
		If (Text = "")
		{
			SetTimer, %A_ThisFunc%, Off
			Return LastClip := Clipboard
		}
		Else If ReSelect and ((ReSelect = True) or (StrLen(Text) < 3000))
		{
			SetTimer, %A_ThisFunc%, Off
			SendInput, % "{Shift Down}{Left " StrLen(StrReplace(Text, "`r")) "}{Shift Up}"
		}
	}
	SendInput, {Ctrl Up}
	SendInput, {V Up}
	SendInput, {Shift Up}
	Return
	fClip:
	Return fClip()
}
Gewerd_Strauss
Posts: 24
Joined: 12 Nov 2020, 02:34

Re: Zipping selected files from a folder using native windows

17 Apr 2021, 05:05

Hi there,

after a day of digging through the code and trying to understand it, it works... in 85% of the time. Way faster than using 7zip, at least.
So. Here're my problem(s):
1. Some files are not inserted into the zip-archive. This happens when zipping both a large and small number of files, regardless of directory, or kind of file. Sometimes, 1 to five files are missing, and I am not quite sure right now how to resolve that. Sure, I could just repeat the same procedure on the same files again, and usually the missing files will then be included. However, in that case I am also clicking through a messagebox from the system informing me every other file is already existing in the directory. This gets very annoying as soon as you have to spam escape 150 times.



Hence, I'd need to figure out a way to

1. Get the files already existing in the directory into an array "ZippedArr"
2. Compare for existence of the values of the original "FileArray" inside "ZippedArr".
2.1 if file does not exist in ZippedArr, copy that entry to a new array, and repeat the copying.

And, I have had next to no success with this. I can't find a solution to resolve point 1 so far.
I have found https://www.autohotkey.com/boards/viewtopic.php?t=28636, which does work, but I haven't had luck adapting it to only search the zip-directory, instead of all files in the directory. And now I am stuck.

And while writing this I just realised that this won't work anyways as is, unless I do janky shit to get the filenames from the first array separated. So I'm back at square one :/





The current Code

Code: Select all

#If WinActive("ahk_class CabinetWClass")
;_____________________________________________________________________________________
;_____________________________________________________________________________________
#z:: ; FileZipper || Zip Selected Files into directory
;fFileZipper()
/*
	Date: 17 April 2021 10:42:46:
	PROBLEM: some files are not inserted into the 
	zip-file. However, repeating the same process
	again would mean spamming close on all opening
	windows
	
	Idea:
	after zipping, query the file-names in the new
	zip-file, and compare to the filearray
	if contents of file-array not found in folder,
		copy to backup-array and run that one again on the
	same folder
	
*/
{
	global foldername
	foldername:=""
	Store:=ClipboardAll
	FilesToZip:=fClip() ; because we are taking text, this seems to muddy the clipboard? weird, that's exactly what it should prevent
	gui_control_options := "xm w220 " . cForeground . " -E0x200"  ; remove border around edit field
	Gui, Margin, 16, 16
	Gui, +AlwaysOnTop -SysMenu -ToolWindow -caption +Border
	cBackground := "c" . "1d1f21"
	cCurrentLine := "c" . "282a2e"
	cSelection := "c" . "373b41"
	cForeground := "c" . "c5c8c6"
	cComment := "c" . "969896"
	cRed := "c" . "cc6666"
	cOrange := "c" . "de935f"
	cYellow := "c" . "f0c674"
	cGreen := "c" . "b5bd68"
	cAqua := "c" . "8abeb7"
	cBlue := "c" . "81a2be"
	cPurple := "c" . "b294bb"
	Gui, Color, 1d1f21, 373b41, 
	Gui, Font, s11 cWhite, Segoe UI 
	gui, add, text,xm ym, Enter Name of zipped directory
	Gui, add, Edit, %gui_control_options% -VScroll vfoldername
	Gui, add, Button, default gSubmitFileZipper h0 w0  xs-50  ys -50
	Hotkey, Esc, gui_destroy_FileZipper, On ; FileZipper || Escape Key 
	gui, show,, FileZipper
	return
	gui_destroy_FileZipper:
	Hotkey, Esc, gui_destroy_FileZipper, Off ; FileZipper || Escape Key 
	gui, destroy
	return
	
	
	SubmitFileZipper:
	gui, submit
	gui, destroy
	CurrDir:=fGetActiveFolderPath()
	sZip:=CurrDir . "\" . foldername . ".zip"
	Zip(FilesToZip,sZip)
	
	Clipboard:=""
	Clipboard:=Store
	;Notify().AddWindow("Directory`n"""fileName . """:`nZipping Complete",{Title:"FileZipper",TitleColor:"0x000000",Time:5000,Color:"0x000000",Background:"0xFFFFFF",TitleSize:10,Size:10,ShowDelay:0})
	return
}

#If WinActive("FileZipper")
^Backspace::Send ^+{Left}{Backspace}  				; Windows Explorer: File Zipper|| Delete last word 
#If
And all relevant functions:

Code: Select all

; Clip() - Send and Retrieve Text Using the Clipboard
; by berban - updated February 18, 2019
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=62156

; adapted by Gewerd Strauss
fClip(Text="", Reselect="")
{
	
	;MsgBox, %A_ThisLabel%`n%A_ThisFunc%
	; msgbox, Text imported:`n|%Text%|
	if RegExMatch(Text,"[&|]") ; check if needle contains cursor-pos. 
	{
		move := StrLen(Text) - RegExMatch(Text, "[&|]")
		Text := RegExReplace(Text, "[&|]")
		sleep, 20
		MoveCursor=true
	}
	Static BackUpClip, Stored, LastClip
	If (A_ThisLabel = A_ThisFunc)
	{
		If (Clipboard == LastClip)
			Clipboard := BackUpClip
		BackUpClip := LastClip := Stored := ""
	} 
	Else 
	{
		If !Stored 
		{
			Stored := True
			BackUpClip := ClipboardAll ; ClipboardAll must be on its own line
		} 
		Else
			SetTimer, %A_ThisFunc%, Off
		LongCopy := A_TickCount, Clipboard := "", LongCopy -= A_TickCount ; LongCopy gauges the amount of time it takes to empty the clipboard which can predict how long the subsequent clipwait will need
		If (Text = "") 
		{
			SendInput, ^c 
			ClipWait, LongCopy ? 0.6 : 0.2, True
		} 
		Else 
		{
			Clipboard := LastClip := Text
			ClipWait, 10
			SendInput, ^v
			;msgbox, fclip:`n %Clipboard%
			if MoveCursor
			{
				/*
					Date: 04 April 2021 17:59:25:
					stupid hotfix for uni mail below, because the
					parsing doesn't work if there is NO MSGBOX in this
					code. WTF
				*/
				if WinActive("E-Mail – [email protected] - Google Chrome")
				{
					WinActivate
					MsgBox, %A_Space%,BS-msgbox
					sleep, 20
					WinActivate, "E-Mail – [email protected] - Google Chrome"
					WinClose, BS-msgbox-msgbox
					SendInput, % "{Left " move-1 "}"
				}	
				else
					SendInput, % "{Left " move-1 "}"
			}
		}
		SetTimer, %A_ThisFunc%, -700
		Sleep 20 ; Short sleep in case Clip() is followed by more keystrokes such as {Enter}
		If (Text = "")
		{
			SetTimer, %A_ThisFunc%, Off
			Return LastClip := Clipboard
		}
		Else If ReSelect and ((ReSelect = True) or (StrLen(Text) < 3000))
		{
			SetTimer, %A_ThisFunc%, Off
			SendInput, % "{Shift Down}{Left " StrLen(StrReplace(Text, "`r")) "}{Shift Up}"
		}
	}
	SendInput, {Ctrl Up}
	SendInput, {V Up}
	SendInput, {Shift Up}
	Return
	fClip:
	Return fClip()
}


;_____________________________________________________________________________________
;_____________________________________________________________________________________
; FileZipper functions
Zip(FilesToZip,sZip)
{
	Files2Zip:=FilesToZip
	FileArray:=StrSplit(FilesToZip,"`n")
	MaxEntries:=FileArray.MaxIndex()
	If Not FileExist(sZip)
		CreateZipFile(sZip)
	psh:=ComObjCreate( "Shell.Application" )
	pzip:=psh.Namespace( sZip )
	if InStr(FileExist(FilesToZip), "D")
		FilesToZip .= SubStr(FilesToZip,0)="\" ? "*.*" : "\*.*"
	loop, %MaxEntries%
	{
		FilesToZip:=FileArray[A_Index]
		zipped++
		CurrFile:=strReplace(FilesToZip,"`r")
		CurrFile:=strReplace(CurrFile,"`n")
		ToolTip Zipping %CurrFile%
		pzip.CopyHere( CurrFile, 4|8|16|1024)
	}
	ToolTip
}

CreateZipFile(sZip)
{
	Header1 := "PK" . Chr(5) . Chr(6)
	VarSetCapacity(Header2, 18, 0)
	file := FileOpen(sZip,"w")
	file.Write(Header1)
	file.RawWrite(Header2,18)
	file.close()
}

;_____________________________________________________________________________________
;_____________________________________________________________________________________

User avatar
mikeyww
Posts: 26891
Joined: 09 Sep 2014, 18:38

Re: Zipping selected files from a folder using native windows

17 Apr 2021, 06:15

I haven't tested it. Others here on the forum may know more.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 341 guests