Integration of Virtual Earth with Project Professional
First we are going to see few cases of integration or business scenarios where such type of integration can add values to business. These business scenarios will give you a better insight into the appropriate use of the integration of VE and project.
Business Scenarios I -
A project is in progress at different geographical locations or in various units which are geographically distributed. So the project is dispersed over various geographical locations. Now the Project Managers or the Management want to have check the status of progress location wise or unit wise with its tasks details and status and they find it very difficult to check the status location wise quickly.
Here we can take the advantage of virtual earth and its features by integrating VE Map with Project.
Solution –
So this integration of VE and project brings about a remarkable solution for the project managers and management to have a look on the status of the project which is geographically dispersed.
On the screen a push pin indicates a single geographical location and when we move the mouse over any particular unit or location, it shows the tasks information and its status in a popup window.
Business Scenarios II - Event Management
For managing an event the team has to make many arrangements such as they need to do some shopping, find the vendors for different articles and so on. The team needs to find the vendors who are located nearby the place where the event is going to take place.
They need to find information about vendors like address , URL etc … which can be used in various project’s tasks.
Solution-
The integration of virtual earth and Project Professional can play a vital role in displaying the required details. In such scenarios we can use the proximity search of Virtual Earth to find the item within the given map boundaries.
Business Scenarios III - Task Management
A hardware engineer has to visit several client locations daily to provide customer support. He has a customer address entity associated with each task. The main issue for him is to find an optimum path so as to cover all the tasks on time as he has to visit several locations, he might be unaware of the correct path to those locations.
Solution:
Architecture Diagram:
The Project Window will have the Add-in on it and this add-in is having a COM class. This class will fetch the data from PSI ( or from Project Object Model ) according to our business requirement. Data can be fetched for a single project or multiple projects or resource information.
The instance of COM class will call these methods inside the ‘GetDataPlotting’ function. After parsing it will return the required data array and using VE Operations we can plot the data on VE Map.
Project Window Architecture:
The window of project professional is having three main elements.
(a) Project Guide Toolbar - Displayed along with the standard toolbar in MS Project.
(b) Side pane - It is used for navigation within a particular goal area. So according to the architecture of Project window it is embedded inside the web browser control. It is shown in figure as Frame1
(c) Main Area - It is to the right of the side pane, It shows the view of project data. So the Mainpage.htm consists of two frames : Left Frame and Right Frame
We’ll do customization of right frame. We are going to divide the right frame into two frames (Top and Bottom). The bottom frame will be used for our Map component hosting.
Map Component hosting:
Project Professional uses IEControl object to load the entire right pane using right.htm as its source page.
<!-- This frame loads the Microsoft Project ActiveX control into the top half of the view's content space. Right.htm is the default Project Guide's right pane, and contains nothing but the Microsoft Project view control. -->
<iframe id="topFrame"name="ViewFrame"
style="position:relative; left:0; top:0; width:100%; height:40%"
frameborder=1marginheight=0marginwidth=0tabIndex=2
src="right.htm">
</iframe>
<!-- This loads the custom Web version of the Task Forms view into the bottom half of the view's content space. -->
<iframe id="bottomFrame"name="ViewFrameBottom"
style="position:relative; left:0; top:0; width:100%; height:60%"
frameborder=1marginheight=0marginwidth=0tabIndex=3>
</iframe>
Now we have customized this source page to display task details and bottom pane separately. We have divided this into two iFrames - top frame and bottom frame. We have also defined the dimensions of both iframes. We’ll use this bottom iFrame for our VE Page hosting.
Add-in Initialization
The OnConnection event fires whenever the add-in is connected. Once the add in loads , all the application variables will be initialized and our command bar will be added, where we have one button control.
We are creating a new “Command Bar” and a “Command Bar Button” at the time of “OnConnection” event. We have created an event handler for “Command Bar Button” to perform our custom actions.
PublicSub OnConnection(ByVal application AsObject, ByVal connectMode As Extensibility.ext_ConnectMode, ByVal addInInst AsObject, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
applicationObject = CType(application, VEPROj.MSProject.Application)
addInInstance = CType(addInInst, Microsoft.Office.Core.COMAddIn)
'Create the command bar and get the reference of the newly added bar
customTolBar = AddProjectProToolbar(applicationObject, "VEToolBar")
IfNot customTolBar IsNothingThen
'Call this method to add command button
MakeANewButton(customTolBar, "Show Map", 43, AddressOf OnShowMap_Click)
EndIf
addInInstance.Object = Me
_PSIServiceManagerObject = New PSIServiceManager()
EndSub
'Method will create a new button and will attach event handler to it.
PrivateFunction MakeANewButton(ByVal commandBar As _
Microsoft.Office.Core.CommandBar, ByVal caption AsString, _
ByVal faceID AsInteger, ByVal clickHandler As _
Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler) _
As Microsoft.Office.Core.CommandBarButton
Try
'Create a new button.
newButton = CType(commandBar.Controls.Add( _
Microsoft.Office.Core.MsoControlType.msoControlButton), _
Microsoft.Office.Core.CommandBarButton)
'Set the button properties.
With newButton
.Caption = caption
.FaceId = faceID
.BeginGroup = True
.Tag = caption
.OnAction = "!<VEProjectAddIn.Connect>"
.Visible = True
.DescriptionText = caption
.Style = Microsoft.Office.Core.MsoButtonStyle.msoButtonIconAndCaption
EndWith
AddHandler newButton.Click, clickHandler
Return newButton
Catch ex As System.Exception
ThrowNew Exception(ex.Message)
EndTry
EndFunction
Get Project Data
Now we have to create a COM Class that interacts with PSI to fetch data from project server (we can also use Project Object Model to fetch data of current project). Here we have two methods one is “GetProjectDetail” and the other one is “GetCustomFields” both of these methods are being used to get data from Project Server. The GetProjectDetail Method uses “Project” web service of PSI to retrieve data related to project and tasks from Project Server. Here we have invoked “ReadProject” web method of “Project” web service and second method GetCustomFields uses the “CustomFields” web service to fetch all enterprise custom fields’ information.
We need these custom fields’ data to plot push pins on the Map. Each task has a custom field which holds the Address and Active flag.
'Method will fetch Project and Task details from PSI.
PublicFunction GetProjectDetail(ByVal ProjectUID AsString) AsString
Dim ProjDs AsNew ProjectWebSvc.ProjectDataSet() 'Create a new instance on ProjectDataset Class
Try
ProjectSvc = New ProjectWebSvc.Project() 'Create a new instance of Project Class
ProjectSvc.Url = objMyConfig.Url + sProjectWebService 'Assign the dynamic Project web service URL
ProjectSvc.Credentials = GetCredential() 'Get the credentials
'Invoke the ReadProject web method
ProjDs = ProjectSvc.ReadProject(New Guid(ProjectUID), ProjectWebSvc.DataStoreEnum.WorkingStore)
Catch ex As Exception
ThrowNew Exception(ex.Message)
EndTry
Return ProjDs.GetXml() ' Return the result as xml string
EndFunction
'Method will fetch all enterprise Custom fields from PSI
PublicFunction GetCustomFields() AsString
Dim CustFieldsDs AsNew CustomFieldsWebSvc.CustomFieldDataSet() 'Create a new instance on CustomFieldDataSet Class
Try
CustomFieldsSvc = New CustomFieldsWebSvc.CustomFields() 'Create a new instance of Custom Fields Class
CustomFieldsSvc.Url = objMyConfig.Url + sCustomFieldsWebService 'Assign the dynamic Custom Fields web service URL
CustomFieldsSvc.Credentials = GetCredential() 'Get the credentials
'Invoke the ReadCustomFields web method
CustFieldsDs = CustomFieldsSvc.ReadCustomFields(String.Empty, False)
Catch ex As Exception
ThrowNew Exception(ex.Message)
EndTry
Return CustFieldsDs.GetXml() ' Return the result as xml string
EndFunction
Get Data Plotting
The getProjectDetails is a JavaScript function in which we are using COM object and will generate the address array which is going to be used for push pin adding.
function GetProjectDetails()
{
try
{ var sResponseXml;
var sPeojectResponseXml;
var comPSIManager=window.external.Application.COMAddIns.item(AddinName).Object.comPSIManager;
sResponseXml= comPSIManager.GetCustomFields();
xmlDocCustom = new ActiveXObject("Microsoft.XMLDOM");
xmlDocCustom.loadXML(sResponseXml);
sResponseXml= comPSIManager.GetProjectDetail(ProjectUID);
xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); //Create new XmlDocumenent for TaskDetails.
xmlDoc.loadXML(sResponseXml);
//Get the "MD_PROP_ID" of "Address" and "Is Active" enterprise custom fields using XPath.
var AddressProp_UID = xmlDocCustom.selectSingleNode("//CustomFields[MD_PROP_NAME='Address']").selectSingleNode("MD_PROP_ID").text;
var IsActiveProp_UID = xmlDocCustom.selectSingleNode("//CustomFields[MD_PROP_NAME='Is Active']").selectSingleNode("MD_PROP_ID").text;
//Get all nodes of "TaskCustomFields" element where "Is Active" field value equal to "true".
var allActiveTask = xmlDoc.selectNodes("//TaskCustomFields[MD_PROP_ID=" + IsActiveProp_UID +" and FLAG_VALUE='true']");
var taskNameArr = new Array(); //Create an array to store "Task Name"
var taskAddressArr = new Array(); //Create an array to store "Address"
for(i=0;i<allActiveTask.length;i++)
{
var tastUID = allActiveTask[i].selectSingleNode("TASK_UID").text; //Get TaskUID
var taskName = xmlDoc.selectNodes("//Task[TASK_UID='" + tastUID + "']")[0].selectSingleNode("TASK_NAME").text; //Get TaskName
var taskAddress = xmlDoc.selectNodes("//TaskCustomFields[MD_PROP_ID=" + AddressProp_UID +" and TASK_UID='" + tastUID + "']")[0].selectSingleNode("TEXT_VALUE").text; //Get Address
taskNameArr[i] = taskName; //Add TaskName to array
taskAddressArr[i] = taskAddress; //Add Address to array
}
GetDirections(taskAddressArr,taskNameArr)
}
catch(e)
{
ShowErrorMessage("GetProjectDetails:-",e);
}
}
VE Operations
//Get the optimal route
function GetDirections(points,displayName)
{
try
{
map.DeleteRoute(); //Delete route if any.
var options = new VERouteOptions();
options.RouteOptimize = VERouteOptimize.MinimizeDistance;
options.DrawRoute = true;
options.SetBestMapView = true;
options.RouteCallback = ShowTurns;
options.DistanceUnit = VERouteDistanceUnit.Mile;
options.ShowDisambiguation = true;
map.SetZoomLevel(5); // Set map zoom level to 5
map.GetDirections(points, options); //Plot route on map
}
catch(e)
{
ShowErrorMessage("GetDirections:-",e)
}
}
In a same window where the hardware engineer gets the details about his tasks, he can view an interactive Virtual Earth map showing the locations of his clients. The features of Virtual Earth will help him show a step by step optimum path.
Summary:
Integration of Project Professional and VE Map provides a good platform for application scenarios like:
• Visually displaying of Project tasks and the associated location parameters on a virtual map
• Display all the tasks for a resource from various project plans along with location details
• Visually display location priorities and routes for execution profiles of tasks
• Use of Geometry and Geography data-types available in SQL Server 2008, in custom web services
• MapCruncher can be useful in case of civil engineers project specially, where they can put their own custom map
Contributed by Virsharma