Accessing info using the Address Book framework

I am working on an Applescript Studio app for my employer. Part of this app involves entering data that can be found in the Address Book. I would like to be able to access Address Book’s data in the same way as Mail.app does in the “To:” line (when creating a new outgoing email). I know that I can access this data via applescript and launching the Address Book when needed, but I’d much rather gain access to this data using the framework. (If for no other reason than the learning experience.)

Jonn created a demo app demonstrating how to access this data using the People Picker object http://bbs.applescript.net/viewtopic.php?pid=30400#p30400. I have figured out how to get the phone number based on his obj-c code. However, I haven’t been able to figure out how to get more than a single phone number (or email address, as his code originally did).

Also, I would like to be able to input the person’s name in a text field and search the Address Book data based on the text field’s data (as the Mail.app does).

I also wished I understood obj-c MUCH better than I do now, but that is another “ball of wax” entirely! :lol: Right now, my understanding of obj-c is VERY limited.

Thanks in advance to anybody that can help me out,
Brad Bumgarner, CTA

Hi Brad,

here an example for a (far from perfect) search method you can use from AppleScript:

adressbooksearch.h:


#import <Cocoa/Cocoa.h>
#import <AddressBook/AddressBook.h>

@interface adressbooksearch : NSObject {}
+(NSArray *)searchAdressbookForName:(NSString *)theName;

@end

adressbooksearch.m:

#import "adressbooksearch.h"


@implementation adressbooksearch

+(NSArray *)searchAdressbookForName:(NSString *)theName{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	ABAddressBook *AB = [ABAddressBook sharedAddressBook];
	ABSearchElement *lastNameSearch = [ABPerson searchElementForProperty:kABLastNameProperty label:nil key:nil value:theName comparison:kABContainsSubStringCaseInsensitive]; 
	NSArray *searchResults = [AB recordsMatchingSearchElement:lastNameSearch];
	int cnt = [searchResults count];
	if (cnt > 0) {
		int i;
		NSMutableArray *resultNames = [[NSMutableArray alloc] init];
		for (i=0;i<cnt;i++) {
			NSString *firstN = [[searchResults objectAtIndex:i] valueForProperty:kABFirstNameProperty];
			NSString *lastN  = [[searchResults objectAtIndex:i] valueForProperty:kABLastNameProperty];
			if ( firstN == nil ) {
			[resultNames addObject:[NSString stringWithFormat:@"%@",lastN ]]; 
			} else {
			[resultNames addObject:[NSString stringWithFormat:@"%@, %@", lastN, firstN ]]; 
			} 
		}
		[resultNames retain];
		[pool release];
		return (resultNames);
	} else {
		[pool release];
		return nil;
	}
}

@end

the call from AppleScript:


set searchString to contents of text field "search" of window "main"
set searchResult to (call method "searchAdressbookForName:" of class "adressbooksearch" with parameter searchString)
log (searchResult)

It searches the last name field for a string (finds case independent and substrings) and results an array (list) with all found entries (Lastname, Firstname)

Hope it helps …

D.

Dominik,

Thanks for the search routine. I’ll plug this code into my project as soon as I get the opportunity to do so.

Brad Bumgarner, CTA

I was able to figure out how to search for first names but not first and/or last names. Looks like it’s time to break down and learn some object-c.:lol: I also need to figure out how to get a list of email addresses and phone/fax numbers. Time to get a good book and learn.

Thanks again for your help.
Brad Bumgarner, CTA

Hi Brad,

learning Objectve-C is definitively a good idea ;-). Unfortunately ABRecord/ABPerson are not really simple Objects since they can hold many different sub and sub-sub objects (NSDirectories, NSArrays, NSData, NSDate, NSString, NSNumber etc …) :wink:

So meanwhile … here’s an other method for you which you could use for searching even without writing any external code - maybe this is already sufficient for your needs?
You can search in any of the existing ABPerson properties (choose one from property record ‘ABProperties’) using one of the comparison methods (choose from property record ‘ABComparisonTypes’).
The result (‘ResultString’) are textual representations of the found ABPersons. Not really an elegant solution maybe - but it could be used to filter the information you need (phone, eMail etc. …).

D.


property ABComparisonTypes : {kABEqual:0, kABNotEqual:1, kABLessThan:2, kABLessThanOrEqual:3, kABGreaterThan:4, kABGreaterThanOrEqual:5, kABEqualCaseInsensitive:6, kABContainsSubString:7, kABContainsSubStringCaseInsensitive:8, kABPrefixMatch:9, kABPrefixMatchCaseInsensitive:10, kABBitsInBitFieldMatch:11, kABDoesNotContainSubString:12, kABDoesNotContainSubStringCaseInsensitive:13, kABNotEqualCaseInsensitive:14, kABSuffixMatch:15, kABSuffixMatchCaseInsensitive:16, kABWithinIntervalAroundToday:17, kABWithinIntervalAroundTodayYearless:18, kABNotWithinIntervalAroundToday:19, kABNotWithinIntervalAroundTodayYearless:20, kABWithinIntervalFromToday:21, kABWithinIntervalFromTodayYearless:22, kABNotWithinIntervalFromToday:23, kABNotWithinIntervalFromTodayYearless:24}
property ABProperties : {kABFirstNameProperty:"First", kABLastNameProperty:"Last", kABFirstNamePhoneticProperty:"FirstPhonetic", kABLastNamePhoneticProperty:"LastPhonetic", kABBirthdayProperty:"Birthday", kABOrganizationProperty:"Organization", kABJobTitleProperty:"JobTitle", kABHomePageProperty:"HomePage", kABURLsProperty:"URLs", kABEmailProperty:"Email", kABAddressProperty:"Address", kABPhoneProperty:"Phone", kABAIMInstantProperty:"AIMInstant", kABJabberInstantProperty:"JabberInstant", kABMSNInstantProperty:"MSNInstant", kABYahooInstantProperty:"YahooInstant", kABICQInstantProperty:"ICQInstant", kABNoteProperty:"Note", kABMiddleNameProperty:"Middle", kABMiddleNamePhoneticProperty:"MiddlePhonetic", kABTitleProperty:"Title", kABSuffixProperty:"Suffix", kABNicknameProperty:"Nickname", kABMaidenNameProperty:"MaidenName", kABOtherDatesProperty:"ABDate", kABRelatedNamesProperty:"ABRelatedNames", kABDepartmentProperty:"ABDepartment", kABPersonFlags:"ABPersonFlags"}

on clicked theObject
	set searchString to contents of text field "search" of window "main"
	set AB to (call method "sharedAddressBook" of class "ABAddressBook")
	set theSearch to (call method "searchElementForProperty:label:key:value:comparison:" of class "ABPerson" with parameters {(kABLastNameProperty of ABProperties), null, null, searchString, (kABEqual of ABComparisonTypes)})
	set searchResults to (call method "recordsMatchingSearchElement:" of AB with parameter theSearch)
	set ResultCount to (count of searchResults)
	if (ResultCount > 0) then
		repeat with i from 1 to ResultCount
			set ResultString to (call method "description" of (item i of searchResults))
			log ResultString
		end repeat
	end if
end clicked



Dominik,

Thank you, again, for your efforts. I will certainly look at this code at my next opportunity. Looking forward to seeing how it works.

Brad Bumgarner, CTA