listapplescriptreminders

AppleScript Error -1700 when trying to access Apple Reminders


I get an AppleScript script error with the following and would be very grateful if someone could explain why.

In Apple's Reminders application, I have created a simple list with four reminder items, named as follows:

      List Name:   Colours

     Reminders:   Red, Yellow, Light Green, Dark Green

In AppleScript, I've then set up this variable:

set lstMyList to {"Red", "Yellow", "Orange", "Blue"}

What I do not understand is the following, where the first two statements work but the third does not.

Statement 1. (succeeds)

This returns true, as the name of reminder 1 ("Red") is in lstMyList

tell application "Reminders"
    return (name of reminder 1 of list "Colours") is in lstMyList
end tell

Statement 2. (succeeds)

This returns {"Light Green", "Dark Green"}

tell application "Reminders"
    return (name of every reminder in list "Colours") whose name contains "Green"
end tell

Statement 3. (fails)

This should return {"Red", "Yellow"}, but instead triggers a -1700 error

tell application "Reminders"
    return (name of every reminder in list "Colours") whose name is in lstMyList
end tell

The full error that pops up is:

"Reminders got an error: Can’t make {"Red", "Yellow", "Orange", "Blue"} into type specifier." number -1700 from {"Red", "Yellow", "Orange", "Blue"} to specifier

I cannot understand what's happening in this third case, as the first statement uses "is in lstMyList" without any problem, and the second statement uses "whose" without any problem.

I should add that I'm aware that the error can be bypassed completely by turning the code around, e.g. looping through lstMyList and checking the reminders. However, I am trying to avoid such a solution because that would entail the repeated sending of Apple events, which would result in a marked increase in run time, especially with large numbers of list items.

Any explanations and/or advice here would be much appreciated. Thank you.


Solution

  • It's a matter of who you're talking to.

    When you say

    return (name of reminder 1 of list "Colours") is in lstMyList
    

    two things happen.

    1. First, an Apple event is sent fetching the name of reminder 1 of list "Colours". The work here is done by the Reminders app; the specifier name of reminder 1 of list "Colours" is a hierarchy that it can understand.

    2. Second, internally (within this script), AppleScript-the-language takes the resulting string and checks the list for containment of that string.

    When you say

    return (name of every reminder in list "Colours") whose name contains "Green"
    

    you are sending a single Apple event to Reminders and that's all you are doing. Nothing guarantees that Reminders is going to be willing to do this calculation for you, but it happens that it is willing. It works out the whole specifier and returns the result to you.

    Similarly when you say

    return (name of every reminder in list "Colours") whose name is in lstMyList
    

    you are asking Reminders to do this as a single Apple event too. You are hoping that the is in lstMyList specifier is something that Reminders is willing to do. And it isn't. AppleScript is, but Reminders isn't. Containment in a list is just not a specifier Reminders does. You are sending this Apple event:

    get «property pnam» 
        of every «class remi» 
        of «class list» "Colours" 
        whose {"Red", "Yellow", "Orange", "Blue"} contains «property pnam»
    

    That Apple event is just too weird. You cannot know, without trying, what specifiers an application will respond to; it happens that Reminders doesn't like this one, and there's nothing you can do about it.

    The way I would do this is to say

    set lstMyList to {"Red", "Yellow", "Orange", "Blue"}
    set output to {}
    tell application "Reminders"
        tell list "Colours"
            set rems to (get every reminder)
            set names to (get name of every reminder)
        end tell
        repeat with i from 1 to count of names
            if item i of names is in lstMyList then
                set end of output to item i of rems
            end if
        end repeat
    end tell
    

    We have now collected references to the correct reminders (in output), but we sent only two Apple events, which is cheap and fast. The rest of the work was done internally by AppleScript. And of course if you wanted only the names, not a reference to the actual reminder, you could do it with just one Apple event, to collect the names.