| iiBudgetID | input | integer | BudgetID; if a value for this paramater is passed then the value of parameter icBudgetCode is not taken into account. |
| icBudgetCode | input | character | BudgetCode; if a value for paramater iiBudgetID was passed then the value of this parameter is not taken into account. |
| iiProjectID | input | integer | ProjectID; when a value is passed for this parameter then the parameters iiBudgetID and icBudgetCode are disgarded. The budget of the project will then be used. |
| icProjectCode | input | character | ProjectCode: only applied in case ProjectID is empty |
| iiCostCentreID | input | integer | CostCentreID; when a value is passed for this parameter then the parameters iiBudgetID and icBudgetCode are disgarded. The operational budget of the cost-centre will then be used. |
| icCostCentreCode | input | character | CostCentreCode: only applied in case CostCentreID is not filled |
| ilSkipLevelOneNodes | input | logical | SkipLevelOnNodes |
| ilSkipJointOperResNodes | input | logical | SkipJointOperResNodes |
| ilSkipOverheadNodes | input | logical | SkipOverheadNodes |
| ilSkipDraftNodes | input | logical | SkipDraftNodes |
| ilSkipPureRevenueNodes | input | logical | SkipPureRevenueNodes |
| ilSkipPureCostNodes | input | logical | SkipPureCostNodes |
| icRestrictedBusComponent | input | character | RestrictedBusComponent; Code of the business-component that will be used to restrict the selectable nodes. |
| ilAssignBudgetWBSIsSelectable | input | logical | AssignBudgetWBSIsSelectable; set to true in case you want the method to assign field tViewBudgetWBS.tlBudgetWBSIsSelectable depending on the db-content. If the value for this parameter is false, then the values of tViewBudgetWBS.tlBudgetWBSIsSelectable will be true. |
| tViewBudgetWBS | output | temp-table | Overview of the budgetWBS |
| oiBudgetID | output | integer | Budget ID |
| oiReturnStatus | output | integer | Return status of the method. |
QadFinancials
/* ============================== */
/* Clear the instance-less output */
/* ============================== */
empty temp-table tViewBudgetWBS.
/* ======================================================= */
/* State the budget based on the project or CC when filled */
/* ======================================================= */
if iiProjectID = ? then assign iiProjectID = 0.
if icProjectCode = ? then assign icProjectCode = "":U.
if iiProjectID <> 0 or (icProjectCode <> "":U and icProjectCode <> ?)
then do :
if iiProjectID = 0 and icProjectCode <> "":U
then do:
<Q-27 run ProjectPrim (all) (Read) (NoCache)
(input viCompanyId, (CompanyId)
input ?, (ProjectID)
input icProjectCode, (ProjectCode)
output dataset tqProjectPrim) in BProject >
find first tqProjectPrim no-error.
assign iiProjectID = if available tqProjectPrim
then tqProjectPrim.tiProject_ID
else 0.
end.
<Q-10 run BudgetByProjectCostCentre (all) (Read) (NoCache)
(input ?, (CompanyId)
input ?, (CostCentreCode)
input ?, (CostCentreID)
input (if iiProjectID = 0 then icProjectCode else ?), (ProjectCode)
input iiProjectID, (ProjectID)
input ?, (RowidToSkip)
input ?, (BudgetStatus)
output dataset tqBudgetByProjectCostCentre) in BBudget >
if iiProjectID = 0
then find first tqBudgetByProjectCostCentre where
tqBudgetByProjectCostCentre.tcProjectCode = icProjectCode
no-lock no-error.
else find first tqBudgetByProjectCostCentre where
tqBudgetByProjectCostCentre.tiProject_ID = iiProjectID
no-lock no-error.
if available tqBudgetByProjectCostCentre
then assign iiBudgetID = tqBudgetByProjectCostCentre.tiBudget_ID.
else return.
end. /* if iiProjectID <> 0 and */
if iiCostCentreID = ? then assign iiCostCentreID = 0.
if icCostCentreCode = ? then assign icCostCentreCode = "":U.
if iiCostCentreID <> 0 or (icCostCentreCode <> "":U and icCostCentreCode <> ?)
then do :
if iiCostCentreID = 0 and icCostCentreCode <> "":U
then do:
<Q-28 run CostCentrePrim (all) (Read) (NoCache)
(input viCompanyId, (CompanyId)
input ?, (CostCentreID)
input icCostCentreCode, (CostCentreCode)
output dataset tqCostCentrePrim) in BCostCentre >
find first tqCostCentrePrim no-error.
assign iiCostCentreID = if available tqCostCentrePrim
then tqCostCentrePrim.tiCostCentre_ID
else 0.
end.
<Q-11 run BudgetByProjectCostCentre (all) (Read) (NoCache)
(input ?, (CompanyId)
input (if iiCostCentreID = 0 then icCostCentreCode else ?), (CostCentreCode)
input iiCostCentreID, (CostCentreID)
input ?, (ProjectCode)
input ?, (ProjectID)
input ?, (RowidToSkip)
input ?, (BudgetStatus)
output dataset tqBudgetByProjectCostCentre) in BBudget >
if iiCostCentreID = 0
then find first tqBudgetByProjectCostCentre where
tqBudgetByProjectCostCentre.tcCostCentreCode = icCostCentreCode
no-lock no-error.
else find first tqBudgetByProjectCostCentre where
tqBudgetByProjectCostCentre.tiCostCentre_ID = iiCostCentreID
no-lock no-error.
if available tqBudgetByProjectCostCentre
then assign iiBudgetID = tqBudgetByProjectCostCentre.tiBudget_ID.
else return.
end. /* if iiCostCentreID <> 0 and */
empty temp-table tqBudgetByProjectCostCentre.
/* =============================================== */
/* Validate input parameters // clear output table */
/* Convert the Code into the ID when needed */
/* =============================================== */
if (iiBudgetID = 0 or iiBudgetID = ?) and
(icBudgetCode = "":U or icBudgetCode = ?)
then do :
assign oiReturnStatus = -3
vcMessage = trim(#T-22'You must enter the budget identification (ID/code) to retrieve the budget WBS information.':255(442)T-22#).
<M-5 run SetMessage
(input vcMessage (icMessage),
input '':U (icArguments),
input '':U (icFieldName),
input '':U (icFieldValue),
input 'E':U (icType),
input 3 (iiSeverity),
input '':U (icRowid),
input 'QADFIN-1246':U (icFcMsgNumber),
input '' (icFcExplanation),
input '' (icFcIdentification),
input '' (icFcContext),
output viFcReturnSuper (oiReturnStatus)) in BBudget>
Return.
end.
if iiBudgetID = 0 or iiBudgetID = ?
then do :
<Q-2 run BudgetPrim (all) (Read) (NoCache)
(input ?, (BudgetID)
input icBudgetCode, (BudgetCode)
output dataset tqBudgetPrim) in BBudget >
find first tqBudgetPrim no-lock no-error.
if not available tqBudgetPrim
then do :
assign oiReturnStatus = -3
vcMessage = trim(substitute(#T-23'Invalid budget code: &1.':255(443)T-23#,string(icBudgetCode))).
<M-6 run SetMessage
(input vcMessage (icMessage),
input '':U (icArguments),
input '':U (icFieldName),
input '':U (icFieldValue),
input 'E':U (icType),
input 3 (iiSeverity),
input '':U (icRowid),
input 'QADFIN-1248':U (icFcMsgNumber),
input '' (icFcExplanation),
input '' (icFcIdentification),
input '' (icFcContext),
output viFcReturnSuper (oiReturnStatus)) in BBudget>
Return.
end. /* if not available tqBudgetPrim */
assign iiBudgetID = tqBudgetPrim.tiBudget_ID.
end. /* if iiBudgetID = 0 or iiBudgetID = ? */
else do :
<Q-14 run BudgetPrim (all) (Read) (NoCache)
(input iiBudgetID, (BudgetID)
input ?, (BudgetCode)
output dataset tqBudgetPrim) in BBudget >
find first tqBudgetPrim no-lock no-error.
if not available tqBudgetPrim
then do :
assign oiReturnStatus = -3
vcMessage = trim(substitute(#T-24'Invalid budget identification: &1.':255(444)T-24#,string(iiBudgetID))).
<M-15 run SetMessage
(input vcMessage (icMessage),
input '':U (icArguments),
input '':U (icFieldName),
input '':U (icFieldValue),
input 'E':U (icType),
input 3 (iiSeverity),
input '':U (icRowid),
input 'QADFIN-1804':U (icFcMsgNumber),
input '' (icFcExplanation),
input '' (icFcIdentification),
input '' (icFcContext),
output viFcReturnSuper (oiReturnStatus)) in BBudget>
Return.
end. /* if not available tqBudgetPrim */
end. /* not if iiBudgetID = 0 or iiBudgetID = ? */
assign oiBudgetID = iiBudgetID.
/* ================================ */
/* State the currency of the budget */
/* ================================ */
<Q-4 run BudgetByBudgetIDCodeStatus (all) (Read) (NoCache)
(input iiBudgetID, (BudgetID)
input ?, (BudgetCode)
input ?, (BudgetStatus)
input ?, (CompanyId)
input ?, (ProjectCode)
input ?, (CostCentreCode)
input ?, (BudgetIsCheckActualOnLine)
input ?, (BudgetIsCheckCommitOnLine)
input ?, (BudgetIsAutoRollUp)
input ?, (ProjectID)
input ?, (CostCentreID)
input ?, (BudgetType)
output dataset tqBudgetByBudgetIDCodeStatus) in BBudget >
find first tqBudgetByBudgetIDCodeStatus no-lock no-error.
/* ===================================== */
/* Query for the budgetwbs of the budget */
/* ===================================== */
<Q-1 run BudgetWBSByBudgetIDWBSCode (all) (Read) (NoCache)
(input iiBudgetID, (BudgetID)
input ?, (BudgetWBSID)
input ?, (BudgetWBSCode)
input ?, (ParentBudgetWBSID)
input ?, (BudgetCode)
input ?, (BudgetStatus)
output dataset tqBudgetWBSByBudgetID) in BBudget >
/* ==================== */
/* Compose output table */
/* ==================== */
for each tqBudgetWBSByBudgetID no-lock :
create tViewBudgetWBS.
assign tViewBudgetWBS.tcBudgetCode = tqBudgetByBudgetIDCodeStatus.tcBudgetCode
tViewBudgetWBS.tcCurrencyCode = tqBudgetByBudgetIDCodeStatus.tcCurrencyCode
tViewBudgetWBS.tcBudgetWBSCode = tqBudgetWBSByBudgetID.tcBudgetWBSCode
tViewBudgetWBS.tiBudgetWBSID = tqBudgetWBSByBudgetID.tiBudgetWBS_ID
tViewBudgetWBS.tiParentBudgetWBSID = tqBudgetWBSByBudgetID.tiParentBudgetWBS_ID
tViewBudgetWBS.tcUnitCode = tqBudgetWBSByBudgetID.tcUnitCode
tViewBudgetWBS.tcBudgetWBSTcRowid = tqBudgetWBSByBudgetID.tc_rowid
tViewBudgetWBS.tcFDSType = tqBudgetWBSByBudgetID.tcBudgetFDSType
tViewBudgetWBS.tiBudgetFDSSeq = tqBudgetWBSByBudgetID.tiBudgetFDSSeq
tViewBudgetWBS.tdBudgetWBSSeq = tqBudgetWBSByBudgetID.tdBudgetWBSSeq
tViewBudgetWBS.tcBudgetWBSStatus = tqBudgetWBSByBudgetID.tcBudgetWBSStatus
tViewBudgetWBS.tcBudgetWBSCostType = tqBudgetWBSByBudgetID.tcBudgetWBSCostType
tViewBudgetWBS.tcBudgetWBSCostRevenue = tqBudgetWBSByBudgetID.tcBudgetWBSCostRevenue
tViewBudgetWBS.tcBudgetWBSFDSList = tqBudgetWBSByBudgetID.tcBudgetWBSFDSList
tViewBudgetWBS.tlBudgetIsReportStruct = tqBudgetWBSByBudgetID.tlBudgetIsReportStruct
tViewBudgetWBS.tlBudgetWBSIsHideOnReport = tqBudgetWBSByBudgetID.tlBudgetWBSIsHideOnReport
tViewBudgetWBS.tcBudgetWBSFDSFromCode = tqBudgetWBSByBudgetID.tcBudgetWBSFDSFromCode
tViewBudgetWBS.tcBudgetWBSFDSToCode = tqBudgetWBSByBudgetID.tcBudgetWBSFDSToCode
tViewBudgetWBS.tcBudgetWBSFDSCode = tqBudgetWBSByBudgetID.tcBudgetWBSFDSCode
tViewBudgetWBS.tiBudgetGroup_ID = tqBudgetWBSByBudgetID.tiBudgetGroup_ID
tViewBudgetWBS.tcBudgetGroupCode = tqBudgetWBSByBudgetID.tcBudgetGroupCode
tViewBudgetWBS.tlBudgetWBSIsInvertBase = tqBudgetWBSByBudgetID.tlBudgetWBSIsInvertBase
tViewBudgetWBS.tiGLSharedSet_ID = tqBudgetWBSByBudgetID.tiGLSharedSet_ID
tViewBudgetWBS.tiDivisionSharedSet_ID = tqBudgetWBSByBudgetID.tiDivisionSharedSet_ID
tViewBudgetWBS.tiCostCentreSharedSet_ID = tqBudgetWBSByBudgetID.tiCostCentreSharedSet_ID
tViewBudgetWBS.tlBudgetWBSIsWithSumLine = tqBudgetWBSByBudgetID.tlBudgetWBSIsWithSumLine
tViewBudgetWBS.tlBudgetWBSIsRollup = tqBudgetWBSByBudgetID.tlBudgetWBSIsRollUp
tViewBudgetWBS.tiAltCOAGroup_ID = tqBudgetWBSByBudgetID.tiAltCOAGroup_ID
tViewBudgetWBS.tcAltCOAGroupCode = tqBudgetWBSByBudgetID.tcAltCOAGroupCode
tViewBudgetWBS.tcBudgetWBSCategory = tqBudgetWBSByBudgetID.tcBudgetWBSCategory
tViewBudgetWBS.tlBudgetWBSIsSelectable = true
tViewBudgetWBS.tiBudgetWBSLineNumber = tqBudgetWBSByBudgetID.tiBudgetWBSLineNumber
tViewBudgetWBS.tcBudgetWBSTopicDescription = tqBudgetWBSByBudgetID.tcBudgetWBSTopicDescription
tViewBudgetWBS.tlBudgetWBSIsPrintDesc = tqBudgetWBSByBudgetID.tlBudgetWBSIsPrintDesc.
end. /* for each tqBudgetWBSByBudgetID */
empty temp-table tqBudgetByBudgetIDCodeStatus.
/* ============================================================================== */
/* If ilSkipDraftNodes or ilSkipJointOperResNodes or ilSkipOverheadNodes is true, */
/* then delete some tqBudgetWBSByBudgetID-records */
/* ============================================================================== */
if ilSkipDraftNodes = true or
ilSkipJointOperResNodes = true or
ilSkipOverheadNodes = true
then do :
<M-17 run ApiGetBudgetWBSDelete
(input ilSkipJointOperResNodes (ilSkipJointOperResNodes),
input ilSkipOverheadNodes (ilSkipOverheadNodes),
input ilSkipDraftNodes (ilSkipDraftNodes),
input ilSkipPureRevenueNodes (ilSkipPureRevenueNodes),
input ilSkipPureCostNodes (ilSkipPureCostNodes),
output viFcReturnSuper (oiReturnStatus)) in BBudget>
if viFcReturnSuper <> 0 then assign oiReturnStatus = viFcReturnSuper.
if oiReturnStatus < 0 then return.
end. /* if ilSkipDraftNodes = true or */
/* =========================================================================== */
/* If ilSkipLevelOneNodes = true the */
/* - Remove all nodes on FDS-level 1 */
/* - Set for the nodes on FDS-level 2 ParentBudgetWBSID = ? */
/* - Join nodes on FDS-level 2 that have the same name (just keep 1 of them */
/* but move the childs of the removed nodes into the 1 node that is kept) */
/* We set ParentBudgetWBSID = -999999999 because otherwise the for-each */
/* would acces the records wherefor ParentBudgetWBSID was set to ? in the loop */
/* =========================================================================== */
if ilSkipLevelOneNodes = true
then do :
<M-13 run ApiGetBudgetWBSDeleteLevelOne (output viFcReturnSuper (oiReturnStatus)) in BBudget>
if viFcReturnSuper <> 0 then assign oiReturnStatus = viFcReturnSuper.
if oiReturnStatus < 0 then return.
end. /* if ilSkipLevelOneNodes = true */
/* ==================================================================================== */
/* In case ilAssignBudgetWBSIsSelectable is true then we have to make sure that field */
/* tViewBudgetWBS.tlBudgetWBSIsSelectable: */
/* - Nodes that are not on the lowest FDS-level: false */
/* - Nodes that are on the lowest FDS-level: */
/* - true in case icRestrictedBusComponent is empty */
/* - false in case icRestrictedBusComponent is filled and the WBS does have */
/* underlaying BudgetWBSBusComponents but does not have a BudgetWBSBusComponent */
/* record that fits icRestrictedBusComponent */
/* ==================================================================================== */
if ilAssignBudgetWBSIsSelectable = true
then do:
/* ======================== */
/* Get the lowest FDS-level */
/* ======================== */
<Q-18 run BudgetFDSByBudgetIDType (all) (Read) (NoCache)
(input iiBudgetID, (BudgetID)
input ?, (BudgetFDSType)
input ?, (BudgetFDSID)
output dataset tqBudgetFDSByBudgetIDType) in BBudget >
for each tqBudgetFDSByBudgetIDType :
if viHighestFDSLevel < tqBudgetFDSByBudgetIDType.tiBudgetFDSSeq
then assign viHighestFDSLevel = tqBudgetFDSByBudgetIDType.tiBudgetFDSSeq.
end. /* for each tqBudgetFDSByBudgetIDType */
/* =========================================================================================== */
/* Actions needed in case icRestrictedBusComponent is filled */
/* =========================================================================================== */
if icRestrictedBusComponent = ?
then assign icRestrictedBusComponent = "":U.
if icRestrictedBusComponent <> "":U
then do :
/* =========================================================================================== */
/* Convert the icRestrictedBusComponent into the corresponding ID (viRestrictedBusComponentID) */
/* =========================================================================================== */
<Q-19 run BusComponentByLabelCodeID (all) (Read) (NoCache)
(input ?, (BusComponentID)
input icRestrictedBusComponent, (BusComponentCode)
input ?, (BusComponentLabel)
output dataset tqBusComponentByLabelCodeID) in BBusinessComponent >
find first tqBusComponentByLabelCodeID where
tqBusComponentByLabelCodeID.tcBusComponentCode = icRestrictedBusComponent
no-lock no-error.
if not available tqBusComponentByLabelCodeID
then do :
assign oiReturnStatus = -3
vcMessage = trim(substitute(#T-25'Cannot restrict the view on the budget WBS based on an invalid business class (&1).':255(445)T-25#,icRestrictedBusComponent)) + chr(10) +
trim(substitute(#T-26'Business component name received: &1.':255(446)T-26#,icRestrictedBusComponent)).
<M-20 run SetMessage (input vcMessage (icMessage),
input '':U (icArguments),
input '':U (icFieldName),
input '':U (icFieldValue),
input 'E':U (icType),
input 3 (iiSeverity),
input '':U (icRowid),
input 'QADFIN-2278':U (icFcMsgNumber),
input '' (icFcExplanation),
input '' (icFcIdentification),
input '' (icFcContext),
output viFcReturnSuper (oiReturnStatus)) in BBudget>
Return.
end. /* if not available tqBusComponentByLabelCodeID */
/* ================================================================================================ */
/* Get all BudgetWBSBusComponent-records of the budget in case viRestrictedBusComponentID is filled */
/* ================================================================================================ */
<Q-21 run BudgetWBSBusComponentByIDs (all) (Read) (NoCache)
(input iiBudgetID, (BudgetID)
input ?, (BudgetWBSID)
input ?, (BusComponentID)
output dataset tqBudgetWBSBusComponentByIDs) in BBudget >
end. /* if icRestrictedBusComponent <> "":U */
/* ============================================================================ */
/* Go through all output-records and set tlBudgetWBSIsSelectable (default=true) */
/* ============================================================================ */
for each tViewBudgetWBS :
if tViewBudgetWBS.tiBudgetFDSSeq <> viHighestFDSLevel or
(icRestrictedBusComponent <> "":U and
can-find (first tqBudgetWBSBusComponentByIDs where
tqBudgetWBSBusComponentByIDs.tiBudgetWBS_ID = tViewBudgetWBS.tiBudgetWBSID) and
not can-find (tqBudgetWBSBusComponentByIDs where
tqBudgetWBSBusComponentByIDs.tiBudgetWBS_ID = tViewBudgetWBS.tiBudgetWBSID and
tqBudgetWBSBusComponentByIDs.tiBusComponent_ID = tqBusComponentByLabelCodeID.tiBusComponent_ID))
then assign tViewBudgetWBS.tlBudgetWBSIsSelectable = false.
end. /* for each */
end. /* if ilAssignBudgetWBSIsSelectable = true */
/* ========================== */
/* Clear query-table contents */
/* ========================== */
empty temp-table tqBusComponentByLabelCodeID.
empty temp-table tqBudgetWBSBusComponentByIDs.
empty temp-table tqBudgetByProjectCostCentre.
empty temp-table tqBudgetPrim.
empty temp-table tqBudgetByBudgetIDCodeStatus.
empty temp-table tqBudgetWBSByBudgetID.
empty temp-table tqBudgetFDSByBudgetIDType.define temp-table ttContext no-undo
field propertyQualifier as character
field propertyName as character
field propertyValue as character
index entityContext is primary unique
propertyQualifier
propertyName
index propertyQualifier
propertyQualifier.
define dataset dsContext for ttContext.
define variable vhContextDS as handle no-undo.
define variable vhExceptionDS as handle no-undo.
define variable vhServer as handle no-undo.
define variable vhInputDS as handle no-undo.
define variable vhInputOutputDS as handle no-undo.
define variable vhOutputDS as handle no-undo.
define variable vhParameter as handle no-undo.
/* Create context */
create ttContext.
assign ttContext.propertyName = "programName"
ttContext.propertyValue = "BBudget".
create ttContext.
assign ttContext.propertyName = "methodName"
ttContext.propertyValue = "ApiGetBudgetWBS".
create ttContext.
assign ttContext.propertyName = "applicationId"
ttContext.propertyValue = "fin".
create ttContext.
assign ttContext.propertyName = "entity"
ttContext.propertyValue = "1000".
create ttContext.
assign ttContext.propertyName = "userName"
ttContext.propertyValue = "mfg".
create ttContext.
assign ttContext.propertyName = "password"
ttContext.propertyValue = "".
/* Create input dataset */
create dataset vhInputDS.
vhInputDS:read-xmlschema("file", "xml/bbudget.apigetbudgetwbs.i.xsd", ?).
vhParameter = vhInputDS:get-buffer-handle("tParameterI").
vhParameter:buffer-create().
assign vhParameter::iiBudgetID = <parameter value>
vhParameter::icBudgetCode = <parameter value>
vhParameter::iiProjectID = <parameter value>
vhParameter::icProjectCode = <parameter value>
vhParameter::iiCostCentreID = <parameter value>
vhParameter::icCostCentreCode = <parameter value>
vhParameter::ilSkipLevelOneNodes = <parameter value>
vhParameter::ilSkipJointOperResNodes = <parameter value>
vhParameter::ilSkipOverheadNodes = <parameter value>
vhParameter::ilSkipDraftNodes = <parameter value>
vhParameter::ilSkipPureRevenueNodes = <parameter value>
vhParameter::ilSkipPureCostNodes = <parameter value>
vhParameter::icRestrictedBusComponent = <parameter value>
vhParameter::ilAssignBudgetWBSIsSelectable = <parameter value>.
/* Connect the AppServer */
create server vhServer.
vhServer:connect("-URL <appserver-url>").
if not vhServer:connected()
then do:
message "Could not connect AppServer" view-as alert-box error title "Error".
return.
end.
/* Run */
assign vhContextDS = dataset dsContext:handle.
run program/rpcrequestservice.p on vhServer
(input-output dataset-handle vhContextDS by-reference,
output dataset-handle vhExceptionDS,
input dataset-handle vhInputDS by-reference,
input-output dataset-handle vhInputOutputDS by-reference,
output dataset-handle vhOutputDS).
/* Handle output however you want, in this example, we dump it to xml */
if valid-handle(vhExceptionDS)
then vhExceptionDS:write-xml("file", "Exceptions.xml", true).
if valid-handle(vhOutputDS)
then vhOutputDS:write-xml("file", "Output.xml", true).
/* Cleanup */
vhServer:disconnect().
assign vhServer = ?.
if valid-handle(vhInputDS)
then delete object vhInputDS.
if valid-handle(vhOutputDS)
then delete object vhOutputDS.
if valid-handle(vhExceptionDS)
then delete object vhExceptionDS.