The Omni Group Forums

The Omni Group Forums (http://forums.omnigroup.com/index.php)
-   OmniFocus Extras (http://forums.omnigroup.com/forumdisplay.php?f=44)
-   -   OF Applescript bug: querying for dates with missing values (http://forums.omnigroup.com/showthread.php?t=16709)

RobTrew 2010-07-09 01:16 AM

OF Applescript bug: querying for dates with missing values
 
Now that Tim has added the excellent [B]flattened tasks[/B] and other related properties to the OF Applescript library in the Sneaky Peek builds, it would be very useful to find all tasks that lack start dates (or perhaps due dates).

Queries of this kind do work well in OO3. If we have an OmniOutliner document with a user-defined date column, we can find any undated rows with code like:

[CODE]tell application id "com.omnigroup.OmniOutlinerPro3"
if (count of documents) < 1 then return
tell front document
try
set lngCol to index of (first column whose type is date)
on error
display dialog "There are no date columns in the front document" & return & return & ¬
"Open or create a document with a user-defined date column, and try again ..."
return
end try
[B]set refUndatedRows to a reference to (rows where value of cell lngCol is missing value)[/B]
set expanded of refUndatedRows to true
set selected of refUndatedRows to true
display dialog ((count of refUndatedRows) as string) & " undated rows selected"
end tell
end tell
[/CODE]

In OmniFocus (sneaky peek builds), however, this kind of code currently fails. Lines like:

[CODE]set lstNoStart to flattened tasks where start date is missing value
set lstNoDue to flattened tasks where due date is missing value[/CODE]

will generate the error:
[CODE]OmniFocus got an error: Can’t make missing value into type date.[/CODE]

The problem seems to be that the underlying data type of a missing value (for any property) is made available in OO3, but is [B]not[/B] currently retrievable for several properties in OF.

This is suggested by the output of the code pasted below, in which the specific class of missing values for several OF properties appears to be opaque.

OmniOutliner missing values are all typed:
[IMG]http://farm5.static.flickr.com/4141/4776923524_ffed5e45e0_o.jpg[/IMG]

But several kinds of missing value in OF are not
(including start and due dates):
[IMG]http://farm5.static.flickr.com/4074/4776290167_53f4ef63bd_b.jpg[/IMG]

(Note that an indeterminacy in property sequence when records are coerced to lists seems to have flipped the class string for id and parent task in the second graphic)

Quick test code below:

[CODE]on run
tell application "OmniOutliner Professional"
tell front document
set oRow to make new row at end of rows
set lstProps to my proplist(oRow)
end tell
end tell

set lstSelns to {}
repeat with oProp in lstProps
if oProp contains "class" then ¬
if not (oProp begins with "class") then set end of lstSelns to oProp
end repeat
choose from list lstProps with title "OMNIOUTLINER Row" with prompt "Data type of all values available ..." default items lstSelns with multiple selections allowed


tell application "OmniFocus"
tell front document
set oTask to make new task at end of tasks of first project
set lstProps to my proplist(oTask)
end tell
end tell

set lstSelns to {}
repeat with oProp in lstProps
if oProp contains "class" then ¬
if not (oProp begins with "class") then set end of lstSelns to oProp
end repeat
choose from list lstProps with title "OMNIFOCUS Task" with prompt "Data type of several values unavailable ..." default items lstSelns with multiple selections allowed

-- BOTH WHERE QUERIES FAIL
-- (though analogous queries work with OmniOutiner)
tell application "OmniFocus"
tell front document
set lstNoStart to flattened tasks where start date is missing value
set lstNoDue to flattened tasks where due date is missing value
end tell
end tell
end run

------------

-- Build a list of the names and classes of the properties of an object
on proplist(oObj)
set recProps to (properties of oObj)

-- AND LIST THE CLASSES OF EACH PROPERTY
set lstProps to recProps as list
set lstClass to {}
repeat with oValue in lstProps
set end of lstClass to class of oValue as string
end repeat

-- EXTRACT THE NAME OF EACH PROPERTY
-- BY CONVERTING THE PROPERTY LIST TO A STRING
-- AND TRANSLATING EACH 4-LETTER CODE TO AN ENGLISH PROPERTY NAME
set strDelim to text item delimiters

-- Convert the record to a string (by decoding an error message :-)
set strProps to my Rec2Str(recProps)
set text item delimiters to ", «"
set lstItems to text items of strProps
set text item delimiters to ""
set first item of lstItems to (characters 3 thru end of first item of lstItems) as text

set lstPropName to {}
repeat with oItem in lstItems
-- Extract the class property from the start
set text item delimiters to "»"
set lstParts to text items of oItem
set strClass to "«" & first item of lstParts & "»"
set oClass to run script strClass
set end of lstPropName to (oClass as string)

-- Look for any other properties in the rest of the string
set strRest to item 2 of lstParts
set text item delimiters to ", "
set lstRest to text items of strRest
repeat with strPart in lstRest
set text item delimiters to space
set strPossible to first item of text items of strPart
set text item delimiters to ":"
set lstCommaParts to text items of strPossible
if length of lstCommaParts is 2 then
set strPropName to first item of lstCommaParts
if length of strPropName > 0 then ¬
set end of lstPropName to strPropName
end if
end repeat
end repeat

-- COMBINE THE PROPERTY NAMES WITH THE LIST OF CLASSES
-- (ALLOWING FOR ALTERNATIVE CLASSES IN THE CASE OF THE 'PARENT' PROPERTY)

repeat with iProp from 1 to count of lstPropName
set (item iProp of lstPropName) to (item iProp of lstPropName) & " - " & item iProp of lstClass
end repeat

set text item delimiters to strDelim

-- SORT THE LIST ALPHABETICALLY
set lstPropName to ShellSort(lstPropName)
return lstPropName
end proplist

-- Convert a record to a string by stealing the interesting part of an error message ...
on Rec2Str(rec)
-- trigger the simplest error to get the measure of its message
set recDummy to {a:1} as record
try
recDummy as string
on error strShortMsg
set strDelim to text item delimiters
set text item delimiters to {"{a:1}"}
set lngStart to (length of first text item of strShortMsg) + 1
set lngEnd to length of last text item of strShortMsg
set text item delimiters to strDelim
end try
-- trigger an informative error and grab its string representation
-- of the record
try
rec as string
on error strRecordMsg
set lngEnd to ((length of strRecordMsg) - lngEnd)
set strRecord to text lngStart thru lngEnd of strRecordMsg
end try
return strRecord
end Rec2Str

-- use a shell script to sort a list
on ShellSort(lst)
set strDelim to text item delimiters
set text item delimiters to {ASCII character 10} -- linefeed
set strList to (lst as string)
set strNew to do shell script "echo " & quoted form of strList & " | sort -f"
set lstNew to (paragraphs of strNew)
set text item delimiters to strDelim
return lstNew
end ShellSort
[/CODE]

RobTrew 2010-07-09 03:16 AM

PS There are some other routes to the same result, but they are slow and clumsy, and being able to use [I]missing value[/I] correctly would be very much faster and simpler.

This, for example, proves slow ...

[CODE]-- set dte to missing value as date
tell application "OmniFocus"
set today to my TimelessToday()
tell front document
count of flattened task
[B]set refTasksNoStart to a reference to (flattened tasks where not (start date < today) and not (start date ≥ today))
set refTasksNoDue to a reference to (flattened tasks where not (due date < today) and not (due date ≥ today))[/B]

display dialog (((count of refTasksNoStart) as string) & " without start date" & return & return & ¬
(count of refTasksNoDue) as string) & " without due date" with title ("Total of " & (count of flattened tasks) as string) & " tasks"
end tell
end tell

on TimelessToday()
set dte to current date
date "00:00" of dte
end TimelessToday

[/CODE]

RobTrew 2010-07-09 03:26 PM

This problem has now been fixed ! (with very impressive speed)

As of Sneaky Peek build revision: 135625, the following now works well:

[CODE]tell application "OmniFocus"
tell front document
set refTasksNoStart to a reference to (flattened tasks where start date is missing value)
set refTasksNoDue to a reference to (flattened tasks where due date is missing value)
set refProjectsNoStart to a reference to (flattened projects where start date is missing value)
set refProjectsNoDue to a reference to (flattened projects where due date is missing value)
end tell
end tell
[/CODE]


All times are GMT -8. The time now is 04:05 AM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, vBulletin Solutions, Inc.