Creating a master report data source

A sub report is a report that is started from within another report via a START REPORT statement.

The START REPORT statement for the sub report takes no arguments. Do not add TO XML HANDLER for the sub report call.

Sub reports can be called from any control block wherever printing in loops is allowed: ON EVERY ROW, BEFORE GROUP, AFTER GROUP, or ON LAST ROW.

The START REPORT must be in the calling report block. The START REPORT statement cannot be placed inside a function called from the report.

The START REPORT, OUTPUT TO REPORT, and FINISH REPORT statements must be in the same control block. The OUTPUT TO REPORT and FINISH REPORT statements can be placed inside a function or functions called from the report, however those functions must be in the same control block as the START REPORT statement.

You can have multiple calls to sub reports from the same control block, however the calls cannot be nested.

Valid:

REPORT master_report(...)
...
FORMAT
  BEFORE GROUP ...
  ...
  START REPORT detail_report_1
  FOREACH ...
    OUTPUT TO REPORT detail_report_1(...)
  END FOREACH
  FINISH REPORT detail_report_1
  START REPORT detail_report_2
  FOREACH ...
    OUTPUT TO REPORT detail_report_2(...)
  END FOREACH
  FINISH REPORT detail_report_2
...
END REPORT
Not valid:
REPORT master_report(...)
...
FORMAT
  BEFORE GROUP ...
  ...
  START REPORT detail_report_1
  START REPORT detail_report_2 -- Not allowed until after 
                               -- FINISH REPORT detail_report_1
  ...
END REPORT
Sub reports can be nested to arbitrary depth, but recursion is not allowed.
REPORT master_report(...
 ...
FORMAT
  ON EVERY ROW    
    ...
    START REPORT detail_report
      FOREACH ...
        OUTPUT TO REPORT detail_report(...
      END FOREACH
      FINISH REPORT detail_report 
END REPORT

REPORT detail_report(...
  ...
  FORMAT
    ON EVERY ROW
      ...
      START REPORT other_detail_report -- Since recursion is not allowed, we are 
                                       -- not allowed to call "master-report" or 
                                       -- "detail_report" from here.
      FOREACH ...
        OUTPUT TO REPORT other_detail_report(...
      END FOREACH
      FINISH REPORT other_detail_report
END REPORT

Detected sub report calls are shown in the report designer. They appear as nodes in the data view, triggers the structure view, and images in the document view.

Code Example

This code example shows a master report master_report that calls two sub reports (report_orders and report_items) from the ON EVERY ROW section. The invocation of a sub report requires the START REPORT, OUTPUT TO REPORT and FINISH REPORT from within the master report.

The START REPORT instructions for sub reports cannot include the TO clause (START REPORT repname TO XML HANDLER); doing so will yield unexpected results.

FUNCTION run_master_report
...
  START REPORT master_report TO XML HANDLER handler
  FOREACH ...
    OUTPUT TO REPORT master_report
  END FOREACH
  FINISH REPORT master_report
END FUNCTION

REPORT master_report()
  DEFINE
    orderline OrderType,
    ch base.channel

  FORMAT  
    ON EVERY ROW

      # Data source for first sub report
      LET ch = base.Channel.create()
      CALL ch.openFile(dataFile,"r")

      # First sub report
      START REPORT report_orders   -- Notice there is no TO XML HANDLER  
                                   -- for the sub report
      WHILE ch.read([orderline.*])
        OUTPUT TO REPORT report_orders(orderline.*)
        IF fgl_report_getErrorStatus() THEN
          DISPLAY "FGL: STOPPING REPORT, msg=\"",fgl_report_getErrorString(),"\""
          EXIT WHILE
        END IF 
      END WHILE
      FINISH REPORT report_orders

      CALL ch.close()

      # Data source for second sub report
      LET ch = base.Channel.create()
      CALL ch.openFile(dataFile,"r")

      # Second sub report
      START REPORT report_items    -- Notice there is no TO XML HANDLER 
                                   -- for the sub report
      WHILE ch.read([orderline.*])
        OUTPUT TO REPORT report_items(orderline.*)
        IF fgl_report_getErrorStatus() THEN
          DISPLAY "FGL: STOPPING REPORT, msg=\"",fgl_report_getErrorString(),"\""
          EXIT WHILE
        END IF
      END WHILE
      FINISH REPORT report_items

      CALL ch.close()

END REPORT

REPORT report_orders
  ...
END REPORT

REPORT report_items
  ...
END REPORT