We can simplify this down to five lines:
tell application "Address Book"
add (every person whose birth date is missing value) to ¬
make new group with properties {name:"No Birthday"}
save addressbook
end tell
It turns out that add
can take a list as well as a single object, so we can skip the loop. (Note that if you had used a loop, you could have used the repeat with thePerson in people ... end repeat
form, as that's cleaner than what you had.) Next, it appears that Address Book stores missing birthdays as missing value
(effectively null
), so we should check for that rather than comparing against an early date. Thus, to get a list of the birthdayless people, we write every person whose birth date is missing value
, which does exactly what it says. The whose
clause filters the preceding list so that it only contains values matching the given predicate. We then add
that list to the new group, which we create inline. Finally, save addressbook
saves the changes and makes them visible.
However, in this case, you don't need an AppleScript at all. Address Book supports smart groups; to create one, option-click the new group button. Choose "No Birthdays" for the smart group's name, and tell it to match cards for which "Birthday" (from the first dropdown) "is not set" (from the second dropdown). This will give you a dynamically-updating group of people who have no set birthday.
Edit: It seems that while add
takes a list on Leopard, it doesn't on Snow Leopard, so we'll need to use an explicit repeat
loop (which works on Leopard too):
tell application "Address Book"
set noBirthdays to make new group with properties {name:"No Birthday"}
repeat with p in (every person whose birth date is missing value)
add p to noBirthdays
end repeat
save addressbook
end tell
This works almost the same way as the above solution, except we make the group beforehand, and then add each item individually. Rather than iterating over the indices, we iterate over the elements directly, since that's all we care about here.
Edit: For other properties, things are similar; in fact, when using the smart group, things are identical. From the AppleScript side, the question is the format of the data. Most slots have missing value
when they're unset, but email
is an exception. As we can see by testing, they're stored in a list, so we want every person whose email is {}
. However, this doesn't work for me—probably because email
is a list, but I'm not sure—so you'll instead want
repeat with p in every person
if email of p is {} then add p to noEmails
end repeat
And voilà, everything should work.
In- and excluding businesses is also easy, but as far as I can tell, Address Book doesn't provide a way to create a smart group for them. However, the relevant property is company
, which is true
for businesses and false
for others. Thus, to create a list without companies, you want to do
repeat with p in (every person whose company is false)
add p to noCompanies
end repeat
If you want one master list with all of these criteria, there are two ways. First, from AppleScript, you take the two condition and and
them, then add conditioning on whether or not they have an email:
repeat with p in (every person whose company is false and ¬
birth date is missing value)
if email of p is {} then add p to masterGroup
end repeat
The other option is to do this from Address Book. You first need to create a No Companies
group the AppleScript way. You then create a smart group matching all of three conditions (you add them with the +
button): "Email is not set", "Birthday is not set", and "Card is a member of 'No Companies'". This is probably the best option, although it's unfortunate that you have to use AppleScript for the No Companies
group (I feel like there should be a way, but I can't see what it is).