AppleScript path being replaced at compile time (New Keynote scripting trouble) - scripting

We've got an applescript that tells keynotes to delete slides based on criteria. The new keynote does not have an applescript dictionary, but leaves the old keynote in a subdirectory. So I'm trying to tell AppleScript to talk with the older app rather than the new one.
If I just
tell application "Clean Install:Applications:iWork '09:Keynote.app"
It works, but it doesn't recognize any of the keynote dictionary terms. (delete a slide). So I need to pull out my old friend "using terms from". The challenge here is that this is a precompile directive, so you have to use a string literal, which I don't have on the end user's machine due to different hard drive names.
Ok, still have a plan here. I will write out a new applescript file with the 'using terms from application "Clean Install:Applications:iWork '09:Keynote.app"' and then execute that file... Genius... except for the fact that when AppleScript compiles this line:
using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
Gets changed to:
using terms from application "Keynote"
Which of course calls the new keynote's dictionary which is empty.
Any thoughts on how to keep applescript from helping me out in this way? (or is there a better plan?)
full code:
using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
--using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
tell application "Clean Install:Applications:iWork '09:Keynote.app"
activate
end tell
end using terms from
many thanks!

I'm flyin' blind here (don't have keynote) ... but have you tried using a pre-defined app string as a variable and raw event codes?
You can use Smile to easily get raw event codes by
making a new script window in Smile;
using the "tell" menu item from the Action menu to make that script window application-specific (no tell
block needed);
write a line of code; select line of code
then use the "Copy translate" menu item (cmd-shift-C)
to copy the raw event codes
pasting that raw event code code into a different window that has your working (normal tell block) script
This is what it looks like when I do this for the Mail app:
set origMail to "MyDrive:Applications:Mail.app"
tell application origMail
delete («class mssg» 1 of «class mbxp» "INBOX" of «class mact» 1)
end tell
( When put in a normal tell block, that line of code would be "delete (message 1 of mailbox "INBOX" of account 1)" )

I haven't tried this but I think it will work... when you compile your code with "using terms from" just place your new version of Keynote in the trash. That should force it to use the old version of Keynote's dictionary and your code should compile. If you then save that code as an "applescript application" then it should work on anybody's computer without need to recompile. NOTE: you may need to restart your computer before this trick would work.
Then you just have the problem of targeting the right application on the user's computer because they too might have both versions. Here's some code to find the path to older versions of Keynote and how you would target that.
set lsregister to "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister"
set appName to "Keynote.app"
set nonapplescriptVersion to "6.0"
-- get the path to all Keynote apps
set appPaths to paragraphs of (do shell script lsregister & " -dump | grep " & quoted form of appName)
-- find the one with a version number less than the nonapplescriptVersion of Keynote
set appPath to missing value
repeat with anApp in appPaths
try
-- extract the path
set AppleScript's text item delimiters to "/"
set tis to text items of anApp
set thisPath to "/" & (items 2 thru end of tis) as text
set AppleScript's text item delimiters to ""
-- check the version
if (version of application thisPath) is less than nonapplescriptVersion then
set appPath to thisPath
exit repeat
end if
end try
end repeat
if appPath is missing value then error "Needed application version not installed."
-- use the older version
using terms from application "Keynote"
tell application appPath
activate
-- do whatever
end tell
end using terms from

Related

Is there any benefit to opening a file in VBA using a Sub vs using FollowHyperlink

So a little background - I have been using VBA for a few months now to write a program to speed up some of the work I do. This involves opening files, and at the moment I have been opening files with Autocad using the following sub:
Sub OpenAutocadFile(AutocadFile)
If AutocadVariable Is Nothing Then
Set AutocadVariable = CreateObject("AutoCAD.Application")
If AutocadVariable Is Nothing Then
MsgBox "Could not start Autocad"
Exit Sub
End If
Else
Set AutocadVariable = GetObject(, "AutoCAD.Application")
End If
Set AutocadApp = AutocadVariable
AutocadApp.Visible = True
AutocadApp.Documents.Open (AutocadFile)
End sub
Not perfect I know, but it works the majority of the time.
I also have been opening PDF files using:
ActiveWorkbook.FollowHyperlink(PDFFile)
Now my question is, is there any advantage to using one method or the other for opening a file in VBA?
I already know that with the dedicated sub, you can specify what program you want to use whereas with the hyperlink method it uses the default one.
So other than that am I missing something? Does one run faster than the other? Is one method preferable for certain file types whereas the other is for other file types?
The difference is functional, as they do different things to get similar results.
The CreateObject method uses an explicit application to open the reference, while FollowHyperlink uses the default application registered for that protocol, and passes the reference to that.
Which one is preferable is up to the developer, as sometimes you want user expected behaviour ("Open a PDF in my fave PDF viewer") and other times you may not want this. For example, maybe you know that the "open with" handler for this system doesn't do what you or the user wants.
Whether one is faster than the other isn't actually that important, as they are intended for different use cases.

applescript to move files in numeric order

i started a project for a friend, that involved moving large quantities of files into specific folders. i was using automator as I'm handling the project on my mac, however automator does not have a feature to move section of files that are numbered numerically. for instance i will have files that are say "this file 100" and ill have 100 files like that. and then files that say "That file 50" and ill have 200 files like that. the project is splitting these files into there own folder but in section. so ill need "This file" 1-25 in one folder 26-80 in anther and so on. same is true for the "THAT FILES" but there isn't a pattern just the requirement my friend has asked for.
is there a easy way to write a script that could grab 1-25 or any sequel ordering with the same file name? because moving each file one at a time with automator has been taking to long.
thank you so much in advanced
I am not sure tu fully understand your naming convention, but overall , yes, with Applescript, you can move files into folders based on names, eventually adding sequence numbers.
Because I am not sure about your requirements, at least, here are some sample of syntax for main operations :
Get list of files with names containing xxx in folder myFolder :
Tell Application "Finder" to set myList to every file of myFolder whose name contains "xxx"
Then you have to do a repeat / end repeat loop :
Repeat with aFile in myList
-- do something here with aFile : example with name of aFile
end repeat
In that loop you can extract name, parse it, add a counter,...
To move file to new folder, you must use "move" instruction in a tell "Finder" bloc. Instruction "make" can also be used to create new destination folder based on name or root names of files. You must remember that Applescript commands will give error if same file name already exists in destination folder : Finder is able to add "copy" in the name, but you must do it yourself in Applescript.
Last advice if about the number of files to handle. If that number is not so high (less than few hundreds) Applescript is still OK for speed. If your number of files is much higher, then you must use either shell command or, better, a mix of AS and shell commands. The shell commands can be called from AS with a "do shell script". For instance, getting the list of 1000 files from a folder is time consuming with AS, but much quicker with 'ls' command ! Same for a copy. here is an example of copy using shell 'cp' :
do shell script "cp " & quoted form of (POSIX path of (aFile as string)) & " " & quoted form of (POSIX path of DestFolder) & (quoted form of newFileName)
Note : "Posix path" converts the AS file path (Users:myName:Documents:File.txt) into shell path (Users/myName/Documents/File.txt)
I hope it helps.

Why has my VB.net program decided to be case fussy?

I have a small VB.net program that opens some text files, 2 Excel files, a PDF file & creates a new Word document, or opens it if it already exists. Nothing clever, no databases & it works just fine.
I have just bought a Lima device (https://meetlima.com) and have moved my data & program onto the HD attached to it. This is showing on my PC as the "L" drive and everything seems to work EXCEPT the program has now decided to be fussy about the case of the data names !!!
For instance, this code worked just fine before I moved it from my "D" drive to "L" when trying to use the file Tes1 when the value of myLeftCB is TES
myRARfile = myFolder + myLeftCB + mySession + ".zip"
Now I have had to edit the code to this
myRARfile = myFolder + StrConv(myLeftCB, VbStrConv.ProperCase) + mySession + ".zip"
The trouble is, there are a number of similar checks & I don't really want to change all of them, if possible I'd just like to know why something has changed, and where, so I can hopefully change it back !!!
Because Lima is a separate device acting as a file system it's almost certain to be running some form of *nix and that means a case sensitive file system. In order to map case insensitive Windows filenames onto case-sensitive storage they must be doing some magic, leading to your unexpected results.
I agree with #Steve that you're going to have to seek answers from the vendor documentation for this one. In particular, examine the technical documentation to see if there are settings that control how case sensitivity is managed.
If you've got a number of places where this code is duplicated then I'd say that you've already got a weak point in your code. I suggest replacing all of those lines with call to a function that returns the filename. That's a pain to do but it replaces the code duplication so if you have to change the code in future you're only changing it in one place. Your code is easier to maintain and when the Lima vendors change their API in two months you'll only have to change the code in one place to fix it.

Embed Applescript in Global Field to (Export Container and Trigger Printing with Acrobat)

I am trying to tie together a filemaker script that will export PDFs to a temporary space and use and apple script to print them.
I was able to cull together info from this and some other boards to create an applescript that will print the PDFs using Acrobat from a folder.
I have already created a script that finds the Related attachments and exports them to the desktop.
What I'm having trouble with is merging the two.
I need to export the PDF to a folder or temporary place and trigger the apple script to initiate the printing...
This great Suggestion was provided by Chuck of chivalrysoftware.com/…...
Calculate the location to export by appending the filename to Get( TemporaryPath ).
Export the container field contents to FileMaker to that path.
Save the path to a global field in FileMaker
Use an embedded AppleScript to access the global field path
Use AppleScript to open the file in Preview and print it
This is my apple script:
set myFolder to (path to desktop folder as text) & "Print:"
set myfiles to list folder myFolder without invisibles
repeat with myfile in myfiles
set mycurrentfile to ((myFolder as string) & (myfile as string)) as string
batchprint(mycurrentfile)
end repeat
on batchprint(mycurrentfile)
tell application "Adobe Acrobat Pro"
activate -- bring up acrobat
open alias mycurrentfile -- acrobat opens that new file
tell application "System Events"
tell process "Acrobat"
click menu item "Print..." of menu 1 of menu bar item "File"¬
of menu bar 1
click button "Print" of window "Print"
tell application "System Events"
tell process "Acrobat"
click menu item "Close" of menu 1 of menu bar item "File"¬
of menu bar 1
end tell
end tell
end tell
end tell
end tell
tell application "Finder" -- to move the printed file out
set x to ((path to desktop folder as text) & "Printed PDFs:")
if alias x exists then
beep
else
make new folder at the desktop with properties {name:"Printed PDFs"}
end if
move alias mycurrentfile to folder "Printed PDFs"
end tell
end batchprint
My Filemaker script is:
Go to Related Record[
Show only related records; From table: 'Attachments";
Using layout: "Attachements Report' (Attachments); New window
]
Enter Find Mode
Constrain Found Set [Restore]
Sort Records [Restore; No dialog]
# After finding the related attachments and constraining them to the specific type
# we rename and export them to the desktop
Go to Record/Request/Page [First]
Loop
Set Variable [$Path; Value:
Get ( DesktopPath ) & Attachments::Record number & "-"
& Attachment Type List 2::Prefix_z & Lien::Lien_ID_z1]
Export Field Contents [Attachments::file_c; $Path]
Go to Record/Request/Page [Next: Exit after last]
End Loop
Close Window [Current Window]
First of all, the FileMaker part. Create a global text field in one of your tables. It looks like the Attachments table would be the best place for it. I'll call it g_applescript_parameter for this.
Now we're going to use your $Path variable, which given the calc you've provided should be something like /Aslan/Users/chuck/Desktop/1234-ABC4321. I'd recommend appending a .pdf to the end of it since you'll be exporting PDF files. This may help later.
Also, I would recommend that you use Get( TemporaryPath ) instead of Get( DesktopPath ). Anything you place in the temporary folder will be automatically deleted when you quit FileMaker, which means you don't have to write anything to clean up the desktop folder later and you don't have to manually trash them either. Let FileMaker do that work for you. :)
Regardless, FileMaker uses a path of the form filemac:/volumeName/directoryName/fileName (see the notes in the Specify output file dialog box for the Export Field Contents script step). So you should also prepend filemac: to the beginning of your path variable.
All told, your $Path should be set to something like this:
"filemac:" & Get( DesktopPath ) & Attachments::Record number & "-" &
Attachment Type List 2::Prefix_z & Lien::Lien_ID_z1 & ".pdf"
So your export path for FileMaker should work better now. But AppleScript requires a different format for the path to the same file. Given the above, AppleScript's version should be something like /Users/chuck/Desktop/1234-ABC4321.pdf. In other words, everything after the drive name. Fortunately FileMaker can get the drive name with the Get( SystemDrive ) function. For me that function returns /Aslan/. So if we take the $Path variable as defined above and remove filemac: and the name of the drive as defined by Get( SystemDrive ) and add an extra slash at the beginning, that would convert our FileMaker path into an AppleScript path:
"/" & Substitute( $Path; "filemac:" & Get( SystemDrive ); "" )
Use Set Variable to create an $ASPath variable and set it to the above.
Now within your loop store the contents of the $ASPath variable within that global text field:
Loop
Set Variable[ $Path; …]
Set Variable[ $ASPath; …]
Set Field[Attachments::g_applescript_parameter; $ASPath)
Export Field Contents[Attachments::file_c; $Path]
Go to Record/Request/Page[Next; Exit after last]
End Loop
Now AppleScript can extract that information. I'm assuming that given an accurate file being passed to the batchprint function, batchprint will work, so keep that, but remove everything before it and use something like this:
set _pdf_path to contents of cell "g_applescript_parameter" of current layout
batchprint(_pdf_path)
on batchprint(mycurrentfile)
...
end batchprint
Add a Perform AppleScript step after the Export Field Contents step and place the above code in it.
Note that the first line of the above AppleScript will only work as written from within FileMaker. If you're testing this outside of FileMaker in, for example, Script Editor, then you'll need to make that first line read
tell applicaiton "FileMaker" to set _pdf_path ...
You don't need to do this within the Perform AppleScript script step because by default commands are sent to the enclosing FileMaker application.

Add time and date in custom/user Code Snippet in XCode

How can I add date time in my custom code snippet?
I need frequent use to add my codes on other codes, and for others, I need to add my name and date time.
I created a code snippet with shortcut _ase, but I am not finding any help on net how can I add time to it.
You can't add date or time automatically using the native Xcode snippet grammar.
Snippets do not have anything other than token substitution using the <#VisibleTokenName#> syntax.
File templates are generated differently and have token substitution for a small subset of predefined tokens (like ___DATE___) in addition to the ability for custom tokens gathered in the UI.
You could write a bash script (or whatever) to update the snippet file for you with the correct date.
Looks like you can't do this using XCode snippets but I can suggest a quick workaround using apple script:
set str to "// Created by Anoop Vaidya on " & (do shell script "date '+%d/%m/%Y'")
tell application "Xcode"
activate
set the clipboard to (str as text)
tell application "System Events"
keystroke "v" using command down
end tell
end tell
You can set date using apple script:
set str to ("// Created by Anoop Vaidya on " & day of (current date) & "/" & ((month of (current date)) as integer) as string) & "/" & year of (current date)
but it is not so convenient as using shell script.
Now you need only to bind that script to some shortcut (using FastScripts for example) and use it.
You can add some additional functionality to the script like saving previous value from clipboard and then restoring it or may be just using some XCode scripting properties to directly insert text without clipboard.