Hi.
If you can get the information into Contacts correctly identified as ‘phone’, ‘email’, ‘address’, or whatever, it’s certainly possible to set custom labels where the numbers, addresses, etc. contain semicolons.
The script below contains several similar sections because different Contacts references are needed for each type of contact detail. It’s possible to telescope them together, but I think the code’s probably easier to edit and maintain as it is.
setCustomLabels()
on setCustomLabels()
-- Get the required information from Contacts all at once for speed: the id and current value (or street) of every address, custom date, email, phone, related name, and url of every contact in the application, along with every contact's id. It's assumed that in the case of an address, any semicolon marker will be in the 'street' field.
tell application "Contacts"
set {addressInfo, cDateInfo, emailInfo, phoneInfo, rNameInfo, urlInfo, peopleIDs} to {{street, id} of addresses, {value, id} of custom dates, {value, id} of emails, {value, id} of phones, {value, id} of related names, {value, id} of urls, id} of people
-- There's a problem referencing 'instant messages' with AppleScript in Contacts 9.0, so they're not included here. I don't know anything about 'social profiles'.
end tell
-- Now identify and effect any required label and value changes or deletions, starting with addresses.
set theseChanges to getChanges(addressInfo, peopleIDs)
repeat with thisChange in theseChanges
set {newLabel, newValue, dataID, contactID} to thisChange
if (newLabel > "") then
tell application "Contacts" to tell address id dataID of person id contactID to set {its label, its street} to {newLabel, newValue}
else
-- Zero-length label returned for semicolon-only field value. Delete the object.
tell application "Contacts" to delete address id dataID of person id contactID
end if
end repeat
-- Custom dates.
set theseChanges to getChanges(cDateInfo, peopleIDs)
repeat with thisChange in theseChanges
set {newLabel, newValue, dataID, contactID} to thisChange
if (newLabel > "") then
tell application "Contacts" to tell custom date id dataID of person id contactID to set {its label, its value} to {newLabel, newValue}
else
-- Simile.
tell application "Contacts" to delete custom date id dataID of person id contactID
end if
end repeat
-- Emails.
set theseChanges to getChanges(emailInfo, peopleIDs)
repeat with thisChange in theseChanges
set {newLabel, newValue, dataID, contactID} to thisChange
if (newLabel > "") then
tell application "Contacts" to tell email id dataID of person id contactID to set {its label, its value} to {newLabel, newValue}
else
tell application "Contacts" to delete email id dataID of person id contactID
end if
end repeat
-- Phones.
set theseChanges to getChanges(phoneInfo, peopleIDs)
repeat with thisChange in theseChanges
set {newLabel, newValue, dataID, contactID} to thisChange
if (newLabel > "") then
tell application "Contacts" to tell phone id dataID of person id contactID to set {its label, its value} to {newLabel, newValue}
else
tell application "Contacts" to delete phone id dataID of person id contactID
end if
end repeat
-- Related names.
set theseChanges to getChanges(rNameInfo, peopleIDs)
repeat with thisChange in theseChanges
set {newLabel, newValue, dataID, contactID} to thisChange
if (newLabel > "") then
tell application "Contacts" to tell related name id dataID of person id contactID to set {its label, its value} to {newLabel, newValue}
else
tell application "Contacts" to delete related name id dataID of person id contactID
end if
end repeat
-- URLs.
set theseChanges to getChanges(urlInfo, peopleIDs)
repeat with thisChange in theseChanges
set {newLabel, newValue, dataID, contactID} to thisChange
if (newLabel > "") then
tell application "Contacts" to tell url id dataID of person id contactID to set {its label, its value} to {newLabel, newValue}
else
tell application "Contacts" to delete url id dataID of person id contactID
end if
end repeat
-- Save the changes.
tell application "Contacts" to save
end setCustomLabels
-- Find any semicolon markers in the info batch for a particular contact detail type, work out new label and value settings, and return a list of all the changes required for the batch along with the relevant IDs.
-- {{label, value, info id, contact id}, {label, value, info id, contact id}, . }
on getChanges(thisInfo, peopleIDs)
-- thisInfo contains two lists, each of which contains as many lists as there are contacts. Each list in the first list corresponds to a contact and contains the value of every instance of the current contact detail type the contact may have. The matching lists in the second list contain the ids of the actual data objects in the application.
-- peopleIDs contains the IDs of all the contacts in the application, the order matching that of the lists in thisInfo.
script o
property currentValues : beginning of thisInfo
property dataIDs : end of thisInfo
property contactIDs : peopleIDs
property changes : {}
end script
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ";"
-- For each contact .
repeat with contact from 1 to (count peopleIDs)
-- . and for each instance it may have of this type of contact detail .
set theseValues to item contact of o's currentValues
repeat with i from 1 to (count theseValues)
-- . check the instance's value. If it contains a semicolon, append a list to this handler's output containing the text before the semicolon, the text after it, the ID of the object in the application, and the ID of the contact.
set thisValue to item i of theseValues
if (thisValue contains ";") then
-- It's assumed there are no white spaces next to the semicolon(s). Where there's ONLY a semicolon in the field, the texts either side are zero-length.
set end of o's changes to {text item 1 of thisValue, text item 2 of thisValue, item i of item contact of o's dataIDs, item contact of o's contactIDs}
end if
end repeat
end repeat
set AppleScript's text item delimiters to astid
-- Return whatever changes are needed with this kind of contact detail.
return o's changes
end getChanges
Edit: The script now deletes contact-detail objects whose values only contain a semicolon.