33
SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com © 2011 SAP AG 1 How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP Netweaver Gateway, SharePoint BDC programming. Summary This article describes how to create Web Parts that are using BDC’s to connect SharePoint with Duet Enterprise. Author: Ravi Sharma Company: C2C Consulting Created on: 30 January 2011 Author Bio Ravi Sharma is a Development Architect and solution manager working for C2C consulting in Germany. His current Tasks: Duet Enterprise For Microsoft SharePoint and SAP, SAP NetWeaver Gateway and iPhone / Android Apps, SAP ESOA Tools & Utilities SAP IDM & GRC Integration. Knowledge of SAP ABAP, Cross Applications, ALE/IDOC, RFC's qRFC, tRFC, BADI, OOP's Concepts, CCMS and Solution Manager, SAP RFID, SAP Dynpro, SAP ABAP Webdynpro, SAP Net weaver, DUET 1.5, ABAP and Java Web services.

How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

  • Upload
    others

  • View
    24

  • Download
    0

Embed Size (px)

Citation preview

Page 1: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 1

How to Create Duet SharePoint

Web Parts

Applies to:

Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP Netweaver Gateway, SharePoint BDC programming.

Summary

This article describes how to create Web Parts that are using BDC’s to connect SharePoint with Duet Enterprise.

Author: Ravi Sharma

Company: C2C Consulting

Created on: 30 January 2011

Author Bio

Ravi Sharma is a Development Architect and solution manager working for C2C consulting in Germany. His current Tasks: Duet Enterprise For Microsoft SharePoint and SAP, SAP NetWeaver Gateway and iPhone / Android Apps, SAP ESOA Tools & Utilities SAP IDM & GRC Integration. Knowledge of SAP ABAP, Cross Applications, ALE/IDOC, RFC's qRFC, tRFC, BADI, OOP's Concepts, CCMS and Solution Manager, SAP RFID, SAP Dynpro, SAP ABAP Webdynpro, SAP Net weaver, DUET 1.5, ABAP and Java Web services.

Page 2: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 2

Table of Contents

Introduction ..................................................................................................................................................... 3

Expense Approval ........................................................................................................................................... 3 External Lists ............................................................................................................................................................... 3

Web Parts .................................................................................................................................................................... 4

HR Transfer ................................................................................................................................................... 10 External Lists ............................................................................................................................................................. 12

Web Parts .................................................................................................................................................................. 15

Utility Functions .......................................................................................................................................................... 22

Using the Console Applications .................................................................................................................... 23

Creating the project ....................................................................................................................................... 25

Adding Code ................................................................................................................................................. 29

Deploying the Code ....................................................................................................................................... 30

Add the Web Parts to SharePoint ................................................................................................................. 31

Related Content ................................................................................................................................................ 32

Copyright........................................................................................................................................................... 33

Page 3: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 3

Creating Duet SharePoint Web Parts

Introduction

This document describes how to create Web Parts for SharePoint and Duet Enterprise and how to deploy them. The Web Parts used in this sample were created for a Proof of Concept to show how the interaction with SAP and SharePoint works.

Expense Approval

In the Expense Approval Process a manager can approve Travel Expenses for his employees.

The HR Transfer consists of one external list and one Web Part

External Lists

The Web Part uses the Duet build-in WorkflowTask External Content Type

Page 4: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 4

The WorkflowTask has a method wfUpdate which has to be called to update the SAP Task

Parameters are

0001 Approve

0003 Reject

Web Parts

The Web Part first retrieves a list of active Workflow tasks. The Currency and the Amount are passed as extended properties private void ListTasks() { SPWeb oSPWeb2; ExpenseTaskList.Clear(); SPSite oSPSite = SPControl.GetContextSite(Context); using (oSPWeb2 = oSPSite.OpenWeb(approvalSite)) { SPListCollection collList = oSPWeb2.Lists; SPList timesheets = oSPWeb2.Lists["Workflow Tasks"]; SPListItemCollection collItem = timesheets.Items;

Page 5: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 5

int itemCount = 0; foreach (SPListItem oItem in collItem) { string workflowData = SPWorkflowTask.GetWorkflowData(oItem); Dictionary<string, string> workflowDict = getOwsValues(workflowData); string ows_TaskInstanceParentId = getOwsValue(workflowDict, "ows_TaskInstanceParentId"); string status = oItem["Status"].ToString().Trim().ToLower(); if (status != "completed") { string ows_Title = getOwsValue(workflowDict, "ows_Title"); string ows_ParentInitiator = getOwsValue(workflowDict, "ows_ParentInitiator"); string ows_StartDate = getOwsValue(workflowDict, "ows_StartDate"); string ows_DueDate = getOwsValue(workflowDict, "ows_StartDate"); string ows_WorkflowLink = getOwsValue(workflowDict, "ows_WorkflowLink"); string from = ows_ParentInitiator; string sent = convertDate(ows_StartDate); string workflowLink = ows_WorkflowLink.Replace("'", ""); string[] a = workflowLink.Split(','); SPListItem sapBusinessDocListItem = oSPWeb2.GetListItem(a[0]); XmlDocument sapBusinessXmlDoc = new XmlDocument(); XmlNamespaceManager nsm = new XmlNamespaceManager(sapBusinessXmlDoc.NameTable); nsm.AddNamespace("z", "#RowsetSchema"); sapBusinessXmlDoc.LoadXml(sapBusinessDocListItem.Xml); string ows_AMOUNT = sapBusinessXmlDoc.SelectSingleNode("z:row", nsm).Attributes["ows_AMOUNT"].Value; string ows_CURRENCY = sapBusinessXmlDoc.SelectSingleNode("z:row", nsm).Attributes["ows_CURRENCY"].Value; string amount = ows_CURRENCY + " " + ows_AMOUNT; string subject; try { string ows_description = sapBusinessXmlDoc.SelectSingleNode("z:row", nsm).Attributes["ows_ZDESCRIPTION"].Value; subject = ows_description; } catch (Exception) { subject = splitTitle(ows_Title); } string ows_FileDirRef = getOwsValue(workflowDict, "ows_FileDirRef"); string fileDirRef = ows_FileDirRef.Replace("'", ""); a = fileDirRef.Split('#'); string link = @"/" + a[1] + "/dispform.aspx?ID=" + oItem.ID.ToString().Trim(); string due = convertDate(ows_DueDate); ExpenseTaskList.Add(new ExpenseTaskEntry(

Page 6: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 6

oItem.ID.ToString(), oItem.Title.ToString(), SPEncode.HtmlEncode(subject), SPEncode.HtmlEncode(from), SPEncode.HtmlEncode(sent), SPEncode.HtmlEncode(amount), SPEncode.HtmlEncode(due), link, status, SPEncode.HtmlEncode(ows_TaskInstanceParentId) )); itemCount++; } } if (itemCount == 0) { lblNoItems.Visible = true; DataGrid1.Visible = false; btnSubmitTasks.Visible = false; } } DataGrid1.DataSource = ExpenseTaskList; DataGrid1.DataBind(); }

When the user approves or rejects a task the SAP Workflow is triggered.

const string opApproved = "Approved"; const string opRejected = "Rejected";

private void SubmitTasks() { SPWeb oSPWeb2; string statusMsg = ""; SPSite oSPSite = SPControl.GetContextSite(Context); using (oSPWeb2 = oSPSite.OpenWeb(approvalSite)) { SPList timesheets = oSPWeb2.Lists["Workflow Tasks"]; SPListItemCollection collItem = timesheets.Items; foreach (SPListItem oItem in collItem) { foreach (DataGridItem item in DataGrid1.Items) { Label lbl = (Label)item.FindControl("ID"); int TaskID = Int32.Parse(lbl.Text); if (oItem.ID == TaskID) { string operation = "";

Page 7: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 7

RadioButtonList rbl = (RadioButtonList)item.FindControl("Selection"); string clickedOperation = rbl.SelectedValue.ToString(); TextBox txt = (TextBox)item.FindControl("Reason"); string reason = txt.Text; if (clickedOperation == "Approve") operation = opApproved; if (clickedOperation == "Reject") operation = opRejected; if (operation == opApproved || operation == opRejected) { string workflowData = SPWorkflowTask.GetWorkflowData(oItem); Dictionary<string, string> workflowDict = getOwsValues(workflowData); string ows_TaskInstanceParentId = getOwsValue(workflowDict, "ows_TaskInstanceParentId"); string owsOperation = (operation == opApproved ? "0001" : "0003"); { string result = updateSAPTask(ows_TaskInstanceParentId, owsOperation, reason); if (result == "") { try { updateSharePointTask(oItem, operation); statusMsg = statusMsg + ows_TaskInstanceParentId + " updated successfully <br /><br />"; } catch (Exception ex) { statusMsg = statusMsg + ows_TaskInstanceParentId + " failed: <br />" + SPEncode.HtmlEncode(ex.Message) + "<br /><br />"; } } else { statusMsg = statusMsg + ows_TaskInstanceParentId + " failed: <br />" + SPEncode.HtmlEncode(result) + "<br /><br />"; } } } } } } }

lblPopupInfo.Text = "Thank you. Your transaction has been submitted"; lblTransactionID.Text = statusMsg; ModalInfo.Show(); ListTasks();

Page 8: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 8

}

The reference to the SAP Workflow Task is passed as ows_TaskInstanceParentId.

private string updateSAPTask(string ows_TaskInstanceParentId, string owsperation, string comment) { string result = ""; using (new Microsoft.SharePoint.SPServiceContextScope(SPServiceContext.GetContext(SPContext.Current.Site))) { IMetadataCatalog databaseCatalog = null; BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>(String.Empty); if (null != bdcService) { databaseCatalog = bdcService.GetDatabaseBackedMetadataCatalog(SPServiceContext.Current); } string @namespace = "SAP.Office.DuetEnterprise.Workflow"; string entityName = "WorkflowTask"; string lsiName = "WorkflowWebService"; IEntity entity = databaseCatalog.GetEntity(@namespace, entityName); ILobSystem lobSystem = entity.GetLobSystem(); ILobSystemInstance lobSysteminstance = lobSystem.GetLobSystemInstances()[lsiName]; INamedMethodDictionary methodDictionary = entity.GetMethods(); IView view = entity.GetUpdaterView("wfUpdate"); IMethodInstance method = entity.GetMethodInstance("wfUpdate", MethodInstanceType.Updater); IParameterCollection parameters = method.GetMethod().GetParameters(); ITypeReflector reflector = parameters[0].TypeReflector; ITypeDescriptor rootTypeDescriptor = parameters[0].GetRootTypeDescriptor(); object[] methodParamInstances = method.GetMethod().CreateDefaultParameterInstances(method); Object instance = methodParamInstances[0]; ITypeDescriptor actionTypeDescriptor = rootTypeDescriptor.GetChildTypeDescriptors()[0]; ITypeDescriptor bcsCorrelationIdTypeDescriptor = rootTypeDescriptor.GetChildTypeDescriptors()[1]; ITypeDescriptor commentsTypeDescriptor = rootTypeDescriptor.GetChildTypeDescriptors()[2]; ITypeDescriptor iwWfTaskIdTypeDescriptor = rootTypeDescriptor.GetChildTypeDescriptors()[3]; ITypeDescriptor outcomeTypeDescriptor = rootTypeDescriptor.GetChildTypeDescriptors()[4]; ITypeDescriptor reassignedToTypeDescriptor = rootTypeDescriptor.GetChildTypeDescriptors()[5];

Page 9: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 9

reflector.Set(actionTypeDescriptor, rootTypeDescriptor, ref instance, "EXEC"); reflector.Set(bcsCorrelationIdTypeDescriptor, rootTypeDescriptor, ref instance, ""); reflector.Set(commentsTypeDescriptor, rootTypeDescriptor, ref instance, comment); reflector.Set(iwWfTaskIdTypeDescriptor, rootTypeDescriptor, ref instance, ows_TaskInstanceParentId); reflector.Set(outcomeTypeDescriptor, rootTypeDescriptor, ref instance, owsperation); reflector.Set(reassignedToTypeDescriptor, rootTypeDescriptor, ref instance, ""); try { entity.Execute(method, lobSysteminstance, ref methodParamInstances); } catch (Exception ex) { result = ex.InnerException.Message; } finally { if (lobSysteminstance != null) lobSysteminstance.FlushConnections(); } return result; } }

The SharePoint Task has also to be updated Operation is "Approved" or "Rejected"

private void updateSharePointTask(SPListItem oItem, string operation) { Hashtable ht = new Hashtable(); ht["Completed"] = "TRUE"; ht["PercentComplete"] = 1f; ht[SPBuiltInFieldId.Comments] = "Test" + operation; ht[SPBuiltInFieldId.TaskStatus] = "Completed"; ht[SPBuiltInFieldId.WorkflowOutcome] = operation; ht[SPBuiltInFieldId.FormData] = SPWorkflowStatus.Completed; ht["ows_TaskStatus"] = operation; bool result = SPWorkflowTask.AlterTask(oItem, ht, true); }

Page 10: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 10

HR Transfer

The HR Transfer is used to transfer an employee from one manager to another manager

It consists of three external lists and three Web Parts.

A HR Transaction in started by the first Manager

The second manager gets the Approval Tasks on his workflow list

Page 11: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 11

To complete and approve the Transfer he has enter the position, reason, schedule and salary

Page 12: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 12

External Lists

The Web Parts are using the following custom External Content Types

It exposes two Methods:

ZGET_EMPLOYEELIST retrieves a list for employees for the current logged in manager

ZREAD_EMPLOYEE gets the details for an employee

Page 13: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 13

The Employee Transfer Content Type is used to manage the Transfers

It has three Methods:

CreateEmployeeTransfer creates a new Transfer Workflow on the backend

ReadEmpTransferByID gets the details for a started Transfer

UpdateEmployeeTransfer updates the workflow to approved or rejected

Page 14: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 14

The third Content Type is used to find the open positions that a manager has to fill

The two methods are

FindOpenPositions gets a list of vacancies for the current manager

ReadOpenPostionsByID gets a single vacancy

Page 15: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 15

Web Parts

The Start Transaction Web Part calls the Backend to start the SAP Workflow private string startEmployeeTransfer(string category, string process, string country, string empObjectID, string manObjectID, string effectiveDate, string note) { using (new Microsoft.SharePoint.SPServiceContextScope(SPServiceContext.GetContext(SPContext.Current.Site))) { BdcService service = SPFarm.Local.Services.GetValue<BdcService>(String.Empty); IMetadataCatalog catalog = service.GetDatabaseBackedMetadataCatalog( SPServiceContext.Current); IMetadataCatalog databaseCatalog = null; BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>(String.Empty); if (null != bdcService) { databaseCatalog = bdcService.GetDatabaseBackedMetadataCatalog(SPServiceContext.Current); } string @namespace = @"https://<hostname>:<port>/tasks"; string entityName = "EmployeeTransfer"; string lsiName = "SCLEmployeeTransfer"; IEntity entity = databaseCatalog.GetEntity(@namespace, entityName); ILobSystem lobSystem = entity.GetLobSystem(); ILobSystemInstance lobSysteminstance = lobSystem.GetLobSystemInstances()[lsiName]; IView view = entity.GetCreatorView("CreateEmployeeTransfer"); IFieldValueDictionary fieldValueDictionary = view.GetDefaultValues(); IFieldCollection fieldCollection = view.Fields; foreach (IField field in fieldCollection) { try { fieldValueDictionary[field.Name] = ""; } catch (Exception) { } } fieldValueDictionary["EmpSclKey"] = "Dummy"; fieldValueDictionary["Category"] = category; fieldValueDictionary["Process"] = process; fieldValueDictionary["CountryOfEmp"] = country; fieldValueDictionary["EmpObjectType"] = "P "; fieldValueDictionary["EmpObjectID"] = empObjectID; fieldValueDictionary["ManObjectType"] = "P "; fieldValueDictionary["ManObjectID"] = manObjectID; fieldValueDictionary["EffectiveDate"] = effectiveDate; fieldValueDictionary["Note"] = note; fieldValueDictionary["HRPosObjID"] = "0";

Page 16: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 16

Identity id = entity.Create(fieldValueDictionary, lobSysteminstance); if (id != null) { Object[] returnValues = id.GetIdentifierValues(); return returnValues[0].ToString(); } else { return ""; } } }

Reading the task list for the receiving manager is similar to the Expense Approval Web Part. The Reference to the SAP Transfer ID is passed as extended property in ows_TRANSFER_GUID. The description ows_ZDESCRIPTION is also passed as xprop. private void ListTasks() { SPWeb oSPWeb2; HRTaskList.Clear(); string txt = ""; SPSite oSPSite = SPControl.GetContextSite(Context); using (oSPWeb2 = oSPSite.OpenWeb(approvalSite)) { SPListCollection collList = oSPWeb2.Lists; SPList timesheets = oSPWeb2.Lists["Workflow Tasks"]; SPListItemCollection collItem = timesheets.Items; int itemCount = 0; foreach (SPListItem oItem in collItem) { string workflowData = SPWorkflowTask.GetWorkflowData(oItem); Dictionary<string, string> workflowDict = getOwsValues(workflowData); string ows_TaskInstanceParentId = getOwsValue(workflowDict, "ows_TaskInstanceParentId"); string status = oItem["Status"].ToString().Trim().ToLower(); if (status != "completed") { string ows_Title = getOwsValue(workflowDict, "ows_Title"); string ows_ParentInitiator = getOwsValue(workflowDict, "ows_ParentInitiator"); string ows_StartDate = getOwsValue(workflowDict, "ows_StartDate"); string ows_DueDate = getOwsValue(workflowDict, "ows_StartDate"); string ows_WorkflowLink = getOwsValue(workflowDict, "ows_WorkflowLink"); string from = ows_ParentInitiator; string sent = convertDate(ows_StartDate); string ows_FileDirRef = getOwsValue(workflowDict, "ows_FileDirRef"); string fileDirRef = ows_FileDirRef.Replace("'", ""); string[] a = fileDirRef.Split('#');

Page 17: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 17

string link = @"/" + a[1] + "/dispform.aspx?ID=" + oItem.ID.ToString().Trim(); string due = convertDate(ows_DueDate); string workflowLink = ows_WorkflowLink.Replace("'", ""); a = workflowLink.Split(','); SPListItem sapBusinessDocListItem = oSPWeb2.GetListItem(a[0]); XmlDocument sapBusinessXmlDoc = new XmlDocument(); XmlNamespaceManager nsm = new XmlNamespaceManager(sapBusinessXmlDoc.NameTable); nsm.AddNamespace("z", "#RowsetSchema"); sapBusinessXmlDoc.LoadXml(sapBusinessDocListItem.Xml); string transferID = sapBusinessXmlDoc.SelectSingleNode("z:row", nsm).Attributes["ows_TRANSFER_GUID"].Value; transferID = transferIdPrefix + transferID + transferIdPostfix; string ows_description = sapBusinessXmlDoc.SelectSingleNode("z:row", nsm).Attributes["ows_ZDESCRIPTION"].Value; string subject = ows_description; string workflowID = "000000000"; HRTaskList.Add(new HRTaskEntry( oItem.ID.ToString(), oItem.Title.ToString(), SPEncode.HtmlEncode(subject), SPEncode.HtmlEncode(from), SPEncode.HtmlEncode(sent), SPEncode.HtmlEncode(due), link, status, transferID, SPEncode.HtmlEncode(ows_TaskInstanceParentId), SPEncode.HtmlEncode(workflowID) )); itemCount++; } } if (itemCount == 0) { lblNoItems.Visible = true; DataGrid1.Visible = false; } } DataGrid1.DataSource = HRTaskList; DataGrid1.DataBind(); }

When the transfer is finished the CompleteTransfer Web Part is used. First the Transfer Data for is retrieved from the backend. Parameter is the TransferID which was passed as xprop in the previous Web Part.

private void getTransferData(string id) {

Page 18: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 18

using (new Microsoft.SharePoint.SPServiceContextScope(SPServiceContext.GetContext(SPContext.Current.Site))) { BdcService service = SPFarm.Local.Services.GetValue<BdcService>(String.Empty); IMetadataCatalog catalog = service.GetDatabaseBackedMetadataCatalog( SPServiceContext.Current); IMetadataCatalog databaseCatalog = null; BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>(String.Empty); if (null != bdcService) { databaseCatalog = bdcService.GetDatabaseBackedMetadataCatalog(SPServiceContext.Current); } string @namespace = @"https://<hostname>:<port>/tasks"; string entityName = "EmployeeTransfer"; string lsiName = "SCLEmployeeTransfer"; IEntity entity = databaseCatalog.GetEntity(@namespace, entityName); ILobSystem lobSystem = entity.GetLobSystem(); ILobSystemInstance lobSysteminstance = lobSystem.GetLobSystemInstances()[lsiName]; IView view = entity.GetSpecificFinderView("ReadEmpTransferByID"); IFieldValueDictionary valueDictionary = view.GetDefaultValues(); IFieldCollection fieldCollection = view.Fields; IEntityInstance result = entity.FindSpecific(new Identity(id), "ReadEmpTransferByID", lobSysteminstance); foreach (IField field in fieldCollection) { if (result[field.Name] != null) TransferData.Add(field.Name, result[field.Name].ToString()); else TransferData.Add(field.Name, ""); } } } Then the list of vacant position is retrieved from the backend. As parameter the currently logged in username is passed. The result is added to a Dictionary<string, string> which holds the positions that are displayed on the UI.

private void getOpenPositions(string managerName) { using (new Microsoft.SharePoint.SPServiceContextScope(SPServiceContext.GetContext(SPContext.Current.Site))) { BdcService service = SPFarm.Local.Services.GetValue<BdcService>(String.Empty);

Page 19: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 19

IMetadataCatalog catalog = service.GetDatabaseBackedMetadataCatalog( SPServiceContext.Current); IMetadataCatalog databaseCatalog = null; BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>(String.Empty); if (null != bdcService) { databaseCatalog = bdcService.GetDatabaseBackedMetadataCatalog(SPServiceContext.Current); } string @namespace = @"https://<hostname>:<port>/tasks"; string entityName = "FindOpenPositions"; string lsiName = "SCLFindOpenPositions"; IEntity entity = databaseCatalog.GetEntity(@namespace, entityName); ILobSystem lobSystem = entity.GetLobSystem(); ILobSystemInstance lobSysteminstance = lobSystem.GetLobSystemInstances()[lsiName]; IMethodInstance methodInstance = entity.GetMethodInstance("FindOpenPostions", MethodInstanceType.Finder); IFilterCollection filters = methodInstance.GetFilters(); foreach (ComparisonFilter filter in filters) { if (filter.Name == "FindByManager") filter.Value = managerName; } IEntityInstanceEnumerator ientityInstanceEnumerator = entity.FindFiltered(filters, lobSysteminstance); Positions.Add("-1", "Select Position"); while (ientityInstanceEnumerator.MoveNext()) { string objectID = ientityInstanceEnumerator.Current["ObjectId"].ToString(); string objectName = ientityInstanceEnumerator.Current["ObjectName"].ToString(); Positions.Add(objectID, objectName); } } }

Updating the SAP Task is a two step process. To get the values and parameters from the backend first the finder view method with ReadEmpTransferByID is called. This is necessary because the input parameters can’t retrieved directly from the updater. The result is similar to result["EmpSclKey"] = "3211_0050568700DF1EE0A1AB7D0FED5389C2_Z_EMP_TRANS_TCE_800"; result["TransferGUID"] = ""; result["TransferID"] = "0050568700DF1EE0A1DABC176924E9C2"; result["Category"] = "11"; result["Process"] = "02"; result["CountryOfEmp"] = "US"; result["Employee"] = "P 00100015"; result["EmpObjectType"] = "P"; result["EmpObjectID"] = "00100015";

Page 20: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 20

result["RecevingManager"] = "P 00100152"; result["ManObjectType"] = "P"; result["ManObjectID"] = "00100152"; result["EffectiveDate"] = "20110517"; result["Note"] = "Updating"; result["CreatedBy"] = ""; result["CreatorObjectType"] = ""; result["CreatorUserName"] = ""; result["CreatedAt"] = ""; result["HRPosition"] = "Test"; result["HRPosObjType"] = "P"; result["HRPosObjID"] = "50008525"; result["Reason"] = ""; result["Schedule"] = ""; result["Salary"] = "123"; result["CurrencyKey"] = "EUR"; result["Periodicity"] = ""; result["ChangedBy"] = ""; result["ChangedByOtype"] = ""; result["ChangedByObjID"] = ""; result["ChangedAt"] = ""; result["ExtensionContainer1"] = "APPROVED"; result["ExtensionContainer2"] = "000001111957"; result["ExtensionContainer3"] = ""; result["ExtensionContainer4"] = ""; result["ExtensionContainer5"] = ""; result["ExtensionContainer6"] = "";

After setting the parameters to the new values the updater view UpdateEmployeeTransfer is called private string updateSAPTransfer(string transferID, string taskParentID, string hRPosition, string hRPosObjID, string schedule, string reason, string salery, string currencyKey, string periodicity, string decision) { using (new Microsoft.SharePoint.SPServiceContextScope(SPServiceContext.GetContext(SPContext.Current.Site))) { BdcService service = SPFarm.Local.Services.GetValue<BdcService>(String.Empty); IMetadataCatalog catalog = service.GetDatabaseBackedMetadataCatalog( SPServiceContext.Current); IMetadataCatalog databaseCatalog = null; BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>(String.Empty); if (null != bdcService) { databaseCatalog = bdcService.GetDatabaseBackedMetadataCatalog(SPServiceContext.Current); } string @namespace = @"https://<hostname>:<port>/tasks"; string entityName = "EmployeeTransfer"; string lsiName = "SCLEmployeeTransfer"; IEntity entity = databaseCatalog.GetEntity(@namespace, entityName); ILobSystem lobSystem = entity.GetLobSystem();

Page 21: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 21

ILobSystemInstance lobSysteminstance = lobSystem.GetLobSystemInstances()[lsiName]; IView view = entity.GetSpecificFinderView("ReadEmpTransferByID"); IFieldValueDictionary valueDictionary = view.GetDefaultValues(); IFieldCollection fieldCollection = view.Fields; IEntityInstance result = entity.FindSpecific(new Identity(transferID), "ReadEmpTransferByID", lobSysteminstance); IView updateView = entity.GetUpdaterView("UpdateEmployeeTransfer"); IFieldValueDictionary updateValueDictionary = updateView.GetDefaultValues(); IFieldCollection updateFieldCollection = updateView.Fields; result["ExtensionContainer2"] = taskParentID; result["HRPosition"] = "S " + hRPosObjID; result["HRPosObjID"] = hRPosObjID; result["HRPosObjType"] = "S"; if (decision == opApproved) { result["Reason"] = reason; result["Schedule"] = schedule; result["Salary"] = salery; result["CurrencyKey"] = currencyKey; result["Periodicity"] = periodicity; result["ExtensionContainer1"] = opApproved.ToUpper(); } else { result["ExtensionContainer1"] = opRejected.ToUpper(); } IMethodInstance method = entity.GetMethodInstance("UpdateEmployeeTransfer", MethodInstanceType.Updater); IParameterCollection parameters = method.GetMethod().GetParameters(); ITypeReflector reflector = parameters[0].TypeReflector; ITypeDescriptor rootTypeDescriptor = parameters[0].GetRootTypeDescriptor(); object[] methodParamInstances = method.GetMethod().CreateDefaultParameterInstances(method); Object instance = methodParamInstances[0]; int i = 0; foreach (IField field in updateFieldCollection) { string param; ITypeDescriptor typeDescriptor = rootTypeDescriptor.GetChildTypeDescriptors()[i]; string lobName = typeDescriptor.LobName.ToString(); try { param = result[lobName].ToString(); } catch (Exception) { param = "";

Page 22: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 22

} reflector.Set(typeDescriptor, rootTypeDescriptor, ref instance, param); i++; } string returnValue = ""; try { entity.Execute(method, lobSysteminstance, ref methodParamInstances); } catch (Exception ex) { returnValue = ex.InnerException.Message; } finally { if (lobSysteminstance != null) lobSysteminstance.FlushConnections(); } return returnValue; } }

To update the SharePoint Task the same code as in ExprenseApproval is used private void updateSharePointTask(SPListItem oItem, string operation) { Hashtable ht = new Hashtable(); ht["Completed"] = "TRUE"; ht["PercentComplete"] = 1f; ht[SPBuiltInFieldId.Comments] = "Update " + operation; ht[SPBuiltInFieldId.TaskStatus] = "Completed"; ht[SPBuiltInFieldId.WorkflowOutcome] = operation; ht[SPBuiltInFieldId.FormData] = SPWorkflowStatus.Completed; ht["ows_TaskStatus"] = operation; bool result = SPWorkflowTask.AlterTask(oItem, ht, true); }

Utility Functions

Most Web Parts are using regular expression to parse the XML files. The .NET XML classes can’t be used because the response is not always well formed. private Dictionary<string, string> getOwsValues(string rawData) { Regex regex = new Regex(@"(ows_[^=]*)='([^=]*)'"); Dictionary<string, string> dict = new Dictionary<string, string>(); MatchCollection mc = regex.Matches(rawData); foreach (Match m in mc) { try { dict.Add(m.Groups[1].Value, m.Groups[2].Value); } catch (Exception) { } } return dict; }

Page 23: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 23

private string getOwsValue(Dictionary<string, string> ows, string key) { try { return ows[key]; } catch (Exception) { return (""); } }

Using the Console Applications

To develop and test BDC Models it can be useful to test them first in a console application. This has the advantage that no deployment to SharePoint is necessary and the application runs faster because no ASP code is executed. Here is a sample for the FindOpenPostions BDC using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Text.RegularExpressions; using System.Xml; using Microsoft.BusinessData.Infrastructure; using Microsoft.BusinessData.MetadataModel; using Microsoft.BusinessData.MetadataModel.Collections; using Microsoft.BusinessData.Runtime; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; using Microsoft.SharePoint.BusinessData.Runtime; using Microsoft.SharePoint.BusinessData.SharedService; using Microsoft.SharePoint.Workflow; namespace SharePointTest1 { class Program { const string siteUrl = "https://<hostname>:<port>"; static void Main() { testReadOpenPositions(); Console.ReadLine(); }

private static void testReadOpenPositions() { SPServiceContext context = SPServiceContext.GetContext(new SPSite(siteUrl)); IMetadataCatalog databaseCatalog = null;

Page 24: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 24

BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>(String.Empty); if (null != bdcService) { databaseCatalog = bdcService.GetDatabaseBackedMetadataCatalog(context); } string @namespace = @"https://<hostname>:<port>/tasks"; string entityName = "FindOpenPositions"; string lsiName = "SCLFindOpenPositions"; IEntity entity = databaseCatalog.GetEntity(@namespace, entityName); ILobSystem lobSystem = entity.GetLobSystem(); ILobSystemInstance lobSysteminstance = lobSystem.GetLobSystemInstances()[lsiName]; INamedMethodDictionary methodDictionary = entity.GetMethods(); IMethodInstance methodInstance = entity.GetMethodInstance("FindOpenPostions", MethodInstanceType.Finder); IFilterCollection filters = methodInstance.GetFilters(); foreach (ComparisonFilter filter in filters) { Console.WriteLine("Filter = {0}", filter.Name); if (filter.Name == "FindByManager") filter.Value = "TABASCOT"; } IEntityInstanceEnumerator ientityInstanceEnumerator = entity.FindFiltered(filters, lobSysteminstance); int i = 0; while (ientityInstanceEnumerator.MoveNext()) { i++; string empSclKey = ientityInstanceEnumerator.Current["EmpSclKey"].ToString(); Console.WriteLine(empSclKey); } Console.WriteLine("No or Records: {0}", i); Console.WriteLine("Ready"); } } }

Page 25: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 25

Creating the project

First an empty SharePoint 2010 Project/Solution has to be created

Page 26: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 26

For each Web Part add another Empty SharePoint Project to the Solution

Page 27: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 27

Add a new Visual Web Part to each project

Add a reference to Microsoft.BusinessData.dll. It’s located in the directory

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI

Page 28: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 28

The creating the Web Part projects the initially created project can be removed

The Solution should look like this

Page 29: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 29

Adding Code

Add your code to the Web Parts.

Add also the usings to the code using System; using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Xml; using Microsoft.BusinessData.Infrastructure; using Microsoft.BusinessData.MetadataModel; using Microsoft.BusinessData.MetadataModel.Collections; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; using Microsoft.SharePoint.BusinessData.SharedService; using Microsoft.SharePoint.Utilities; using Microsoft.SharePoint.WebControls; using Microsoft.SharePoint.Workflow;

The Description and Title can be entered in the .Web Part file

Page 30: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 30

Deploying the Code

The Web Parts can simply build and deployed from the context menu. Sometimes it’s necessary to retract the last deployment from SharePoint

Page 31: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 31

Add the Web Parts to SharePoint

In SharePoint Designer create a new Web Part Page

The Web Part can be added from the List of available Web Parts

Page 32: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 32

Related Content

Professional Business Connectivity Services in SharePoint 2010

Scot Hillier, Brad Stevenson / Wrox / February 2011

Duet for Microsoft Office and SAP

http://www.sdn.sap.com/irj/sdn/duet

Duet Enterprise for Microsoft SharePoint and SAP

http://technet.microsoft.com/en-us/library/ff972436.aspx

Microsoft Business Connectivity Services Team Blog

http://blogs.msdn.com/b/bcs/

Everything You Need to Know about BDC

http://SharePointmagazine.net/articles/everything-you-need-to-know-about-bdc-part-1-of-8 (ff)

Page 33: How to Create Duet SharePoint Web Parts - Archive...How to Create Duet SharePoint Web Parts Applies to: Duet Enterprise for Microsoft Sharepoint and SAP version 1.5 and above, SAP

How to Create Duet SharePoint Web Parts

SAP COMMUNITY NETWORK SDN - sdn.sap.com | BPX - bpx.sap.com | BA - boc.sap.com | UAC - uac.sap.com

© 2011 SAP AG 33

Copyright

© Copyright 2012 SAP AG. All rights reserved.

No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP AG. The information contained herein may be changed without prior notice.

Some software products marketed by SAP AG and its distributors contain proprietary software components of other software vendors.

Microsoft, Windows, Excel, Outlook, and PowerPoint are registered trademarks of Microsoft Corporation.

IBM, DB2, DB2 Universal Database, System i, System i5, System p, System p5, System x, System z, System z10, System z9, z10, z9, iSeries, pSeries, xSeries, zSeries, eServer, z/VM, z/OS, i5/OS, S/390, OS/390, OS/400, AS/400, S/390 Parallel Enterprise Server, PowerVM, Power Architecture, POWER6+, POWER6, POWER5+, POWER5, POWER, OpenPower, PowerPC, BatchPipes, BladeCenter, System Storage, GPFS, HACMP, RETAIN, DB2 Connect, RACF, Redbooks, OS/2, Parallel Sysplex, MVS/ESA, AIX, Intelligent Miner, WebSphere, Netfinity, Tivoli and Informix are trademarks or registered trademarks of IBM Corporation.

Linux is the registered trademark of Linus Torvalds in the U.S. and other countries.

Adobe, the Adobe logo, Acrobat, PostScript, and Reader are either trademarks or registered trademarks of Adobe Systems Incorporated in the United States and/or other countries.

Oracle is a registered trademark of Oracle Corporation.

UNIX, X/Open, OSF/1, and Motif are registered trademarks of the Open Group.

Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, and MultiWin are trademarks or registered trademarks of Citrix Systems, Inc.

HTML, XML, XHTML and W3C are trademarks or registered trademarks of W3C®, World Wide Web Consortium, Massachusetts Institute of Technology.

Java is a registered trademark of Oracle Corporation.

JavaScript is a registered trademark of Oracle Corporation, used under license for technology invented and implemented by Netscape.

SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP Business ByDesign, and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and other countries.

Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius, and other Business Objects products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of Business Objects S.A. in the United States and in other countries. Business Objects is an SAP company.

All other product and service names mentioned are the trademarks of their respective companies. Data contained in this document serves informational purposes only. National product specifications may vary.

These materials are subject to change without notice. These materials are provided by SAP AG and its affiliated companies ("SAP Group") for informational purposes only, without representation or warranty of any kind, and SAP Group shall not be liable for errors or omissions with respect to the materials. The only warranties for SAP Group products and services are those that are set forth in the express warranty statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional warranty.