Applescript loop to parse CSV and inject values - loops

I am trying to loop through each comma separated value in a file and have each item undergo a series of actions. Essentially the workflow is this:
CSV file:
123,456,789
Workflow:
[1] Take '123'
[2] Inject '123' into a text field
[3] Click on buttons
[4] Repeat until (and including) last value in CSV
My current code is as follows, but I'm not being able to correctly loop or inject the current item into the text field.
Any pointers you could give me?
set pathInputFile to (choose file with prompt "Select the CSV file" of type "csv")
set strFileContents to read pathInputFile
set parFileContents to (paragraphs of strFileContents)
set numRows to count of parFileContents
repeat with iPar from 1 to number of items in parFileContents
set lstRow to item iPar of parFileContents
if lstRow = "" then exit repeat -- EXIT Loop if Row is empty, like the last line
set lstFieldsinRow to parseCSV(lstRow as text)
----------
-- now I would need to pass the current value to the next block
-- and "paste" it into the text field
----------
tell application "System Events"
tell process "App"
set frontmost to true
click menu item "Query Window..." of menu "Network" of menu bar 1
click radio button "Number" of tab group 1 of window "Query"
set focused of text field 1 of tab group 1 of window "Query" to true
delay 0.1
keystroke "a" using command down
delay 0.1
keystroke "v" using command down
click UI element "Query" of group 4 of splitter group 1 of window "Query"
end tell
end tell
end repeat -- with iPar
EDIT:
set pathInputFile to (choose file with prompt "Select the CSV file" of type "csv")
set strFileContents to read pathInputFile
log strFileContents
Output:
(*147782
167482
182676
185309
184119
188494*)
What delimiter should I use in this case?

If the CSV is simple CSV (without double quotes as additional field separators) it's also simple to separate the items with AppleScript's text item delimiters.
set theCSV to "123,456,789"
set {TID, text item delimiters} to {text item delimiters, ","}
repeat with anItem in (get text items of theCSV)
display dialog anItem buttons {"OK"} default button 1
end repeat
set text item delimiters to TID
If all fields are wrapped in double quotes you can use this
set theCSV to "\"123\",\"456\",\"789\""
set trimmedCSV to text 2 thru -2 of theCSV
set {TID, text item delimiters} to {text item delimiters, quote & "," & quote}
repeat with anItem in (get text items of trimmedCSV)
display dialog anItem buttons {"OK"} default button 1
end repeat
set text item delimiters to TID
The data structure in the EDIT part seems to be line separated (one item per line) not really CSV. In this case neither text item delimitersnor a repeat loop is needed. paragraphs of reads the text line separated (it considers LF, CR and CRLF).
set strFileContents to paragraphs of (read pathInputFile)

Related

Turn list into applescript array

I have an applescript function which processes each item of an array. I'm looking for a way to drop a list like the following into my applescript file:
arrayitem1
arrayitem2
arrayitem3
and to use applescript to automatically format it into the proper applescript array syntax so I end up with this:
set array1 to {"arrayitem1", "arrayitem2", "arrayitem3"}
As you can imagine, for longer arrays it would be a hassle to manually add all the commas and quotations.
Thanks!
set stringofitems to "
item1
item2
item3
"
set text item delimiters to "
"
set listofitems to text items of stringofitems
repeat with theitem in listofitems
# stuff to do with each item
end repeat
If the original file is a line separated text, "paragraphs" can be used to split it. endList has to be defined as list '{}' Now thru repeat, each line of the content in the clipboard will be entered as a new entry into the list endList.
set {var, endList} to {the clipboard, {}}
repeat with x in paragraphs of var
set endList to endList & x
end repeat
If I understand what all you're wanting, I'd suggest a script where you select and copy the string in your google doc, then run a script that pulls the string from the clipboard, does the changes you want, then puts the result onto the clipboard ready to be pasted where you want.
Here's an example using what you said you wanted.
-- get the string into the script through the clipboard
set theString to the clipboard
-- convert the string into a list, using paragraphs
set theParagraphs to paragraphs of theString
-- convert the list to a string, with ", " between items
set AppleScript's text item delimiters to "\", \""
set theResult to ("\"" & theParagraphs as string) & "\""
set AppleScript's text item delimiters to ""
set the clipboard to theResult
-- "arrayitem1", "arrayitem2", "arrayitem3"

VBA: Variable length array from user input (6 optional text boxes)

I have a UserForm with 6 text-boxes, which the user can fill (or not) 2, 3, 4, or 6 or whatever he/she wants. These are called:
eb1, eb2, eb3, ...
At the end of the form there is also an 'accept' buttom, and when the user clicks it a text should appear as follows:
eb1, eb2, eb3, eb4...
Of course one of the problems is that if the user only fills 3 boxes, the result might be:
eb1, eb2, eb3, , ,
How can I do this? I guess I need something like a variable array and a for loop, but no idea how to do that, I am pretty new to VBA.
Thanks a lot.
Try below.
Create user form with 6 textboxes & name them as eb1, eb2, eb3, eb4, eb5 & eb6. Then add command button & paste below code to it. Then run the userform & enter some values to text boxes.
Click on the command button to see the msgbox.
Private Sub CommandButton1_Click()
dim str as string
dim a as integer
'Check for text box name & loop through textboxes
for a=1 to 6 'No of text boxes have.(remember that your text boxes should have names like eb1
'find out if there is any blank textboxes & avoid them
if Controls("eb" & a).Value <> "" then
'Correction for front , if eb1 is empty
if str="" then
str=Controls("eb" & a).Value
else
str=str & " , " & Controls("eb" & a).Value
end if
end if
next
msgbox str
end Sub
Final messagebox will give you the result you want. (If I understood your question clearly). I have assumed that you don't need to show anything regards empty textboxes.
Keashan

Find and replace in text files using AppleScript

I am trying to write an applescript which will run via a launch agent. What the script needs to do is edit a user preference plist file so that default save locations are specific to that user. I am aware that this can be done by just setting "~/documents" as the location in the template plist. But Premier Pro for example also needs to write scratch files to a local drive. For simplicity I would like each user to have these put in a locations based on their username. This script will only need to run if the local profile has just been created from a template at first log on.
I have started by using some sample code found on this site and just making a simple test below. This test should edit a txt file and replace one word with another. This script is currently not working. When tested it opens up test.txt in TextEdit but does nothing more. No errors are displayed either.
Thank you in advance
John.
replaceText("replace this", "replace with this", "/Volumes/USB_Drive/test.txt")
on replaceText(search_string, replacement_text, this_document)
tell application "TextEdit"
open this_document
set AppleScript's text item delimiters to the search_string
set this_text to the text of the front document as list
set AppleScript's text item delimiters to the replacement_text
set the text of the front document to (this_text as string)
close this_document saving yes
end tell
end replaceText
Here an version that doesn't need text edit. It will read the file in utf-8 encoding, update it's contents and store that back into the file as utf-8 encoded text. The reason I use an try block around writing the file is that there will be an error if another application has the file open with read permission at the same time. The considering case block can be wrapped around the set ti to every text item of theContent if you want the search and replace case sensitive. There is no need for this to be active when you replace the string, only for finding it.
set stringToFind to "replace that"
set stringToReplace to "with this"
set theFile to choose file
set theContent to read theFile as «class utf8»
set {oldTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, stringToFind}
set ti to every text item of theContent
set AppleScript's text item delimiters to stringToReplace
set newContent to ti as string
set AppleScript's text item delimiters to oldTID
try
set fd to open for access theFile with write permission
set eof of fd to 0
write newContent to fd as «class utf8»
close access fd
on error
close access theFile
end try
Well, yes, as #dj_bazzie_wazzie points out, you really don't need a text editor for this, you can use the terminal and do something like:
perl -pi -e 's/old text/new text/g' /path/to/theFile.plist
which of course you can use in AppleScript with the powerful do shell script command:
do shell script "perl -pi -e 's/" & search_string & "/" & replacement_text & "/g' " & quoted form of (POSIX path of file_path)
--assuming file_path is a variable with Mac-style (colon-separated) file path.
Modified from http://discussions.apple.com/message/20542594#20542594, the handler below does what you want. I made a few changes and added your variables. A few notes: (1) the 'my' before the handler call makes sure it is seen as the script's handler and not something TextEdit should interpret 'internally' (because it is in a tell block); (2) 'considering case' makes the handler case sensitive, which I assume you want; (3) You might consider something like TextWrangler, which has robust and feature-rich AppleScript support, and includes text replacement in its AS dictionary, as does Smile, a fantastic Script Editor (which can work with text, and formats plist files nicely).
tell application "TextEdit"
set workingWin to open this_document
set this_text to the text of the workingWin
set the text of the workingWin to (my replaceText(this_text, search_string, replacement_text))
close workingWin saving yes
end tell
to replaceText(someText, oldItem, newItem)
(*
replace all occurances of oldItem with newItem
parameters - someText [text]: the text containing the item(s) to change
oldItem [text, list of text]: the item to be replaced
newItem [text]: the item to replace with
returns [text]: the text with the item(s) replaced
*)
considering case
set {tempTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, oldItem}
try
set {itemList, AppleScript's text item delimiters} to {text items of someText, newItem}
set {someText, AppleScript's text item delimiters} to {itemList as text, tempTID}
on error errorMessage number errorNumber -- oops
set AppleScript's text item delimiters to tempTID
error errorMessage number errorNumber -- pass it on
end try
end considering
return someText
end replaceText

How to create a new List of files and return them?

I'm using the following AppleScript in my Automator workflow:
on run {input, parameters}
--say input
set result_array to {} as list
try
repeat with this_file in input
tell application "Image Events"
launch
set this_image to open this_file
copy dimensions of this_image to {W, H}
close this_image
end tell
set text item delimiters to ":"
set file_name to last text item of (this_file as string)
set text item delimiters to ""
set filter_string to W & "x" & H as string
if file_name contains filter_string then
set the end of result_array to this_file
end if
end repeat
return result_array
on error error_message
display dialog error_message
end try
end run
The script runs after a Get Folder Contents action.
There is something wrong with the result array but I can't figure out what.
The result has to be a list of files which have their size in their names.
If I understood correctly use one of the following :
if file_name contains filter_string then
-- set the end of result_array to this_file as alias
-- set the end of result_array to this_file as text
end if
Currently this_file is like a pointer to the original list of files. When used directly it includes the index of the current value and the full list.
This is probably due to how the repeat with a in b is implement in Applescript.

How to detect files (even in subfolders) with a specific extension and open them?

I'm trying to make a droplet applscript app. It should do:
when a folder is dropped it should "scan" the folder,its subfolders and files
every file with a specific extension (such as: .txt" should be opened in an program and something should be done
that's all
I get this error when I detected the right file and if it is trying to open it (the app won't be started- before that I get this error and the script cancels):class nmxt of alias "the path to the file" could not be read
Currently my script:
on open {input}
set theFiles to (getFilesRecursively(input, "plhs"))
repeat with oneFile in theFiles
if name extension of oneFile is "plhs" then
tell application "Applic"
open oneFile
activate
tell application "System Events"
tell process "Applic"
click menu item "Save" of menu 1 of menu bar item "File" of menu bar 1
end tell
end tell
end tell
end if
end repeat
end open
on getFilesRecursively(fContainer, fExt)
tell application "Finder"
set recursiveFileList to entire contents of fContainer as alias list
set resultFileList to {}
repeat with aFile in recursiveFileList
if name extension of aFile contains fExt then
set resultFileList to resultFileList & aFile
end if
end repeat
end tell
return resultFileList
end getFilesRecursively
Here is a germinal script that should get you going:
property kTargetFileExtension : "txt"
property pValidFileList : {}
on open of theFiles -- Executed when files or folders are dropped on the script
set fileCount to (get count of items in theFiles)
repeat with thisFile from 1 to fileCount
set theFile to item thisFile of theFiles
tell application "System Events"
set file_info to get info for theFile
end tell
if visible of file_info is true then -- check for the file extension here as well
if folder of file_info is true then
my createList(theFile)
else
set fileName to name of file_info
set targetFileFound to isTargetFile(fileName, kTargetFileExtension) of me
if (targetFileFound) then
set end of pValidFileList to theFile
end if
end if
end if
end repeat
display dialog "pValidFileList = " & pValidFileList
(* do something with your files listed in pValidFileList here *)
end open
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 as alias)
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 fileName to the_item
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 -- check for the file extension here as well
if folder of file_info is true then
my createList(the_item)
else
set targetFileFound to isTargetFile(fileName, kTargetFileExtension) of me
if (targetFileFound) then
set end of pValidFileList to the_item
end if
end if
end if
end repeat
end createList
on isTargetFile(theFilename, theTargetExtension) -- (string, string) as boolean
set AppleScript's text item delimiters to "."
set fileNameList to every text item of theFilename
set AppleScript's text item delimiters to ""
try
set theFileExtension to item 2 of fileNameList as string
on error
return false
end try
if theFileExtension is theTargetExtension then
return true
end if
return false
end isTargetFile
A couple things to note:
System Events is the current best practice for getting lists and information about files. Just asking for the entire contents is faster but known to be unreliable. This method of crawling manually is slower but there is no doubt you will be getting the files you need.
isTargetFile actually just works with the filename as a string, as opposed to relying on the system to give the information. Six of one, half dozen of the other if you ask me, but this does reduce the number of calls to the system, so I imagine it makes this a bit faster.
I also tend to add an on run {} block to these things to allow for manual selection of a folder. Doing so also facilitates testing.
How to use:
Save the script as an application, and you should get a droplet (the Applescript application icon with the arrow pointing down).
on open of theFiles is the equivalent of main(). You can drop any combination of files and folders onto the droplet, and it will handle the rest. It ends up with a list of target files that you can then loop through for processing. I will leave it as an exercise for you to add in that bit.
To customize the target, change the string in the first line, property kTargetFileExtension : "txt", to whatever extension you are looking for. This can also be changed to an array—property kTargetFileExtension : {"txt", "rtf", "doc} for example—but you will also need to update isTargetFile(theFilename, theTargetExtension) to loop through those as well.
Beyond that, this just works. Right now, it will gather a list of txt files for processing.
Add salt to taste.

Resources