Unhandled Script Exception: Attempt to use old()/diff() from a field that does not have focus.


Dave DueskA common situation that can happen when coding with Dexterity is an error that you attempted to use the old()/diff() function from a field that doesn’t have focus. The exact error message is as follows:


Unhandled Script Exception: Attempt to use old()/diff() from a field that does not have focus.


This situation can arise when you try to focus to a field and then do a run script on that field. The most likely place that you run into this is in the SOP Entry scrolling window although this can happen in other places as well. Most of the fields in the scrolling window use an old()/diff() function in the field change script. The issue that causes this problem is that even though you issue a focus field statement followed by setting the field and then a run script statement, the focus field is actually executed after the run script statement. So the focus field runs after the call stack is complete. When the field change script runs, the field doesn’t yet have focus and that produces this error. The following is a way to work around this issue using a dummy form and sequencing the focus, setting the field and running the script on the field.


For this example, we are going to be setting the Item Number field in the SOP Entry scrolling window. The situation is that the customer has one and only one vendor for each item and they prefer to enter the vendor item number instead of the item number. After the user enters the vendor item number field, then the item number is automatically populated with the item number and its change script is run. The Item Number uses the old() function, so you will receive the message above if you are in test mode and you have show debug messages turned on.


In runtime, you will never get this error because show debug messages is turned off automatically. However, that doesn’t mean that everything will work in the scrolling window and it can cause unpredictable results. So you really want to deal with the issue instead of ignoring it.


Assume that a vendor item number field has been added to the SOP Entry window and is verified and stored in a companion table along with the SOP line item. You won’t see that code here, we are just focusing on the old/diff error. Here is what the window would look like:


SOP Entry Scroll


In this case the user can enter either the item number field or the vendor item number field and the necessary information will be defaulted to the line item.


The trigger registration script on the ‘Vendor Item Number’ field is as follows. Even though the field is added to the window, you would still want to use a trigger and keep all the code in a global script and not put the code on the window field.



Code Example


l_result = Trigger_RegisterFocus(anonymous(‘Vendor Item Number’ of window Line_Scroll of form SOP_Entry), TRIGGER_FOCUS_CHANGE, TRIGGER_BEFORE_ORIGINAL, script gp_vendoritem_change);
if l_result <> SY_NOERR then
warning “Focus trigger registration on Vendor Item Number failed.”;
end if;



The script gp_vendoritem_change is as follows:



Code Example


try
if not empty(‘Vendor Item Number’ of window Line_Scroll of form SOP_Entry) then
range clear table IV_Item_MSTR_VNDR;
set ‘Vendor Item Number’ of table IV_Item_MSTR_VNDR to ‘Vendor Item Number’ of window Line_Scroll of form SOP_Entry;
clear ‘Item Number’ of table IV_Item_MSTR_VNDR;
clear ‘Vendor ID’ of table IV_Item_MSTR_VNDR;
range start table IV_Item_MSTR_VNDR by number 6;
fill ‘Item Number’ of table IV_Item_MSTR_VNDR;
fill ‘Vendor ID’ of table IV_Item_MSTR_VNDR;
range end table IV_Item_MSTR_VNDR by number 6;

get first table IV_Item_MSTR_VNDR by number 6; {there is only one record in this case}
if err() = OKAY then
open form gp_dummy;
set ‘Item Number’ of window Window1 of form gp_dummy to ‘Item Number’ of table IV_Item_MSTR_VNDR;
run script ‘(L) Focus’ of window Window1 of form gp_dummy;
else
warning “This vendor item doesn’t exist. You must select an existing vendor item.”;
restart field;
end if;
end if;

else
{do nothing}
end try;



The gp_dummy form is just a form that has one window on it. The autopen property of the window is set to false, so the user would never see this form or know that it is opening. The window title property is set to ~internal~ so security does not have to be set to the form, it will always open. Here is what the gp_dummy form would look like in Dexterity.


GP Dummy


There is an Item Number field on the window that is set, there is no code on this field. The ‘(L) Focus’ button has the following script:



Code Example


focus field ‘Item Number’ of window Line_Scroll of form SOP_Entry;
run script delayed ‘(L) Set’;



The ‘(L) Set’ button has the following script:



Code Example


set ‘Item Number’ of window Line_Scroll of form SOP_Entry to ‘Item Number’;
run script delayed ‘(L) run script’;



The ‘(L) run script’ button has the following script:



Code Example


run script delayed ‘Item Number’ of window Line_Scroll of form SOP_Entry;
close form gp_dummy;



At this point, the form closes an the Item Number field has been populated and a run script has been done, so the rest of the fields on the window have been initialized.


The main point here is that if you run into the old/diff error, then you need the focus statement to run before the run script statement. By opening the dummy form and doing a run script on the first button, the focus is set, then you can set the field and do a run script on the field in the subsequent buttons. This will eliminate the old/diff error and also ensure that the window still works properly.


Dave Dusek


MBS Dev Support


// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

Comments (1)

  1. AlmasMahfooz says:

    That is a wonderful post and have a nice information.

    >> the focus field is actually executed after the run script statement. So the focus field runs after the call stack is complete.<<

    I have done the same by just following the sequence of command, that should be run to update unit price field of GP for custom window setup.

           focus '(L) Unit Price' of window Line_Scroll of form SOP_Entry;

    'Unit Price' of window Line_Scroll of form SOP_Entry=costKg;

    run script delayed '(L) Unit Price' of window Line_Scroll of form SOP_Entry;

Skip to main content