I'm trying to set up an Indesign script that copies the link information of a selected image and appends it to a text file to the desktop, if the text file does not exist it creates one. The link information is copied to the clipboard using a custom key command in inDesign. The problem is if I copy some text or an image beforehand, that text remains on the clipboard. Even though I copy new link info and set that clipboard to a variable.
I know this is an ugly script, I'm just good enough to get by, but barely.
Any suggestions on how to clear out the clipboard?
Thanks,
~David
--dialog box
display dialog "What do you need done" default answer "Remove Background"
set theAnswer to (text returned of result)
set this_story to "
------------------- " & theAnswer & " -------------------
"
set this_file to (((path to desktop folder) as string) & "Corrections.txt")
my write_to_file(this_story, this_file, false)
on write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as string
set the open_target_file to open for access file target_file with write permission
if append_data is true then set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
--copy link information using keyboard short
activate application "Adobe InDesign CC 2015"
tell application "System Events" to keystroke "l" using {shift down, control down}
end
---
set myVar to the clipboard
my write_clip_file(myVar, this_file, false)
on write_clip_file(myVar, target_file, append_data)
try
set the target_file to the target_file as string
set the open_target_file to open for access file target_file with write permission
if append_data is true then set eof of the open_target_file to 0
write myVar to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_clip_file
Here is a cleaned up version of your script. You don't need to code the same handler twice... both times you right to the file, you can use the same handler. Also, I reversed the logic on the append_data variable, because you had the logic backwards. (if you DO append, then you DON'T set eof to 0 cause that erases the current content).
I don't know what function you're calling in InDesign, but sounds like it's placing the file path/link of a selected image onto the clipboard. When using the clipboard to get data and to place the data into a variable, it's a good practice to put some delays in the script, to avoid the script moving on to the next commands before the app you're working with finishes it's work. I'm betting that the problem you're having is that the script is proceeding before InDesign has finished copying to the clipboard. So, in this script, you can see I placed three delays surrounding the work with the clipboard. You can play with reducing the delay times to see what will still work reliably.
--dialog box
display dialog "What do you need done" default answer "Remove Background"
set theAnswer to (text returned of result)
set this_story to "
------------------- " & theAnswer & " -------------------
"
set this_file to (((path to desktop folder) as string) & "Corrections.txt")
my write_to_file(this_story, this_file, true)
--copy link information using keyboard short
tell application "Adobe InDesign CC 2015"
-- tell application "TextEdit" -- for testing purposes
activate
delay 0.9 -- give app time to come to the front before copying to clipboard
tell application "System Events" to keystroke "l" using {shift down, control down}
-- tell application "System Events" to keystroke "c" using {command down} -- for testing purposes
delay 0.9 -- wait til clipboard is copied before continuing with the script
end tell
set myVar to the clipboard
delay 0.1 -- wait til variable is pulled from clipboard before moving on
my write_to_file(myVar, this_file, true)
--
on write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as string
set the open_target_file to open for access file target_file with write permission
if append_data is false then set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
Try this out and tweak it as you need to, and then let me know if anything is still not working.
Related
Good evening all,
I am trying to understand why I can run the below script in Applescript Editor but am unable to successfully run it in an Xcode Cocoa-Applescript application.
Can someone please explain why this function will not run in Xcode and what I need to do to have it run correctly?
set this_data to ((current date) as string) & space & "WHY DOESN'T THIS LOG!!!!" & return
set this_file to (((path to desktop folder) as string) & "MY LOG FILE")
my write_to_file(this_data, this_file, true)
on write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as string
set the open_target_file to open for access file target_file with write permission
if append_data is false then set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
This is one of the Xcode behaviours I can't explain, but it works if you add tell current application like this:
tell current application to set the open_target_file to open for access file target_file with write permission
It might be better to put the whole function in a tell current application block.
I have an applescript that looks like this:
repeat
tell application "Adobe Reader"
open "filepath/name.pdf"
end tell
delay (60)
tell application "Adobe Reader"
open "filepath/name1.pdf"
end tell
delay (60)
tell application "Adobe Reader"
open "filepath/name2.pdf"
end tell
delay (60)
end repeat
I want to be able to close pdf windows after they have been opened. The issue is that these pdfs reside on a share and users have the ability to update them. The script will only display the updated pdf if it is stopped and restarted. I do not want to have to do this manually. How can I do this?
Here's a solution, which makes Preview scriptable and then continues to open and close a file of your choice.
-- http://www.macworld.com/article/1053391/previewscript.html
on addAppleScriptFeatures()
try
tell application "Finder"
set the Preview_app to (application file id "com.apple.Preview") as alias
end tell
set the plist_filepath to the quoted form of ¬
((POSIX path of the Preview_app) & "Contents/Info")
do shell script "defaults write " & the plist_filepath & space ¬
& "NSAppleScriptEnabled -bool YES" with administrator privileges
do shell script "chmod -R 755 " & the quoted form of (POSIX path of the Preview_app) with administrator privileges
return true
on error myErr number MyNr
display dialog myErr & " (" & MyNr & ")." buttons {"OK"} default button "OK" with icon 0
return false
end try
end addAppleScriptFeatures
if addAppleScriptFeatures() then
set f to choose file
tell application "Preview"
activate
open f
delay 5 -- short for testing
close window 2
end tell
end if
I write an AppleScript:
to check if two specific dictionaries (File1 and File2) files exit in /Library/Dictionaries/
if either of the two files exits, then completely delete that file and the other
The script works fine in AppleScript Editor. I then save the script as an app, test it, and the app also works just fine. I mean both the script in AppleScript Editor and the saved app detect and remove both File1 and File2 from /Library/Dictionaries/.
However in PackageMaker Post Action, when called, the app removes neither File1 nor File2 although it detects them and even shows the dialog message (see code line below).
Here is the code:
tell application "System Events"
if exists (application process "Dictionary") then
tell application "Dictionary" to quit
end if
end tell
try
set theOtherFile1 to POSIX file "/Library/Dictionaries/File1.dictionary"
set theOtherFile2 to POSIX file "/Library/Dictionaries/File2.dictionary"
tell application "Finder"
if exists file theOtherFile1 then
display dialog "File1/File2 exits. Do you want to remove it?" with title "Note" buttons {"No", "Yes"} default button "Yes"
if the button returned of the result is "No" then
delay 2
else
do shell script "rm -R /Library/Dictionaries/File1.dictionary" with administrator privileges
do shell script "rm -R /Library/Dictionaries/File2.dictionary" with administrator privileges
end if
end if
end tell
end try
delay 5
tell application "Dictionary" to activate
Try this:
tell application "System Events"
if exists (application process "Dictionary") then
tell application "Dictionary" to quit
end if
end tell
try
set theOtherFile1 to POSIX file "/Library/Dictionaries/File1.dictionary"
set theOtherFile2 to POSIX file "/Library/Dictionaries/File2.dictionary"
tell application "Terminal" to activate
tell application "System Events"
keystroke ("sudo chmod 777 " & theOtherFile1) as string
display dialog "Click the button after you've typed the root password into Terminal." buttons {"OK"}
keystroke return
keystroke ("chmod 777 " & theOtherFile2) as string
display dialog "Click the button after you've typed the root password into Terminal." buttons {"OK"}
end tell
do shell script "rm -rf /Library/Dictionaries/File1.dictionary"
do shell script "rm -rf /Library/Dictionaries/File2.dictionary"
This should do the trick.
I'm using a PC at the moment, otherwise I'd check first, but I think this will run correctly.
I have a massive set of files (4000+) that are in an old Apple format (Appleworks). My employed needs them all updated to PDF. By opening the documents in Appleworks and using the system print dialogue, I can save them to PDF—this is ideal. I'm a complete nub with Applescript/Automator, however.
Using a Python script I was able to gather all the Appleworks files from my bosses computer and put them in a directory; each file is then in a subdirectory with a .txt file containing its original location (where, eventually, I will have to put them back).
I need the script to move recursively through this massive directory, getting every file that's neither a folder nor a .txt document, and save it to PDF in the same directory in which the original file was found. ie.
/Appleworks/Boss_File_1/
will contain
/Appleworks/Boss_File_1/Boss_file_1.cwk and
/Appleworks/Boss_File_1/path.txt
But must eventually also contain /Appleworks/Boss_File_1/Boss_File_1.pdf
I can get half way with either solution, but don't know how to make them work together. The Applescript I'm using looks like:
set appleworksFolder to choose folder
tell application "Finder"
set folderItems to (files of entire contents of appleworksFolder)
repeat with I from 1 to number of items in folderItems
set the_doc to item I of folderItems
if name of the_doc is not "path.txt" then
try
tell application "AppleWorks 6"
open the_doc
tell application "System Events"
tell process "Appleworks"
keystroke "p" using command down
click menu button "PDF" of window "Print"
click menu item "Save as PDF…" of menu 1 of menu button "PDF" of window "Print"
click button "Save" of window "Save"
end tell
end tell
end tell
end try
else
tell application "Finder"
delete the_doc
end tell
end if
end repeat
end tell`
This opens the print dialogue but never gets any further and I have no idea why. I realize this script also doesn't deal with putting the document back in its original folder, but in Applescript I could easily enough do this if I could get past the actual printing-to-PDF bit.
Meanwhile, in Automator, using this workflow:
Get Specified Finder Items
Get Folder Contents
Filter Finder Items (by kind and then by file extension is not .txt)
Open Finder Items (with Appleworks)
I then am stuck; using the actual Print Finder Items and choosing Adobe PDF seems to actually do nothing at all, and recording myself using the print to pdf process live is useless because I don't know how to get Automator to retain the path the file originated from and ensure it prints to it.
If anyone can help me put this together somehow, I'd be enormously grateful. Thanks.
Convert using Pages
If you have Pages (part of iWork), it can open .cwk files and save them as PDF: just replace your if block with this:
if (the_doc's name extension is not "txt") then
set newName to my makeNewFileName(the_doc, "pdf")
try
tell application "Pages"
open (the_doc as alias)
set thisDoc to front document
save thisDoc as "SLDocumentTypePDF" in newName
close thisDoc saving no
end tell
on error
display dialog "Error: cannot export " & (name of the_doc) & " to PDF."
end try
end if
(you will need this custom function makeNewFileName):
(* prepare new file name with extension ext *)
on makeNewFileName(finderItem, ext)
tell application "Finder"
set fname to finderItem's name
set thePath to (finderItem's container) as alias as text
return (thePath & (text 1 thru ((length of fname) - (length of (finderItem's name extension as text))) of fname) & ext)
end tell
end makeNewFileName
(complete working script)
GUI scripting
Alternatively, you could do GUI scripting upon AppleWorks as you attempted, but it has the disadvantage that you cannot programmatically specify where to save the PDF file.
This snippet works for me:
tell application "AppleWorks 6"
open the_doc
activate
tell application "System Events" to tell process "AppleWorks"
keystroke "p" using command down
delay 1 -- or longer, if it takes longer
click menu button "PDF" of window "Print"
click menu item "Save as PDF…" of menu 1 of menu button "PDF" of window "Print"
delay 1 -- or longer
click button "Save" of window "Save"
end tell
end tell
Unfortunately, AppleWorks doesn't seem to properly listen to AppleScript's close command, therefore you may need to close the file by also simulating the cmd+W keystrokes.
Try this:
set appleworksFolder to choose folder
set thePath to POSIX path of appleworksFolder as string
tell application "Finder"
set folderItems to files of appleworksFolder
repeat with aFile in folderItems
set {name:fileName, name extension:nameExtension} to aFile
set filePath to POSIX path of (aFile as alias) as string
if nameExtension is not "txt" then
set theLocation to POSIX path of (aFile as text)
set baseName to text 1 thru ((get offset of "." & nameExtension in fileName) - 1) of fileName
set destLocation to (thePath & baseName & ".pdf")
set theCommand to "/System/Library/Printers/Libraries/./convert -f \"" & filePath & "\"" & " -o " & "\"" & destLocation & "\"" & " -j \"application/pdf\""
do shell script theCommand
else
tell application "Finder" to delete aFile
end if
end repeat
end tell
I needed to do this today on Mountain Lion with a bunch of RTF receipts; here's how I did it:
#!/bin/bash
for file in *.rtf ; do
filename=$(basename "$file")
/usr/sbin/cupsfilter "$file" > "$filename.pdf"
done
Worked great; super easy. No Automator or AppleScript silliness.
on run {input}
set filepath to POSIX path of input
do shell script "touch " & quoted form of filepath & "untitled"
return input
end run
Is what I have so far, and it works, but is there a way to then focus on the file then trigger a rename? I dont want the rename to be automatic, just trigger the event (like pressing "return" while you have a file selected). And I dont want to use any sort of modal...
Quick Side question: is there a way to set this so that i dont have to select a folder or file directly, but can do it by, lets say, clicking in a white space in a folder as long as it's in Finder? Right now I have my "Service receives selected" to "files or folders" in Finder.app.
== UPDATED CODE ==
on run {input}
set filepath to POSIX path of input
do shell script "touch " & quoted form of filepath & "untitled"
tell application "Finder"
activate
set target of Finder window 1 to POSIX file "/Users/oscargodson/Documents/designs/untitled"
end tell
tell application "System Events"
tell process "Finder"
keystroke return
end tell
end tell
return input
end run
If i hardcode the path it works! But how do I get it as a var that works?
Here's one way. I think a modal window where you ask for the name would be better but you can try this. Notice you do not use "POSIX path" in this code. Applescript doesn't use POSIX paths. Also {input}, as indicated by the brackets around it, is a list of items. Therefore you act on the items of the list, and in this case we act on the first item.
set filepath to item 1 of input
tell application "Finder"
activate
reveal filepath
end tell
tell application "System Events"
tell process "Finder"
keystroke return
end tell
end tell
EDIT: With your updated code, here's a working script...
on run {input}
if (class of input) is not list then set input to {input}
set theFolder to (item 1 of input) as text
try
alias theFolder
tell application "Finder"
if (class of item theFolder) is not folder then error "input is not a folder."
activate
set theFile to make new file at folder theFolder with properties {name:"untitled"}
reveal theFile
end tell
delay 0.2
tell application "System Events"
tell process "Finder"
keystroke return
end tell
end tell
on error theError number errorNumber
tell me
activate
display dialog "There was an error: " & (errorNumber as text) & return & return & theError buttons {"OK"} default button 1 with icon stop
return
end tell
end try
return input
end run
tell application "Finder"
activate
reopen -- in case there are no open windows
set target of Finder window 1 to POSIX file "/Applications/Safari.app"
end tell
reveal and select always open a new window, set target and set selection don't.
I don't know why, but when set selection it used in column view, you can only select items in the entire contents of the target of the front window. The same thing doesn't happen in other views, so it seems like a bug.
Fix for the code in the edited question:
on go(input)
set p to POSIX path of (input as text)
set p2 to p & "untitled"
do shell script "touch " & p2
tell application "Finder"
reopen
activate
set target of Finder window 1 to POSIX file p2
end tell
delay 0.3 -- time to release modifier keys
tell application "System Events" to keystroke return
end go
tell application "Finder"
set fold to folder (path to documents folder)
end tell
go(fold)
(That on go and the last lines are just for testing.)
I've created an AppleScript based on the #regulus6633's one, but with some improvements.
Note: This answer was originally posted as an AskDifferent answer. I'm copy/pasting here for convenience.
The idea is to create an Automator workflow and assigning a shortcut to it using the following steps:
Open Automator and create a Service;
Set the input to no input, and the application to Finder.app;
Drag and Drop the Run AppleScript workflow element onto the grey space;
Put the contents of this AppleScript in the textbox;
Save the workflow with a reasonable name (like New File);
Go to Settings -> Keyboard -> Shortcuts -> Services and assign a shortcut to it.
Now, let's show the AppleScript:
set file_name to "untitled"
set file_ext to ".txt"
set is_desktop to false
-- get folder path and if we are in desktop (no folder opened)
try
tell application "Finder"
set this_folder to (folder of the front Finder window) as alias
end tell
on error
-- no open folder windows
set this_folder to path to desktop folder as alias
set is_desktop to true
end try
-- get the new file name (do not override an already existing file)
tell application "System Events"
set file_list to get the name of every disk item of this_folder
end tell
set new_file to file_name & file_ext
set x to 1
repeat
if new_file is in file_list then
set new_file to file_name & " " & x & file_ext
set x to x + 1
else
exit repeat
end if
end repeat
-- create and select the new file
tell application "Finder"
activate
set the_file to make new file at folder this_folder with properties {name:new_file}
if is_desktop is false then
reveal the_file
else
select window of desktop
set selection to the_file
delay 0.1
end if
end tell
-- press enter (rename)
tell application "System Events"
tell process "Finder"
keystroke return
end tell
end tell
For convenience, I'm putting this AppleScript in this GitHub Gist.