project QadFinancials > class BGLMask > method ApiSetGLMasks

Description

ApiSetGLMasks; this method will create and delete a number of G/L-Masks bases on the content of the input temp-table that contains GLMasks.

Before calling this method, you can call method ApiSetGLMasksInitialise to make sure that the table that is used as input for ApiSetGLMasks is initiatised.

Normaly, this Api-method will be called after calling Api-method 'ApiGetGLMaskCombinations' that returns the same temp-table as isused as input by this method.

Only the records in this temp-table with field 'tcStatus' equal to 'N' (new) or 'D' (delete) will be handled.
If tcStatus=D then field tiGLMaskID should be filled as well. If tcStatus=N then the ID-fields will be discarded and the Code-fields will be used for the creation.
Records with a value for field 'tcStatus' that differs from these values, will be discarded.

Note that this api-method will start by clearing all instance-data.

Do also note that field 'tlSelected' is of no use here.


Parameters


ilResolveIdsFromCodesinputlogical
tSetGLMaskCombinationsinputtemp-tableSetGLMaskCombinations; temp-table that is used by Api-methods to hold the selected/existing masks and the possible masks.
tNewGLMasksoutputtemp-tableNewGLMasks; temp-table that is used by Api-method SetGLMasks to inform the caller about the newly created records and their ID.
oiReturnStatusoutputintegerReturn status of the method.


Internal usage


unused


program code (program9/bglmask.p)

/* ================================================================ */
    /* If there are no new/deleted records then give warning and return */
    /* ================================================================ */
    if not can-find (first tSetGLMaskCombinations where 
                           tSetGLMaskCombinations.tcStatus = "N":U or 
                           tSetGLMaskCombinations.tcStatus = "D":U)
    then Return.
    
    /* ================================================================ */
    /* Records that are marked for deletion should have GLMaskID filled */
    /* ================================================================ */
    if can-find (first tSetGLMaskCombinations where 
                       tSetGLMaskCombinations.tcStatus = "D":U and 
                       (tSetGLMaskCombinations.tiGLMaskID = ? or
                        tSetGLMaskCombinations.tiGLMaskID = 0))
    then do :
        assign oiReturnStatus = -3
               vcMessage      = trim(substitute(#T-17'If the input table contains GL masks that are marked for deletion, specify the ID of these masks because they are deleted based on the value in this field.':255(2261)T-17#,"tiGLMaskID":U)) + chr(10) + trim(#T-18'No further actions will be taken.':255(2262)T-18#).
        <M-3 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-151':U (icFcMsgNumber),
                     input  '' (icFcExplanation),
                     input  '' (icFcIdentification),
                     input  '' (icFcContext),
                     output viFcReturnSuper (oiReturnStatus)) in BGLMask>
        Return.
    end. /* if can-find */
    
    empty temp-table tNewGLMasks.
    /* ============================================== */
    /* Make sure that we start with an empty instance */
    /* ============================================== */    
    <M-21 run ClearData (output viFcReturnSuper (oiReturnStatus)) in BGLMask>
    if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
    then assign oiReturnStatus = viFcReturnSuper.
    if oiReturnStatus < 0 then Return.

    assign viRecordCounter     = 0
           vcGLMaskIDsToDelete = "":U.

    DELETEBLOCK:
    for each tSetGLMaskCombinations where
             tSetGLMaskCombinations.tcStatus = "D":U
             break by tSetGLMaskCombinations.tcGLCode:                        
        /* ============================================================================================= */
        /* Go through all records that are marked as Deleted; First go through all deleted ones and hold */ 
        /* their GLMask_IDs in a string, then performa a DataLoad using the string with the GLMask_IDs.  */
        /* Then for through all marked-for-deletion ones and delete them from the loaded instances.      */       
        /* ============================================================================================= */
        assign viRecordCounter = viRecordCounter + 1.
        find tGLMask where
             tGLMask.GLMask_ID = tSetGLMaskCombinations.tiGLMaskID
             no-error.
        if not available tGLMask
        then assign vcGLMaskIDsToDelete = vcGLMaskIDsToDelete + chr(4) + string(tSetGLMaskCombinations.tiGLMaskID).            

        if viRecordCounter >= 500 or last(tSetGLMaskCombinations.tcGLCode)
        then do :
            assign vcGLMaskIDsToDelete = substring(vcGLMaskIDsToDelete,2,-1,"CHARACTER":U).
            <M-16 run DataLoad
               (input  ? (icRowids), 
                input  vcGLMaskIDsToDelete (icPkeys), 
                input  ? (icObjectIds), 
                input  '' (icFreeform), 
                input  false (ilKeepPrevious), 
                output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            assign vcGLMaskIDsToDelete = "":U.
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Return.

            /* ================================== */
            /* Mark the loaded records as deleted */
            /* ================================== */
            for each tGLMask:
                assign tGLMask.tc_Status = "D":U.
            end.

            /* ======================================================= */
            /* Take actions; Validate, AdditionalUpdates               */
            /* ======================================================= */
            <M-23 run ValidateBC (output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Return.
            
            <M-24 run AdditionalUpdates (output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Return.    

            <M-25 run DataSave (output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Return.

            /* ============================================== */
            /* Make sure that we start with an empty instance */
            /* ============================================== */    
            <M-26 run ClearData  (output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Return.
            
            assign viRecordCounter     = 0
                   vcGLMaskIDsToDelete = "":U.
        end. /* if viRecordCounter >= 500 or last(rowid(tSetGLMaskCombinations) */
    end. /* DELETEBLOCK */  

    NEWBLOCK:
    for each tSetGLMaskCombinations where
             tSetGLMaskCombinations.tcStatus = "N":U
             break by tSetGLMaskCombinations.tiDomainID
                   by tSetGLMaskCombinations.tcGLCode:   
        assign viRecordCounter = viRecordCounter + 1.

        /* ========================================== */
        /* retrieve the primary company of the domain */
        /* ========================================== */
        if first-of(tSetGLMaskCombinations.tiDomainID)
        then do:
            <Q-31 run DomainForOperartionalInfo (all) (Read) (NoCache)
               (input tSetGLMaskCombinations.tiDomainID, (DomainID)
                input '':U, (DomainCode)
                output dataset tqDomainForOperartionalInfo) in BDomain >
            find first tqDomainForOperartionalInfo where
                       tqDomainForOperartionalInfo.tiDomain_ID = tSetGLMaskCombinations.tiDomainID
                       no-lock no-error.
            if not available tqDomainForOperartionalInfo
            then do:
                assign vcMessage      = trim(substitute(#T-32'Domain with domain ID &1 could not be found.':255(71049)T-32#, trim(string(tSetGLMaskCombinations.tiDomainID)) ))
                       oiReturnStatus = -1.
                <M-33 run SetMessage
                   (input  vcMessage (icMessage), 
                    input  '':U (icArguments), 
                    input  'tset.tidotSetGLMaskCombinations.tiDomainID':U (icFieldName), 
                    input  string(tsetglMaskCombinations.tidomainID) (icFieldValue), 
                    input  'E':U (icType), 
                    input  3 (iiSeverity), 
                    input  '':U (icRowid), 
                    input  'QadFin-8560':U (icFcMsgNumber), 
                    input  '':U (icFcExplanation), 
                    input  '':U (icFcIdentification), 
                    input  '':U (icFcContext), 
                    output viFcReturnSuper (oiReturnStatus)) in BGLMask>
                return.
            end.
        end. /* if first-of(tSetGLMaskCombinations.tiDomainID) */

        /* ============================== */
        /* Create and assign a new record */
        /* ============================== */
        <M-27 run AddDetailLine (input  'GLMASK':U (icTable), 
                    input  '':U (icParentRowid), 
                    output viFcReturnSuper (oiReturnStatus)) in BGLMask>
        if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
        then assign oiReturnStatus = viFcReturnSuper.
        if oiReturnStatus < 0 then Return.
        
        /* ========================== */
        /* GL should always be filled */
        /* ========================== */
        if (tSetGLMaskCombinations.tiGLID = 0 or
            tSetGLMaskCombinations.tiGLID = ?) and
           (tSetGLMaskCombinations.tcGLCode = '':U or
            tSetGLMaskCombinations.tcGLCode = ?)
        then do:
            assign vcMessage      = trim(#T-29'GL can not be left blank for a GL Mask.':255(71048)T-29#)
                   oiReturnStatus = -1.
            <M-30 run SetMessage
               (input  vcMessage (icMessage), 
                input  '':U (icArguments), 
                input  'tSetGLMaskCombinations.tcGLCode':U (icFieldName), 
                input  tSetGLMaskCombinations.tcGLCode (icFieldValue), 
                input  'E':U (icType), 
                input  3 (iiSeverity), 
                input  '':U (icRowid), 
                input  'QadFin-8558':U (icFcMsgNumber), 
                input  '':U (icFcExplanation), 
                input  '':U (icFcIdentification), 
                input  '':U (icFcContext), 
                output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            return.
        end. /* empty glid and glcode */

        /* ================================== */
        /* Resolve the GL code when necessary */
        /* ================================== */
        if ilResolveIdsFromCodes = true or
           (tSetGLMaskCombinations.tiGLID = 0 or
            tSetGLMaskCombinations.tiGLID = ?)
        then do:            
            <Q-34 run GLPrim (all) (Read) (NoCache)
               (input tqDomainForOperartionalInfo.tiPrimaryCompany_ID, (CompanyId)
                input tSetGLMaskCombinations.tcGLCode, (GLCode)
                input ?, (GLId)
                output dataset tqGLPrim) in BGL >
            find tqGLPrim where
                 tqGLPrim.tcGLCode = tSetGLMaskCombinations.tcGLCode
                 no-lock no-error.
            if not available tqGLPrim
            then do:
                assign vcMessage      = trim(substitute(#T-35'Invalid GL Account: &1':255(71050)T-35#, tSetGLMaskCombinations.tcGLCode))
                       oiReturnStatus = -1.
                <M-36 run SetMessage
                   (input  vcMessage (icMessage), 
                    input  '':U (icArguments), 
                    input  'tSetGLMaskCombinations.tcGLCode':U (icFieldName), 
                    input  tSetGLMaskCombinations.tcGLCode (icFieldValue), 
                    input  'E':U (icType), 
                    input  3 (iiSeverity), 
                    input  '':U (icRowid), 
                    input  'QadFin-8561':U (icFcMsgNumber), 
                    input  '':U (icFcExplanation), 
                    input  '':U (icFcIdentification), 
                    input  '':U (icFcContext), 
                    output viFcReturnSuper (oiReturnStatus)) in BGLMask>
                return.
            end. /* if not available tqGLPrim */
            assign tGLMask.GL_ID = tqGLPrim.tiGL_ID.
        end. /* if ilResolveIdsFromCodes = true or */
        else assign tGLMask.GL_ID = tSetGLMaskCombinations.tiGLID.

        /* =================================== */
        /* Resolve the Division when necessary */
        /* =================================== */
        if tSetGLMaskCombinations.tcDivisionCode <> "":U and
           tSetGLMaskCombinations.tcDivisionCode <> ?    and
           (ilResolveIdsFromCodes = true or
            (tSetGLMaskCombinations.tiDivisionID = 0 or
             tSetGLMaskCombinations.tiDivisionID = ?))
        then do:
            <Q-40 run DivisionPrim (all) (Read) (NoCache)
               (input tqDomainForOperartionalInfo.tiPrimaryCompany_ID, (CompanyId)
                input '':U, (DivisionID)
                input tSetGLMaskCombinations.tcDivisionCode, (DivisionCode)
                output dataset tqDivisionPrim) in BDivision >
            find tqDivisionPrim where
                 tqDivisionPrim.tcDivisionCode = tSetGLMaskCombinations.tcDivisionCode
                 no-lock no-error.
            if not available tqDivisionPrim
            then do:
                assign vcMessage      = trim(substitute(#T-39'Invalid Sub-Account: &1':255(71051)T-39#, tSetGLMaskCombinations.tcDivisionCode))
                       oiReturnStatus = -1.
                <M-38 run SetMessage
                   (input  vcMessage (icMessage), 
                    input  '':U (icArguments), 
                    input  'tSetGLMaskCombinations.tcDivsionCode':U (icFieldName), 
                    input  tSetGLMaskCombinations.tcDivisionCode (icFieldValue), 
                    input  'E':U (icType), 
                    input  3 (iiSeverity), 
                    input  '':U (icRowid), 
                    input  'QadFin-8562':U (icFcMsgNumber), 
                    input  '':U (icFcExplanation), 
                    input  '':U (icFcIdentification), 
                    input  '':U (icFcContext), 
                    output viFcReturnSuper (oiReturnStatus)) in BGLMask>
                return.
            end. /* if not available tqDivisionPrim */
            assign tGLMask.Division_ID = tqDivisionPrim.tiDivision_ID.
        end. /* if ilResolveIdsFromCodes = true or */
        else assign tGLMask.Division_ID = tSetGLMaskCombinations.tiDivisionID.

        /* =================================== */
        /* Resolve the Project when necessary  */
        /* =================================== */
        if tSetGLMaskCombinations.tcProjectCode <> "":U and
           tSetGLMaskCombinations.tcProjectCode <> ?    and
           (ilResolveIdsFromCodes = true or
            (tSetGLMaskCombinations.tiProjectID = 0 or
             tSetGLMaskCombinations.tiProjectID = ?))
        then do:
             <Q-44 run ProjectPrim (all) (Read) (NoCache)
                (input tqDomainForOperartionalInfo.tiPrimaryCompany_ID, (CompanyId)
                 input '':U, (ProjectID)
                 input tSetGLMaskCombinations.tcProjectCode, (ProjectCode)
                 output dataset tqProjectPrim) in BProject >
            find tqProjectPrim where
                 tqProjectPrim.tcProjectCode = tSetGLMaskCombinations.tcProjectCode
                 no-lock no-error.
            if not available tqProjectPrim
            then do:
                assign vcMessage      = trim(substitute(#T-43'Invalid Project: &1':255(71052)T-43#, tSetGLMaskCombinations.tcProjectCode))
                       oiReturnStatus = -1.
                <M-42 run SetMessage
                   (input  vcMessage (icMessage), 
                    input  '':U (icArguments), 
                    input  'tSetGLMaskCombinations.tcProjectCode':U (icFieldName), 
                    input  tSetGLMaskCombinations.tcProjectCode (icFieldValue), 
                    input  'E':U (icType), 
                    input  3 (iiSeverity), 
                    input  '':U (icRowid), 
                    input  'QadFin-8563':U (icFcMsgNumber), 
                    input  '':U (icFcExplanation), 
                    input  '':U (icFcIdentification), 
                    input  '':U (icFcContext), 
                    output viFcReturnSuper (oiReturnStatus)) in BGLMask>
                return.
            end. /* if not available tqProjectPrim */
            assign tGLMask.Project_ID = tqProjectPrim.tiProject_ID.
        end. /* if ilResolveIdsFromCodes = true or */
        else assign tGLMask.Project_ID = tSetGLMaskCombinations.tiProjectID.

        /* ====================================== */
        /* Resolve the CostCentre when necessary  */
        /* ====================================== */
        if tSetGLMaskCombinations.tcCostCentreCode <> "":U and
           tSetGLMaskCombinations.tcCostCentreCode <> ?    and
           (ilResolveIdsFromCodes = true or
            (tSetGLMaskCombinations.tiCostCentreID = 0 or
             tSetGLMaskCombinations.tiCostCentreID = ?))
        then do:
             <Q-48 run CostCentrePrim (all) (Read) (NoCache)
                (input tqDomainForOperartionalInfo.tiDomain_ID, (CompanyId)
                 input 0, (CostCentreID)
                 input tSetGLMaskCombinations.tcCostCentreCode, (CostCentreCode)
                 output dataset tqCostCentrePrim) in BCostCentre >
            find tqCostCentrePrim where
                 tqCostCentrePrim.tcCostCentreCode = tSetGLMaskCombinations.tcCostCentreCode
                 no-lock no-error.
            if not available tqCostCentrePrim
            then do:
                assign vcMessage      = trim(substitute(#T-47'Invalid Cost Center: &1':255(71054)T-47#, tSetGLMaskCombinations.tcCostCentreCode))
                       oiReturnStatus = -1.
                <M-46 run SetMessage
                   (input  vcMessage (icMessage), 
                    input  '':U (icArguments), 
                    input  'tSetGLMaskCombinations.tcCostCentreCode':U (icFieldName), 
                    input  tSetGLMaskCombinations.tcCostCentreCode (icFieldValue), 
                    input  'E':U (icType), 
                    input  3 (iiSeverity), 
                    input  '':U (icRowid), 
                    input  'QadFin-8564':U (icFcMsgNumber), 
                    input  '':U (icFcExplanation), 
                    input  '':U (icFcIdentification), 
                    input  '':U (icFcContext), 
                    output viFcReturnSuper (oiReturnStatus)) in BGLMask>
                return.
            end. /* if not available tqCostCentrePrim */
            assign tGLMask.CostCentre_ID = tqCostCentrePrim.tiCostCentre_ID.
        end. /* if ilResolveIdsFromCodes = true or */
        else assign tGLMask.CostCentre_ID = tSetGLMaskCombinations.tiCostCentreID.

        assign tGLMask.tcGLCode         = tSetGLMaskCombinations.tcGLCode 
               tGLMask.tcDivisionCode   = tSetGLMaskCombinations.tcDivisionCode
               tGLMask.tcProjectCode    = tSetGLMaskCombinations.tcProjectCode
               tGLMask.tcCostCentreCode = tSetGLMaskCombinations.tcCostCentreCode.
        
        if viRecordCounter >= 500 or last(tSetGLMaskCombinations.tcGLCode)
        then do:
            /* ======================================================= */
            /* Take actions; Validate, AdditionalUpdates               */
            /* ======================================================= */
            <M-10 run ValidateBC (output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Return.
            <M-7 run AdditionalUpdates (output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Return.    
        
            /* ======================================================================= */
            /* Take actions; DataSave                                                  */
            /* Before the DataSave is done we create tNewGLMasks records representing  */
            /* the new GLMasks. This is done to make sure the caller of this method is */
            /* informaed about the GLMask_ID of the new records                        */
            /* ======================================================================= */
            for each tGLMask where
                     tGLMask.tc_Status = "N":U 
                     no-lock :
                create tNewGLMasks.
                assign tNewGLMasks.tiCostCentreID   = tGLMask.CostCentre_ID
                       tNewGLMasks.tiDivisionID     = tGLMask.Division_ID
                       tNewGLMasks.tiGLID           = tGLMask.GL_ID
                       tNewGLMasks.tiProjectID      = tGLMask.Project_ID
                       tNewGLMasks.tiGLMaskID       = tGLMask.GLMask_ID.
            end. /* for each tGLMask where */            
            <M-8 run DataSave (output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Return.

            /* ============================================== */
            /* Make sure that we start with an empty instance */
            /* ============================================== */    
            <M-28 run ClearData  (output viFcReturnSuper (oiReturnStatus)) in BGLMask>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Return.
            
            assign viRecordCounter     = 0.
        end. /* if viRecordCounter >= 500 or last(rowid(tSetGLMaskCombinations) */
    end. /* NEWBLOCK */


Sample code: how to call this method through RPCRequestService (QXtend Inbound)

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 = "BGLMask".
create ttContext.
assign ttContext.propertyName = "methodName"
       ttContext.propertyValue = "ApiSetGLMasks".
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/bglmask.apisetglmasks.i.xsd", ?).
vhParameter = vhInputDS:get-buffer-handle("tParameterI").
vhParameter:buffer-create().
assign vhParameter::ilResolveIdsFromCodes = <parameter value>.

vhParameter = vhInputDS:get-buffer-handle("tSetGLMaskCombinations").
vhParameter:buffer-create().
assign vhParameter::<field-name-1> = <field-value-1>
       vhParameter::<field-name-2> = <field-value-2>
       ...

/* 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.