Community
Showing results for 
Search instead for 
Do you mean 
Reply

Newbie Starting out. Parsing a list of Contacts.

New Member
Posts: 7
Country: USA

Newbie Starting out. Parsing a list of Contacts.

What I am ultimately trying to do is scan through all Contacts created within a given date range. Parse a record from the History tab that is created by Swift page and then take those parsed items and fill custom fields in the same contact record.

So my first baby step was to create a Custom Menu. That worked!

My next step was to get a list of all contacts and then print the count in a message box. That FAILED!

I keep getting an Multi-Part SQL Error. I suspect the GetContactFieldDescriptor has the wrong value, but since I can 't find a list of the Field Descriptors I have not idea.

Here is my code:


using System;
using System.ComponentModel;
using System.Windows.Forms;
using Act.UI;
using Act.Shared.Collections;
using Act.Framework;
using Act.Framework.Contacts;
using Act.UI.Core;

namespace Act.Samples
{
class CustomMenuPlugin : IPlugin
{

private const string CONNECTED_MENUBAR = "Connected Menus";
private const string DISCONNECTED_MENUBAR = "Disconnected Menus";

private const string CUSTOM_MENU_URN = "act-ui://com.act/application/menu/tools/custom";
private const string CUSTOM_MENU_TEXT = "Hightower";

private ActApplication application;

void IPlugin.OnLoad(ActApplication application)
{
// hold on to the application
this.application = application;

// be sure to keep track of when a user logs in or is logged out
application.AfterLogon += new EventHandler(Application_AfterLogon);
application.BeforeLogoff += new EventHandler(Application_BeforeLogoff);

}

void IPlugin.OnUnLoad()
{

// this is equivalent to being disposed,
// so make sure to detach from any events
if (application != null)
{
application.AfterLogon -= new EventHandler(Application_AfterLogon);
application.BeforeLogoff -= new EventHandler(Application_BeforeLogoff);
ActFramework framework = application.ActFramework;
if (framework != null)
{
framework.Database.BeforeDatabaseLock -= new Act.Framework.Database.DatabaseLockHandler(Database_BeforeDatabaseLock);
}
}
}

private void Application_AfterLogon(object sender, EventArgs e)
{
//TODO: attach to any events or perform actions

// also, keep track of when we're about to be locked out
application.ActFramework.Database.BeforeDatabaseLock += new Act.Framework.Database.DatabaseLockHandler(Database_BeforeDatabaseLock);



// add custom menu
AddMenuItem(CUSTOM_MENU_URN, CUSTOM_MENU_TEXT, new Act.UI.CommandHandler(DoStuff));

this.application.ActFramework.Database.BeforeDatabaseLock += new Act.Framework.Database.DatabaseLockHandler(this.BeforeDatabaseLock);


}

private void Application_BeforeLogoff(object sender, EventArgs e)
{
// make sure to detatch from anything framework/database/user related,
//as we are about to be logged out

// Remove this so it doesn't become part of the customized menus
RemoveMenuItem(CUSTOM_MENU_URN);
}

private void DoStuff(string command)
{

ActFramework ActFwk = application.ActFramework;

MessageBox.Show("Do something");

try
{

MessageBox.Show("Before Field Descriptor");

ContactFieldDescriptor cfd1 = ActFwk.Contacts.GetContactFieldDescriptor("TBL_CONTACT.CREATEDATE", true);

SortCriteria[] sCriteria ={ new SortCriteria(cfd1, ListSortDirection.Descending) };

ContactList cList;



System.DateTime d1;

System.DateTime d2;

d1 = System.DateTime.Parse("01/01/1980");

d2 = System.DateTime.Parse("12/31/2008");



IFilterCriteria[] oFilterCriteria = { new DateFilterCriteria(cfd1, d1, d2) };

MessageBox.Show("Before Get Contats");

cList = ActFwk.Contacts.GetContacts(sCriteria, oFilterCriteria);


MessageBox.Show("clist count = " + cList.Count.ToString());


///Continue your code ....

}

catch (Exception ex)
{

MessageBox.Show(ex.ToString());

}


}


public void BeforeDatabaseLock(object obj, Act.Framework.Database.DatabaseLockInformation LockInfo)
{

}

#region Custom Menu

private void AddMenuItem(string urn, string text, Act.UI.CommandHandler Handler)
{
try
{
if (MenuItemExists(urn) == true)
{
RemoveMenuItem(urn);
}
Act.UI.Core.CommandBarControl parentMenu = this.application.Explorer.CommandBarCollection[CONNECTED_MENUBAR].ControlCollection[GetParentControlURN(urn)];
Act.UI.Core.CommandBarButton newMenu = new Act.UI.Core.CommandBarButton(text, text, null, urn, null, null);
newMenu.DisplayStyle = Act.UI.Core.CommandBarControl.ItemDisplayStyle.TextOnly;
this.application.RegisterCommand(urn, new Act.UI.CommandHandler(Handler), Act.UI.RegisterType.Shell);
parentMenu.AddSubItem(newMenu);
}
catch { }
}

private void RemoveMenuItem(string urn)
{
try
{
this.application.RevokeCommand(urn);
Act.UI.Core.CommandBarControl RemoveMenu = this.application.Explorer.CommandBarCollection[CONNECTED_MENUBAR].ControlCollection[urn];
this.application.Explorer.CommandBarCollection[CONNECTED_MENUBAR].ControlCollection[GetParentControlURN(urn)].RemoveSubItem(RemoveMenu);
}
catch { }
}

private bool MenuItemExists(string urn)
{
return (application.Explorer.CommandBarCollection[CONNECTED_MENUBAR].ControlCollection[urn] != null);
}

private string GetParentControlURN(string urn)
{
return urn.Substring(0, urn.LastIndexOf("/"));
}

#endregion

private void Database_BeforeDatabaseLock(object sender, Act.Framework.Database.DatabaseLockInformation databaseLockInformation)
{
//TODO: we're about to be forced out, so perform any cleanup
}

}
}
New Member
Posts: 8
Country: USA

Re: Newbie Starting out. Parsing a list of Contacts.

You can get a list of all of your contact descriptors pretty easily:
 
                    Dim cFields() As ContactFieldDescriptor = ActFwk.Contacts.GetContactFieldDescriptors()
                    Array.Sort(cFields, New CompareFileInfoEntries(CompareByOptions.DisplayName))
                    Dim myDescriptorList As String = ""
                    Dim myDescriptor As ContactFieldDescriptor

                    For Each myDescriptor In cFields
                        myDescriptorList += myDescriptor.DisplayName + " - " + myDescriptor.Name + vbCrLf
                    Next
 
                    MsgBox(myDescriptorList)
 
You might need to use a multi-line text box with vertical scrollbars instead of a msgbox if you have a lot of descriptors. Just print it out once and you'll have all of your descriptors for easy reference.
 
Also, that code is in VB.NET and will need to be converted to C# if that's what you use...
 
-Cameron
New Member
Posts: 8
Country: USA

Re: Newbie Starting out. Parsing a list of Contacts.

Oh and take out the array.sort, unless you want to use the CompareFileInfoEntries class:
 
Public Enum CompareByOptions
    DisplayName
End Enum
Public Class CompareFileInfoEntries
    Implements IComparer
    Private compareBy As CompareByOptions = CompareByOptions.DisplayName
    Public Sub New(ByVal cBy As CompareByOptions)
        compareBy = cBy
    End Sub
    Public Overridable Overloads Function Compare(ByVal file1 As Object, _
           ByVal file2 As Object) As Integer Implements IComparer.Compare
        'Convert file1 and file2 to FileInfo entries
        Dim f1 As ContactFieldDescriptor = CType(file1, ContactFieldDescriptor)
        Dim f2 As ContactFieldDescriptor = CType(file2, ContactFieldDescriptor)
        'Compare the file names
        Select Case compareBy
            Case CompareByOptions.DisplayName
                Return String.Compare(f1.DisplayName, f2.DisplayName)
        End Select
    End Function
End Class
 
Copper Contributor
Posts: 98
Country: United States

Re: Newbie Starting out. Parsing a list of Contacts.

Hey Dale,
 
CREATEDATE should be the correct columnname.
 
What is the exact error message you are getting?
Carlton Jones
Sage Software
New Member
Posts: 7
Country: USA

Re: Newbie Starting out. Parsing a list of Contacts.

[ Edited ]
Here is the error message. I know this is a SQL Server thing.

"The multi-part identifier \"TBL_CONTACT.CREATEDATE\" could not be bound.
The multi-part identifier \"TBL_CONTACT.CREATEDATE\" could not be bound."

Act.Framework.Contacts.ContactManagerDB.ContactManagerDBException was unhandled
Message="Error retrieving contact keys"
Source="Act.Framework"
StackTrace:
at Act.Framework.Contacts.ContactManagerDB.GetDataKeys(SortCriteria[] sortCriteria)
at Act.Shared.Collections.DataList`1.Init()
at Act.Shared.Collections.DataList`1..ctor(SortCriteria[] sortCriteria, Object dataSource, Int32 batchSize, Boolean deferInitialKeyFetch)
at Act.Shared.Collections.DataList..ctor(SortCriteria[] sortOrder, Object dataSource)
at Act.Framework.Contacts.ContactManager.GetContacts(SortCriteria[] sortCriteria, IFilterCriteria[] filterCriteria)
at ActThree.Form1.button1_Click(Object sender, EventArgs e) in Z:\Development\Trident\ActThree\ActThree\Form1.cs:line 117
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at ActThree.Program.Main() in Z:\Development\Trident\ActThree\ActThree\Program.cs:line 17
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

Message Edited by daleedom on 04-07-2008 04:49 PM

Message Edited by daleedom on 04-07-2008 04:51 PM
Copper Contributor
Posts: 98
Country: United States

Re: Newbie Starting out. Parsing a list of Contacts.

[ Edited ]
Dale,
 
I'd hoped that would not be the case.
I've already reported this behavior. I haven't tested all the assembly versions but I with the 10.0.2 assemblies you get this error.
It could be worth trying some older assemblies to see if this works there.
 
Otherwise, as we wait on a fix/clarification in a future release we'll probably need to code around this issue.
 
This is by no means graceful coding but I think it should help for the time being:
 
Code:
try
            {
                //declare objects and specify the criteria
                ContactFieldDescriptor cfd = ActFwk.Contacts.GetContactFieldDescriptor("Contact.Edit Date", false);
                SortCriteria[] sCriteria = { new SortCriteria(cfd, ListSortDirection.Descending) };
                //ContactList with no Filter Criteria (aka all contacts)
                ContactList cList = ActFwk.Contacts.GetContacts(sCriteria);
                //Declaring the Contact Array I am going to store the results in.
                Contact[] cArray = new Contact[cList.Count];
                //Our Dates to filter on
                DateTime d1 = DateTime.Parse("04/01/2008");
                DateTime d2 = DateTime.Parse("04/30/2008");

                //My counter
                int x = 0;
                //Looping though all contacts in cList
                foreach (Contact c in cList)
                {
                    //Parse our Contact Edit Date into a temp DateTime
                    DateTime temp = DateTime.Parse(cfd.GetValue(c).ToString());

                    //Our 'IFilterCriteria' = After April 1st and Before April 30th
                    if (temp > d1 && temp < d2 )
                    {
                        //Add to your Collection
                        listBox1.Items.Add(c);
                        cArray[x] = c;
                        x++;
                    }
                    
                }
                //Display the number of results
                MessageBox.Show("Count " + x);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }


Message Edited by Carlton_Jones on 04-07-2008 05:25 PM
Carlton Jones
Sage Software
New Member
Posts: 7
Country: USA

Re: Newbie Starting out. Parsing a list of Contacts.

Carlton,

Thanks for the response.

At this point the main purpose of the date search was to not have to scan the entire list. So for now we are good without the date lookup. I am scanning the list looking for imported data from Swiftpage.

Now my Tools menu is Grayed out, but that is in another post.

Thanks,

Dave
New Member
Posts: 10
Country: Ireland

Re: Newbie Starting out. Parsing a list of Contacts.

Hi Guys

 

I also get "Error retrieving contact keys" error when trying to filter by date (10.0.2 assemblies)

 

Any idea when this bug might get sorted?

 

Thanks

Mark 

Copper Contributor
Posts: 98
Country: United States

Re: Newbie Starting out. Parsing a list of Contacts.

Its been reported and should be fixed in upcoming releases.
Carlton Jones
Sage Software