Multiple Independent Tables on the Same Level

An example for this would be a list of customers followed by a chart of employees. Both tables can be independent. The print loop for this looks very similar to the print loop in the last chapter – with one difference. Usually, you tell List & Label that a table is finished (no more data) by calling LlPrintFieldsEnd(). Now you may get the return value LL_WRN_TABLECHANGE, meaning that there is another table to print in the layout.

We suggest splitting your print loop into different subroutines.

The first part declares the data and the structure, starts the print job and initializes the first page so that printing of a table can be started. For ease of reading, the optional part of the print loop is not shown here, as it has already been shown in the last chapter.

<define data structure>
       (LlDbAddTable,
        LlDbAddTableRelation,
        LlDbAddTableSortOrder)
<define all possible variables>
       (LlDefineVariableStart,
        LlDefineVariable,
        LlDefineVariableExt,
        LlDefineVariableExtHandle)
<define all possible fields>
       (LlDefineFieldStart,
        LlDefineField,
        LlDefineFieldExt,
        LlDefineFieldExtHandle)
        LlSetPrinterDefaultsDir
<begin print>
       (LlPrintStart,
        LlPrintWithBoxStart)
<define options>
       (LlPrintSetOption,
        LlPrintSetOptionString,
        LlPreviewSetTempPath) 
<define fixed variables>
       (LlDefineVariable,
        LlDefineVariableExt,
        LlDefineVariableExtHandle)
<print variables>      (print all objects)
               (LlPrint)
<as long as warning repeat>
               (LlPrint)

The second part of the print loop needs an auxiliary function. This function prints the data of a single (database) table

function PrintTable(DataTable Dataobject)
{
       // 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 line>
               (LlPrintFields)
               <as long as warning repeat >
                       (LlPrint,
                        LlPrintFields)
                <next data record in DataTable>
       }
       <until last data record in DataTable reached>

       <print footer line>    
               (Ret = LlPrintFieldsEnd)
       <as long as warning "page full" repeat>
               (Ret = LlPrintFieldsEnd)
       <result = Ret>
}

The return value specifies whether another table follows (LlPrintFieldsEnd() returns LL_WRN_TABLECHANGE) or if the print can be finished (return value 0).

With this function, the second part of the print – the part after the initialization of the first page – can be coded as follows:

<repeat>
{
       <get current table name >
               (LlPrintDbGetCurrentTable)
       <get current sorting>
               (LlPrintDbGetCurrentTableSortOrder)
       <generate a corresponding DataTable object>
       <Ret=PrintTable(DataTable)>
}
<until Ret <> LL_WRN_TABLECHANGE>

<finish printout>
       (LlPrintEnd)

 

If you have declared the "LLStaticTable" table for free contents and LlPrintDb­Get­Current­Table() provides this table as the current table, your printing loop must react to it by printing a single data line via LlPrintFields(). In the above example, you could simply generate a DataTable object with just one data record for the case of "LLStaticTable", and printing will then automatically run correctly.

This code already allows an arbitrary sequence of multiple tables in series. In the following chapter, we will expand it to print sub-tables as well.