Simple 1:n Relations

The typical example for this case is the previously discussed 1:n relation order – order details. After each record with order data, the order details for that data shall be printed.

The printing of a data line is triggered by LlPrintFields(). Analogously to the behavior of LlPrintFieldsEnd() in the last section, the function returns LL_WRN_TABLECHANGE if the user has placed a sub-table, and you then have to respond.

You can ask for the table relation with LlPrintDbGetCurrentRelation() and for the name of the child table with LlPrintDbGetCurrentTableName(). With this information, you can invoke the auxiliary function PrintTable() from the last section again. This call must be placed directly after LlPrintFields() – thus from the function PrintTable() itself. The function must be changed in order to call itself recursively:

function PrintTable(DataTable data object)
{
       // DataTable is an adequate object for data access, e.g. a
       // table of a database, a class array or similar

       <repeat>
       {
               <define fields of DataTable>
                        (LlDefineField,
                         LlDefineFieldExt,
                         LlDefineFieldExtHandle)
               <print row>
                        (LlPrintFields)
               <as long as warning repeat>
                        (LlPrint,
                         Ret = LlPrintFields)
               <as long as Ret = LL_WRN_TABLECHANGE repeat>
               {
                        <get current table name>
                                (LlPrintDbGetCurrentTable)
                        <get current relation>
                                 (LlPrintDbGetCurrentTableRelation)
                        <get current sorting>
                               (LlPrintDbGetCurrentTableSortOrder)
                        <generate an appropriate DataTable child object>
                        <Ret = PrintTable(child DataTable)>
               }
      
               <next record in DataTable>
       }
       <until last record in DataTable is reached>
      
       <print footer line>    
               (Ret = LlPrintFieldsEnd)
       < as long as warning "page full" repeat >
               (Ret = LlPrintFieldsEnd)
       <result = Ret>
}

Any sequence of tables and sub-tables can be printed with this code. The recursion ensures that it works properly with any "depth", i.e. this code can control arbitrary multilevel relations.