Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1]
  Reply  |  Print  
Author Topic: TERMINATE REPORT in GRW  (Read 30490 times)
Anderson P.
Posts: 82


« on: April 02, 2014, 06:47:02 pm »

When generating a report in GRW the normal workflow is to start the report, output the data in a foreach statement and then finish the report.

The problem is when the foreach doesn't output any data, in this case we can't use the "Finish Report" command, this will cause an "Expression error" because the report was expecting data and did't receive it, but if we don't finish the report we get the following error next time we try to generate a report: "Premature end of file Cause:XML document structures must start and end within the same entity".

So i guess that when no data is outputted the correct procedure is to use the "Terminate report" instead of "Finish report". The "Terminate report" command really seems to cancel the report generation, but when we try to generate another report we still get the "Premature end of file" error when the function fgl_report_commitCurrentSettings() is called.

My question is, what is the correct procedure to cancel a GRW report generation? Is there something that has to be done to stop the "XML document structures must start and end within the same entity" error?
Alex G.
Four Js
Posts: 155


« Reply #1 on: April 03, 2014, 02:43:43 pm »

Hi,
>The problem is when the foreach doesn't output any data, in this case we can't use the "Finish Report" command, this will cause an "Expression error" because the report was expecting data a
You are getting the error because you are accessing look-ahead variables from a list (trigger) that is empty. That typically happens in report headers where you access for example the customer name that is shipped in the order details. If the report has no order details then the header references a variable that is not shipped and an error is raised.

There are two patterns to avoid that as follows:
Pattern 1:
1) Add a variable to your report and declare is as the first variable in your ORDER EXTERNAL.
2) Populate the variable with a constant value in OUTPUT TO REPORT.
Example introducing the variable "k" in the report as described:
START REPORT myreport TO XML HANDLER handler
FOREACH ...
    OUTPUT TO REPORT myreport(1,rec.*) #Note that k is always 1
END FOREACH
FINISH REPORT myreport
REPORT myreport(k,rec)
DEFINE k INTEGER, rec RECORD LIKE ...
ORDER EXTERNAL BY k,rec....
END REPORT

In the report designer you will have a trigger for "Group k" in which you place your entire report content including the page root(s). In the case the OUTPUT TO REPORT is never called, the trigger "k" will not be executed and the report will not produce any output at all and no errors will be raised.

The pattern has the additional benefit that you can have a trigger "BEFORE GROUP OF k" that is the equivalent of "FIRST PAGE HEADER" but allows you to put a dynamic number of PRINT inside (That is not allowed in FIRST PAGE HEADER). This way you could for example have a dynamic list of items in the page header.

Pattern 2 (Code not tested):
Delay the output by always reading ahead one record as follows:
Example code before the change:
DEFINE orderline OrderType
..
    START REPORT report_all_orders TO XML HANDLER handler
    FOREACH c_order INTO orderline.*
        OUTPUT TO REPORT report_all_orders(orderline.*)
    END FOREACH
    FINISH REPORT report_all_orders
Example code after the change:

DEFINE orderline, nextRow OrderType,
            startedReport BOOLEAN
..
   LET startedReport=FALSE

    FOREACH c_order INTO nextRow.*
        IF NOT startedReport THEN
            LET startedReport=TRUE
            START REPORT report_all_orders TO XML HANDLER handler
        ELSE
            OUTPUT TO REPORT report_all_orders(orderline.*)
        END IF
        LET orderline.*=nextRow.*
    END FOREACH
    IF startedReport THEN
        OUTPUT TO REPORT report_all_orders(orderline.*)
        FINISH REPORT report_all_orders
    END IF
Regards,
Alex
Anderson P.
Posts: 82


« Reply #2 on: April 03, 2014, 03:38:52 pm »

Hi Alex

Thanks for the replay!

We was already using the Pattern 2 as a workaround for this error, but indeed the solution proposed in Pattern 1 is also very interesting as it is a nice trigger to detect if the report has been started.

But reading de Genero Studio Help Documentation it seems to me that using the "Terminate Report" instruction instead of "Finish Report" is the most "correct" or "code friendly" solution in this case, as it deletes any intermediate files or temporary tables that were created in processing the report.
Alex G.
Four Js
Posts: 155


« Reply #3 on: April 03, 2014, 04:17:34 pm »

Hi,
>But reading de Genero Studio Help Documentation it seems to me that using the "Terminate Report" instruction instead of "Finish Report" is the most "correct" or "code friendly" solution in this case, as it deletes any intermediate files or temporary tables that were created in processing the report.
Yes, absolutely. We need to suppress error messages like "Unexpected EOF" in case that a report is terminated by "TERMINATE REPORT" or "EXIT REPORT" (This is a known issue: "Bug 20411 - TERMINATE REPORT is not handled in GRE")
Regards,
Alex
Anderson P.
Posts: 82


« Reply #4 on: April 03, 2014, 04:38:04 pm »

I think it's weird that the error only occurs if you try to start another report, when the function fgl_report_commitCurrentSettings() is called the error pops up...

Seems like there is some trash remaining, that's why i asked in the original thread if i had forgot something, i suppose the first time i call fgl_report_commitCurrentSettings() it start the XML, writing the header and stuff and when you use terminate command it don't delete this data, so the second time the function is called it gets confused and pops the error.

But that's me just guessing, i suppose it's just better to wait for the fix.
Alex G.
Four Js
Posts: 155


« Reply #5 on: April 03, 2014, 06:06:09 pm »

Hi,
>I think it's weird that the error only occurs if you try to start another report, when the function fgl_report_commitCurrentSettings() is called the error pops up...
it is a bit internal but if you want an explanation of the current behavior then here it is:
TERMINATE REPORT or EXIT REPORT perform the documented cleanup but fail to notify and close the XML channel.
It is only when we start a new XML report that the previous XML channel is closed and we detect the incomplete document.
>But that's me just guessing, i suppose it's just better to wait for the fix.
Yes, perhaps you could make the error "Unexpected EOF" appear immediately after TERMINATE REPORT by patching the libraries but I wouldn't advise it. Making the "Unexpected EOF" go away altogether requires changes to the DVM and GRE or the usage of the patterns described.
Regards,
Alex
Anderson P.
Posts: 82


« Reply #6 on: April 03, 2014, 06:17:42 pm »

Ok, now i understand...

Thanks for the explanation
Reuben B.
Four Js
Posts: 1119


« Reply #7 on: April 07, 2014, 11:43:13 pm »

I wonder if fgl_report_stopGraphicalCompatabilityMode()
https://4js.com/online_documentation/fjs-gst-manual-html/#c_grw_fgl_report_stopGraphicalCompatibilityMode.html

is also possible as an interim solution  (haven't tested to verify)

Really wanted to comment on ...

Quote
You are getting the error because you are accessing look-ahead variables from a list (trigger) that is empty. That typically happens in report headers where you access for example the customer name that is shipped in the order details. If the report has no order details then the header references a variable that is not shipped and an error is raised.

... and suspect that if that is the case the 4gl should be

ORDER EXTERNAL BY header.id, detail.id

BEFORE GROUP OF header.id
   -- Information for Page Header
   PRINTX header.*

ON EVERY ROW
   -- Information for Line Detail
   PRINTX detail.*

rather than

ON EVERY ROW
   PRINTX header.*, detail.*

i.e normalise what is sent through. 

Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Anderson P.
Posts: 82


« Reply #8 on: April 08, 2014, 01:27:35 pm »

Hi Reuben
Thanks for the reply

Quote
I wonder if fgl_report_stopGraphicalCompatabilityMode()
https://4js.com/online_documentation/fjs-gst-manual-html/#c_grw_fgl_report_stopGraphicalCompatibilityMode.html

is also possible as an interim solution  (haven't tested to verify)

Have tested calling fgl_report_stopGraphicalCompatibilityMode() before and after Terminate Report with no success, still getting the reported message.

Quote
... and suspect that if that is the case the 4gl should be

ORDER EXTERNAL BY header.id, detail.id

BEFORE GROUP OF header.id
   -- Information for Page Header
   PRINTX header.*

ON EVERY ROW
   -- Information for Line Detail
   PRINTX detail.*

rather than

ON EVERY ROW
   PRINTX header.*, detail.*

Actually, my 4gl is like

REPORT print(header.*, detail.*)

FORMAT
     FIRST PAGE HEADER
          PRINTX header.*

     ON EVERY ROW
          PRINTX detail.*

END REPORT
Alex G.
Four Js
Posts: 155


« Reply #9 on: May 15, 2020, 09:28:21 am »

Seeing by chance that this topic is currently the one with the most views, I would like to point out that since version 3.10 one can use the FirstPageHeader trigger for this purpose.
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines