I have a script that I'm using to automate a small workflow but I am stuck trying to get the Subject to list the current month.
Here is my script:
tell application "Finder" to set selectedItem to item 1 of (get selection)
set theAttachment to selectedItem as alias
set fileName to name of selectedItem
tell application "Microsoft Outlook"
set newMessage to make new outgoing message with properties {subject:"(current month) as string Message from John Doe"}
tell newMessage
make new attachment with properties {file:theAttachment}
end tell
open newMessage
get newMessage
end tell
Is this possible? I've tried searching online and in Script Debugger but I keep coming up short. Thanks in advance.
I don't use Microsoft Outlook, so I'm going to assume that your script executes without error, but simply produces an undesired result, namely an new outgoing email with the words "(current month) as string Message from John Doe" in the subject line.
On this basis, to get your subject line to contain only the current month, find the relevant line in your script that contains this:
{subject:"(current month) as string Message from John Doe"}
and replace it with this
{subject:(current date)'s month as text}
If you want the subject line to include additional text after the month, as your original script does, then you can instead replace it with this:
{subject:((current date)'s month as text) & " Message from John Doe"}
I'm new to Applescript and I've built this from code I've found online, and can't really get it to work.
What I want to do is the following
A rule in Apple Mail will trigger the script to find 2 text strings inside the body of the mail.
I want to extract two things from the e-mail
Due date (Återlämningsdatum)
Title of the book (Titel)
Then I want to create a todo in Things with the title of the book as name of the todo and the due date as due date.
The problem I run into now is that I don't get any data from the mail, just a empty todo is created.
Any ideas?
E-mail below
2017-03-22 18:43:55
MALMÖ STADSBIBLIOTEK
Stadsbiblioteket
Låntagarnummer: **********
Utlån
-------------------------
Titel: Ägg : recept & teknik / Tove Nilsson ; [fotografi: Charlie Drevstam]
Exemplarnummer: 3054550018
Återlämningsdatum: 2017-04-19
-------------------------
Antal utlånade material: 1
Code below
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set subjectText to "Återlämningsdatum: "
set contentSearch to "Titel: "
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
tell application "Mail"
set theContent to content
set theDate to my getFirstWordAfterSearchText(subjectText, theContent)
set theTitle to my getFirstWordAfterSearchText(contentSearch, theContent)
end tell
end perform mail action with messages
end using terms from
tell application "Things3"
set newToDo to make new to do
set name of newToDo to theTitle
set due date of newToDo to theDate
end tell
(*============== SUBROUTINES =================*)
on getFirstWordAfterSearchText(searchString, theText)
try
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, searchString}
set textItems to text items of theText
set AppleScript's text item delimiters to tids
return (first word of (item 2 of textItems))
on error theError
return ""
end try
end getFirstWordAfterSearchText
In my testing, your script returns the following values:
theDate: "2017"
theTitle: "Ägg"
So, I'm assuming you should perhaps get a blank to-do named "Ägg" ? If not, you could try:
tell application "Things3" to make new to do with properties ¬
{name: theTitle, due date: theDate}
(although I neither use nor own Things 3, so cannot test this for you).
Anyway, to address the original problem, the issue is in only asking your handler getFirstWordAfterSearchText to return the first word. I don't speak Swedish, but it looks to me that the title contains more than one word. The date most definitely does, as each word is separated by a hyphen (which is considered a non-word character in AppleScript).
My suggestion would be to split the email content into paragraphs, isolate the lines of text that start with either "Titel" or "Återlämningsdatum", then return those lines, excluding any unwanted words. Here's a handler that does this:
to getFirstParagraphThatStarts on searchString ¬
from theText ¬
apart from excludedStrings : null
local searchString, theText, excludedStrings
repeat with P in theText's paragraphs
if P starts with the searchString then exit repeat
end repeat
set the text item delimiters to {null} & the excludedStrings
text items of P as text
end getFirstParagraphThatStarts
I called the handler much like you did yours:
set theDate to getFirstParagraphThatStarts on subjectText from theContent
set theTitle to getFirstParagraphThatStarts on contentSearch from theContent
(I omitted the apart from parameter to begin with, to test the return result before any exclusions were imposed). The return result was this:
theDate: "Återlämningsdatum: 2017-04-19"
theTitle: "Titel: Ägg : recept & teknik / Tove Nilsson ; [fotografi: Charlie Drevstam]"
Then I added in the apart from parameter:
set theDate ¬
to getFirstParagraphThatStarts on subjectText ¬
from theContent ¬
apart from subjectText
set theTitle ¬
to getFirstParagraphThatStarts on contentSearch ¬
from theContent ¬
apart from contentSearch
and the return results were as follows:
theDate: "2017-04-19"
theTitle: "Ägg : recept & teknik / Tove Nilsson ; [fotografi: Charlie Drevstam]"
which, I think, is more along the lines of what you are wanting.
ADDENDUM 1: Dates
Another thought I had regarding Things 3 is that the due date property might require an actual AppleScript date object, rather than just a string that looks like it might be a date. That is, "2017-04-19" might not be a valid due date. Again, I neither use nor own Things 3, so this is just speculation.
AppleScript date formats are intrinsically tied to your system settings. As I have my system date/time preferences set to use international ISO-8601 date representations, i.e. yyyy-mm-dd, I can create the AppleScript date object straight from theDate variable like so:
date theDate
If this is the case with you, and it turns out that you do require a date object, then you can simply set due date of newToDo to date theDate, or (if using my suggested code from above):
tell application "Things3" to make new to do with properties ¬
{name: theTitle, due date: date theDate}
If, however, your system settings are set differently, you'll need to construct the AppleScript date object yourself. Here's a handler that will do this:
to makeASdate out of {year:y, month:m, day:d}
local y, m, d
tell (the current date) to set ¬
[ASdate, year, its month, day, time] to ¬
[it, y, m, d, 0]
ASdate
end makeASdate
You would then use your theDate variable with this handler like so:
makeASdate out of {year:word 1, month:word 2, day:word 3} of theDate
--> date "Wednesday, 19 April 2017 at 0:00:00"
ADDENDUM 2: Scripting Mail (added 2018-08-12)
After further testing and debugging, you've found that there are other issues with your script that stop it from functioning. This was an oversight on my part, as I ought to have highlighted these errors initially, but became focussed on your handler returning incomplete strings that I neglected to come back to the rest of the script and address its other problems.
The problem section, as you've discerned, is this one here:
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
tell application "Mail"
set theContent to content
set theDate to my getFirstWordAfterSearchText(subjectText, theContent)
set theTitle to my getFirstWordAfterSearchText(contentSearch, theContent)
end tell
end perform mail action with messages
end using terms from
You tell application "Mail" to set theContent to content, however, you haven't specified what the content belongs to (or, rather, implicitly, you've specified that the content belongs to application "Mail", which it doesn't).
Presumably, you wish to refer to the content of theMessages that are sent through to this script by your mail rules ?
The other major thing to note is that on perform mail action with messages is an event handler, i.e. it responds to an event taking place in Mail, which causes the handler to be invoked. Defining other handlers elsewhere in the script is perfectly fine; but having stray lines of code that don't belong to any explicit handler will therefore belong to an implicit (hidden) on run handler. This, in a way, is an event handler as well: it responds to a script being run, which is problematic if the script is also being asked to respond to a Mail event simultaneously.
Therefore, the tell app "Things3" block needs to be moved, and I imagine the variable declarations at the beginning need to be housed as well.
Bearing all this in mind, I reworked your script to quite a large extent, whilst also trying to keep it resembling your original so it was somewhat recognisable:
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
set dateToken to "Återlämningsdatum: "
set titleToken to "Titel: "
repeat with M in theMessages
set theContent to getMessageContent for M
set datum to restOfLineMatchedAtStart by dateToken from theContent
set titel to restOfLineMatchedAtStart by titleToken from theContent
if false is not in [datum, titel] then
set D to makeASdate out of (datum's words as list)
createToDoWithDueDate on D given name:titel
end if
end repeat
end perform mail action with messages
end using terms from
to makeASdate out of {Y, M, D}
local Y, M, D
tell (the current date) to set ¬
[ASdate, year, its month, day, time] to ¬
[it, Y, M, D, 0]
ASdate
end makeASdate
to createToDoWithDueDate on D as date given name:N as text
tell application "Things3" to make new to do ¬
with properties {name:N, due date:D}
end createToDoWithDueDate
to getMessageContent for msg
local msg
tell application "Mail" to return msg's content
end getMessageContent
on restOfLineMatchedAtStart by searchString from theText
local searchString, theText
ignoring white space
repeat with P in theText's paragraphs
if P starts with the searchString then
set i to (length of searchString) + (offset of searchString in P)
try
return text i thru -1 of P
on error -- matched entire line
return ""
end try
end if
end repeat
end ignoring
false -- no match
end restOfLineMatchedAtStart
Now, as I don't use Mail and cannot test these mail rules out myself, there could be one or two minor tweaks that you'll discover need to be made before it's running properly. On the other hand, it might run correctly as it is, which would amaze me. But, having spent a lot of time thinking about each line of code, I'm hopeful it's close to what you need.
The major change you can see is that every piece of code now belongs inside a handler. The custom handlers each get called from inside the main event handler, on perform mail action with messages. I also changed some of the variable names, mainly as part of my mental debugging that was going on (I changed them several times, and have left them to what their last meaningful label was in my head).
Let me know how it goes. Report back any errors.
NOTE: Don't forget, however, that this script is designed to be called by the Mail application in response to a mail rule being actioned. Running it from within Script Editor will not do anything.
I have an filemaker Pro 13 database with around 120 records (it's for a conference). I want to team it up with BBEdit to create individual files for each abstract, thus applescript. Much to my surprise (and despite a lot of web tips on scripting) '[tag:current record]' is not recognised in the script.
The relevant bit is this:
FM Script:
Loop
Perform Applescript
tell application "FileMaker Pro"
activate
set MyFileName to cell "WebAbstractFileName" of table "SelectionProcess"
set MyWebAbstract to cell "WebAbstract" of table "SelectionProcess" as text
end tell
-- (BBEdit bit, which works fine in testing)
Go to Next Record (exit after last)
End Loop
This works fine if I only want to retrieve the first record!
This applescript is set within a filemaker script which loops through the records but the script doesn't care which record it's in.
I've tried adding 'of current record' before the table reference but it then gives me errors (eg error "FileMaker Pro got an error: Object not found." number -1728 from cell "WebAbstractFileName" of current record of table "SelectionProcess") Without 'current record' it works fine, but only gives me the first record.
Here's (roughly) how you could do this in a Filemaker script:
Go to Layout [ “YourTable” ]
# FIND THE RECORDS OF INTEREST
Perform Find [ Restore ]
Go to Record/Request/Page [ First ]
Loop
New Window [ ]
# ISOLATE THE CURRENT RECORD
Show All Records
Omit Record
Show Omitted Only
Set Variable [ $path; Value:Get ( DocumentsPath ) & "someFolder/" & YourTable::Somefield & ".html" ]
Export Records [ No dialog; “$path” ]
Close Window [ Current Window ]
Go to Record/Request/Page [ Next; Exit after last ]
End Loop
This will export every record in the found set as an individual file into the folder "someFolder" located in the user's Documents folder, using the contents of the YourTable::Somefield field as the filename.
If, as you say, you don't need the separate files, then of course this can be much simpler.
More tinkering solved this. The crucial bit was to change the syntax. The script now reads:
tell application "FileMaker Pro"
activate
tell current record to set MyFileName to cell "WebAbstractFileName"
tell current record to set MyWebAbstract to cell "WebAbstract"
end tell
What seems to happen is that the fields must be visible (yet I had that not be a problem at one point...go figure. If they're visible, you can drop the table specification). This script, wrapped in a Loop block, will act on the found set and (if instructed) exit after the last record.
I append the bbedit script to create a new file and save it with a variable taken from another field in case it's of interest.
tell application "BBEdit"
set notesPath to ":Users:ophiochos:Dropbox:TL Conference Admin:Webpage materials:Abstracts:"
set newFilePath to notesPath & MyFileName & ".html"
set newDoc to make new text document with properties {contents:MyWebAbstract}
tell newDoc
set source language to "HTML"
save to newFilePath
close window
end tell
end tell
Or you could simply create a calculated field that contains the contents of the desired export file for each record, loop through the records one by one, and just use an Export Field Contents ['YourCalculatedField_c'] script step.
You can also use FM to preview the html output by using a web viewer to display your html. This, along with exporting individually, you can get all this functionality without the need for an external program.
If you need to change the text encoding for output files, you can also specify those in an xslt for outputting files:
http://filemakerhacks.com/2012/09/23/export-field-contents-as-utf-8/
Also, if performing applescript from within FileMaker, the "tell application" line is not needed since it is implied.
Usually i quickly update my TODO list creating a new empty file named like this:
2013-10-01 Tell a friend that stackoverflow rocks
2013-10-23 Prepare my super meeting about coding
and so on..
i just need a workflow or applescript that take all file in the folder, extract the date and the title from the file name and creates a new iCal event on that day with that title!
it seems so easy, but how can i achieve that?
Here's something in straight Applescript.
Note: It depends on you changing your date format to DD-MM-YYYY (due to Applescripts in built date parser)
tell application "Finder"
set data_folder to folder POSIX file "/Users/me/Desktop/my_ical_data"
set all_items to every item of data_folder
end tell
set my text item delimiters to {" "}
repeat with cur_item in all_items
set nm to the name of cur_item
set event_date to date (text item 1 of nm)
set event_desc to (text items 2 thru -1 of nm) as string
tell application "iCal"
tell calendar "Work" -- name of calendar you wish to add to
make new event with properties {summary:event_desc, start date:event_date, description:""}
end tell
end tell
end repeat
This does not require you to change the date format in System Preferences:
tell application "Finder" to name of items of folder POSIX file "/Users/username/todo"
repeat with l in result
set s to text ((offset of space in l) + 1) thru -1 of l
set d to current date
tell d to set {year, month, date, time} to {text 1 thru 4 of s, text 6 thru 7 of s, text 9 thru 10 of s, 0}
tell application "iCal" to tell calendar "Work"
make new event with properties {summary:s, start date:d}
end tell
end repeat
I have built an applescript based app in Xcode V3.2.6 under OSX 10.6.7.
I want to have additional code to my application so when the system launched, it will compare the date I set in the application with the system date.
If date within range specified, proceed. If date check is out of range then terminate program immediately.
currently the code looks something like this:
on clicked the Object
if name of theObject = "One" then
try
display dialog "ONE"
end try
else if name of theObject = "two" then
try
display dialog "TWO"
end try
end if
end clicked
on action theObject
end action
One of the very nice users in this fourm post Chuck has posted something. The code works great under apple scripter but not when I pasted into the Xcode.
Can any one tell me what I am doing wrong?
posted by Chuck
set range to 3 * days
set targetDate to (date "Saturday, March 19, 2011 12:00:00 AM")
set currDate to current date
if abs(targetDate - currDate) > range then
display dialog "quit"
else
display dialog "continue"
end if
on abs(n)
if n < 0 then
return -n
else
return n
end if
end abs
Thanks so much!
It's been a long time since I worked with the technology formerly known as AppleScript Studio. :) However, I just created a Cocoa-AppleScript application and I see that the file UntitledAppDelegate.applescript has the following by default:
script UntitledAppDelegate
property parent : class "NSObject"
on applicationWillFinishLaunching_(aNotification)
-- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching_
on applicationShouldTerminate_(sender)
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate_
end script
Note the on applicationWillFinishLaunching_ handler and the comment placed there by Xcode. This is where you want to place code that will execute when the program launches. For example, I placed a beep statement in there and the application beeped when it launched. So I'm guessing you could have something like this:
on applicationWillFinishLaunching_(aNotification)
-- Insert code here to initialize your application before any files are opened
set range to 3 * days
set targetDate to (date "Saturday, March 19, 2011 12:00:00 AM")
set currDate to current date
if (currDate - targetDate) > range then
display dialog "quit"
else
display dialog "continue"
end if
end applicationWillFinishLaunching_