Hi!
I managed to build a script to filter contacts by zip code.
Unfortuantely it is very slow. Does anyone know how to make this faster by using ASOC?
Here is my script:
tell application "Contacts"
set _ids to every person whose zip of first address starts with "82"
set _names to {}
repeat with _id in _ids
set _name to name of _id
set the end of _names to _name
end repeat
return _names
end tell
use AppleScript version "2.5" -- Mac OS 10.11 (El Capitan) or later.
use framework "Foundation"
use framework "Contacts"
on join(listOfText, delimiter)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set txt to listOfText as text
set AppleScript's text item delimiters to astid
return txt
end join
on run argument
-- set argument to {"82"}
if (argument's class is list) then set argument to beginning of argument
set |⌘| to current application
set contactStore to |⌘|'s class "CNContactStore"'s new()
-- Request one copy of every contact of every container (although there's probably only one container)
-- along with their names, addresses, and IDs and build a single mutable array of all the results.
set allContainers to contactStore's containersMatchingPredicate:(missing value) |error|:(missing value)
set contactArray to |⌘|'s class "NSMutableArray"'s new()
set keysNeeded to |⌘|'s class "NSArray"'s arrayWithArray:({|⌘|'s CNContactGivenNameKey, |⌘|'s CNContactFamilyNameKey, |⌘|'s CNContactOrganizationNameKey, |⌘|'s CNContactTypeKey, |⌘|'s CNContactPostalAddressesKey, |⌘|'s CNContactIdentifierKey})
repeat with thisContainer in allContainers
set contactPredicate to (|⌘|'s class "CNContact"'s predicateForContactsInContainerWithIdentifier:(thisContainer's identifier()))
set theseContacts to (contactStore's unifiedContactsMatchingPredicate:(contactPredicate) keysToFetch:(keysNeeded) |error|:(missing value))
tell contactArray to addObjectsFromArray:(theseContacts)
end repeat
-- Filter the array for contacts having any address with a post (zip) code beginning with the given argument.
set zipFilter to |⌘|'s class "NSPredicate"'s predicateWithFormat_("ANY postalAddresses.value.postalCode BEGINSWITH %@", argument)
tell contactArray to filterUsingPredicate:(result)
-- Get the previously requested info re the survivors' given names, family names,
-- and/or organisation names, and IDs, coercing the results to AppleScript lists of text.
set givenNames to (contactArray's valueForKey:("givenName")) as list
set familyNames to (contactArray's valueForKey:("familyName")) as list
set organisationNames to (contactArray's valueForKey:("organizationName")) as list
set contactTypes to (contactArray's valueForKey:("contactType")) as list
set IDs to (contactArray's valueForKey:("identifier")) as list
-- Collate the results, constructing the names according to contact type.
set _results to {}
repeat with i from 1 to (count contactTypes)
if (item i of contactTypes is 0) then -- Person.
set _name to (item i of givenNames) & space & (item i of familyNames)
else -- item i of contactTypes is 1 (organisation)..
set _name to (item i of organisationNames)
end if
set end of _results to "{'title':" & quoted form of _name & ",'icon':'personTemplate.png','url':'addressbook://" & item i of IDs & "'}"
end repeat
-- Coerce the results list to a single text.
-- It's best practice always to set Applescript's text item delimiters explicitly for this.
return join(_results, ",")
end run
Edit: Modified in the light of the reply immediately below.
I developed my script a bit further in the meantime for use within my LaunchBar action. I mainly added the entry ID. This way I can directly open a given result in Contacts (with some cleanup in the javascript part of my LaunchBar action)
I just don’t know how to integrate the ID part in your version. I guess I need to learn ASOC eventually.
Again, thank you!
on run (argument) -- e.g. "82"
-- set argument to "82
tell application "Contacts"
set _persons to every person whose zip of first address starts with argument
end tell
set _results to {}
repeat with _person in _persons
set _name to name of _person
set _id to id of _person as string
set _result to "{'title':'" & _name & "','icon': 'personTemplate.png', 'url':'addressbook://" & _id & "'},"
set the end of _results to _result
end repeat
set output to _results as string
return output
end run