Tuesday, April 10, 2007

PSI - Add Resource custom field values based on a Lookup table values

When you are trying to add values based on Project Server 2007 lookup values the code can get a little tricky so I thought I would outline the steps and include the appropriate code for your reference.

1. Establish a ResourceDataset object
2. Populate the ResourceDataset using the Resource GUID
3. Call my AddResCF function as below passing in the value text (Please refer to the inline comments for further direction)

private bool AddResCFs(Proxy.ResourceDataSet resourceDS, string CFText)
{
bool result = false;
Guid structGuid = Guid.Empty;
string cf_md_prop_name = "";
Guid cf_md_prop_uid = Guid.Empty;
int cf_md_prop_id = int.MinValue;
byte cf_md_prop_type_enum = byte.MinValue;
try
{

//establish a LookupTable dataset using the name of the lookup table which in my case is a class variable (I haven't included the GetLookup_UID function as its pretty straight forward).
Guid LTGuid = new Guid(CustomUtils.GetLookup_UID(lookupName));
//create a lookup table dataset
Proxy.LookupTableDataSet dsLookup = new Proxy.LookupTableDataSet();

//Populate the LookupDataset using the Guid returned above
dsLookup = utils.LookupTableProxy.ReadLookupTablesByUids(new Guid[] { LTGuid }, false, int.Parse(LANGUAGE_ID.ToString()));

//Now check if the value exists in the Lookup table ( in this instance I am querying the description column instead of the name column) The LU_ValueExists just does a for each on the rows in the LookupTableDataset and set the result to true if the value is located
if (LU_ValueExists(dsLookup,"lt_value_desc", CFText))
{
//Create a ResourceCustomFieldsRow and populate the neccesary columns
Proxy.ResourceDataSet.ResourceCustomFieldsRow cfRow = resourceDS.ResourceCustomFields.NewResourceCustomFieldsRow();

//the following fields are not required but should be set to null for correctness
cfRow.SetNUM_VALUENull();
cfRow.SetFLAG_VALUENull();
cfRow.SetDUR_VALUENull();
cfRow.SetDUR_FMTNull();
cfRow.SetDATE_VALUENull();
cfRow.SetTEXT_VALUENull();

//Next populate the custom fields row with the correct property values using the Enterprise field name (different from LookupTable name). Again I am using a class variable for this purpose.
cf_md_prop_uid = CustomUtils.GetCustomFieldsProps(entfieldName, out cf_md_prop_name, out cf_md_prop_id, out cf_md_prop_type_enum);
if (cf_md_prop_uid != Guid.Empty)
{
cfRow.MD_PROP_UID = cf_md_prop_uid;
cfRow.MD_PROP_ID = cf_md_prop_id;
cfRow.CUSTOM_FIELD_UID = Guid.NewGuid();
cfRow.FIELD_TYPE_ENUM = cf_md_prop_type_enum;
cfRow.CODE_VALUE = skill_struct_uid;
cfRow.RES_UID = (Guid)resourceDS.Resources.Rows[0]["RES_UID"];
//add row to ResourceDataset
resourceDS.ResourceCustomFields.Rows.Add(cfRow);
result = true;
}
else
{
result = false;
}
}
return result;
}

4. Call the UpdateResources of your PSI Resources proxy object
private bool UpdateResourceEntField(Proxy.ResourceDataSet ResourceDS, Guid resGuid)
{
//add situation for exception handling
Proxy.ExceptionHandlers.Situation situation = Proxy.ExceptionHandlers.Situation.AddResourceSkills;
try
{
//check the resource out before calling the update method (I prefer this to the included check-//out boolean included in the function call)
//NB: Remember to include checkin code in your exception handlers as the resource will remain checked out if an handled exception occurs
bool bCheckOut = false;
bCheckOut = CheckOutResource(resGuid);
Proxy.Global.utils.ResourceProxy.UpdateResources(ResourceDS, false, false);
//Checkin the resource
bCheckOut = CheckInResource(resGuid);
return true;
}

Please note the above assumes that you already know the lookup table row value so you can read the loopuptable using a filter with the value specified. Also I have tried at length to just create an empty ResourceDataSet and then just add a populated ResourceCustomFields row but kept getting a GeneralUnhandledException from the PSIErrors collection. NICE!

The above is not a full set of functions but should get you going in the right direction. If I receive enough requests I'll polish it up into a little sample app for download.

Also I thought a little call to action: We have to share our Project Server Interface (PSI) code as MS didn't give us much to go on. The more that gets out there, the easier it will become to find resources on people's blog and discussion groups. Thanks for listening to my rant :-)

2 comments:

Hassan Voyeau said...

I understand how to add a custom field value to a resource but I can't seem to figure out how to update an existing custom field value. An example would be greatly appreciated.

Hassan.Voyeau@gmail.com

Marc Baguena said...

It's a great example of PSI's use! Thanks!!