Siebel Interview Questions & Answers - Part 1

Download the word file of Siebel Q&A 1st part

What is difference between Incremental Compile and Full Compile?

Incremental Compile: When we select a single object (BC, Applet etc), several objects (Multiple BC, Applets, BO etc), single project or several projects to compile in an existing SRF file that is known as Incremental Compile.

Full Compile: When you compile all the projects in a SRF file that is known as Full Compile.

: Difference:

SRF File: We do an Incremental compile on an existing SRF file and Full Compile results in creation of a New SRF file.

SRF Size: SRF size is more when we do an Incremental Compile as compared to Full Compile. For example if a Full Compile results in a 28 MB SRF file then an Incremental compile on that file can increase it’s size up to 32 MB

 

2) How to update a field based on change in another field?

How to update a field based on change in another field?

OR

How to update a field when another field is updated?
Scripting

  • On Field Update Set n user property. (This is the answer interviewer is looking for though)

Explanation:

Scripting:

You can write script on SetFieldValue event of buscomp to update the target field. But the problem with this solution is if user UNDO the record then your script won’t revert back the changes that it has done.

One more solution can be to check in SetFieldValue event if that field is being updated through global flag and then on WriteEvent of buscomp execute your script only if that flag is set to true. But again you will have to set global flag to false may be Delete event (this is fired when user undo the record).

These solutions by scripting are really cumbersome. So we generally use On Field Update set n User property for this kind of requirement.

On Field Update Set n:

As the name suggests that this user property is used to set value of another field when a particular field is updated. In this user property n is the incremental number which is 1 more than the number used in the last On Field Update Set user property.

Value:
The value of the On Field Update Set user property consists of three quoted parameters separated by a comma and a space which is as following “FieldToCheck”, “FieldToSet”, “[Value]“

Example:
You want to set TargetField with SourceField value whenever SourceField is updated. So you will specify it like this.

Property: On Field Update Set 1
Value : “SourceField”, “TargetField”, “[SourceField]”

You can also make use of expression in the Value that you specify.

Example:

“SourceField”, “TargetField”, “[SourceField] + [AnotherField]”

 

3) What is the primary purpose of using surrogate key?

  1. What is the primary purpose of using surrogate key?
  2. Will those be used in fact tables? If not then what is the purpose in using it?

Answer:

Surrogate key is used for indexing purpose  i.e. as a primary key for a table.

Reason of using Surrogate Key over Primary Key:
Primary Key may take more or less memory i.e. it may contain characters but Surrogate Key contains only number.  So comparison of numbers is easy when comparing with characters. Yes, Surrogate Key will be used in fact tables to establish a relationship between dimensions.  Surrogate keys are implemented by using the Sequence generator.

 

4) Position and Responsibility relationship – Interview Question

An important question (every question asked in an interview is important isn’t it ) involving quite a few important entities in Siebel such as Position and Responsibilities. This question can come in variety of ways I am just giving a single question, but other flavors might be exist

What kind of relationship exists between Position and Responsibilities?

It is a question that requires a subjective answer, and answer can vary from person to person. I will try to give answer to the above question(s) but before that I would like to give a disclaimer.

The views presented in this post are mine and only mine. No person dead or living has anything to do with it. Please use the answer in interview at your own risk and if somebody is offended by it or feels differently he is free to express his views by the way of comments in this post

Answer or Explanation

There is no direct relationship between Responsibility and Position.
The indirect relationship between Responsibility and Position is of Visibility. Both of them drive Visibility in Siebel.

  • Responsibility restricts access to particular view so that user cannot see those views.
  • Position restricts access to particular set of data.

So, as a result both are used to limit visibility of users of application.

After discussing with my friends and peers about this question I am getting a feeling that I am putting my hand in a bee nest but I think this could end up as a new learning to me and for all.

So guys I beg you to tell me your views what do you think about this question so that this post can become the new answer for all of us.

 

 5) What will happen if I provide value in both Pre-Default and Post-Default properties?

I will try to explain the answer with the help of an example of  “Status” field.

We will assume the following values have been given for Pre-Default and Post-Default properties of Status Field

Pre-Default Value:  “In Process”
Post-Default Value:  “Complete”

Following are the scenarios which can take place:

User creates a New Record and saves the record without changing value of status field:
Pre-Default value (In Process) will be assigned to Status field.

User creates a New Record and changes the value of Status field to “Planning”
Pre-Default value is going to take effect as soon as user creates a new record but Post-Default value will not take effect. [Corrected as pointed by Gururaj]
User creates a New Record and changes the value of Status field to blank
Post Default Value (“Complete”) will take effect

User copies an existing record where value of status field is “Planning”
Neither Post-Default nor Pre-Default will take effect

User copies an existing record where value of status field is blank
Pre-Default (“In-Process”) Value will take effect

User copies an existing record  and makes the value of the field as blank
Post-Default Value (“Complete”) will take effect

User changes the value of existing record to blank and saves the record.
Neither Post-Default nor Pre-Default will take effect as these values only takes when the record is initially created and saved.

 

6)  Siebel Workflow Step – Missing Query Operation

 Loading ...

Problem:

I had to create a workflow and the first step in the workflow was Query Operation on Opportunity BC.  I dragged the Siebel Operation Step into designer and then started entering Values for this step which were as following

Type: Siebel Operation
Business Component: Opportunity
Operation: Query

But to my utter surprise Query was missing in the Operation field dropdown and only Insert and Update were available.

 When I entered Query manually in the field it accepted the value but started giving error

“Error loading Step Definition: Query Operation not found”
(Not exact error message)

Solution:

After going through the logs and thinking logically I was able to find the solution of the problem. My logical thinking that gave met he answer was.

Drop down is a pick list in Siebel and picklist gets its values from List of Values. I queried with Insert in the Display Value in List of Values view and there was a LOV Type called “WF_SIEBEL_OPER_TYPE_CD” which had Insert and Update as active and “Query” was inactive.
After making “Query” record Active and restarting tools I was able to execute my workflow successfully.
 

Note: Even if you provide LIC of this LOV in small case then also you will get the error. For this LOV Display value has to be in Camel Case and LIC in caps

Hope this will save someone from a lot of hassel and I still have to find the person who made this LOV inactive.

 

7) High Interactivity Framework Problem.

Loading ... Loading ...

We faced this problem quite often in Siebel 7.7. I am yet to face this error in Siebel 7.8 but I think there are lot of people that are still using Siebel 7.7 or even Siebel 7.5 so they might be facing this kind of problem.

Problem:

When clicking on Pick Applet in Siebel 7.7 application the application IE instance used to crash and we had to reopen the application. It happened only in case we were working with Pick Applet.

Reason:

This error was due to High Interactivity Framework files getting corrupt. For those who feel this is new term I will just give a background.

Siebel can operate with two types of framework

  • Standard Interactivity
  • High Interactivity.

The difference between both the frameworks is how Siebel Client communicates with Server. In case of standard interactivity the changes you make to record are not committed automatically to the database and use has to explicitly save the record and in High interactivity even if you step of the record or screen the changes are committed automatically.

Solution:

Solution of this problem is to go and remove the High Interactivity framework files and open the application again. When you open your application Siebel downloads fresh interactivity file from server.

These are steps you can follow to remove and reinstall the interactivity files

Goto Internet Explorer –> Tools Menu –> Internet Options

Click on Settings Button

Click on View Objects Button

Locate High Interactivity Files

 

8) Siebel CRM – How To Call a Workflow Asynchronously?

 Loading ...This Article is about Siebel CRM 7.X Workflows and Runtime Events. It tells you how can we use them to our advantange.
We all want the response time of our Application to be as fast as it can and we do everything that we can to achieve that. I am going to tell you about a way which can help you to reduce the response time without actually reducing any functionality. Siebel can execute workflows in two ways.

  • Synchronous
  • Asynchronous

Synchronous Execution : When workflows are executed Synchronously then user gets the control back only when the workflow has finished it execution.

Asynchronous Execution: When workflows are executed Asynchronously then user gets back the control immediately and the workflow is submitted to workflow process manager (WPM) as a job to be executed. WPM then executes the job later.

Often we have a functionality where large amount of processing needs to be done on an object which user is not going to use access right now. I can explain it with an example.

When user clicks copy button on a opportunity or quote we want certain custom entities to be copied over but which user will not access at that time but later.

So, we can reduce our response time by just copying the quote or opportunity synchronously and placing the code of copying of custom entities in workflow and executing that workflow asynchronously.

There are two way to execute a workflow asynchronously

  • Workflow Policy
  • Runtime Event and Business Service (BS) Combination


Workflow Policy is pretty traditional method of executing a workflow process.
You create a policy. Enter the conditions Specify the workflow to be executed Generate Triggers
I wouldn’t go into details of creating a policy but I will tell you some disadvantages of using Workflow Policy

  1. Slow Execution
  2. Difficult to setup
  3. Not Reliable and Error Prone

But from siebel 7.7 onwards we have another more robust, efficient and quicker way to do that which is Runtime Events and Business Service.

This Article is about Siebel CRM 7.X Workflows and Runtime Events. It tells you how can we use them to our advantange.

In this article I will tell you about the actual process of Setting up Runtime Event and Business Service assuming you have working knowledge of both. If you want to know the basics of these please see other posts of my blog.

Just one important thing that you should know about runtime evetns is that they are executed even before the Business Component Events. To explain it better I am taking an example where our requirement is to execute a workflow when you click Submit Oppty button on Opportunity Form Applet.

  1. Goto Administration ==>Runtime Events Screen
  2. Goto Action Sets View
  3. Create a New Record in the Action Set View of Runtime Events Administration Screen
  4. Enter Any Name in the Name Field of the Action Set List Applet
  5. Create New Record List Applet Below it
  6. Enter

Name = “TestRuntimeEvent” ;
Action Type = “Business Service” ;
Sequence = “1″

  1. In the Form Applet Below Enter the Following Details Business Service = “TestBS” ; Business Service Method = “TestMethod”8. Click Menu ==> Reload Runtime Events Make Sure that you have Active Flag checked in both List Applets.

You are done in Action Set View.

Now Goto Events view and Follow the steps given below

  1. Click New and Enter the Following Information

Sequence = 1 ;
Object Type = “Applet” ;
Object Name = “Opportnity Form Applet” ;
Event = “InvokeMethod” ;
Sub Event = “Submit Oppty” ;
Action Set = “TestRunTimeEvent”

Conditional Expression should be given if you want the restrict the execution of this Runtime Event to certain conditions and Action Set Name is always the name of the action set that we created.

2. Click Menu ==> Reload Runtime Events.

Now we are going to write the code in the busines service which will actually result in the execution of Workflow Process Asynchronously.

  1. Go To Administration ==> Business Service
  2. Create a Business Record with name “TestBS”
  3. Create a Record in List Applet for Service_PreInvokeMethod and choose Programming Langauge as “eScript”

Write the Following code in Code Window inside the function Service_PreInvokeMethod

if(MethodName == “TestMethod”)
{
var svc;
var child;
var input;
var output;
var rowid;
var bo = TheApplication().ActiveBusObject();
var bc = bo.GetBusComp(“Opportunity”); // Change the BusComp name with the name of the BusComp you want to execute the workflow with
svc = TheApplication().GetService(“Asynchronous Server Requests”); // Don’t change this – Actual BS that is responsible for submitting a job to WPM
input = TheApplication().NewPropertySet();
child = TheApplication().NewPropertySet();
output = TheApplication().NewPropertySet();
input.SetProperty(“Component”, “WfProcMgr”);
rowid = bc.GetFieldValue(“Id”);
// We would like to pass the row id of the Current record on which the user is working – You can pass more than one arguments
child.SetProperty(“ProcessName”, “Service Agreement – Agreement Status”); // Workflow process you want to execute
child.SetProperty(“RowId”, rowid); // passing the values
input.AddChild(child);
svc.InvokeMethod(“SubmitRequest”, input, output); /// invoking the business service method
svc = null; // nullfiying the objects
child = null;
output = null;
input = null;
return(CancelOperation);
}

 

9) DefaultAppletFocus user property

Loading ... Loading ...Problem:

In Siebel 7.5 the default focus in Order Detail View was on the Order header applet, however in Siebel 8.1 the default focus was on the line items applet due to which when I used the F9 functionality to send email the dropdown did not show values and sometimes didn’t work at all.

First I checked the settings in the Help > User preferences > Outbound Communications and set the Default Meassage Type to “ HTML” but it didn’t help and finally I was able to solve this problme by using DefaultAppletFocus user property.

Details:

DefaultAppletFocus user property : Allows us to set the applet within a view that should receives focus by default i.e before user changes the focus to any other applet by clicking on it.

As per Siebel the applet to receive the default focus is decided by the “Default Applet Focus” property of a view. If this property is left as blank then the default applet is decided on the basis of the “Type” property in
The Screen > Screen View of the Siebel tools:

  • If the View Type is Detail View, focus is placed on the second applet, if the view consists of two or more applets.
  • If the view type is any other type, or there is only one applet on the view, focus is placed on the first applet..

Usage:

Name: DefaultAppletFocus
Value: The name of an applet in the view, not enclosed in quotes.

After defining this user property on the view F9 functionality started working as expected.

 

10) Use Literals For Like

Loading ... Loading ...While working on Performance issues, I came across a rarely used user property known as ‘Use Literals For Like’.

Purpose:

If you have gone through logs sometime then you might have noticed that if you query with a text in a field then the query generated at backend has lot of like clauses which queries with all the permutations and combinations for that text. For example if I query on the Last Name Field with “SADMIN” in application the query generated at backend might have clause as shown below

((T11.LAST_NAME LIKE :2 OR T11.LAST_NAME LIKE :3 OR T11.LAST_NAME LIKE :4 OR T11.LAST_NAME LIKE :5) AND UPPER(T11.LAST_NAME) = UPPER(:6))

And the bind variables will have values like

Now, this can lead to performance issues in cases if the query is done on long fields such as Comments or Description field in Service Request BC. In that case using this user property might help.

  • 2:= ‘sa%’
  • 3:= ‘Sa%’
  • 4: = ’sA%’
  • 5:= ‘SA%’
  • 6:= ‘SADMIN’

If you use this user property on a particular field then for that field bind variables will not be used, it will be replaced by the values directly.

Usage:

It is a field level user property. Follow the steps given below to define this property.

  • Open Siebel Tools
  • Query for the BC which contains the field on which you want to define the user property
  • Query for the Field
  • Click on the + sign on Field Object in Object Explorer
  • Select Field User Property Object
  • In the Field User Property List Applet create a New Record
  • Provide following detail
    Name: Use Literals For Like
    Value: TRUE

And you are done. After you do that the query generated on backend will not use bind variables for this particualr column and your query will look like

(T11.LAST_NAME LIKE ‘SADMIN%’)

 

11) Limiting Text Field Length – User Property

Loading ... Loading ...

Lot of time we have requirement which involves restricting user input to certain length. Most common way to do that is to specify the Text Length property of the field. I used to do that until recently when I came to know that even after specifying field length user was able to enter more than the allowed limit.

Going through the bookshelf I read a note which said

“Text Length property is usually ignored and the length is retrieved from the underlying column definition”

So, that in effect means that whatever is the column length at the database level is limit at the BC level too. But that is not what we wanted so after further exploration we came across a user property that could help us to limit length without modifying the column at database level.

  • Text Length Override

Text Length Override and it can have a value as TRUE which means enforce the Text Length field property or it can have a different value such as 10 or 20 which means that will become the new limit.

Here is a step by step procedure on how to use this user property.

  • Query for the BC in which the desired field is present
  • Select the field on which you want to enforce the limit
  • In object explorer click on the + sign against field and select User Property option as shown below
  • Create a new record in the Field User Property area
  • Enter the following information

Name: Text Length Override
Value: TRUE
OR
Name: Text Length Override
Value: 10

  •  

Where the number is the limit that you want to enforce and you are done. Compile and see the changes.

Note: This user property can only be used with text type fields.

 12) Making Record and Fields Read Only

Loading ... Loading ...

A pretty common requirement is to make a specific field or a record read only. In this post I will describe various ways to accomplish that in siebel

Making the Field Read only on UI

  • Set the Read only property on applet object to true for that field. 

Making the Field Read only on Business Component

  • Set the Read Only property of that field to true. (But this property is rarely used and doesn’t make any sense to create a field and then to make it read only… anybody any pointers)
  • Field Read Only Field: fieldname user property is used to make the field read only

Syntax:
Property Name
Field Read Only Field: Status

Value
Status Flag

In this user property value is a name of field 
If the value of the status flag (field name) is True then Status will become read only and if the Status Flag is false then this field will be editable.

Making the Business Component record Read only

  • BC Read only Field user property is used to make the BC Record Read only.

Syntax:

Property Name
BC
Read Only Field

Value
Status

Here value is the name of the field that will determine whether the Record will become read only or not. If the value of the field specified is evaluated to true then Record will be read only otherwise editatble.

 

13) Debugging Workflow – A case study

Loading ... Loading ...Quite a few readers have asked me about real time scenarios of various posts that I have written. I try to explain with examples so that it is easy to understand but I think putting it in real working scenario will make more sense and more understanding. So, today I am going to narrate a story how I debugged a workflow error that we faced in our Development environment.

One fine day I an email with the following content in it

Error Code: (SBL-BPR-00187)–(SBL-BPR-00100)–(SBL-EXL-00151)–(SBL-SCR-00141), Error Message: Error updating business component at step ‘Update Sales Stage’.(SBL-BPR-00187)

This error is returned when the workflow is executing the Siebel Operation business service.(SBL-BPR-00100)

 

What I could figure out from this mail was that there is an error in a workflow which has a step named ‘Update Sales Stage’ but I had to find answer to the questions like

  • Which Workflow?
  • From where it is being invoked?
  • Why it is failing?

So to find the RC (Root Cause) this is what I did.

Went to Administration Server > Server Management > Tasks

Queried for Workflow process manager (WPM) records

Only realized that the log level is too low to get any information

So Went to Administration Server > Server Configuration > Components to increase the log level

Queried for WPM component and increase the log level for the following components

  • Workflow Definition Loading
  • Workflow Engine Invoked
  • Workflow Process Execution
  • Workflow Step Execution
  • SQL Tracing

Went again to Administration Server > Server Management > Tasks. Now I could see enough details of workflow process to figure out which Process is failing.

The name of the process was GEAE Update Quote Sales Stage

So, I went to tools had a look at workflow only to know that It was trying to update the opportunity sales stage and there was a script on the BC that was firing and preventing the status from being updated hence resulting in the workflow failure.

This post is supposed to give you a direction on which you can proceed. It will be only with experience that you will know what exactly needs to be done in different situations.

 

14) How To invoke a Siebel Business Service

Loading ... Loading ...

In this post I will elaborate how we can invoke a business service in various ways. But first just an overview of what business service is.

Business Service (BS): Is a place where you write to code to implement business rules and process.

We can also write the code at Bus Comp and Applet level but that makes our code and business logic to be

  • Distributed
  • Difficult to manage
  • Cannot be reused

Siebel Business service has a slight more overhead than the code at Applet or Bus Comp level but it helps us to make our code

  • Centralized
  • Easier to manage
  • Can be reused

 So general rule of thumb to select where to write the code is

If same business rules are applicable on more than one entity then we write a generalized code at BS level.

You can create business services in

Siebel Tools: Code change is SRF dependent.
Siebel Client: Code change is SRF independent.

We can invoke a business Service through

  1. Runtime Events
  2. eScript
  3. User Property
  • Runtime Events

To call a business service through runtime events

Enter the following information in the Action Set that you are creating

Business Service: Business Service Name
Business Service Method: Method Name
Business Service Context: “Input Argument”, “Value”

And based on the Event that you choose this business service will be invoked

  • eScript

You can use the following Code to invoke a business service from escript

var svc = TheApplication().GetService(“BS Name”);
var Input = TheApplication().NewPropertySet();
var Output = TheApplication().NewPropertySet();
Input.SetProperty(“Type”,this.GetFieldValue(“Status”)); // Input Agruments
svc.InvokeMethod(“BSMethod”, Input, Output);

  • User Property

You can use named method property to invoke a business service from BC but this method is rarely used as it including complex conditions in the User property might not be possible. But it can come quite handy if you just want to invoke BS based on simple conditions

Name: Named Method 1
Value: “New Record”, “INVOKESVC”, “BS Name”, “BS Method”, “‘Input Agrument’”, “Value”, “‘Input Argument 2’”, “Value”

 

15) Multiple Records selection and Pick Applet

Loading ... Loading ...

 Requirement:

I have a user request that you can select mulitple records in the list applet and then change a value for all records at the same time. The field they want to change uses a pick applet in the form applet, and it is through this pick applet they wish to change all the records to the same value.

Solution

Here is the script that THusvaeg provided that is working for him

function XX_PreSetFieldValue(FieldName, FieldValue)
{
var ActiveViewName = TheApplication().ActiveViewName();

// selecting the views under the BC for which the multiple selection should be available, could repeat this for any view / BC
if(ActiveViewName == “XX Vessel List View” || ActiveViewName == “XX Vessel List View – Admin”)
{
// this if must be reiterated for every field you want to work with multiple selection (why we don’t have it for the entire application)
if(FieldName == “XX Fleet Manager Last Name”)
{
var oThisBO = this.BusObject();
var oXXAssetBC = oThisBO.GetBusComp(“Asset Mgmt – Asset”);
var sConId = oXXAssetBC.GetFieldValue(“XX Fleet Manager Id”);

var bFirstSelected = oXXAssetBC.FirstSelected();
while(bFirstSelected)
{
oXXAssetBC.SetFieldValue(“XX Fleet Manager Id”, sConId);
bFirstSelected = oXXAssetBC.NextSelected();
}
}

if(FieldName == “XX Super Intendent Last Name”)
{
var oThisBO = this.BusObject();
var oXXAssetBC = oThisBO.GetBusComp(“Asset Mgmt – Asset”);
var sConId = oXXAssetBC.GetFieldValue(“XX Super Intendent Id”);

var bFirstSelected = oXXAssetBC.FirstSelected();
while(bFirstSelected)
{
oXXAssetBC.SetFieldValue(“XX Super Intendent Id”, sConId);
bFirstSelected = oXXAssetBC.NextSelected();
}
}
}
}

 

16) A few tricks with setTimeout()

Loading ... Loading ...There is one function that, if used properly, could do some nice stuff on user interface. This function name is setTimeout() and it allows you to execute a browser script at some point in the future.

It takes two parameters:

  • a function to call
  • time to wait in milliseconds.

I’ll show you two ways of using this function, which are both implemented in our app.

Auto refreshing applet:

Let’s say we have a requirement to refresh certain list applet every couple seconds or so. Our shipment manager is rather lazy and is not particularly fond of manual and tedious requerying of pending shipments list applet :)

To reach this goal we might use setTimeout() to refresh the applet at equal intervals.

Open Browser Script editor on your applet and create a function:

function Refresh()
{
var oMyApplet = theApplication().FindApplet ("Your_Applet_Here");
if (oMyApplet) {
oMyApplet.InvokeMethod ("RefreshBusComp");
setTimeout ("Refresh()", 5000);
}
}


This function will find your applet and refresh it. It will also schedule itself to be reinvoked in 5 seconds.

The only thing left is to call this function for the first time. A perfect place to do it – Applet_Load event.

function Applet_Load ()
{
setTimeout ("Refresh()", 5000)
}


Flashing control/label:

Assume the requirement: draw user attention to a critical field if it has invalid or questionable data.
One cool way to do this is by making the field flashing red for example. We’ll start with creating our main function (Browser Script):

function Flash()
{
var oMyApplet = theApplication().FindApplet ("Your_Applet_Here ");
if (oMyApplet) {
var oMyControl = oMyApplet.FindControl ("Your_Control_Here");
if (oMyControl.GetProperty ("FontColor") == "#FF0000")
oMyControl.SetProperty ("FontColor", "#000000");
else
oMyControl.SetProperty ("FontColor", "#FF0000");
setTimeout ("Flash()", 200)
}
}


And to invoke this function for the first time:

function Applet_Load ()
{
Flash();
}

This way the field will flash red 2.5 times a second. You may enhance the script by adding data validation or even use gradient transition

You might as well flash the control’s label rather than the text. In order to do so you will have to add a control user property useLabelID with value TRUE and use oMyControl.SetLabelProperty instead of oMyControl.SetProperty.

 

17) What is the use of return(CancelOperation)?

 

return(CancelOperation) statement is used to send the control back to Siebel or in other words to stop the normal flow of execution of script of a particular event.

This statement is mandatory if we are defining a custom method. For example:

I create a button and give the method name as “CustomMethod”. Now, in BusComp PreInvoke event I write the following script

if(MethodName == “CustomMethod”)
{
My Script
}

If I don’t write the statement return(CancelOperation) at the end then I am going to get error saying: method “CustomMethod” is not supported by BusComp”

So, the correct and complete script when handling a custom method will be

if(MethodName == “CustomMethod”)
{
My Script
return(CancelOperation);

 

AttachmentSize
Q and A 1.doc205 KB