I tried the suggestion to run other processes out of SODE, but couldn't recreate it. At this point, I've added recovery code to put out a message to the user if this happens again with the value of oBusObj.Lines converted to a number. Thanks again for your help.
Original Message:
Sent: 06-02-2020 16:08
From: David Speck II
Subject: How can a "oBusObj.Lines" reference cause an error 88 in a PreTotals event?
Does it happen after the user has used one of the hyperlinks or upper right dropdown button to go to another inquiry/maintenance task?
If yes, i remember this happening on one of the very first scripts i wrote for Sales Order Entry 5 or 6 years ago. It was intermittent and eluded me for some time until i firgured out it would happen more frequently when returning to the sales order from the customer no. hyperlink to Customer Maintenance.
For some reason, when returning from one of those tasks, oBusObj no longer contains the object handle for the main business object, such SO_SalesOrder_Bus but instead, something like AR_Customer_Bus. You can verify this if you use sClass = "" : oBusObj.GetValue "_Class$", sClass and output the contents of sClass to a message or the trace window. If i remember correctly, the solution was to store off the original oBusObj handle into another variable stored and retrieved using oSession's GetStorageVar and SetStorageVar.
I do not remember if the mishandled oBusObj would only occur if you had scripts on the destination task's table and/or UI events though but it is worth checking out.
EDIT:
Forgot to add that the storing of the original object handle should occur in the Script Initialization event script and then retrieve the object handle in your scripts attached to the regular events. You need to make sure the original handle is stored before anything has a chance to corrupt it and Script Initialization is the best table event for that. You could also use the DMAIN's post load event as that is sure to run once before anything else could be done by the user.
------------------------------
David Speck II
Tennessee Software Solutions
------------------------------
Original Message:
Sent: 06-02-2020 15:58
From: Dan Burleson
Subject: How can a "oBusObj.Lines" reference cause an error 88 in a PreTotals event?
@David Speck II Since the issue is intermittent and it runs correctly on the SODE Pre-Totals event most of the time (I am unable to reproduce it), I am sure it's in the correct context. There is one other identical statement Set statement in a SODE Table Pre-Write event, but it also works correctly and the user reports the issue (with a screen shot) happens when going to the Totals panel and not when using the Accept button.
------------------------------
Dan Burleson
Software Consultant
Connex Software
Corvallis OR
541-224-6642
Original Message:
Sent: 06-02-2020 01:44
From: David Speck II
Subject: How can a "oBusObj.Lines" reference cause an error 88 in a PreTotals event?
Are you absolutely positive the script is executing in the right context and not using any other object handles causing a false positive on oBusObj.Lines?
------------------------------
David Speck II
Tennessee Software Solutions
Original Message:
Sent: 06-02-2020 01:41
From: Dan Burleson
Subject: How can a "oBusObj.Lines" reference cause an error 88 in a PreTotals event?
Thank you @David Speck II! I will likely add use your logic as recovery code after checking whether the Lines property is a proper object, but I am still a bit dumbfounded that the property just doesn't exist without having an error message from Sage!
Now I have to message the user "Sorry, but the 'SO_Invoice_bus' object is having a bad day so your 'ShipVia' field cannot be validated based on the weight of your order. Have a nice day and good luck!"
------------------------------
Dan Burleson
Software Consultant
Connex Software
Corvallis OR
541-224-6642
Original Message:
Sent: 06-02-2020 01:03
From: David Speck II
Subject: How can a "oBusObj.Lines" reference cause an error 88 in a PreTotals event?
It is possible that the Lines object handle might not have been initialized or does not contain a valid handle. I always check if my target object handle is greater than zero before using it with the Set directive.
If oBusObj.Lines > 0 Then Set oLines = oSession.AsObject(oBusObj.Lines) ' Do stuff here. Set oLines = NothingEnd If
In the case of child handles and properties, another way i do this is by first throwing the value into a numeric variable and then check it and if greater than zero, use the variable in the Set.
nLines = 0 : nLines = oBusObj.LinesIf nLines > 0 Then Set oLines = oSession.AsObject(nLines) ' Do stuff here. nCI_ItemCode_Svc = 0 : nCI_Item_Svc = oLines.GetChildHandle("ItemCode") If nCI_ItemCode_Svc > 0 Then Set oCI_ItemCode_Svc = oSession.AsObject(nCI_ItemCode_Svc) ' Do stuff here. Set oCI_ItemCode_Svc = Nothing End If Set oLines = NothingEnd If
In the case of a script that is using NewObject or GetObject and after x number of executions within the same session and you get weird errors like the above, i have changed my scripts to instead first check a storage variable stored in oSession's ScriptObject instead of the oScript (oBusObj's ScriptObject). This is another reason i have made it best practice to first store the numeric value of the object handle since a VBScript object handle can't be passed to SetStorageVar nor can it be retrieved with GetStorageVar so you have to rely on the providex numeric value of the object handle before it is converted to a vbscript object handle.
Here's an example of this approach with extra line breaks for easy readability.
sMsg = ""nIM_AliasItem_Svc = 0 : oScript.GetStorageVar("nIM_AliasItem_Svc", nIM_AliasItem_Svc)If nIM_AliasItem_Svc <= 0 Then nIM_AliasItem_Svc = oSession.GetObject("IM_AliasItem_Svc")If nIM_AliasItem_Svc > 0 Then oScript.SetStorageVar "nIM_AliasItem_Svc", nIM_AliasItem_Svc Set oIM_AliasItem_Svc = oSession.AsObject(nIM_AliasItem_Svc) ' Do stuff here. Set oIM_AliasItem_Svc = NothingElse ' Optionally set a message to warn that the object handle could not be retrieved. sMsg = "Unable to get object handle to ""IM_AliasItem_Svc"". Check role security." & vbCrLf & "Last Error Msg: " & oSession.LastErrorMsg End If' Handle sMsg output here.If sMsg <> "" Then ' Output to trace window. oScript.DebugPrint sMsg ' Output to message box displayed to user. Avoid doing this in a script that might loop through the line from the header as you will aggravate the user unless you use another storage variable to track whether the message has been displayed at least once per new session so they are aware of the issue but will not get repeated messages every time it occurs within the same session. If oSession.UI > 0 Then oSession.AsObject(oSession.UI).MessageBox "", sMsg End If
------------------------------
David Speck II
Tennessee Software Solutions