Thanks for the question, Sankalp.
Asked: June 25, 2000 - 10:52 pm UTC
Last updated: July 23, 2004 - 8:31 am UTC
Version: 8.x
Viewed 1000+ times
You Asked
Dear Tom,
Thnaks for the reply.
a) With "Displaying messages from stored procedures onto form ", what I meant was, Eg we have a stored procedure LOAN CAPITALIZATION used for batch process. Can messages displayed (using dbms_output.put_line...) be displayed on the forms while calling the procedure through form?
Is there any way out to show to the user the status of the batch process,?
b) How to display PROGRES BAR in forms5.0. Thsi progress bar should end when the batch process ends.
Thanks in advance
SANKALP
and Tom said...
We need to use 2 sessions to do this. We can run the batch job in a minimized forms window and "watch" its progress from the other window.
I started with a procedure like:
create or replace procedure long_time( p_id in number,
p_iterations in number )
as
begin
for i in 1 .. p_iterations
loop
dbms_application_info.set_client_info( p_id ||
' Step ' || i ||
' of ' || p_iterations );
dbms_lock.sleep( 1 );
end loop;
end;
/
(you may need to grant execute on dbms_lock to the owner of this procedure to compile this). This procedure is your batch job. I pass into 2 items (in addition to what YOU'll pass it to run yours...). The first is a "unique" key, something we can use in our parent form to identify the row in v$session that represents our batch job. The other in this case is how many times this loop should execute (you in general won't need that one).
I then wrote a standalone form with a block on DUAL and 2 triggers. They are:
WHEN-NEW-FORM-INSTANCE:
DECLARE
timer_clock TIMER;
one_second NUMBER(7):=1000;
BEGIN
dbms_application_info.set_client_info
( '1234 Just Starting' );
set_window_property( FORMS_MDI_WINDOW, WINDOW_STATE,
MINIMIZE );
timer_clock := CREATE_TIMER('CLOCK_TIMER',
one_second,NO_REPEAT);
END;
That trigger simply minimizes our form and then creates a time to fire in 1 second. We need to use a timer to run our batch job since the parent form that will run this form will not get control back until AFTER the new form instance trigger completes.
The second trigger in this form is simply:
WHEN-TIMER-EXPIRED:
-- normally, 1234 will be a parameter the parent form will
-- pass to us
-- it'll be used by the parent to display some info (to help
-- find OUR row)
--
-- 15 is for 15 iterations
long_time( 1234, 15 );
exit_form;
So, if you run this form, it'll simply show itself -- minimize itself -- run the batch job -- and then exit. The batch job will constantly be filling in the CLIENT_INFO field in v$session with our "key" (1234 -- you will pass this in with a unique value so each client can id their rows) and the step it is on.
I then created another form. It had a block on DEPT (just as an example) and a control block (non-database) to show the progress. On this control block I put 3 items:
o a push button to run the job
o a text field I use to display the progress message (name=clock)
o a RED backgrounded text field I'll use to show the "progress
bar" (name=progress_bar)
On the button I put the following trigger:
WHEN-BUTTON-PRESSED:
DECLARE
timer_clock TIMER;
BEGIN
:b1.clock := null;
run_product( FORMS,
'C:\Documents and Settings\Thomas Kyte\Desktop\module2.fmx',
ASYNCHRONOUS, RUNTIME, FILESYSTEM, '', '' );
timer_clock := CREATE_TIMER('CLOCK_TIMER',1000,REPEAT);
set_item_property( 'b1.progress_bar', WIDTH, 0 );
END;
It just fired off another form and ran it asynchronously. I create a timer that fires every second (this will be how frequently we update our progress bar). I set the width of the "progress bar" to ZERO.
I then setup a WHEN-TIMER-EXPIRED trigger that looks like this:
WHEN-TIME-EXPIRED
declare
l_width varchar2(255);
begin
if ( GET_APPLICATION_PROPERTY(TIMER_NAME) = 'CLOCK_TIMER' )
then
begin
select to_char(sysdate,'hh24:mi:ss') || ' ' ||
client_info
into :clock
from v$session
where client_info like '1234 %';
if ( :clock like '%Step % of %' )
then
l_width := substr( :clock, instr(:clock, 'Step ')+4 );
l_width := substr( l_width, 1, instr(l_width,'of')-1 );
l_width := ltrim(rtrim(l_width));
set_item_property( 'b1.progress_bar', WIDTH,
to_number(l_width)*10 );
end if;
exception
when no_data_found then
if ( :clock <> 'Batch completed...' )
then
delete_Timer( 'CLOCK_TIMER' );
end if;
:clock := 'Batch completed...';
end;
end if;
end;
That timer trigger updates the text field with the contents of the CLIENT_INFO field and a timestamp (see the Long_Time procedure above -- it fills in this field). It also gets out the "step X of Y" part I put in there and sets the width of our "red" progress bar to be that wide. Thats our progress bar.
I do not have forms 5.0 installed which is what you have (I currently have 6.0) so I cannot give you the forms directly but I believe the above will get you going in the right direction.
Rating
(9 ratings)
Is this answer out of date? If it is, please let us know via a Comment