I wrote an application for my colleagues so that they can easily set their Outlook signature. Here is the code:
property includeInRandom : false
property sigName : "${signature.name}"
property sigContent : "${signature.content}"
try
tell application "Microsoft Outlook"
activate
set newOutlookSignature to make new signature with properties ¬
{name:sigName, content:sigContent, include in random:includeInRandom}
end tell
end try
The problem is that if a colleague changes his signature in the application and sets it in Outlook again there are two signatures with the same name. Is it possible to check if the current signature already exists and if it exists it should be edited/updated?
I don't have Microsoft Outlook, so I can't test my suggestions out, but I imagine you could get every signature whose name is sigName, then decide if you want to just delete them all and make a new one, or keep one, edit it, and delete the rest. I'm obviously working on the assumption there could be anywhere between 0 and N signatures sharing one name that have accumulated over time. From this standpoint, I'd say that deleting them all and making new one would be easiest coding wise, provided Outlook lets you delete a list of signatures the way, say, Finder lets you delete a list of files in a single command:
tell application "Microsoft Outlook" to delete every signature whose name is sigName
If it doesn't, you would have to construct a repeat loop and delete them one by one:
tell application "Microsoft Outlook" to repeat with S in ¬
(every signature whose name is sigName)
set S to the contents of S # (dereferencing)
delete S
end repeat
If you decide you want to keep one and edit it, then:
tell application "Microsoft Outlook"
set S to every signature whose name is sigName
if (count S) is 0 then
# make new signature
else
set [R] to S
delete the rest of S
set the content of R to the sigContent
end if
end tell
If delete the rest of S doesn't work, a repeat loop again will let you delete items 2 onwards individually, and keep just the first item to edit.
I'm sorry I can't test this for you, but it's at least an indication of how to go about trying to do it.
Related
My Apple Music library is too big. I want to weed it out by removing a whole load of tracks that I have never listened to. I already did the same thing successfully with playlists but my script isn't working to remove tracks:
tell application "Music"
activate
set mytracks_list to (get the id of (every track whose loved is false and played count is 0 and rating is less than 60))
repeat with mytrack_id in mytracks_list
delete (the track whose id is mytrack_id)
end repeat
end tell
The mytracks_list is populated with no problems. The error message I get is:
error "Can’t get track whose id = item 1 of {130098, [............] }
Am I doing something wrong, and can it be made to work?
P.S. This is what worked for my playlists:
tell application "Music"
activate
set myplaylists_to_delete to (get the name of every playlist whose name does not contain "Adrian" and name does not contain "Loved" and name does not contain "Shazam" and name does not contain "Library" and name is not "Music" and name does not contain "Recent" and name does not contain "5 Stars" and name does not contain "Duo")
repeat with myplaylist in myplaylists_to_delete
delete playlist myplaylist
end repeat
end tell
Did you try:
tell app "Music"
delete every track whose loved is false and played count is 0 and rating is less than 60
end tell
Well-designed, well-implemented “AppleScriptable" apps can usually apply a command to multiple objects; you don’t need to iterate the objects yourself. (Hint: Apple event IPC = RPC + queries, not OOP.)
I have written an AppleScript that is activated by a mail rule whenever an email comes in that contains "+".
Why? I host my own mail server that allows for address tagging. What this means is that for example when I'm at a store and they ask for my email address, so they can email the receipt, I can give them my email address like this: whatmyemailnormallyis+nameofstore#domain.com. The applescript should then get the string between the "+" and "#" character, create a mailbox called "nameofstore" and move the message to it. Everything works fine except for I'm getting the following error:
"Mail got an error: Can’t set text item delimiters to {"+", "#"}."
This is my script:
tell application "Mail"
set unreadmessages to the first message of mailbox "INBOX" of account "Account"
set theEmail to extract address from sender of item 1 of unreadmessages
set mystring to theEmail
set text item delimiters to {"+", "#"}
set textlist to text items of mystring
set mylist to {}
repeat with i from 2 to count of textlist by 2
set end of mylist to item i of textlist
end repeat
get mylist
set mailboxName to mylist
set messageAccount to account of (mailbox of item 1 of unreadmessages)
set newMailbox to make new mailbox at (end of mailboxes of messageAccount) with properties {name:mailboxName}
repeat with eachMessage in unreadmessages
set mailbox of eachMessage to newMailbox
end repeat
end tell
When I run only the text extract portion of the script it works fine:
set mystring to "whatmyemailnormallyis+nameofstore#domain.com"
set text item delimiters to {"+", "#"}
set textlist to text items of mystring
set mylist to {}
repeat with i from 2 to count of textlist by 2
set end of mylist to item i of textlist
end repeat
get mylist
result:
{"nameofstore"}
Any help would be greatly appreciated. If anyone with better AppleScript skills than me can improve the script in other areas that would also be greatly appreciated.
This is an inheritance problem. The property (text item delimiters) is a property of the current application (AppleScript) instance, but it's being referenced unqualified inside the tell application block that directs commands to and enumerates properties from the target application, in this case Mail.
The temptation might be to set the text item delimiters outside the tell block, by moving it from its current line position to just before the block declaration. That's reasonable, but I think you've positioned it perfectly, as it's important (and good practice) to keep track of this property to ensure it's always appropriately set and, more significantly, never inappropriately not set. The most reliable way to do this, which also makes it easier to follow for other people, is to do as you've done, which is to set the property immediately prior to any statement where it exerts influence (namely, any time a list is coerced to text, or text is split into text items).
So, to avoid shuffling lines of code around, we need to be able to make it clear to the compiler that the property that we're referencing doesn't belong to application "Mail", but to the top-level scripting object, which will most typically be the current application. The three ways to do this are:
set AppleScript's text item delimiters to ...
set the current application's text item delimiters to ...
set my text item delimiters to ...
Stylistically, I favour the last option. However, my is not a synonym for current application nor for AppleScript, but rather a reference to the parent of your script. Unless the parent property is specifically declared in your script, then it will default to current application. However, there are reasons one might choose to assign a different value, in which case only the first or second of the above three options will be viable.
Here's a slight reworking of your script, which I'm afraid you'll have to test in lieu of my purchase of a new MacBook. I noticed some oddities in yours:
You obtain the first message in the inbox, but on the next line, reference item 1... of, what I imagine you thought would be a list of messages, but would in fact be a single message class object.
This single message object is the only message your script utilises to process the sender's email address. However, later on, you loop through, again, what you expect to be a collection of inbox messages, which, if it were, may not all have the same + tag.
You loopp through the text items generated by splitting the email address, and quite smartly start at index 2, and skip over every other item in the list. However, this list will only have three items in it, so there's never any looping to be done, and you can simply make use of text item 2.
In creating a new mailbox, you didn't first check to see if the mailbox already exists. I'm not sure whether Mail would throw an error, or silently ignore this. But I've redrafted the line to check first, and create if necessary.
Lastly, the final repeat loop is presently not necessary given unreadmessages is not a list (so might actually throw an error). So I removed the loop construct, but otherwise kept the line as it was. I'm not sure whether the mailbox property of a message is one that can be set, i.e. it might be read-only. If this is the case, that will throw an error, and you'll have to invoke the move command in order to move a message to a new mailbox. I may be wrong, though, and it may work just the way you intended.
tell application "Mail"
set firstInboxMessage to the first message in the inbox
set theEmail to extract address from sender of the firstInboxMessage
set my text item delimiters to {"+", "#"}
-- Since the script will trigger only when an email address
-- contains "+", we know text item 2 will always exist and
-- will always represent the slice of text we're after
set mailboxName to text item 2 of theEmail
set messageAccount to account of mailbox of the firstInboxMessage
tell the messageAccount to if the name of its mailboxes does not contain ¬
the mailboxName then make new mailbox at the end of its mailboxes ¬
with properties {name:mailboxName}
set newMailbox to the mailbox named mailboxName in the messageAccount
set the mailbox of the firstInboxMessage to the newMailbox
end tell
In reality, if you're invoking this script as a mail rule, you'll probably want to enclose this within the special handler that you can look up in the Mail scripting dictionary, called something like on receiving messages <messages> for mailbox rule <rule>
I have an applescript that checks for one of several external HDs I connect to my computer and makes an index of their contents. All the HDs follow the naming scheme HK_12345 where the first two letters are always the same but the numbers are different for each drive. I want the script to only check for drives with the 'HK' designation regardless of the ending numbers. I have this but it is not working. Any advice?
set folderContains to "HK_"
tell application "Finder"
set triggerFolder to folder whose name contains folderContains
end tell
tell application "Finder"
if folder triggerFolder exists then
-- some other code
end if
end tell
You should check for disks not folders:
set diskContains to "HK_"
tell application "Finder"
set selectedDisks to disks whose name contains diskContains
-- some other code
end tell
I was wondering how to return just the file extension from a string. I've tried the 'set variable to name extension of...' detailed in this question, but that only seems to work for recognized extensions. The idea is to sort files with the extension '.meta' into their own collection.
What I have now looks like
tell application "Finder'
set everyName to name of every item in entire contents of this_folder
end tell
set metaFiles to {}
repeat with n from 1 to count of everyName
set currentName to item n of everyName
set currentExt to last word of currentName --this assignment fails
if currentExt is "meta" then
set end of metaFiles to currentExt
end if
end repeat
I'm brand new to applescript so I appreciate any and all help/direction. Thanks!
Edit: Hacky Solution
I solved this by using the split function described here to break up the filename after every period. I grabbed the last string, made sure it wasn't the same as the first string in case there were no period characters, and then stored the corresponding filename.
The name includes the file extension, whether the Finder recognizes it or not. So just sort on the name like this...
tell application "Finder"
set metaFiles to (every item in entire contents of this_folder whose name ends with "meta") as alias list
end tell
If you aren't getting a name extension, make sure there actually is one and that you aren't looking at the end of the name. If you are going to be moving files around, you will also need to get the path, and not just the name. I don't think that making a list of your extensions is what you are going for, either - several different characters are used for word boundaries, but a period isn't one of them.
Why not just ask Finder for your file items?
tell application "Finder"
set metaFiles to (every item in entire contents of this_folder whose name extension is "meta") as alias list
end tell
I am building a Applescript droplet to automate some stuff. I have the following line:
tell application "Finder" to duplicate dropped
Dropped being a reference to the file that was dropped on the droplet. The documentation says that this returns a reference to the duplicated object.
I want to set myVariable to the reference that is returned but I can't find in any of the documentation how to actually do that!
if it's a droplet, be aware that the parameter is a list of aliases (you can drag more than one file!), and that if you duplicate a single finder item you will get a finder item, whereas if you duplicate more than one finder item, you will get a list of finder items. i.e. the return value of duplicate depends on the parameters sent to it.
AND... finder items are not very useful outside the finder. You'd be better off with aliases or POSIX paths.
So you probably need something like
on open (dropped)
tell application "Finder"
set duplicate_Finder_items to duplicate dropped
end tell
-- convert the Finder reference for each duplicate item to an AppleScript alias
set duplicate_item_aliases to {}
if class of duplicate_Finder_items is list then
repeat with i from 1 to number of items of duplicate_Finder_items
set the end of duplicate_item_aliases to (item i of duplicate_Finder_items) as alias
end repeat
else -- result was a single Finder item, not a list
set duplicate_item_aliases to {duplicate_Finder_items as alias}
end if
repeat with f in duplicate_item_aliases
set inf to (info for (f as alias))
set n to name of inf
display dialog "You duplicated a file. The duplicate is now known as " & n
end repeat
end open
The duplicate command allows for a location to be specified:
set theResult to duplicate reference ¬
to insertion location ¬
replacing boolean ¬
routing suppressed boolean
Parameter, Required, Type, Description
direct parameter, required, reference, the object(s) to duplicate
replacing, optional, boolean, Specifies whether or not to replace items in the destination that have the same name as items being duplicated
routing suppressed, optional, boolean, Specifies whether or not to autoroute items (default is false). Only applies when copying to the system folder.
to, optional, insertion location, the new location for the object(s)