AppleScript : if and repeat - if-statement

I created a script to check the status of a web search
I added a repeat statement so the script can continue only if the search is completed or if the "SN" is invalid.
repeat 20 times
set theSearchstate to "not ready"
set checkIfSNIsCorrect to ""
set checkIfSNIsInvalid to ""
try
tell application "Google Chrome"
tell front window's active tab to set checkIfSNIsInvalid to execute javascript "document.getElementsByClassName('modal-body ng-scope')[0].innerHTML;"
## Invalid Serial
tell front window's active tab to set checkIfSNIsCorrect to execute javascript "document.getElementsByClassName('subheader ng-binding')[0].innerHTML;"
## SN and device ID
end tell
if theSearchstate is equal to "not ready" then
delay 1
else if checkIfSNIsCorrect contains serialNumber then
set theSearchstate to "Completed"
set checkIfSNIsCorrect to "SN is Correct"
exit repeat
else if checkIfSNIsInvalid contains "Serial Does Not Exists" then
set theSearchstate to "invalid S/N"
exit repeat
else if checkIfSNIsInvalid contains "serviceErrorWhileSearching" then
set theSearchstate to "Error with GCRM"
exit repeat
end if
on error
--
end try
end repeat
return theSearchstate
However this is not working at all, I tried in different way, but I can't make it work.
Any suggestion ?

The variable "serialNumber" is NOT defined:
else if checkIfSNIsCorrect contains serialNumber then
This statement will always return true, so none of the other statements will be executed:
if theSearchstate is equal to "not ready" then
I Revised Your Script
Please test and advise if it works for you.
Be sure to set the serialNumber variable to the correct value.
--- MOVE VARIABLE INIT OUTSIDE OF REPEAT ---
set theSearchstate to "not ready"
set checkIfSNIsCorrect to ""
set checkIfSNIsInvalid to ""
--- ADD THIS ---
set serialNumber to "YourSerialNumber" ## CHANGE to desired value
try
repeat 20 times
tell application "Google Chrome"
tell front window's active tab to set checkIfSNIsInvalid to ¬
execute javascript "document.getElementsByClassName('modal-body ng-scope')[0].innerHTML;"
## Invalid Serial
tell front window's active tab to set checkIfSNIsCorrect to ¬
execute javascript "document.getElementsByClassName('subheader ng-binding')[0].innerHTML;"
## SN and device ID
end tell
### REMOVED if test for "theSearchstate"
if checkIfSNIsCorrect contains serialNumber then
set theSearchstate to "Completed"
set checkIfSNIsCorrect to "SN is Correct"
exit repeat
else if checkIfSNIsInvalid contains "Serial Does Not Exists" then
set theSearchstate to "invalid S/N"
exit repeat
else if checkIfSNIsInvalid contains "serviceErrorWhileSearching" then
set theSearchstate to "Error with GCRM"
exit repeat
end if
--- MOVE DELAY TO HERE ---
--- NONE OF THE ABOVE MATCHED, SO DELAY & TRY AGAIN ---
delay 1
end repeat
on error errMsg number errNum
set msgStr to "[ERROR]" & linefeed & errNum & ": " & errMsg
set titleStr to "Check for Serial Number"
display dialog msgStr ¬
with title titleStr ¬
with icon stop
set buttonStr to button returned of result
set theSearchstate to msgStr
end try
return theSearchstate

Related

How to Overwrite all files in a folder?

I am using the following to copy a file:
on replace:sender
set allFiles to choose file with prompt "Please select your file:" with multiple selections allowed
repeat with theFile in allFiles
tell application "Finder"
set {name:fileName, name extension:nameExtension, file type:fileType} to theFile
if fileType is "png" or nameExtension is "png" then
set myPng to "~/Documents" & fileName as POSIX file
else
delay 0.2
tell current application's NSAlert's alloc's init()
its setMessageText:"Replace Photo"
its setInformativeText:"The file \"" & fileName & "\" is not a PNG file!"
its setAlertStyle:2
its setShowsSuppressionButton:false
its beginSheetModalForWindow:theWindow completionHandler:(missing value)
return
end tell
end if
if exists myPng then
delay 0.2
tell current application
display alert"There is already an older item named \""& fileName &"\" at this location." message ¬
"Do you want to replace it with the newer \"" & fileName & "\" one you're moving?" buttons {"Cancel", "Replace"} default button "Replace" as critical
set response to button returned of the result
if response is "Replace" then
delay 0.2
do shell script "rm -rf " & quoted form of POSIX path of myPng & space & "~/Documents" & myPng with administrator privileges
do shell script "mv " & quoted form of POSIX path of theFile & space & "~/Documents" with administrator privileges
end if
if response is "Cancel" then
return
end if
end tell
else
do shell script "mv " & quoted form of POSIX path of theFile & space & "~/Documents" with administrator privileges
end if
end tell
end repeat
end replace:
If there is a file with the same name in the target folder the user receives an alert, but what is happening is that with each copied file this alert is displayed, I would like to show this alert only once, just as it is done by macOS and then if the user clicks the "Replace" button all files will be replaced at once.
Your script doesn't compile so it didn't allow me to test it to really get a feel for what you're doing, so I hope I'm in the ball park with what I've come up with below.
But, aside from that, I'll be blunt: your script is a mess. You've got a Finder block that contains some AppleScriptObjC code, and then some shell function calls... I think you need to pick one, and then organise the code a bit more logically so people (especially you) can make sense of what's going on.
I typically avoid Finder for file system operations, but in this situation, it is advantageous because it allows one to compare a potential list of items (generated by a whose filter) with a known list of items—something no other application allows (and instead thinks you wish to compare it to the number 64). It also means that a move operation can be undone if necessary:
-- Bits of text for joining
-- Used for the alert dialogs
property lf : linefeed
property lft : linefeed & tab
property lf2 : lf & lf
property lf2t : lf2 & tab
property bullet : "›"
property li : bullet & space
-- Icon files, also used
-- for the alert dialogs
property CoreTypes : "/System/Library/CoreServices/CoreTypes.bundle"
property StopIcon : path to resource "AlertStopIcon.icns" in bundle CoreTypes
property NoteIcon : path to resource "AlertNoteIcon.icns" in bundle CoreTypes
on replace:sender
set prompt to "Please select some files:"
set fs to choose file with prompt prompt ¬
with multiple selections allowed
-- Get the directory in which the chosen files lie
set dir to (some item in fs & "::" as text)
set the text item delimiters to dir's POSIX path
-- Organise the files into two lists:
-- PNG files and non-PNG files
set PNGfs to {}
repeat with f in fs
get text items 2 thru -1 of f's POSIX path as text
set f's contents to the result
tell f to if its contents ends with ".png" then
set end of PNGfs to its contents
set its contents to null
end if
end repeat
set fs to every string in fs
set the text item delimiters to lft & li
if fs ≠ {} then display dialog ["The following files ", ¬
"are not PNG files and will be ignored:", lf2t, ¬
li & fs] as text with title ["Oops…!"] buttons ¬
["D'oh!"] with icon NoteIcon default button 1
if PNGfs = {} then return -- Nothing to move
tell application id "com.apple.Finder"
set here to dir as alias -- The source folder
set there to the (path to the documents folder) -- Destination folder
-- Enumerate files that might be replaced
set duplicates to the name of every file ¬
in there whose name is in PNGfs
if duplicates ≠ {} then tell (display dialog contents ¬
of ["The following files in ", here's POSIX path, ¬
" share names with files in ", there's POSIX path, ¬
":", lf2t & li & duplicates & lf2, "Do you want ", ¬
"to:", lft, "• Move all files anyway, replacing ", ¬
"the ones in ", there's POSIX path, ";", lft, "•", ¬
" Move only the files that can be moved without ", ¬
"replacing anything; OR", lft, "• Don't move any", ¬
" of the files for now ?"] as text ¬
with title ["Replace Existing Files?"] ¬
buttons ["Replace", "Keep", "Abort"] ¬
default button 1 with icon StopIcon) ¬
to set do to its button returned
-- If the user aborts, the script terminates.
-- If the user elects to replace existing files,
-- then we move those existing files to the trash.
-- If the user wishes to keep the existing files,
-- they remain in place. Either way, the final
-- operation is the same: move the files without
-- replacing anything.
if do = "Abort" then return 0 -- No files moved
if do = "Replace" then delete ¬
(files in there whose ¬
name is in ¬
duplicates)
move the (files in here whose ¬
name is in PNGfs) to ¬
there without replacing
end tell
end replace:
Doing it this way avoids the repeat loop and thus you only get a single dialog box per set of grouped events (one if the user selects files of the wrong type; and one if there's a risk of overwriting files).
In fact, you can even get rid of the first repeat loop that is used to split the list into two by file types: the choose file command has a parameter called of type, where you can specify one or more file types that the user's selection will be restricted to:
set fs to choose file with prompt prompt ¬
with multiple selections allowed ¬
of type ["png"] --OR:["public.png"]
"public.png" is the uniform type identifier for PNG files.
The easist way is to add a flag which is false by default and set to true after the user presses "Replace".
I removed the rm line because it's not needed and the syntax is wrong anyway.
on replace:sender
set replaceAll to false
set allFiles to choose file with prompt "Please select your file:" with multiple selections allowed
repeat with theFile in allFiles
tell application "Finder"
set {name:fileName, name extension:nameExtension, file type:fileType} to theFile
if fileType is "png" or nameExtension is "png" then
set myPng to "~/Documents" & fileName as POSIX file
else
delay 0.2
tell current application's NSAlert's alloc's init()
(its setMessageText:"Replace Photo")
(its setInformativeText:("The file \"" & fileName & "\" is not a PNG file!"))
(its setAlertStyle:2)
(its setShowsSuppressionButton:false)
(its beginSheetModalForWindow:theWindow completionHandler:(missing value))
return
end tell
end if
if exists myPng and replaceAll is false then
delay 0.2
tell current application
display alert "There is already an older item named \"" & fileName & "\" at this location." message ¬
"Do you want to replace it with the newer \"" & fileName & "\" one you're moving?" buttons {"Cancel", "Replace"} default button "Replace" as critical
set response to button returned of the result
if response is "Replace" then
delay 0.2
do shell script "mv " & quoted form of POSIX path of theFile & space & "~/Documents" with administrator privileges
set replaceAll to true
end if
if response is "Cancel" then
return
end if
end tell
else
do shell script "mv " & quoted form of POSIX path of theFile & space & "~/Documents" with administrator privileges
end if
end tell
end repeat
end replace:
You can also use NSAlert (as you are earlier) with its suppression button and keep track of the state in the handler, for example (run in the foreground in Script Editor):
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set buttonState to false
repeat -- forever, or at least until canceled
if buttonState then
display dialog "The suppression button state is currently " & buttonState buttons {"Cancel", "Reset", "OK"}
if button returned of the result is "Reset" then set buttonState to false
else
tell current application's NSAlert's alloc's init()
its setMessageText:"Alert"
its setInformativeText:"This alert is going to keep showing until you choose otherwise."
its setShowsSuppressionButton:true
its (suppressionButton's setTitle:"Skip the alerts")
its runModal()
set buttonState to (its suppressionButton's state()) as boolean
end tell
end if
end repeat

Applscript- Use List to Select Specifc Photoshop Action

Ive been trying to write a Applescript using the bits of knowledge I have
current stumbling blocks are
-getting the returned list selection to run the photoshop action
-how to repeat the action on multiple images.
Aim
I want to use a list to extract different cobinations of files (with set naming conventions) from a defined folder,
I would then like that same list selection to choose between mutliple photoshop actions and run the extracted file combination through that action.
Stage 1
-on running open a list
-List to conatain a set of names relating to photoshop actions
-select from list
Stage 2
-choose folder with source images (always 14 images always with the same last 9 characters _0000.tif to _0013.tif)
-Choose a save folder
Stage 3
-dependant on original list selection, automatically gather files from source image folder and run them through a coresponsing photoshop action
e.g If "Action 1" selceted from List select image "_0001.tiff & _0010.tif" from source folder and do photoshop action "Action1"
Stage4
save in chosen "save folder"
The Script So Far
--Stage 1--
set PhotoshopActionList to {"Action1", "Action2", "Action3", "Action4", "Action5"}
set ActionrequiredAnswer to choose from list PhotoshopActionList with title "Actions Picker" with prompt "Choose Action?"
if ActionrequiredAnswer is false then
error number -128 (* user cancelled *)
else
set ActionrequiredAnswer to ActionrequiredAnswer's item 1 (* extract choice from list*)
end if
end run
--Stage 2--
property SourceFolder : missing value
property destinationFolder : missing value
if SourceFolder = missing value then
set SourceFolder to (choose folder with prompt "Choose Base Images:")
set destinationFolder to (choose folder with prompt "Choose Save Location:")
else
tell application "Finder"
set theFolders to every item of entire contents of SourceFolder as list
repeat with thisFolder in theFolders
make new alias file at destinationFolder to thisFolder
end repeat
end tell
end if
--Stage 3--
tell application "Finder"
set filesList to {files of entire contents of SourceFolder contains "_001", "_002", "003"} as alias list
end tell
tell application "Adobe Photoshop"
repeat with aFile in filesList
open aFile
do action "Action1" from "Actionsfolder"
end tell
--Stage 4--
save currentDocument in folder destinationFolder as JPEG
I did not found a way to select entire contents of folder AND filter extension 'tif', 'tiff',.. AND filter files whose name contains your patterns.
As work around, I did 2 steps:
1) select in entire contents only files with target extensions.
2)I loop through these files to check is file name contains the target pattern. This is done by routine FnameOK.
You need to complete the script bellow with your Photoshop action and the 'save as':
set PhotoshopActionList to {"Action1", "Action2", "Action3", "Action4", "Action5"}
set ListOK to {"_001", "_002", "003"}
set ActionRequiredAnswer to choose from list PhotoshopActionList with title "Actions Picker" with prompt "Choose Action?"
if ActionRequiredAnswer is false then
error number -128 (* user cancelled *)
else
set ActionRequiredAnswer to ActionRequiredAnswer's item 1 (* extract choice from list*)
end if
set SourceFolder to (choose folder with prompt "Choose Base Images:")
set DestinationFolder to (choose folder with prompt "Choose Save Location:")
tell application "Finder" to set filesList to files of entire contents of SourceFolder whose name extension is in {"tiff", "tif"}
repeat with aFile in filesList
tell application "Finder" to set NameF to name of aFile
if FNameOK(NameF, ListOK) then -- the file name contains a valid pattern, then process the file
tell application "Adobe Photoshop"
open (aFile as alias)
-- perform action selected
-- save as to Destination Folder
end tell
end if
end repeat
on FNameOK(Local_Name, LocalList) -- check if the file name contains an element of the list
set LocalCheck to false
repeat with OneItem in LocalList
if Local_Name contains OneItem then
return true
end if
end repeat
return false
end FNameOK

else if error on Command part

I can't fix this code that gives Else without If:
Sub aRefreshData()
If Worksheets("Control tab").Range("$I$2").Value = "OFF" Then MsgBox "Enable Connection before refresh"
Else
ActiveWorkbook.Connections("server DB").Refresh
End If
End Sub
You missed ":" after Else
Sub aRefreshData()
If Worksheets("Control tab").Range("$I$2").Value = "OFF" Then
MsgBox "Enable Connection before refresh"
Else:
ActiveWorkbook.Connections("server DB").Refresh
End If
End Sub

Validate input from an inputbox without leaving the inputbox

I created a function with an inputdialog to move lines conditionally (tnx to Romainl).
First thing to do is a search, then to invoke the code below.
My Code:
if !exists("char")
let char = "Move Lines with search match after/before?
\ \n
\ \nMove Line Backwards: Start input with: '?'
\ \nMove Line Forwards: Start input with: '/'
\ \n
\ \np.e.
\ \n?=\\s*$
\"
endif
let a = inputdialog(char)
if a == ""
return
endif
if matchstr(a, '^?') != ''
let minplus = '-'
elseif matchstr(a, '^/') != ''
let minplus = '+'
else
echo "wrong input: input does not start with '?' or '/'"
return
endif
I would like to change the "return" command in a "return back to inputdialog" command:
I would like to check the input entered in the inputbox immediately without leaving the inputbox, is that possible?
The call to inputdialog() is a single, blocking call in Vimscript. None of your code can run while it's open. No events (that can be hooked into with :autocmd are fired. In general, there's no parallelism in Vim.
The best you can do is re-launch the inputdialog() (possibly initialized with the previously entered text) when the validation fails.
Alternatively, you'd have to implement your own input control (e.g. using getchar()). There, you can run validation while waiting for the next pressed character.

Get full directory contents with AppleScript

I need to get the entire (visible) contents of a folder and its subfolders as a list. Is this possible?
see how easy this can be
tell application "Finder"
set file_list to entire contents of (choose folder with prompt "Please select directory.")
end tell
if you want a list of file names then you could do this
tell application "Finder"
set file_list to name of every file of entire contents of (choose folder with prompt "Please select directory.")
end tell
Yes, entire contents does exactly what you say -- but it easily chokes on
large folders, and takes forever. It's OK for
small things, like extracting all the files of one kind out of a folder you
know will only contain a small number of files.
The recursive method also works well -- but it's using "list folder", and
the dictionary listing for it says it's deprecated and we shouldn't use it
any more.
I'm sure there is a shell command that can do this faster, but here is one way in pure Applescript that gives you total control over formatting what info you would like displayed.
property kFileList : {}
tell application "Finder"
set source_folder to choose folder with prompt "Please select directory."
my createList(source_folder)
end tell
on createList(item_list)
set the the_items to list folder item_list without invisibles
set item_list to item_list as string
repeat with i from 1 to number of items in the the_items
set the_item to item i of the the_items
set the_item to (item_list & the_item) as alias
set this_info to info for the_item
set file_name to name of this_info
set end of kFileList to file_name
if folder of this_info is true then
my createList(the_item)
end if
end repeat
end createList
On a side note, there are also a number file listing applications that can do this faster than Applescript.
UPDATE: As a result of this discussion, here is the function again, but this time using the updated API. This could probably could use some cleaning up, but it works cataloging my Desktop handily enough (and that's a deep, deep folder for me):
property kFileList : {}
tell application "Finder"
set source_folder to choose folder with prompt "Please select directory."
my createList(source_folder)
end tell
return kFileList
on createList(mSource_folder)
set item_list to ""
tell application "System Events"
set item_list to get the name of every disk item of mSource_folder
end tell
set item_count to (get count of items in item_list)
repeat with i from 1 to item_count
set the_properties to ""
set the_item to item i of the item_list
set the_item to ((mSource_folder & the_item) as string) as alias
tell application "System Events"
set file_info to get info for the_item
end tell
if visible of file_info is true then
set file_name to displayed name of file_info
set end of kFileList to file_name
if folder of file_info is true then
my createList(the_item)
end if
end if
end repeat
end createList
Wow this is quite late but I checked and it works.
tell application "Finder" to set folder_root to (choose folder with prompt "Please select directory.")
set fl to {}
dump_folder(folder_root)
on dump_folder(f)
global fl
tell application "System Events" to set end of fl to (get the POSIX path of f)
tell application "Finder" to set nfl to (the items of the contents of f)
repeat with nf in nfl
dump_folder(nf as alias)
end repeat
end dump_folder
fl