Applescript to delete contacts from list - iphone

I accidentally added about 600 contacts to my Mac addressbook from a friend's iPhone I synced to my Mac a couple weeks ago. Unfortunately I dont have a backup of my contacts and now they are all synced with my iPhone and iCloud.
I was able to export all the unwanted contacts as ".vcf" files from my friends phone so I have about 600 files like "John Doe.vcf" and also a plain text list of just the contact names.
Ideally I would like a script that matches the data inside the VCF file to make sure I'm deleteing the right contact.
Idea #2 would be to delete the contacts that matches the name in list, skipping the searches that return two or more results (that way I dont lose my own contacts with same name as my friend's)
I started by attempint to delete a single contact using the following applescript but with no luck. Please help!
set daName to "John Doe"
tell application "Contacts"
repeat with onePerson in people
if (value of name of onePerson) is daName then
delete onePerson
end if
end repeat
end tell
--UPDATE--
Here is the final code I used to perform the task. I added a loop at the top that cycles through the list of names copied in the clipboard. I also added the name of the duplicated contact in the dialog box so I could take note of it.
Tips:
Make a backup of all your contacts before running the script.
If you want to see the number of contacts "magically" decreasing
while running the script, scroll down to the of your contacts in
your address book and you'll see the totla amount of contacts
there.
FINAL CODE
set the clipboard to (the clipboard as text)
set the_strings to the clipboard
repeat with this_string in paragraphs of the_strings
set daName to this_string
DeleteContact(daName)
end repeat
on DeleteContact(theName)
tell application "Contacts"
set myList to every person whose name is theName
set Nb to count of myList
if Nb = 0 then return -- no record found
if Nb > 1 then
display dialog theName & " (too many found: do nothing)"
else
set myperson to item 1 of myList -- only 1 found to be deleted
delete myperson
save
end if
end tell
end DeleteContact

The script bellow contains sub-routine which check name and delete. I added some comments to make it easier to adapt for your need :you can build a loop looking for your card and calling the DeleteContact sub-routine.
set daName to "John Doe"
DeleteContact(daName)
on DeleteContact(theName)
tell application "Contacts"
set myList to every person whose name is theName
set Nb to count of myList
if Nb = 0 then return -- no record found
if Nb > 1 then
display dialog "too many found: do nothing"
else
set myperson to item 1 of myList -- only 1 found to be deleted
delete myperson
save
end if
end tell
end DeleteContact
In case same name exist in multiple contact, I display a dialog, but up to you to decide what to do here.

Gio
This is a script I had and it may address your problem although you never said what the problem was.
tell application "Contacts"
local results,dlist,dloop
set results to {}
set dlist to people whose (first name contains "Oxnard" or (last name is equal to "Abercrombe"))
repeat with dloop in dlist
delete dloop
end repeat
set end of results to "Records deleted :" & count of dlist
save
return results
end tell
Note that the Contacts dictionary does define a name property however it will be based on preference settings.

Related

How to explicitly save or close a recordset when a form deactivates?

I apologize if this is too vague a question, but we're having the following problem:
We use a search form to find a record, then load it in a bound-control form where changes are made. Then we return to the search form and open another record. When we do that, the form's BeforeUpdate property fires a 3020 error, "Update without Add New or Edit" and stepping through the code it's referring to the FIRST opened record. This is strange because there is no explicit update call, but after much trial and error I think the error is thus:
Record #1 is opened via the form and changes are made. Record #2 is opened on that same form without closing the first recordset. Even though we now re-opened the form with the second record, Access still assumes we're editing record 1, i.e. that we're trying to edit 2 records concurrently. Same as though we had a datasheet form and we edited one row and then tried to edit a second row without saving the first. What I want to be able to do is have it automatically do an update on the first record when the form deactivates so loading a new record doesn't cause this conflict.
So the bottom line is this: **Is there a way, on say the form's Dirty or Deactivate event, that we can force the form's recordset to update and close ** before loading a second record?
I hope I made this clear enough, it's a complex problem, so any small guidance would help. Btw, you may ask, "Why are you running the same code to open the same form twice?" Good question! Hey it's an old and badly written app (the thing has GoSubs in it for Pete's sake) but I have no choice but to make the best of a bad situation.
EDIT: I was asked to post code, which is reasonable, but it's in several different places. So I have the data form, it has a "Search" button to go back to the search form for opening another record. The search button on the data entry form is:
Private Sub CommandSearch_Click()
On Error GoTo Err_CommandSearch_Click
DoCmd.OpenForm "Reference Form", acNormal 'This is the form that does the searching
Exit_CommandSearch_Click:
Exit Sub
Err_CommandSearch_Click:
MsgBox Err.Description
Resume Exit_CommandSearch_Click
End Sub
When a record is selected on that search form, then the new form is opened with this code. Now this is where it gets tricky. I'm not the original programmer, as I said I think it was written in Access 97 by someone after taking an hour to read "Access for Dummies" :). But it always looks like only one copy of the form is open, so maybe it's re-opening it?
Public Sub CommandLoadCase_Click()
Dim LoadUTUCaseNumber As String, lengthUTUCaseNumber As Integer
lengthUTUCaseNumber = InStr(Forms![Reference Form]![Reference Query SubForm]![UTU Case Number], "-") - 1
If (lengthUTUCaseNumber = 0) Then
LoadUTUCaseNumber = ""
Else
LoadUTUCaseNumber = Left$(Forms![Reference Form]![Reference Query SubForm]![UTU Case Number], lengthUTUCaseNumber)
End If
On Error Resume Next
Forms![Case Appeal_Add-On Form].UTUCaseKeyToFind = LoadUTUCaseNumber
DoCmd.OpenForm "Case Appeal_Add-On Form", acNormal, , , , , LoadUTUCaseNumber
'Case Appeal Add On Form referred to here is the data entry form I refer to above.
End Sub
Finally, the Error 3020 (Update without Add/Edit) is occurring after it executes this line on the data entry form. (I know the code is complicated which is why I didn't enter it at first).
Private Sub Form_BeforeUpdate(Cancel As Integer)
[UTU Claim Sequence Key] = [UTU Claim Alpha Sequence] & CStr([UTU Claim Numeric Sequence])
End Sub

** No sls-discount record is available. (91)

/*
sls-discount i sthe database name
*/Good day. I have another problem in regards again to value change of a specific browse.
my code for Add Button:
FIND CURRENT {&FIRST-TABLE-IN-QUERY-DIALOG-FRAME} NO-LOCK NO-ERROR.
IF AVAIL {&FIRST-TABLE-IN-QUERY-DIALOG-FRAME} THEN DO:
ASSIGN mode = 3.
ASSIGN BROWSE BROWSE-13:READ-ONLY = NO
sls-discount.dsc-amount:READ-ONLY IN BROWSE BROWSE-13 = NO
sls-discount.dsc-discount:READ-ONLY IN BROWSE BROWSE-13 = NO
sls-discount.log:READ-ONLY IN BROWSE BROWSE-13 = NO.
{&OPEN-QUERY-BROWSE-13}
IF BROWSE-13:num-iterations ne 0 then
BROWSE BROWSE-13:SELECT-FOCUSED-ROW().
BROWSE BROWSE-13:INSERT-ROW("BEFORE"). /*will cause value-change in browse*/
APPLY 'entry' TO sls-discount.dsc-discount IN BROWSE BROWSE-13.
RUN disp-enable.
END.
my code for browse-13:
ASSIGN xpromo-no = {&FIRST-TABLE-IN-QUERY-BROWSE-13}.promo-no
mdlrid = {&FIRST-TABLE-IN-QUERY-BROWSE-13}.record-id.
MESSAGE xpromo-no mdlrid VIEW-AS ALERT-BOX INFO.
OPEN QUERY BROWSE-16 FOR EACH sls.sls-disccount-model WHERE sls.sls-disccount-model.promo-no = xpromo-no
AND sls.sls-disccount-model.record-id = mdlrid NO-LOCK,
EACH sls.sls-model WHERE sls.sls-model.car-model = sls.sls-disccount-model.car-model NO-LOCK.
if I uncomment the entire value-change in a browse, it will display the message "** No DBName record is available. (91)" when clicking the add button. but if commented/removed, it will not display the message.
hope you can help me again .. Thanks
You've doubtless run into the infamous "partial field auto-completion" feature / bug. What that means is - if you cite a variable with no local definition for it, the Progress compiler will search all the available tables for a field that starts with the same sequence of letters and use that instead.
What the error is telling you is that the compiler associated a field with something in the "DBName" table, and when the code tries to access that variable, the DBName buffer isn't in scope - which is understandable since accessing it wasn't your intention.
My guess is that you've mis-specified a BROWSE construct. Looking at your first set of constructs, you've got two different forms:
BROWSE BROWSE-13:READ-ONLY = NO
sls-discount.dsc-amount:READ-ONLY IN BROWSE BROWSE-13 = NO
I'll bet one of these is wrong, and the compiler is associating the illegal "browse" citation with a field in DBName that starts with "Browse".
If you compile the code to an XREF file, it'll tell you which variable it's trying to associate with the DBName table. Correct that, and you'll be good to go.
I figure out what the problem on the code.. on click of Add button, the row inside browse-13 was arrange because of the {&OPEN-QUERY-BROWSE-13}. after that, because of BROWSE BROWSE-13:SELECT-FOCUSED-ROW(), it focused on the TOP date on browse and last, BROWSE BROWSE-13:INSERT-ROW("BEFORE"), created a blank data row at the very top. thus triggering value-changed of browse-13. on my value-changed on browse-13, the beginning of the code was to get current browse-13. since it was focused on the blank row, it resulted in an error with no query being found. sorry if i did not include the syntax get current in my first example.

Get the Date of an Email via AppleScript

I am currently trying to customize an AppleScript that is reading the unread Mails in the Inbox.
That basically works fine except the fact, that I can#T manage to get the date of the mails.
After about 2 hours of googling around I found out that the Variable I need should be receivedate or deliverydate, but when trying to use one of these I get an error like this:
"...receivedate of id... cannot be converted to Type reference..."
Someone's got an Idea, how I can convert this?
And this is my current code:
tell application "System Events"
set processList to (name of every process)
end tell
if processList contains "Mail" then
tell application "Mail"
if (unread count of inbox) > 0 then
set messageList to (messages of inbox) whose read status is false
set output to "Mails:" & return & return & ""
repeat with itemNum from 1 to (unread count of inbox)
set itemDate to (receivedate of item itemNum of messageList)
set output to output & itemDate & " - " & (extract name from sender of item itemNum of messageList) & return & subject of item itemNum of messageList & return & return
end repeat
end if
end tell
else
set output to "ÄpplMäil isch aus..."
end if
The term you are looking for is date received
tell application "Mail" to if running then
if (unread count of inbox) > 0 then
set output to "Mails:" & return & return & ""
repeat with thisMsg in (get messages of inbox whose read status is false)
tell thisMsg to set output to output & (date received) & " - " & (extract name from sender) & return & subject & return & return
end repeat
end if
else
set output to "ÄpplMäil isch aus..."
end if
A quicker way to get the help you need is the Applescript dictionarie of Mail.
All commands, classes and properties of Mail are in this dictionary.
One way of opening this dictionary is to use the Open Dictionary item in the File menu of AppleScript Editor. When you use this item, you will get a listing of the available applications that have dictionaries. Choose Mail and click the Open button or use the Browse button to navigate to an unlisted application.
Another way to open a dictionary, is to make use of AppleScript Editor's Library window. It's located in the Window menu below the Result History and Event Log History menu items. The Library window shows a list of default applications whose dictionaries you can open with a double click.

Access 2010 Trying to Enter a unique record through Form

I'm trying to input an error check for my form. I have the user entering the name and I would like a prompt to inform them if they are attempting to use a Name already in the records.
Example: the Person table has 3 records with FNames being: Jeff, Kyle, Darren.
If on the add person form in the Fname Box Kyle is entered, the after update event will notify the user that this name has been claimed and null the field. Where as if Greg was enter no notifications will occur.
I just don't know how to compare a text field value to values in a filtered query list, and Google searches have other loosely related links in the way.
Thank you for help!
If all fnames must be unique, add a unique index to the table. This will prevent duplicates being entered. The form error property will allow you to provide a custom error.
You can also check if the name exists in the Before Update event of the control.
In this example, the control and field are both called AText. Generally, you should rename controls so they are not the same as fields.
Private Sub AText_BeforeUpdate(Cancel As Integer)
Dim IsOk As Boolean
''One of the very few places where the .Text property is used
sLookUp = Me.AText.Text
IsOk = IsNull(DLookup("Atext", "Table1", "Atext='" & sLookUp & "'"))
If Not IsOk Then
MsgBox "Found!"
Cancel = True
End If
End Sub

How can I determine whether or not a contact with a given e-mail address exists in the Address Book?

I'm attempting to create a script that "walks" through a mailbox, checks the Address Book to see if the e-mail's sender is already there, and adds the contact to an Address Book group if found. If the e-mail's sender isn't found, a new contact would be created before it was added to the group.
So far, I've got this for the group adding part:
on addPersonToGroup(person)
tell application "Address Book"
add person to group "wedding guests"
end tell
save addressbook
end addPersonToGroup
and this for looping through selected messages:
tell application "Mail"
set selectedMessages to selection
if (count of selectedMessages) is equal to 0 then
display alert "No Messages Selected" message "Select the messages you want to add to 'wedding guests' address book group before running this script."
else
set weddingGuests to {}
repeat with eachMessage in selectedMessages
set emailAddress to extract address from sender of eachMessage
--if emailAddress is found in Address Book then
-- get the person from the Address Book
--else
-- create new person with emailAddress
--end if
--addPersonToGroup person
end repeat
end if
end tell
The commented-out part inside the "repeat with eachMessage ..." block is what I haven't figured out yet.
What ways are available for searching the Address Book for an e-mail address using AppleScript? Are there alternative scripting languages on the Mac that would be more suitable for such a task?
Below is the script that ultimately got me the result I wanted. Thanks to #fireshadow52 for the assist:
tell application "Mail"
set selectedMessages to selection
if (count of selectedMessages) is equal to 0 then
display alert "No Messages Selected" message "Select the messages you want to add to 'wedding guests' address book group before running this script."
else
set weddingGuests to {}
repeat with eachMessage in selectedMessages
set emailSender to (extract name from sender of eachMessage) as string
set emailAddress to (extract address from sender of eachMessage) as string
my addSender(emailSender, emailAddress)
end repeat
end if
end tell
on splitText(delimiter, someText)
set prevTIDs to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set output to text items of someText
set AppleScript's text item delimiters to prevTIDs
return output
end splitText
on addSender(theSender, theEmail)
tell application "Address Book"
set tmp to my splitText(" ", theSender)
set numOfItems to count tmp
set senderFirst to item 1 of tmp
if (numOfItems) is greater than 1 then
set senderLast to item 2 of tmp
else
set senderLast to ""
end if
try
set the check to get first person whose first name is senderFirst and last name is senderLast
--No error, sender exists
my addPersonToGroup(check)
on error --sender is not in Address Book yet; add sender and email to contacts and add the new contact to group
set newPerson to (make new person with properties {first name:senderFirst, last name:senderLast})
--Add Email
make new email at the end of emails of newPerson with properties {label:"Email:", value:theEmail}
--add the new person to the group
my addPersonToGroup(newPerson)
end try
end tell
end addSender
on addPersonToGroup(theSender)
tell application "Address Book"
add theSender to group "wedding guests"
save
end tell
end addPersonToGroup
Believe it or not you kind of wrote the answer in the question!
--In your "looping through selected messages" script, add this line...
set emailSender to (get sender of eachMessage) as string
--...before this one...
set emailAddress to (extract address from sender of eachMessage) as string
--This will help you later
--You should add this subroutine at the bottom of your script to check whether the contact exists or not; invoke it by doing 'my addSender(emailSender, emailAddress)'
on addSender(theSender, theEmail)
tell application "Address Book"
set the check to (get first person whose first name is theSender) as list
if check is {} --sender is not in Address Book yet; add sender and email to contacts and add the new contact to group
set newPerson to (make new person with properties {first name:theSender, last name:null}) --Sorry if you want the last name too
--Add Email
make new email at the end of emails of newPerson with properties {label:"Email:", value:theEmail}
--add the new person to the group
my addPersonToGroup(newPerson)
else --sender is in Address Book, add sender to group
my addPersonToGroup(check)
end if
end tell
end addSender
As always, if you need help, just ask. :)
P.S. If you get an error in the subroutine, it is most likely the if block's fault. To fix the error (and to keep the script running), just change the if block to a try block, as shown here:
try
set check to (get first person whose first name is theSender) as list
--No error, sender exists
my addPersonToGroup(check)
on error --Error, sender is not in Address Book yet; add sender and email to contacts and add the new contact to group
set newPerson to (make new person with properties {first name:theSender, last name:null}) --Sorry if you want the last name too
--Add Email
make new email at the end of emails of newPerson with properties {label:"Email:", value:theEmail}
--add the new person to the group
my addPersonToGroup(newPerson)
end try
P.P.S. person is a reserved word for Address Book. Change person to some other variable and it will work (referring to the addPersonToGroup subroutine).