Project Server: Resource Plans and the PSI

I was doing some investigations this week on the Resource Plans Web Service and want to share this as it probably gives more information than we have in the SDK currently – or at least pulls it together.  The example I will be working towards is adding a resource to a resource plan, along with an assignment within that resource plan.  My work was specifically with 2007, but as far as the dataset manipulation is concerned this applies equally to Project Server 2010.

But first a quick look round the resource plan dataset and explaining how this maps to the UI.  The SDK article for 2007 is here and for 2010 is here – but to be honest you will be hard pressed to find much difference.

The dataset has four data tables, Utilization, Dates, PlanAssignmentCustomFields and PlanResources.

Utilization – This table shows the utilization type and date – which relate to the UI in this screenshots – 2007 and 2010. The types are as listed 0, 1 and 2 – with the date only applicable for type 2 (plan until:

image           image

From the SDK: The ResourcePlan.UtilizationType type is used in the RESPLAN_UTILIZATION_TYPE column of the ResourcePlanDataSet Utilization table. Values and descriptions for the ResourcePlan.UtilizationType type are provided solely for interpreting the information in this table.

This is not intended to be used directly from your code.

Dates – This table shows the start and end dates of the intervals defined for the Resource Plan.  The overall range will be set by the start and end dates entered when reading the dataset, and it will be broken into intervals according to the TimeScale specified.  The TimeScaleClass enumeration can be used when reading the dataset.  3 = Days, 4 = weeks, 5 = months and 7 = years – or (short)PSLibrary.TimeScaleClass.TimeScale.Months. 

PlanAssignmentCustomFields – You can have custom fields set for the resource’s assignments in a resource plan!  Who knew?  I’m guessing not many people have seen the following screen.  This is from 2007, but almost identical to the 2010 equivalent.  This is also the place you can change the resource from Committed to Proposed – or vice versa.


I’ve not played around with these via the PSI – but this is the table you would work with, and as is usual with Custom Fields, you need to add a row then set the properties.

PlanResource – This table is the one that I will be working with in my sample code where we will be adding a resource.  When you read a Resource Plan you will see it contains a ton of information on the resource, most of which you do not need to enter when adding one, along with a flag for Committed or Proposed (ASSN_BOOKING_TYPE) and a set of fields Interval0 to Interval’n’ which relates to the ‘n’ intervals you will see in the dates table.  When adding a resource you can also add an assignment by putting some value in one or more of these intervals.  The parameters for getting the resource plan dataset using ReadResourcePlan are:

filter – XML filter to limit data returned. For more information, see How to: Use a Filter Parameter with PSI Methods. I am not using filters, and as you can specify the project GUID there probably aren’t many circumstances when you’d need to filter down – unless you have a really large number of resources assigned.
projectUid – Project GUID.
startDate – Start date. This is the start date of the data you want to pull down from the server and manipulate – so it is potentially just a window on the entire resource plan, and need not relate to the date settings within the UI
endDate – End date.
timeScale – Time scale specified by the TimeScaleClass.TimeScale enumeration. Explained above – controls the time intervals
timephasedFTE – If true, return the full time equivalent resources.  This will govern if you enter FTEs, or, if false, then time (in 1/10th of a minutes) for the work values.
autoCheckOut – If true, check out the resource plan for editing.  This will depend exactly what you are doing.  You might want to check out just before the update, and you would also want to check that it wasn’t already checked out too.

A similar set of parameters also apply to the QueueUpdateResourcePlan method:

projectUid – Project GUID.
rpds – ResourcePlanDataSet that specifies changes in the specified resource plan.  Basically a manipulated version of the one you read in.  Don’t AcceptChanges!
timephasedFTE – If true, update with timephased full time equivalent resources. Same meaning as above.
autoCheckIn – If true, check in the resource plan after updating.
jobUid – Queue job GUID.

Also I am assuming there is already a Resource Plan for the project – if not my code would fail with a System.Web.Services.Protocols.SoapException: ProjectServerError(s) LastError=GeneralItemDoesNotExist and you would need to use the UI or QueueCreateResourcePlan method.  And finally you cannot publish the resource plan unless the project plan is published – or you will get another error – System.Web.Services.Protocols.SoapException: ProjectServerError(s) LastError=ResourcePlanProjectPublishIncomplete.  It would be unusual to get this condition as in most cases you create resource plans on published projects, but could happen with Activitity plans and proposals and server-side or other programmatically created projects.

Rather than repeat things I have added comments in the code where I think some explanation is necessary.  This snippet assumes you have a reference to PSLibrary = Microsoft.Office.Project.Server.Library; and a web reference to the Resource Plan web service.  I’ve hardcoded quite a bit of stuff just to show what is going on.


Guid projUid = new Guid("357afdea-0b68-46bc-8358-7557c8f90a8f");            
Guid resUid = new Guid("f249df7c-eca9-41c7-bd52-48def0ab50bc");                        
ResourcePlan resourcePlan = new ResourcePlan();           
resourcePlan.Credentials = CredentialCache.DefaultCredentials;           
resourcePlan.Url = "http://brismithupgrade/2k7/_vti_bin/PSI/resourceplan.asmx";
ResourcePlanDataSet dsResourcePlan = new ResourcePlanDataSet();
// Read in a resource plan dataset for our chosen project 
dsResourcePlan = resourcePlan.ReadResourcePlan(null, projUid               
 ,DateTime.Parse("01/01/2010"), DateTime.Parse("12/31/2010")
 ,(short)PSLibrary.TimeScaleClass.TimeScale.Months , false, false); 
// Create a new Plan Resource Row and set some properties

ResourcePlanDataSet.PlanResourcesRow resourcePlanRow 
= dsResourcePlan.PlanResources.NewPlanResourcesRow();            
resourcePlanRow.PROJ_UID = projUid;            
resourcePlanRow.RES_UID = resUid; 
// Assignment UID does not need to be specified - it will be auto generated             
// The value used against intervalx will depend on the setting for the timePhasedFTE value            
// If set to true, then enter values like 1 for one Full Time Equivalent            
// If set to false the Intervalx values are entered as 1/10th Minutes - 600 = 1h, 4800 = 1d            
// This entry adds 4800 = 1d = 8h, to the 7th interval - August with the settings I am using
resourcePlanRow["Interval7"] = 4800;
// And this one adds 5 days to September
resourcePlanRow["Interval8"] = 48000;
// 0 = Committed and 1 = Proposed or use the enumeration
resourcePlanRow.ASSN_BOOKING_TYPE = (byte)PSLibrary.Resource.BookingType.Committed ;
// Add the row the the resource plan 
// Use the same jobUid for the update and checkin.
Guid jobUid = Guid.NewGuid();
resourcePlan.CheckOutResourcePlans(new Guid[1] { projUid });            
resourcePlan.QueueUpdateResourcePlan(projUid, dsResourcePlan, false, false, jobUid);  
//  Need to be sure the project plan is published or this will fail

resourcePlan.QueuePublishResourcePlan(projUid, Guid.NewGuid());            
resourcePlan.QueueCheckInResourcePlans(new Guid[1] { projUid }, false, new Guid[1] { jobUid });

I hope this help you understand how to work with Resource Plans in a programmatic way.

Comments (13)

  1. John Goodson says:

    Brian, how can we know the ResourcePlan is checked out?  If it is checked out already, the following line will throw an error:

    resourcePlan.CheckOutResourcePlans(new Guid[1] { projUid });

    I've looked through the methods and properties of this web service, as well as the returned data, but I don't see anything to read the checkout status.  What do you think?

  2. BriSmith says:

    Very good question John.  I took a quick look – and I'd have "hoped" that the ResourcePlanStatus might have given this information – but that just tells you if it exists at all, or has been published.  I think you will have to use the call you are making, and handle the exception.  I will ask around if there is something we are both missing.

    Best regards,


  3. Carlos says:

    Brian, how can we get the resource plan start and finish dates (they are displayed right below the ribbon). I noticed that these don't match up with the project's start and finish date.

    Also, is there a way to tell when the resource plan was last saved?



  4. BriSmith says:

    Hi Carlos,

    Firstly apologies for the delay in answering – I knew this would need some investigation.

    These dates are not specifically stored as resource plan start and end dates as they are based on the earliest date and latest date of all resource assignments in the resource plan.  Also it is by design that they need not necessarily agree with the project start and end dates – and the assignment they relate to may not even be shown on the PWA Resource Plan if your date range does not include them.  So to get these dates you'd need to read the resource plan with a broad enough time range that would include the start and finish – and then look for the earliest and latest.  Out of interest what are you looking to use these dates for?  I'm wondering if there is a good reason we should make this easier.  Taking a peak behind the scenes (SQL Profiler Trace) we appear to be calling MSP_DATAEDIT_GET_RESOURCE_PLAN_ASSIGNMENT_DATA_BY_RESOURCE with parameters of the project UID and the resource UID, which does return the "by resource" start and end dates of the assignment.  I assume we then look for the earliest and latest to display.  One final thing I noticed is that for my resource plan I set just one day in the resource plan, yet the start date was set to the earliest date in that current view and the end date to the date the work was set – so these dates may not be entirely reliable.  I don't really see this as an issue as generally we are using broad timescales and not granular daily buckets.  

    Do you think this is a big issue?

    Best regards,


  5. Carlos says:


    It would be nice if their was a way to get the earliest and latest dates so that the query into the Resource Plan does not have to be a huge window. I got around this by querying a 10 year window around the resource plan and getting the "yearly" time scale to add up the full project hours, but this method does not allow be to get the earliest and latest dates to the "day", just the year. I can do the 10 year range by day, but that is 365 days per year to check and I didn't want to take the hit on processing all those checks.

    Also, you didn't answer my other question, is there a way to tell when the resource plan was last saved through the PSI methods so that I can display this to the user? I want to be able to let them know when the plan was last saved so that they can update it if they don't see the latest numbers.

    Come to think of it, the ReadResourcePlan() method does not tell me if it's pulling Saved or Published data. Can you confirm which one it's pulling?

    Thanks in advance!


  6. BriSmith says:

    Hi Carlos, sorry I missed answering the last question.  I can't see any property on the resource plan web service that will give you the last saved date.  I must admit having just taken a peak at the database that this feels like one of the occasions when a PSI extension that does a read of the DB might be a better option for you to get the RESPLAN_START_DATE and RESPLAN_FINISH_DATE, as well as the MOD_DATE.  But don't tell anyone I said so…

  7. Carlos says:


    Thanks for the great information… Just one more question:

    The ReadResourcePlan() method does not tell me if it's pulling Saved or Published data. Can you confirm which one it's pulling and if there is a way to control which data it pulls?


  8. BriSmith says:

    Hi Carlos, it is always pulling from the draft (saved) database.  I can't see any way to change this.

    Best regards,


  9. John Goodson says:

    Brian, thanks again for this great post.   Any suggestions for getting around the ResourcePlanProjectPublishIncomplete issue?  This seems to be occuring when the project publish is stale.  We would like to trap the error, but have not found a good way to do so.  

  10. suso says:

    Hi Brian!

    I've a question related with resource plans. I have created a resource plan for a new project (using Calculate Resource Utilization from Resource Plan) and then I create a new analysis in Portfolio (i tried using RBS and Position Role).

    It occurs something strange, i can see the values assigned to the resource plan within Project Resource Requirements table, but just for January 2011 even if the plan has correct values from november 2010 to march 2011.

    Do you have any idea??

    More data: I'm using custom field based analysis for just one project.

  11. Maureen Parker says:

    Hi Brian



    I have a resource and I have set up a Position Role table and Resource custom field using the Positon Role table.  I have assigned the Position Role of SME to Adam.

    I then go into the Resource plan and get Adam from the build team.

    I add the Position Role field to the Resource plan view view in the Resource plan so that I can see that Adam is an SME but guess what the SME has not pulled through from where I set it against adam in the Manage users section of the Server Settings.  I now need to click on the Edit custom fields icon and add it again against the Positon Role for Adam and then I see it against admin in the Position role column of the Resource plan view on the Resource plan.

    Is this normal behaviour?

    Is there a way to make the position role value that I entered against the user in the Manage user pull through to the Resource plan view?

    Please email me at

    Kind regards


  12. Tom Herrington says:

    Brian, why does Resource Plan sometimes require that a project plan be published before the Resource Plan can be published?  There are some projects that don't require a project plan be published first.  Very inconsistent from my view.



  13. BriSmith says:

    Hi Tom, I thought a plan always needed to be published – but it could be that depending how the plan gets created the publish may happen anyway – and you may not have actually had to say 'publish' to get the same result.  If you have a repro I'd be happy to take a deeper look.

    Best regards,