protected void UpdateTasks(SPItemEventProperties properties)
{
try
{
// Disable event firing for the life of this instance only to prevent concurrency issues
this.DisableEventFiring();
// Invoke the SPWeb object responsibly so that it will be properly disposed of
using (SPWeb web = properties.ListItem.ParentList.ParentWeb)
{
decimal iHours = 0;
// Get the task value from the current item
string strTask = properties.ListItem[strSourceTaskField].ToString();
// Set the source list
SPList lSource = properties.ListItem.ParentList;
// Get a collection of all the list items with the same task value as the initiating item.
SPQuery qrySrcQuery = new SPQuery();
string strSrcQuery = "<Where><Eq><FieldRef Name='" + strSourceTaskField + "' /><Value Type='Choice'>" + properties.ListItem[strSourceTaskField].ToString() + "</Value></Eq></Where>";
qrySrcQuery.Query = strSrcQuery;
SPListItemCollection licSrcItems = lSource.GetItems(qrySrcQuery);
// Get each item that matches the given task. This prevents orphaned task items and keeps the target list in sync.
if (licSrcItems.Count > 0)
{
foreach (SPListItem liSrcItem in licSrcItems)
{
iHours = iHours + Convert.ToDecimal(liSrcItem[strSourceTimeField].ToString());
}
}
// Instantiate the target list. Pass in a CAML Query to get the matching list items.
SPList lTarget = web.Lists[strTargetListName];
SPQuery query = new SPQuery();
string strQuery = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>" + strTask + "</Value></Eq></Where>";
query.Query = strQuery;
SPListItemCollection licTargetItems = lTarget.GetItems(query);
// A quick and dirty way to prevent duplicates. This method is a bit fragile and could use better logic to insure uniqueness.
if (licTargetItems.Count > 0 && licTargetItems.Count < 2)
{
// Get the singular item
SPListItem liTargetItem = licTargetItems[0];
// Cast the field that contains the completion percentage. Note that this is the DISPLAY NAME of the field
// not the actual name as stored in the global variable. Modify this value if you have changed the DisplayName in the UI.
SPField liTargetField = liTargetItem.Fields["% Complete"];
decimal iTotalHours = Convert.ToDecimal(liTargetItem[strTargetEstHours].ToString());
decimal dPercComp = 0;
string sPercComp = "";
// If the event is ItemDeleting, subtract the value of the deleted item's hours from the total.
if (bDeleted)
{
iHours = iHours - Convert.ToDecimal(properties.ListItem[strSourceTimeField].ToString());
}
// Check to see if the display type is with Percentage or without and modify the value accordingly.
if (liTargetField.SchemaXml.Contains("Percentage=\"TRUE\""))
{
dPercComp = iHours / iTotalHours;
sPercComp = dPercComp.ToString().Substring(0, 4);
}
else
{
dPercComp = Math.Round((iHours / iTotalHours) * 100, 0);
sPercComp = dPercComp.ToString();
}
// Check the status value and update the target item with the new Status, Completion Percentage, and Total Hours values.
if (liTargetItem["Status"].ToString() != "Completed")
{
liTargetItem["Status"] = "In Progress";
liTargetItem[strTargetComplete] = sPercComp;
liTargetItem[strTargetTotalHours] = iHours;
liTargetItem.Update();
}
}
}
// Turn event firing back on
this.EnableEventFiring();
}
catch // Add explicit exception handling
{
//Write to the event log if you wish.
}
} |