Contacts.app (AddressBook): Show Existing Info for selected contact

Simple script to check quickly the existing contact info:


tell application id "com.apple.AddressBook" to set thePeople to name of people

set theChoice to choose from list thePeople
if theChoice is false then return

tell application id "com.apple.AddressBook"
	close windows
	set selectedContact to person named (item 1 of theChoice)
	tell selectedContact
		set {|birth date|, |company|, |creation date|, |department|, |first name|} to ¬
			{birth date, company, creation date, department, first name}
		set {|home page|, |id|, |job title|, |last name|, |maiden name|} to ¬
			{home page, id, job title, last name, maiden name}
		set {|middle name|, |modification date|, |name|, |nickname|, |note|, |organization|} to ¬
			{middle name, modification date, name, nickname, note, organization}
		set {|phonetic first name|, |phonetic last name|, |phonetic middle name|} to ¬
			{phonetic first name, phonetic last name, phonetic middle name}
		set {|selected|, |suffix|, |title|, |vcard|} to {selected, suffix, title, vcard}
		set |1st Phone Number| to value of phone 1
	end tell
end tell

tell application "System Events" to open location "addressbook://" & |id|

set theText to "Creation date:                " & |creation date| & return
set theText to theText & "Modification date:          " & |modification date| & return
if not (|1st Phone Number| is missing value) then set theText to "1st Phone number:         " & |1st phone Number| & return
if not (|birth date| is missing value) then set theText to "Birth date:                      " & |birth date| & return
set theText to theText & "Company:                       " & company & return
if not (department is missing value) then set theText to theText & "Department:                   " & department & return
if not (|first name| is missing value) then set theText to theText & "First name:                      " & |first name| & return
if not (|home page| is missing value) then set theText to theText & "Home page:                    " & |home page| & return
if not (|job title| is missing value) then set theText to theText & "Job title:                          " & |job title| & return
if not (|last name| is missing value) then set theText to theText & "Last name:                      " & |last name| & return
if not (|maiden name| is missing value) then set theText to theText & "Maiden name:                 " & |maiden name| & return
if not (|middle name| is missing value) then set theText to theText & "Middle name:                  " & |middle name| & return
if not (|name| is missing value) then set theText to theText & "Name:                              " & |name| & return
if not (nickname is missing value) then set theText to theText & "Nickname:                       " & nickname & return
if not (|note| is missing value) then set theText to theText & "Note:                                " & |note| & return
if not (organization is missing value) then set theText to theText & "Organization:                  " & organization & return
if not (|phonetic first name| is missing value) then set theText to theText & "Phonetic first name:       " & |phonetic first name| & return
if not (|phonetic last name| is missing value) then set theText to theText & "Phonetic last name:        " & |phonetic last name| & return
if not (|phonetic middle name| is missing value) then set theText to theText & "Phonetic middle name:  " & |phonetic middle name| & return
set theText to theText & "ID:                                    " & |id| & return
set theText to theText & "Selected:                         " & selected & return
if not (suffix is missing value) then set theText to theText & "Suffix:                              " & suffix & return
if not (title is "") then set theText to theText & "Title:                                " & title
set theText to theText & return

tell application id "com.apple.AddressBook"
	display dialog theText buttons {" ...........................-------------------                         CLOSE INFO                         --------------------- ............................."} with title "CONTACT's INFO"
	quit it
end tell

return theText & vcard

Hi KniazidisR.

A few observations on trying your script.

  1. The value of the contact’s selected property is always false unless Contacts is already open with the chosen contact selected when the script’s run and the script doesn’t close the windows before reading the ‘selected’ property.
  2. The script errors if the contact doesn’t have a phone number. It’s best to get the phones initially and then, if the result’s not {}, get the first item’s value. Or of course set |1st Phone Number| to missing value if the result is {}.
  3. open location is a StandardAdditions command, so System Events isn’t needed.
  4. Your third and fourth lines setting theText don’t use concatenation, so they lose whatever’s been set already.
  5. (My error. This point deleted.)
  6. The line which appends the title does so if the value’s not “”. On my machine, the absence of a title is indicated by missing value, as with the other properties. On the other hand, one of my contacts has “” instead of missing value as its note value. Maybe deleted text gets rendered thus?
  7. The order in which the information’s appended to the text makes for rather strange reading, but I’m assuming you have your own reasons for this.

All those long if not … then lines are crying out for a repeat, so here’s an attempt to implement one and fix some of the above issues. It’s basically your script revamped.

on main()
	tell application id "com.apple.AddressBook" to set {wasOpen, thePeople} to {running, name of people}
	
	set theChoice to choose from list thePeople
	if theChoice is false then return
	
	tell application id "com.apple.AddressBook"
		set selectedContact to person named (item 1 of theChoice)
		set values to selectedContact's {creation date, modification date, phones, birth date, ¬
			company, department, first name, home page, ¬
			job title, last name, maiden name, middle name, ¬
			name, nickname, note, organization, ¬
			phonetic first name, phonetic last name, phonetic middle name, id, ¬
			selected, suffix, title, vcard}
		set theirPhones to item 3 of values
		if (theirPhones is {}) then
			set item 3 of values to missing value
		else
			set item 3 of values to value of theirPhones's first item
		end if
		if not (wasOpen) then quit
	end tell
	set labels to {"Creation date:                ", "Modification date:          ", "1st Phone number:         ", "Birth date:                       ", ¬
		"Company:                       ", "Department:                   ", "First name:                      ", "Home page:                    ", ¬
		"Job title:                          ", "Last name:                      ", "Maiden name:                 ", "Middle name:                  ", ¬
		"Name:                              ", "Nickname:                       ", "Note:                                ", "Organization:                  ", ¬
		"Phonetic first name:       ", "Phonetic last name:        ", "Phonetic middle name:  ", "ID:                                    ", ¬
		"Selected:                         ", "Suffix:                              ", "Title:                                "}
	
	set output to {}
	repeat with i from 1 to (count labels) -- 1 fewer labels than values. 
		set value to item i of values
		set vClass to value's class
		if (((vClass is text) and (value is not "")) or (vClass is date)) then
			set end of output to item i of labels & value
		else if (vClass is boolean) then
			set end of output to item i of labels & item ((value as integer) + 1) of {"No", "Yes"}
		end if
	end repeat
	set theText to join(output, linefeed)
	set vcard to end of values
	
	display dialog theText buttons {" ...........................-------------------                         CLOSE INFO                         --------------------- ............................."} with title "CONTACT's INFO"
	
	return theText & (linefeed & linefeed & vcard)
end main

on join(lst, delim)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to delim
	set txt to lst as text
	set AppleScript's text item delimiters to astid
	return txt
end join

main()

Thank you for taking the time to improve my simple script. I will write your version in my script library, because it is really more correct than mine. :slight_smile:

My apologies, KniazidisR. The point I made originally about the company property in your script was nonsense. This property’'s meant to be a boolean and indicates whether or not the contact’s a company as opposed to an individual. A company name, if any, is covered by the organization property. I’ve corrected my post and script above.

And here for your delectation is a version which uses the Contacts framework instead of the Contacts app. It doesn’t include the selected state, which is a property of the app, or the creation and modification dates, for which I can’t find framework equivalents.

use AppleScript version "2.5" -- OS X 10.11 (El Capitan) or later.
use framework "Foundation"
use framework "Contacts"
use scripting additions

on main()
	set |⌘| to current application
	
	-- Get every contact in the store, including the properties required for sorting and name formatting.
	set contactStore to |⌘|'s class "CNContactStore"'s new()
	set keyDescriptor to |⌘|'s class "CNContactVCardSerialization"'s descriptorForRequiredKeys()
	-- A nil predicate matches all contacts.
	set allContacts to (contactStore's unifiedContactsMatchingPredicate:(missing value) ¬
		keysToFetch:({keyDescriptor}) |error|:(missing value))
	-- Sort the contacts in the default name order set on the machine.
	set comparator to |⌘|'s class "CNContact"'s comparatorForNameSortOrder:(|⌘|'s CNContactSortOrderUserDefault)
	set allContacts to (allContacts's sortedArrayUsingComparator:(comparator)) as list
	-- Replace them in the list with their formatted names.
	set nameFormatter to |⌘|'s class "CNContactFormatter"'s new()
	repeat with thisContact in allContacts
		set thisContact's contents to (nameFormatter's stringFromContact:(thisContact)) as text
	end repeat
	
	-- Ask the user to choose one of the names.
	set theChoice to (choose from list allContacts with prompt "Which contact?")
	if (theChoice is false) then error number -128
	set chosenName to theChoice's beginning
	
	-- Get the contact associated with the chosen name.
	set namePred to |⌘|'s class "CNContact"'s predicateForContactsMatchingName:(chosenName)
	set chosenContact to (contactStore's unifiedContactsMatchingPredicate:(namePred) ¬
		keysToFetch:({keyDescriptor}) |error|:(missing value))'s firstObject()
	
	-- Get the particular details we want and append them with labels to a list.
	-- Concatenating the details to the AS text labels coerces them to text themselves.
	set output to {"ID:                                    " & chosenContact's identifier(), "Name:                              " & chosenName}
	set labels to {"Title:                                ", "First name:                      ", "Middle name:                  ", ¬
		"Last name:                      ", "Maiden name:                 ", "Suffix:                              ", ¬
		"Nickname:                       ", "Phonetic first name:       ", "Phonetic middle name:  ", ¬
		"Phonetic last name:        ", "Birth date:                       ", "Organization:                  ", ¬
		"Department:                   ", "Job title:                          ", "Company:                        ", ¬
		"1st Phone number:         ", "Home page:                    ", "Note:                                "}
	set values to chosenContact's {namePrefix(), givenName(), middleName(), ¬
		familyName(), previousFamilyName(), nameSuffix(), ¬
		nickname(), phoneticGivenName(), phoneticMiddleName(), ¬
		phoneticFamilyName(), birthday(), organizationName(), ¬
		departmentName(), jobTitle(), contactType(), ¬
		phoneNumbers(), urlAddresses(), |note|()}
	repeat with i from 1 to (count values)
		set value to item i of values
		if (value is missing value) then -- No birth date given.
		else if ((value's class is integer) or (value's isKindOfClass:(|⌘|'s class "NSNumber"))) then -- Company (1) or not (0)? 
			set end of output to (item i of labels) & (item ((value as integer) + 1) of {"No", "Yes"})
		else if (value's isKindOfClass:(|⌘|'s class "NSString")) then -- String value.
			if (value's |length|() > 0) then set end of output to (item i of labels) & value
		else if (value's isKindOfClass:(|⌘|'s class "NSArray")) then -- Phone(s) or Web URL(s).
			if (value's |count|() > 0) then
				set value to value's firstObject()'s value()
				if (value's isKindOfClass:(|⌘|'s class "CNPhoneNumber")) then set value to value's stringValue()
				if (value's |length|() > 0) then set end of output to (item i of labels) & value
			end if
		else -- NSDateComponents object for birth date.
			set end of output to (item i of labels) & (value's |date|() as date)
		end if
	end repeat
	
	set theText to join(output, linefeed)
	display dialog theText buttons {" ...........................-------------------                         CLOSE INFO                         --------------------- ............................."} with title "CONTACT's INFO"
	
	set vcardData to |⌘|'s class "CNContactVCardSerialization"'s dataWithContacts:({chosenContact}) |error|:(missing value)
	set vcard to |⌘|'s class "NSString"'s alloc()'s initWithData:(vcardData) encoding:(|⌘|'s NSUTF8StringEncoding)
	
	return theText & (linefeed & linefeed & vcard)
end main

on join(lst, delim)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to delim
	set txt to lst as text
	set AppleScript's text item delimiters to astid
	return txt
end join

main()

Thanks for both brilliant versions of the script you provided.