I do not yet own DTP, but I’m very interested in it because of its ability to reveal relationships between documents. But, I also need to:
- keep track of to-do items,
- relate them to other documents in a database,
- have these to-do documents sort properly (in ascending and descending date order) in a list, and
- have their due dates readily visible,
- in one app,
all without having to manually paw through the to-do documents themselves.
As far as I can tell, DTP does not have any date field that can be used for assigning a Due Date to a document. (I think I read somewhere that one could reset the Date Created, but this will not work for my purpose, and besides, is not enough to uniquely identify a to-do item. I could, I suppose, add “ToDo” in the text of a document, but having to change two attributes makes this scheme fail if I forget to change one.)
So, in lieu of a Due Date attribute for documents, I am left to putting the due date in the subject of a document, and using a Smart Group to filter these documents out of the collection. But to do this, I must identify the to-do documents uniquely (which would be a snap if there were a “Due Date” attribute and support for it in Smart Groups, but I repeat myself…).
So, OK. In a document’s title, I can insert a unique character and a properly-formatted “date” string that sorts properly (“YYYY-MM-DD”). But, this is a pain, and the scheme fails if I make a typing error and don’t catch it.
So, OK. I can use AppleScript. But, AppleScript has no date picker control, and its input facilities are primitive and there’s no way to create forms, so I can’t build my own date picker. And, I’m an AppleScript novice, and always bang my head bloody against the wall when trying to use it.
But, OK. I worked all day to create the below AppleScript. It puts up a list of dates, and if one is selected, copies a string to the clipboard, of the format:
YYYY - MM - DD, DOW
where:
- is a unique character that a Smart Group can use to detect a dated to-do item, followed by a space,
- “YYYY - MM - DD” is a string composed of the 4-digit year, " - " (space, hyphen, space), the 2-digit (zero-padded) month, " - " (space, hyphen, space), and the 2-digit (zero-padded) day of the month,
- “, DOW” is a comma, a space, and the first three letters of the day of the week of the date represented in the string, and
- “” are two tab characters.
(I use space, hyphen, space in the string to aid readability. I zero-pad the month and day and use tabs at the end of the string to provide a fake form of justification, so that things hopefully line up in the titles of documents returned by a Smart Group’s action. I expect that a future version of the script could set the string directly into the beginning of a DTP document’s title, preserving anything that’s already in the title.)
There are some problems with this approach, one of the more important for me is: preparing the list can be time-consuming, so I need to start on some date, and calculate for some defined duration. Preparing a list of the dates for a year takes roughly a second on my 2.8GHz Core II Duo. This is acceptable, and I expect that most of my due dates will fall within this range.
So, OK. But, some life events take place farther in the future than one year from the current date. I can’t generate an infinite list of dates, nor can I use some sort of “More…” button to conveniently and rapidly fetch another year’s worth of dates. (Oh, for a scriptable date picker…in lieu of a DTP “Due Date” attribute…)
So, OK. To avoid these problems, before preparing a list of dates to choose from, the script first asks for a range:
- between now and 1 year from now
- between 1 - 5 years from now
- between 5 - 10 years from now
- between 10 - 20 years from now
Given that I expect that most of my to-do’s will be in the upcoming year from the current date, I used larger periods in the durations of the farther-away ranges, so that the inconvenience of waiting will be endured not so frequently.
Then, having set the start date and duration for the range, the script chews away and creates a list, which AppleScript unfriend-ily tosses up onto the screen in a miserable-looking, screen-high list box format, and I can choose a date, or cancel. If I select a date, the script then reformats the date to make it (what I think will be) friendly to the eyes in a DTP list generated by a Smart Group that looks for the unique character in documents’ titles.
So, OK, mission (sorta) accomplished. But, geez, what a pain this is. It’s just one compromise after another, to overcome limitation after limitation. This would be soooo simple if DTP had a “Due Date” attribute for documents.
What am I missing? Is there an easier way to accomplish in this sophisticated AI-enabled program what Journler can do with ease (using its “Due Date” attribute)? I’d really like to use DTP to meet other requirements, but dated to-do’s are important, and my tasks and way of working require supporting documentation with my to-do items. (Project management systems, and putting to-do items into a calendar with an alarm, do not work for me. I need my to-do’s and supporting documentation contained within one app.)
I cannot accept that assigning a due date to a DTP document, which can be filtered through Smart Groups, sorts properly in ascending and descending date order, and is readily visible and changeable, is outside DTP’s scope.
Please tell me that my approach is ridiculously overkill, and show me an easier way of meeting these requirements, and ideally, that DTP does in fact have a “Due Date” attribute for documents, which I’ve somehow stupidly overlooked. My head really hurts. Thanks very much everyone, for your advice.
(The board does not allow attaching .scpt, .txt, or .rtf files, so I could not attach the script as a file.)
-- ==================================================
-- Date Picker
-- display consecutive dates in a list box, and return the date selected in an easy-to-read format that sorts properly in text controls.
-- method:
-- 1. because preparing a list of dates can be time-consuming, prompt first for a time period to select from, i.e.,
-- between the current date and 1 year from the current date,
-- between 1 - 5 years from the current date,
-- between 5 - 10 years from the current date,
-- between 10 - 20 years from the current date.
-- 2. list the dates in the period selected in the format: "mm/dd/yyyy, DOW" e.g., "09/05/2011, Mon"
-- 3. return the date selected from a call to "choose from list" (if none selected, or Cancel button clicked, quit)
-- 3a. because a string is returned, not a date, prepare it in yyyy-mm-dd, dow format, so that these date strings will sort in proper ascending & descending order in text controls.
-- 3b. also, format the string so that it is easy to read in text controls such as lists, and
-- 3c. add a distinctive prefix to the selected date string, throw a couple of tabs onto the end to provide a fake form of justification, and copy it to the clipboard.
-- revision history:
-- 2011-09-04: original code
-- ==================================================
set magic to "›"
set curdate to current date
set datelist to {}
set padding to tab & tab & "-" & tab
-- promptlist, startat, and duration are parallel lists. their elements are accessed through a common index.
set promptlist to {¬
"Now" & tab & padding & "1 year from now", ¬
"1 year" & padding & "5 years from now", ¬
"5 years" & padding & "10 years from now", ¬
"10 years" & padding & "20 years from now"}
-- when, in months after the current date, to start counting the interval
set startat to {0, 12, 60, 120}
-- how many months to include in the interval
set duration to {12, 48, 60, 120}
-- ==================================================
-- 1. because preparing a list of dates can be time-consuming, prompt first for a time period to select from, i.e.,
-- between the current date and 1 year from the current date,
-- between 1 year from the current date and 5 years from then,
-- between 5 years form the current date and 10 years from then, and
-- between 10 years from the current date and 20 years from then.
set response to choose from list promptlist with prompt "Due Date between:" default items "Now" & tab & padding & "1 year from now" OK button name "Choose"
if response is equal to false then
return
end if
-- not finding a match should only happen during development & testing, but trap it.
set ctr to finditeminlist(response, promptlist)
if ctr is equal to 0 then
display dialog "Could not find " & "'" & response & "'" & " in the list." & return & return & "Click Cancel to exit." buttons "Cancel" default button "Cancel"
return
end if
-- ----------------------------------------------------------------------
-- set the start and end dates for the list.
-- both the start and end dates will use the current day number.
set startday to day of curdate as integer
-- i want the list to (at least roughly) reflect months, because it's a familiar concept: "2 months from now," etc.
-- the problem is that applescript does not natively know how to increment months.
-- applescript does natively understand how to increment weeks, but dealing with weeks is not intuitive -- is 2 months from now 8 weeks? sometimes, and sometimes not. it depends.
-- so, the script extracts the month from the start date, and adds the required number of months to that to get the end date.
-- calculate the start date: add the proper number of months to today to get the month to start from.
set startmonth to (month of curdate as integer) + (item ctr of startat) mod 12
-- add the proper number of months to today to get the year to start from.
set startyear to (year of curdate as integer) + ((item ctr of startat) / 12) as integer
-- convert these values to a date object for the start date.
set thestr to ((startmonth as string) & "/" & startday as string) & "/" & startyear as string
set startdate to date thestr
-- calculate the end date:
-- how many whole years must be added to today's date to get the year to end in?
set yearstoadd to ((item ctr of duration) / 12) as integer
-- how many months must be added to today's month to get the month to end in?
set monthstoadd to (item ctr of duration) mod 12
set endmonth to startmonth + monthstoadd
set endyear to startyear + yearstoadd
-- correct for year and month for months greater than 12.
if endmonth is greater than 12 then
set endyear to endyear + 1
set endmonth to endmonth - 12
end if
-- convert these values to a date object for the end date.
set thestr to ((endmonth as string) & "/" & startday as string) & "/" & endyear as string
set enddate to date thestr
-- display dialog (response as string) & return & "Start on: " & short date string of startdate & return & "End on: " & short date string of enddate
-- ----------------------------------------------------------------------
-- 2. list the dates in the period selected in the format: "mm/dd/yyyy, DOW" e.g., "09/05/2011, Mon"
set thedate to startdate
repeat while thedate is less than or equal to enddate
set listitem to (month of thedate as integer) & "/" & day of thedate & "/" & year of thedate as string
set newdate to (date (listitem)) as date
set wd to weekday of newdate
set wd to text items 1 through 3 of (weekday of newdate as string)
set listitem to listitem & ", " & wd
copy listitem to the end of datelist
set thedate to thedate + 1 * days
-- display dialog listitem
end repeat
-- ----------------------------------------------------------------------
-- 3. return the date selected from a call to "choose from list" (if none selected, or Cancel button clicked, quit)
set selected to choose from list (datelist) with prompt "Choose a Due Date:" OK button name "Choose"
if selected is equal to false then
-- cancelled with escape or clicking Cancel button
return
end if
-- "choose from list" returns a list object, which we needed to trap as "false" if the selection was cancelled.
-- but, now we need a string object to work with, so cast the result "as string".
set selected to selected as string
-- 3a. because a string is returned, not a date, prepare it in yyyy-mm-dd, dow format, so that these date strings will sort in proper ascending & descending order in text controls.
-- 3b. also, format the string so that it is easy to read in text controls such as lists, and
-- 3c. add a distinctive prefix to the selected date string, throw a couple of tabs onto the end to provide a fake form of justification, and copy it to the clipboard.
-- (i didn't pad the dates in the list because they are hard to distinguish if they all have the same length.)
set len to length of selected
if len is not equal to 15 then
-- selected is not "mm/dd/yyyy, dow" (15 characters long), so split it into chunks and see if month, day, or both need to be padded.
set delims to text item delimiters
set text item delimiters to "/"
set theitems to text items of selected
set monthitem to text item 1 of theitems
set dayitem to text item 2 of theitems
if length of monthitem is equal to 1 then
-- month is less than 10, so pad it
set m to "0" & monthitem
else
-- month is at least 10, no padding necessary
set m to monthitem
end if
if length of dayitem is equal to 1 then
-- day is less than 10, so pad it
set d to "0" & dayitem
else
-- day is at least 10, no padding necessary
set d to dayitem
end if
-- month and day are both 2 digits long now, put the pieces back together.
set selected to m & "/" & d & "/" & text item 3 of theitems
set text item delimiters to delims
end if
-- replace "/" with " - " because it seems be easier to read in a list.
-- (dates seem easier to read in the "Choose from list" selection list with slashes.)
set olddelims to text item delimiters
set text item delimiters to "/"
set theitems to text items of selected
-- because a string is returned, not a date, prepare it in yyyy-mm-dd, dow format, so that these
-- date strings will sort in proper ascending & descending order in text controls.
set selected to items 1 through 4 of text item 3 of theitems & " - " & text item 1 of theitems & " - " & text item 2 of theitems & items 5 through 9 of text item 3 of theitems
-- & " - " & text item 2 of theitems & " - " & text item 3 of theitems
-- set selected to text item 1 of theitems & " - " & text item 2 of theitems & " - " & text item 3 of theitems
set text item delimiters to olddelims
-- add the date delimiter to the selected date as a prefix and a suffix, so that it stands out in the subject of a note,
-- and so that notes with due dates can be found by searching.
-- (i left the prefix out of the dates in the list because they are distracting, and not needed.)
-- also, add 2 tabs to the end, to help to justify the entries in a list.
set selected to magic & " " & selected & tab & tab
set the clipboard to selected as string
-- ==================================================
on finditeminlist(lookfor, inlist)
repeat with ctr from 1 to (count of inlist)
set tmp to item ctr of inlist
-- display dialog "ctr=" & ctr & return & "find " & tab & "-" & lookfor & "-" & return & "- in -" & tab & "-" & tmp & "-"
if (lookfor as string) is equal to (item ctr of inlist as string) then
return ctr
end if
end repeat
-- not found
return 0
end finditeminlist